[NestJs] Controller 변경 사항이 부분적으로 반영되지 않는 경우

김현학·2025년 1월 16일
0

Temp

목록 보기
1/8

수정 git commit

1. 문제 상황

nestjs/sample/05-sql-typeorm

import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Post,
  ParseIntPipe,
} from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { User } from './user.entity';
import { UsersService } from './users.service';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() createUserDto: CreateUserDto): Promise<User> {
    return this.usersService.create(createUserDto);
  }

  @Get()
  findAll(): Promise<User[]> {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number): Promise<User> {
    return this.usersService.findOne(id);
  }

  @Delete(':id')
  remove(@Param('id') id: string): Promise<void> {
    return this.usersService.remove(id);
  }
}

다음 provider를 모듈에 등록하면 기대하는 것은
1. POST /users로 Dto 전달하면 서비스 단에서 entity 형태로 데이터 추가
2. GET /users 요청 시, findAll() 호출
3. GET /users/:id 매개변수 포함 요청 시, 정수로 변환하여 findOne(id) 호출
(DELETE /users/:id 생략)

그런데 이상하게 1, 3은 정상 동작하는데 2만 빈 배열 []을 반환하는 현상이 문제였다.

2. 증상 파악

  1. Service 수준에서 메서드를 잘못 호출했나 TypeORM docs 확인했지만 문제 없음
  2. Service 수준에서 메서드 반환값을 임의의 string 형태로 변환했지만, 여전히 빈 배열 반환
    • 🤔 메서드 자체가 호출이 안 되고 있는건가?
  3. 미들웨어 및 nestjs/common 로거 활용하여 레이어 별 호출 여부 파악
    • GET 요청 자체는 제대로 전달됨
    • 컨트롤러 수준 메서드에서부터 호출이 되지 않음
  4. 컨트롤러에 단순한 문자열 반환하는 새로운 매핑을 추가했으나 반영 안 됨
    • 프레임워크 내부적인 문제라는 것을 인식
    • 🤔 뭔가 캐싱이 되어있나?
  5. 초기화를 위한 노력 (모두 실패)
    • node_modules 삭제, lock 파일 삭제 및 재설치
    • pnpm build
    • 컴퓨터 재시작
  6. 추가된 모듈이 소스 수준에서 문제가 없는 것으로 검증된 것임을 기억하고, 사용중이던 Cats 모듈 삭제 (정상 동작 확인 ✅)
  7. 하지만 Cats 모듈도 Users 모듈 추가 전에는 정상 동작했던 것임을 기억하고, 두 모듈 간의 호환성 문제임을 파악

Cats 모듈 내에 두 모듈 간 호환성 문제를 야기하는 무언가가 존재한다는 결론

3. 조치

  • NestJS 프레임워크 내에 서로 다른 두 모듈이 의존성을 가질 수 있는 부분을 Cats 모듈 내에서 살펴보니, Express 라이브러리 의존적인 코드가 존재함을 확인했다. 삭제해보니 정상 동작했다 ✅
  • 삭제해야만 할까? 호환되도록 만들 수는 없을까해서 기존 라이브러리 의존적이었던 CatsModule부터 import하던 것을 마지막에 하도록 순서를 변경했다. 다행히 정상 동작했다 ✅
  • 이러한 시도는 싱글톤 패턴으로 provider들의 인스턴스를 생성하고, imports 후 수정하여 exports하는 것으로 overriding된 모듈을 공유하는 프레임워크의 동작 방식에서 착안한 시도이다. 그러나 엄밀한 이유나 동작 원리에 대한 이해는 없어 우선 기록만 해둔다.

4. 마치며

서로 다른 모듈을 불러오며 라우팅 매핑이 부분적으로 망가지는 경우를 마주했다. 보통 0 또는 1처럼 아예 안 되는 경우가 보편적인데, 프레임워크를 처음 익혀나가는 입장에서 부분적으로 안 되니, 원인 파악이 안 되어 좀 당황했던 것 같다. 이런 상황을 겪을 때면 테스트 기반으로 작업하며, 코드 커밋 전에 검증 단계가 탄탄해야 한다고 생각이 든다.

NestJS 측 샘플 코드의 Mocking된 controller.spec은 DB와의 의존성을 분리했다는 측면에서 좋은 테스트라고 생각하긴 한다. 그렇다면 e2e 테스트를 추가해서 DB가 연결되었을 때에도 정상적으로 동작하는지 확인하는 테스트를 만든다면 이러한 문제를 좀 더 빠르게 확인할 수 있지 않을까 싶다.

0개의 댓글

관련 채용 정보