[2024.06.27 TIL] 내일배움캠프 51일차 (Nest.js 강의 시청, 개발 환경 구축, 모듈, 컨트롤러, 서비스, IoC, 의존성 주입)

My_Code·2024년 6월 27일
2

TIL

목록 보기
66/112
post-thumbnail

본 내용은 내일배움캠프에서 활동한 내용을 기록한 글입니다.


💻 TIL(Today I Learned)

📌 Today I Done

✏️ Express.js의 장점과 단점

  • 장점 :

    • 10줄 이내의 코드로 Express는 가볍게 테스트용 서버를 만들 수 있음
    • 즉, 쉽게 서버를 구축할 수 있고, 가볍고 유연함
    • 라우팅 과정이 간편하고, 직관적임
  • 단점 :

    • 복잡한 웹 서버일 경우 필요한 모듈을 많아져서 관리하기 어려움
    • 레이어드 아키텍처 패턴을 적용하려면 직접 구조를 설계해서 구현해야 함
  • Express에 레이어드 아키텍처 패턴을 적용하려면 프레임워크의 구조를 스스로 설계해서 구현해야 함

  • 이는 요구사항 변경 및 기획이 추가됨에 따라 필요한 개념들을 새롭게 추가해야 함


✏️ Nest.js의 등장!

  • Nest.js는 TypeScript 기반의 웹 프레임워크이기 때문에 타입을 체크해서 여러 예외 상황을 사전에 방지할 수 있음

  • 그리고 명령어 하나로 쉽고 간편하게 계층 생성이 가능함

  • nest g co posts : nest로 posts라는 컨트롤러를 만들겠다 란 뜻의 명령어

  • 컨트롤러 뿐만 아니라 서비스, 미들웨어, 인터셉터 등 웹서버에 필요한 다양한 구성요소를 커맨드로 정확하게 구현 가능함

  • 이는 개발자에게 보다 더 로직에 집중할 수 있는 환경을 제공하는 것임


✏️ Nest.js 개발환경 구축

  • Nest.js 설치
npm i -g @nestjs/cli
  • Nest.js 명령어 실행
nest
  • Nest.js로 새로운 프로젝트 생성 (sparta-nest라는 폴더가 생성됨)
nest new sparta-nest
  • Nest.js는 npm이 가장 잘 호환되기 때문에 npm 선택은 필수
? Which package manager would you ❤️  to use? (Use arrow keys)npm
  yarn
  pnpm
  • 프로젝트가 생성되면 아래와 같은 파일 구조의 폴더가 생성됨


✏️ 진입점 파일

  • 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 파일은 Nest.js 웹 어플리케이션의 진입점으로, 즉 서버 실행시 처음 동작하는 구간임

  • const app = await NestFactory.create(AppModule);

    • 위 코드는 AppModule이라는 모듈을 루트 모듈로 사용하는 Nest.js 어플리케이션 인스턴스를 생성해 달라고 하는 의미

✏️ 모듈

  • 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 {}
  • 모듈은 기능별로 src 디렉토리 밑에 생성하면 됨 ex) user.module.ts, post.module.ts 등

  • @가 붙은 키워드를 데코레이터라고 함

  • 데코레이터는 해당 클래스나 함수가 어떤 역할을 하는 지 Nest.js에게 알려주는 역할을 함

  • 모듈에는 imports, controllers, prociders, exports 속성이 존재함

  • imports
    • 현재 모듈에서 사용하려는 다른 모듈들의 목록을 정의함
    • 예를 들어, API 호출을 위한 HttpModule이나 데이터베이스 작업을 위한 TypeOrmModule등이 여기에 포함될 수 있음
    • 여러 모듈에서 공통으로 사용할 때 좋음
  • controllers
    • 현재 모듈과 관련된 컨트롤러의 목록을 정의함
    • 이 컨트롤러는 해당 모듈의 사용자 요청 처리를 담당함 (request, response)
  • providers
    • 현재 모듈에서 사용하거나 제공하는 서비스, 레포지토리, 팩토리 등의 목록을 정의함
    • 주로 비즈니스 로직 처리나 데이터 액세스와 같은 작업을 수행함
    • 즉, 서비스나 레포지토리와 같은 파일
    • 특정 모듈 내에서만 사용되고 다른 모듈에서는 사용되지 않을 때 좋음
  • exports
    • 현재 모듈에서 다른 모듈로 제공하려는 서비스의 목록을 정의함
  • 그럼 imports와 providers의 차이는?
    • imports는 외부의 라이브러리(JWT, TypeORM 등)를 현재 모듈에 가져와서 공통으로 사용
    • providers는 내가 만든 기능들(Service, 미들웨어 등)을 현재 모듈에 가져와서 공통으로 사용
    • 이렇게 Imports와 Providers를 구분하여 사용하면 Nest.js 애플리케이션의 구조와 재사용성을 높일 수 있음

