NestJS / / 2024. 11. 16. 02:29

NestJS 핫리로드 트러블슈팅

NestJS 핫 리로드 문제 및 ts-node-dev 사용 시 TypeORM 오류 해결

문제 상황

기존 NestJS에서는 서버가 재시작될 때 포트가 이미 사용 중이라는 문제가 발생했고, 이는 핫 리로드 도중 서버가 제대로 종료되지 않고 포트가 남아 있는 상황 때문이었습니다. 이로 인해 NestJS 자체 핫 리로드 기능이 비효율적일 수 있다고 판단하게 되었습니다.

기존 Express 프로젝트에서는 Nodemon을 사용해 핫 리로드 기능을 문제없이 사용했기에, NestJS 기본 핫 리로드 대신 다른 도구를 찾게 되었습니다. 그 결과, ts-node-dev라는 라이브러리를 발견하고 적용했는데, 이번엔 TypeORM 관련 오류가 발생했습니다.

검색과 시도한 해결책

검색을 통해 3000번 포트를 사용하는 프로세스를 찾아 taskkill 명령어로 종료하는 방법을 시도했으나, 이는 일시적인 해결책에 불과했습니다. 포트를 변경해도 문제가 다시 발생했고, 결국 근본적인 해결책이 아니었습니다.

Nodemon을 사용했던 Express 프로젝트에서는 이러한 문제가 발생하지 않았기 때문에, NestJS에서 Nodemon과 비슷한 핫 리로드 도구를 찾아보기로 했습니다. NestJS 프로젝트에서 사용할 수 있는 핫 리로드 도구로 ts-node-devnodemon을 발견했고, ts-node-dev를 선택해 사용하게 되었습니다.

그러나 ts-node-dev 사용 시, 예상치 못한 TypeORM 오류가 발생했습니다.

오류 내용

ts-node-dev로 서버를 실행했을 때, TypeORM이 데이터베이스에 연결할 수 없다는 오류와 함께 다음과 같은 에러 메시지가 발생했습니다:

DataTypeNotSupportedError: Data type "Object" in "UsersModel.role" is not supported by "postgres" database.

오류의 원인은 TypeORM의 엔터티에서 PostgreSQL이 지원하지 않는 데이터 타입을 사용하고 있었기 때문으로 보입니다. 문제가 발생한 UsersModel은 아래와 같은 구조를 가지고 있었습니다:

@Entity()
export class UsersModel extends BaseModel {
  @Column({ length: 20, unique: true })
  nickname: string;

  @Column({ unique: true })
  email: string;

  @Column()
  password: string;

  @Column({ enum: Object.values(RolesEnum), default: RolesEnum.USER })
  role: RolesEnum;

  @OneToMany(() => PostsModel, (post) => post.author)
  posts: PostsModel[];
}

위 코드에서 문제가 된 부분은 @Column()role 필드였습니다. 이 필드는 Object.values(RolesEnum)을 사용해 열거형 값을 정의하고 있었는데, PostgreSQL에서 Object 타입을 직접 지원하지 않기 때문에 TypeORM이 이를 처리하는 과정에서 오류가 발생한 것입니다.

문제 원인 분석

  1. ts-node-dev와 TypeORM의 메타데이터 재검증

    ts-node-dev는 파일 저장 시 전체 서버를 재시작하는 대신 일부 파일만 다시 로드합니다. 이 과정에서 TypeORM이 엔터티의 메타데이터를 PostgreSQL과 다시 검증하게 되는데, 이때 Object 타입이 문제가 되는 것입니다. 이 검증 과정에서 기존에 무시되었던 데이터 타입 문제가 드러나게 됩니다.

  2. PostgreSQL의 엄격한 데이터 타입 지원

    PostgreSQL은 Object 타입을 직접 지원하지 않습니다. 따라서 TypeORM이 이를 인식하지 못하고 오류를 발생시키게 됩니다. 이전에는 서버가 완전한 재시작이 아닌 경우 메타데이터 검증이 덜 엄격하게 이뤄졌을 가능성도 있습니다. 특히 synchronize 옵션을 사용하면서 엔터티와 데이터베이스 스키마 간의 불일치를 발견하지 못할 수도 있습니다.

  3. 환경 차이로 인한 검증 차이

    기존에는 서버가 재시작하지 않는 환경에서 덜 엄격한 검증이 이루어졌을 수 있습니다. 하지만 ts-node-dev를 사용하면 저장할 때마다 데이터 타입 검증을 반복하게 되어 이러한 문제가 노출되었습니다.

해결 방법

  1. 명확한 데이터 타입 정의

    Object 대신 PostgreSQL이 이해할 수 있는 데이터 타입을 사용해야 합니다. role 필드를 정의할 때는 enum: RolesEnum과 같이 명확하게 열거형을 지정해야 합니다. 예를 들면:

     @Column({ enum: RolesEnum, default: RolesEnum.USER })
     role: RolesEnum;

    TypeORM은 이러한 방식으로 열거형을 정의할 때 데이터베이스에 적합하게 매핑할 수 있습니다. Object.values()처럼 동적으로 값을 지정하는 대신, 열거형 자체를 명확하게 설정해야 합니다.

  2. 스키마 동기화 설정 확인

    TypeORM의 스키마 동기화 옵션(synchronize: true)을 사용할 경우, 엔터티 변경 사항이 데이터베이스와 일치하도록 주의해야 합니다. 이 설정이 제대로 작동하지 않으면 메타데이터 검증 오류가 발생할 수 있습니다. 개발 중에는 synchronize 옵션을 사용하되, 프로덕션 환경에서는 마이그레이션 도구를 사용하는 것이 권장됩니다.

  3. 핫 리로드 도구와 TypeORM의 호환성 최적화

    ts-node-dev와 같은 핫 리로드 도구를 사용할 때는 TypeORM 설정 및 데이터 타입 정의를 엄격히 지켜야 합니다. TypeORM이 지원하는 데이터 타입만 사용하고, PostgreSQL과의 호환성을 항상 고려해야 합니다. 이를 통해 핫 리로드 시 발생하는 데이터 타입 검증 오류를 방지할 수 있습니다.

결론

이 문제는 ts-node-dev가 핫 리로드 시 TypeORM의 데이터베이스 검증을 더 엄격하게 수행하면서 발생했습니다. PostgreSQL에서 지원되지 않는 Object 타입 사용을 피하고, 대신 적합한 데이터 타입으로 변경하는 것이 중요합니다. TypeORM과 PostgreSQL의 호환성을 유지하면서 개발 환경을 설정하면 이러한 문제를 방지할 수 있습니다.

앞으로는 핫 리로드를 사용할 때 데이터 타입에 대해 더욱 주의하고, PostgreSQL에서의 데이터 타입 지원 여부를 꼭 확인하는 것이 필요하겠습니다. 특히 ts-node-dev와 같은 도구를 사용할 때는 TypeORM이 기대하는 스키마와 데이터 타입을 명확히 정의하여 문제가 발생하지 않도록 주의해야 합니다.

또한, 핫 리로드 도구를 사용하면서도 데이터베이스 연결과 메타데이터 검증에 있어 안정성을 보장하려면, 가능한 한 엄격한 데이터 타입 정의와 함께 스키마 동기화를 확실하게 하는 것이 중요합니다.

'NestJS' 카테고리의 다른 글

NestJS 데코레이터  (0) 2024.11.16
NestJS Guard  (0) 2024.11.16
NestJS Pipe  (0) 2024.11.15
회원가입로직  (2) 2024.11.14
NestJS DI(Dependency Injection)  (0) 2024.11.06
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유