NestJS | API 만들기(2) - 구조 이해하기

Sua·2021년 3월 20일
2

NestJS

목록 보기
2/9
post-thumbnail

구조 이해하기

NestJS는 우리를 위해 이미 만들어진 기능들을 제공한다. 그래서 프로젝트를 생성하면 여러 파일들이 자동적으로 생성된다.

(src/app.controller.spec.ts 파일은 삭제한다. 나중에 다시 만들어 줄 예정)

우선 다 살펴볼 필요는 없고 가장 중요한 src 폴더를 살펴보자.

src
├── app.controller.ts
├── app.module.ts
├── app.service.ts
└── main.ts

장고 개념으로 비유하면
module은 app,
controller는 url,
service는 view,
main.ts는 manage.py의 역할을 한다고 생각하면 이해가 쉽다.

코드 흐름

service 👉 controller 👉 module 👉 main.ts

service에서 작성한 코드를 controller에서 사용하고,
controller와 service에서 작성한 코드를 module에서 사용하고,
module에서 작성한 코드를 main.ts에서 사용한다.

아키텍쳐

controller와 service를 module로 묶어 한 덩어리로 관리하고 여러 module이 모여 하나의 프로젝트를 구성한다.

기본 생성파일 분석

main.ts

모든 프로젝트는 main.ts을 무조건 가진다. main.ts 이름은 바꾸면 안 된다.

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

main.ts에서는 boostrap이라는 함수를 만든 뒤 바로 실행한다. 함수명은 아무거나 써도 된다.

이 함수가 하는 일은 NestFactory 클래스를 이용해 app이라는 Nest 어플리케이션 인스턴스를 만드는 것이다. 그리고 listen 메소드를 사용해서 3000번 포트를 열어준다. 다시 말해, 이제 어플리케이션은 3000번 포트를 리스닝하고 있다.

여기서, NestFactory 클래스가 받아온 AppModule은 어떤 역할을 할까?
ctrl을 누른 채로 AppModule을 누르면 해당 코드가 작성된 곳으로 이동한다.

app.module.ts

장고에서 하나의 앱이 하나의 기능을 담당했던 것처럼, nest에서는 모듈이 그 역할을 대신한다. 이 모듈들의 조합을 통해 nest의 구조가 결정된다.

그리고 app.module은 모든 것의 루트 모듈 역할을 한다. app module에는 모든 것이 import되어 있어야 한다.

// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Appmodule@Module이라는 데코레이터가 달려 있는 비어있는 클래스이다.
이 데코레이터를 통해 모듈에서 사용할 controllers와 providers를 인스턴스화하고, AppModule로 묶어서 export한다.

데코레이터

데코레이터는 클래스에 함수 기능을 추가할 수 있게 한다. nest에서 데코레이터는 매우 매우 많이 사용된다.

export

변수나 함수, 클래스를 선언할 때 맨 앞에 export를 붙이면 내보내기가 가능하다. 내보낸 값은 다른 프로그램에서 import 문으로 가져가 사용할 수 있다

먼저 @Module() 데코레이터에서 사용한 AppController를 확인해보자.

app.controller.ts

controller는 url을 가져와서 함수를 실행한다.

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

해당 url로 HTTP Get 요청이 들어올 경우 getHello() 함수를 실행하고, Controller 클래스에서 정의한 appServicegetHello() 함수를 리턴한다.

(@Controller() 데코레이터와 @Get() 데코레이터의 인자에는 @Get('/hello')와 같이 엔드포인트 경로를 작성할 수 있다.)

controller에서 특정 url에 반응하는 함수 로직을 바로 작성할 수는 있지만 그렇게 하지 않는다. 비즈니스 로직은 service에서 담당한다.

app.service.ts

service에서는 비즈니스 로직을 작성한다. 그래서 유저에게 제공하는 service라고 이름 붙여졌다.

// app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

provider는 단순히 @Injectable() 데코레이터 주석이 달린 클래스를 말한다. provider 객체는 런타임에 NestJS에 의해 다른 모듈로 주입될 수 있다.
provider는 service를 포함해 repository, factory, helper 등이 될 수 있다.

@Injectable() 데코레이터가 붙어있는 클래스는 constructor를 통해서 의존성을 주입할 수 있다. 이렇게 하면 클래스 내부에서 this를 통해서 해당 서비스에 접근할 수 있게 된다.

정리

  • Module : 기능별로 controller와 provider, module을 묶어 놓은 곳
  • Controller : url을 가져와서 함수를 실행하는 곳
  • Service : 비즈니스 로직을 작성하는 곳

참고사이트
https://nomadcoders.co/nestjs-fundamentals
https://blog.martinwork.co.kr/nestjs/2020/03/22/what-is-nestjs.html
http://jays1204.github.io/nest.js/typescript/2019/03/31/nestjs-tutorial.html
https://velog.io/@kimjeongwonn/NestJS-독학-소개
https://velog.io/@khim89/Nest-시작해보기
https://darrengwon.tistory.com/845
https://velog.io/@kwonh/Nest-Nest-시작하기-1-사용하는-이유-Controller-Provider-Modules
https://changhoi.github.io/posts/backend/nestjs-quicklearn-02/

profile
Leave your comfort zone

0개의 댓글