✏️ 컨트롤러

  • 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();
  }
}
  • constructor(private readonly appService: AppService) {}

  • 위의 코드를 해석하면 인자로 AppService 객체를 받아서 this.appService라는 멤버 변수에 AppService 객체가 주입된다는 것을 의미

  • 이러한 것을 생성자를 통한 의존성 주입(DI)이라고 함

  • 그리고 컨트롤러는 서비스를 반드시 의존해야 함

  • 컨트롤러의 데코레이터는 Http Method를 의미함

  • @Post, @Put, @Patch, @Delete, @Post 데코레이터가 이미 준비되어 있음


✏️ 서비스

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

@Injectable() // <- 난 Inject(주입)될 수 있어! 라고 선언하는 것이에요.
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}
  • 서비스 객체는 실제로 레포지토리를 의존하며 비즈니스 로직 수행을 담당함

  • 서비스 역시 레포지토리를 반드시 의존해야 하며 이는 생성자를 통한 의존성 주입(DI)로 해결해야 함

  • 서비스에서 사용한 @Injectable 데코레이터는 다른 모듈에서 AppService를 의존성 주입을 위해 가져다 사용해도 된다고 표시한 것임


✏️ Ioc (제어 역전)

  • IoC는 Inversion of Control의 준말로서 제어 역전이라고도 함
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  // 1. 사용하고 싶은 서비스 타입 객체를 미리 선언합니다.
  private appService: AppService
  
  constructor() {
    // 2. 생성자에서 실제로 사용할 서비스 객체를 직접 생성합니다.
    this.appService = new AppService();
  }
  ...
}
  • 위와 같은 전통적인 방식은 AppController가 AppService와 강하게 결하뵈더 있음

  • 즉, AppService가 변경되면 개발자도 그에 맞춰 코드를 수정해야하는 번거로움이 발생함

  • 그래서 IoC는 객체의 생명주기 관리 자체를 외부에 위임해서 관리함

  • IoC 원칙은 모듈 간 결합도를 낮추기 때문에 하나의 모듈이 변경되어도 다른 모듈들에는 영향을 최소화 시킴

  constructor(private readonly appService: AppService) {}
  • 그래서 위와 같이 사용하면 AppService의 인스턴스는 Nest.js의 DI 컨테이너에 의해 생성되고 관리됨

  • 즉, 개발자는 직접 객체를 생성하거나 관리할 필요없이 코드의 결합도를 낮추고, 유연성과 테스트 용이성을 향상시킴



📌 Tomorrow's Goal

✏️ Nest.js 강의 시청

  • 일단 오늘 3주차 강의를 진행할 예정

  • 만약 3주차를 다 듣는다면 내일 Nest.js 강의를 끝낼 예정


✏️ 개인과제 발제

  • TypeScript + Nest.js + TypeORM 형태로 과제가 발제될 예정

  • 미리 올라온 발제 문제를 보니 이번에는 기존 과제를 재활용하지 않고 새로운 주제로 진행함

  • 생각보다 구현할게 많아 보여서 재밌어 보임



📌 Today's Goal I Done

