Menu
CoddyTech

서비스

Coddy Node.js 여정의 TypeScript와 NestJS 섹션에 포함된 레슨. 24개 중 9번째.

컨트롤러가 작업을 직접 가지고 있으므로 앱의 다른 부분에서는 작업에 접근할 수 없습니다. 데이터와 로직은 프로바이더에 있어야 합니다. 프로바이더는 Nest가 생성하고 요청한 곳에 전달하는 클래스입니다.

@Injectable()
export class BooksService {
    private books = [{ title: 'Dune' }];
}

@Controller('books')
export class BooksController {
    constructor(private readonly booksService: BooksService) {}
}

@Injectable()은 클래스를 표시하고, 모듈은 이를 providers에 등록합니다. 클래스는 생성자에 이름을 지정해 프로바이더를 요청합니다. 이를 의존성 주입이라고 합니다. 매개변수 앞의 private readonly는 TypeScript의 축약 문법입니다. 필드 this.booksService를 만들고 Nest가 전달하는 값을 저장합니다. Nest는 컴파일러가 데코레이터가 적용된 클래스에 대해 보존하는 매개변수의 타입을 읽고, 프로바이더를 등록한 모듈에 인스턴스를 하나 생성한 다음, 이를 요청하는 해당 모듈의 모든 클래스에 같은 인스턴스를 전달합니다. 데이터는 공유되며, 테스트에서는 대신 가짜 객체를 전달할 수 있습니다.

이 강의는 컨트롤러가 이미 this.tasksService를 호출하는 상태에서 시작합니다.

challenge icon

챌린지

쉬움

이 단계에서는 상태 코드와 오류에서 작업한 프로젝트 파일( src/tasks/tasks.controller.ts 포함)이 아니라, 과정에 준비된 Nest 작업 추적기 프로젝트를 엽니다. 이전 작업은 해당 강의에 그대로 남아 있습니다. src/tasks/tasks.service.ts를 수정하기 전에 제공된 파일을 읽어 보세요. 이 프로젝트에는 Nest 작업 라우트가 있으며, 컨트롤러는 서비스에 처리를 위임하도록 준비되어 있습니다.

작업이 컨트롤러 안에 있으므로 앱의 다른 부분에서는 작업에 접근할 수 없습니다. 작업을 소유하는 클래스인 서비스로 옮기세요. Nest는 서비스를 한 번 생성하고, 서비스를 요청하는 각 클래스에 전달합니다. 컨트롤러는 이미 서비스를 호출하도록 다시 작성되어 있습니다. 서비스 작성을 마치고 둘을 연결하는 것이 여러분의 할 일입니다.

  1. src/tasks/tasks.service.ts에서 @nestjs/common의 @Injectable()을 사용해 TasksService 클래스를 표시하세요. 이렇게 하면 Nest가 서비스를 생성해 전달할 수 있습니다.
  2. 같은 클래스에 create(title) 메서드를 작성하세요. 이 메서드는 사용 가능한 다음 id(this.tasks에서 가장 큰 id보다 1 큰 값), 해당 제목, done: false를 가진 작업을 만듭니다. 작업을 this.tasks에 추가하고 반환합니다. 컨트롤러의 POST /tasks는 요청 본문에서 가져온 제목을 전달해 이 메서드를 호출합니다.
  3. id가 숫자인 remove(id) 메서드를 작성하세요. 해당 id를 가진 작업이 없으면 findOne처럼 404로 응답해야 합니다. 먼저 예외를 발생시키는 this.findOne(id)을 호출하세요. 그런 다음 this.tasks에서 작업을 제거합니다. 아무것도 반환하지 않습니다.
  4. src/tasks/tasks.module.ts에서 ./tasks.service의 TasksService를 가져오세요. 그런 다음 모듈에 controllers 옆에 providers 목록을 추가하고, 그 안에 TasksService를 넣으세요. Nest는 모듈에 나열된 클래스만 생성합니다.
  5. src/tasks/tasks.controller.ts에서 TasksController 안의 주석을 매개변수 하나를 받는 생성자로 바꾸고, 매개변수는 private readonly tasksService: TasksService라고 작성하세요. Nest는 TasksService 타입을 확인하고 서비스 인스턴스를 전달합니다. 매개변수 앞의 private readonly는 전달받은 값을 담는 this.tasksService 필드도 만듭니다. 아래 메서드에서 이미 사용하는 이름입니다.

직접 해보기: /tasks에 POST { "title": "Buy milk" }를 보내세요. 201과 다음 응답을 받습니다.

{ "id": 4, "title": "Buy milk", "done": false }

GET /tasks를 보내면 작업 네 개가 표시되고, 마지막 작업은 Buy milk입니다. DELETE /tasks/4를 보내면 204가 반환됩니다. DELETE /tasks/99를 보내면 "message": "Task 99 not found"와 함께 404가 반환됩니다.

직접 해보기

import { NotFoundException } from '@nestjs/common';

export interface Task {
    id: number;
    title: string;
    done: boolean;
    createdAt?: string;
}

// Nest가 주입할 수 있도록 이 클래스를 프로바이더로 만드세요.
export class TasksService {
    private tasks: Task[] = [
        { id: 1, title: 'Write the README', done: true, createdAt: '2026-01-05T09:00:00.000Z' },
        { id: 2, title: 'Fix the login bug', done: false, createdAt: '2026-01-06T14:30:00.000Z' },
        { id: 3, title: 'Plan the sprint', done: false, createdAt: '2026-01-07T08:15:00.000Z' },
    ];

    findAll(done?: string): Task[] {
        if (done === undefined) {
            return this.tasks;
        }
        return this.tasks.filter((task) => task.done === (done === 'true'));
    }

    findOne(id: number): Task {
        const task = this.tasks.find((task) => task.id === id);
        if (!task) {
            throw new NotFoundException(`Task ${id} not found`);
        }
        return task;
    }

    // 여기에 create(title)과 remove(id)를 작성하세요.
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

TypeScript와 NestJS의 모든 레슨

직접 연습해 보세요: Express 플레이그라운드