Web 공부/NestJS

Nest JS

sumiin 2022. 3. 17. 19:50
반응형
SMALL

NestJS

  • nodejs 위에서 움직이는 framework (백엔드를 구성할 수 있도록 해줌)

  • nest new를 통해 nest 프로젝트 create 가능

    @Module({
    imports: [],
    controllers: [AppController],
    providers: [AppService],
    })
  • decorator (클래스에 함수 기능을 추가할 수 있음)

  • nestjs는 main.ts가 모든 것을 시작

  • main.ts : 하나의 모듈에서 applicaion을 생성

    • const app = await NestFactory.create(AppModule);
  • AppModule -모든 것의 루트 module
    (Module: 어플리케이션의 일부분(한 가지의 역할을 하는 App))

Controller

  • controller: url을 가져오고 함수를 실행
    @Get("/hello")
    sayHello():string{
      return "Hello";
    }
  • /hello url의 요청을 받고 sayHello()라는 함수를 실행
    (누군가가 /hello로 들어오면 sayHello라는 함수가 실행됨)

  • 데코레이터와 함수 사이에 빈칸이 있으면 안됨!!*
  • nest g(generate) co(controller) cmd 명령어를 통해 controller 생성 가능

    • app.module.ts의 controller에 생성된 controller 확인 가능
  • @Controller('movies')의 경우 /movies url에 해당됨

    • 기본 router 일 경우, @Controller()로 해야함
@Controller('movies')
export class MoviesController {
    @Get()
    getAll(){
        return "This will return all movies";
    } // `/movies` 일 경우, 나타남 