✔️ Nest.js 강의 시청

  • 오늘은 Nest.js 강의 1주차, 2주차를 시청함

  • 1주차는 간단한 소개 뿐이었지만 2주차에는 Nest.js의 기본적인 구조에 대한 설명이었음

  • 2주차의 내용은 생각보다 어려워서 정리하고 이해하는 데 시간이 오래 걸렸음

  • 3주차 강의는 다 할 수 있을지 모르겠지만 최대한 진행할 예정



📌 ⚠️ 구현 시 발생한 문제

✔️ Delete eslint (prettier/prettier) 에러

  • Nest.js 강의 중 개발 환경 구축 영상을 시청하다가 eslint와 prettier 관련 에러가 발생함

  • 빨간줄로 에러 표시가 되어있지만 실제로 동작에는 아무런 문제가 없음

  • 하지만 계속 에러 표시로 남기기에는 너무 거슬리기 때문에 문제 해결을 위해 방법을 찾아봄

  • 원인은 ESLint에서의 줄바꿈에 대한 에러를 표시한 것임 (LF, CRLF 문제)

  • 그래서 .eslintrc.js 에서 설정을 바꿔주기로 함

  • 우선 아래와 같이 .eslintrc.js 파일로 이동

  • 그리고 아래와 같이 규칙(Rules)를 추가함

    'prettier/prettier': [
      'error',
      {
        endOfLine: 'auto',
      },
    ],
  • 그러면 아까와 같은 에러 표시가 사라짐

  • 만약 계속 에러 표시가 보인다면 VSCode와 같은 에디터를 껐다가 켜면 됨


📌 ❓ 학습중 생긴 궁금점

✔️ Nest.js가 나오고 Express에서의 불편함을 해소했는데 여전히 Express를 많이 사용하는 이유

  • Nest.js 강의를 시청하다보니 문득 이런 생각이 들었음

  • '이렇게 여러면에서 좋은 Nest.js가 나왔는데 왜 아직도 Express를 많이 사용하는 걸까?'

  • 생각보다 여러가지 이유가 있었지만 그렇게 큰 이유는 아닌 것 같음

  • 익숙함과 학습의 어려움
    • Express : 오랜 시간 동안 Node.js 개발자들 사이에서 널리 사용되어 왔기 때문에 많은 개발자들에게 익숙함
    • Nest.js : 상대적으로 새로운 프레임워크이기 때문에 기존 Epxress 사용자들이 바로바로 학습하기 어려움
  • 간단함과 유연성
    • Express : 매우 가볍고 간단한 프레임워크로, 필요에 따라 자유롭게 구현 가능함
    • Nest.js : Express에 비해 더 많은 기능과 구조를 제공하지만, 프로젝트가 복잡해지고 이로 인해 초기 설계, 구현 단계에서 시간이 더 많이 소요됨
  • 기존 프로젝트와의 호환성
    • 많은 기존 Node.js 프로젝트들이 Express를 사용하고 있기 때문에, 이를 Nest.js로 마이그레이션하기 어려울 수 있음
    • 특히 기존 프로젝트에 대한 유지보수 작업을 할 때, Express를 계속 사용하는 것이 더 효율적일 수 있음
  • 커뮤니티 지원
    • Express는 Node.js 커뮤니티에서 가장 널리 사용되는 프레임워크 중 하나이므로, 더 많은 리소스와 지원을 받을 수 있음
    • 하지만 Nest.js는 상대적으로 새로운 프레임워크이므로, 커뮤니티 지원이 아직 Express만큼 풍부하지 않을 수 있음
profile
조금씩 정리하자!!!

2개의 댓글

comment-user-thumbnail
2024년 7월 1일

저도 계속 esLint 밑줄이 신경쓰였는데 적어주신 코드를 적으니 깔끔하게 해결되었네요 감사합니다(__)

답글 달기
comment-user-thumbnail
2024년 7월 2일

이 게시글을 보고 문제가 해결되었습니다. 감사합니다~

답글 달기