    @Get(":id")
    getOne(){
        return "This will retun one movie";
    } // `/movies/{id}` 일 경우, 나타남 
}
  • Nestjs에서는 무언가가 필요하면 요청해야함

    • 함수의 인자로 @Param("id")를 통해 요청한 것을 얻을 수 있음
      @Get(":id")
        getOne(@Param("id") movieId:string){
            return `This will retun one movie with the id: ${movieId}`;
        } //요청한 id와 movieId가 일치 
      }
      
    
    - Query를 얻고 싶은 경우, `Query()` 
    ```typescript
      @Get("search")
      search(@Query('year') searchingYear:string){
          return `We are searching for a movie made after: ${searchingYear}`;
      } //search가 :id의 Get보다 밑에있으면 search를 id로 판단하는 문제가 생길 수 있음 

    -> url /movies/search/?year=200 일 경우, searchingYear =200 이 됨

  • @Post() :create

    • Post에서 send할 때 보낸 body 를 받고 싶다면 @Body()를 통해 얻을 수 있음
      @Post() //create
      create(@Body() movieData){
          console.log(movieData); //send할 때 보낸 body를 얻은 것을 확인 가능 
          return 'This will create a movie';
      }
  • @Delete(":id"): delete

  • @Put():모든 resource를 update

  • @Patch(':id'): resource의 일부분만 update

  • service 함수에 접근하는 법
    • constructor(private readonly moviesService:MoviesService){} 에서 인자 moviesService를 통해 MoviesService에 접근 가능
    • return this.moviesService.getAll(); controller의 함수에서 this.moviesService.__ 를 통해 MoviesService의 함수들에 접근 가능

Services

  • Nestjs는 controller를 비즈니스 로직이랑 구분짓고 싶어 함

    • controller는 url을 가져오고 함수를 실행 , 나머지 비즈니스 로직은 services (service는 function을 가지는 부분)
  • Single-responsibility principle: 하나의 module,class 혹은 function이 하나의 기능은 꼭 책임져야 하는 것

  • nest g(generate) s(service) cmd 명령어를 통해 service 생성 가능

    • app.module.ts의 providers에 생성된 service 확인 가능
  • DTO (Data Transfer Object) :데이터 전송 객체

    • controller와 service에서 전송하는 객체들의 type 유효성 검사하기 위함

    • app.useGlobalPipes(new ValidationPipe({whitelist:true,forbidNonWhitelisted:true,transform:true}));: main.ts에 작성해 유효성을 검사해줌

      • whitelist: true로 설정하면 아무 decorator도 없는 어떤 property의 object를 거름
      • forbidNonWhitelisted:누군가가 이상한 것을 보내면 request 자체를 막아버림
      • transform: user가 보낸 것을 원하는 타입으로 변환해줌 (url에서 받은 id는 string이지만 number로 명시해준다면 number로 자동으로 변환됨 )
    • npm i class-validator class-transformer :class의 유효성 검사를 위함

    • <create-movie.dto.ts>

      export class CreateMovieDto{
      @IsString()
      readonly title: string;
      @IsNumber()
      readonly year:number;
      @IsString({each:true})
      readonly genres:string[];
      }
      • create(@Body() movieData:CreateMovieDto)를 통해 들어오는 쿼리에 대해 유효성을 검사할 수 있게 해줌
      • input에 대해서도 유효성 검사를 typescript가 실시간으로 하게 됨
    • npm i @nestjs/mapped-types :mapped-types는 타입을 변환시키고 사용할 수 있게 하는 패키지

      • export class UpdateMovieDto extends PartialType(CreateMovieDto){}
      • PartialType은 base Type을 인자로 가지며 그 base type의 인자들이 필수사항은 아님

  • app.module.ts는 Appcontroller와 Appservice만 가져야함 -> app은 여러개의 module로 이뤄져있으므로 module로 다른 것들을 만들어줘야함

  • nest g(generate) mo(module) :imports에 module 생성된 것을 확인할 수 있음

  • spec.ts는 테스트하는 파일
  • jest가 .spec.ts 파일들을 찾아볼 수 있도록 설정되어 있음
  • Test
    • unit test: 서비스에서 분리된 unit을 테스트 (function 하나하나를 테스트)
    • end-to-end(e2e) test: 전체 시스템을 테스트

Unit test

  • .spec.ts : 해당 파일의 unit test 를 위함
    • describe: 테스트를 묘사
    • beforeEach: 테스트를 하기 전에 실행
    • it(",()=>{}): 테스트 실행
    • afterAll: 데이터베이스를 깨끗하게 정리해주는 (모두 지우는 ) function을 넣을 수 있음
   describe("getAll",()=>{
    it("should return an array",()=>{
      const result=service.getAll();
      expect(result).toBeInstanceOf(Array);
    })
  });

-> service = module.get<MoviesService>(MoviesService); 로 인해 MoviesService에 접근 가능

  • npm run test:watch 를 통해 unit test를 하는동안 코드가 수정될 떄마다 변경 사항을 확인할 수 있음 (a: testing all)
  • nom run test:cov 를 통해 test가 얼마나 작동됐는지 확인할 수 있음

e2e test

  • 모든 부분을 test할 때 필요
it("POST",()=>{
      return request(app.getHttpServer())
      .post("/movies")
      .send({
        title:"Test",
        year:2000,
        genres:['test'],
      })
      .expect(201)
    });

-> 서버에 request해서 movies에 post할 때 이 정보를 보내면 201을 받는지 test (create할 때 201 server)

  • beforeAll: 테스트가 새로 생길때마다 새로운 어플리케이션을 만들고 싶지 않을 때 (beforeEach에서 creating module을 실행될때마다 해서 데이터베이스가 계속 비워지게 되는 것을 방지)

  • main.ts에서 transform으로 자동 변환된 type은 pipe에 test를 올리지않았다면 test에서는 적용이 안됨 ( test에서도 똑같이 pipe 적용을 해줘야 함 )

    app = moduleFixture.createNestApplication();
      app.useGlobalPipes(new ValidationPipe({
        whitelist:true,
        forbidNonWhitelisted:true,
        transform:true
      }));
반응형
LIST