[NestJs] TypeORM relations: Cannot access *Entity* before initialization

김현학·2025년 1월 17일
0

Temp

목록 보기
2/8

수정 git commit

1. 문제 상황

nestjs/techniques/database#relations

import { Entity, Column, PrimaryGeneratedColumn, OneToMany } from 'typeorm';
import { Photo } from './photo.entity';

// https://typeorm.io/entities/
@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  firstName: string;

  @Column()
  lastName: string;

  @Column({ default: true })
  isActive: boolean;

  @OneToMany(() => Photo, (photo) => photo.owner)
  photos: Photo[];
}

주어진 예제처럼 작성하고 관계를 설정하여 ORM을 활용하여 작업하려고 한다.
ORM 사용에 숙련된 상태가 아니라 발생한 문제를 천천히 추적해보려 한다.
에러 로그는 다음과 같다.

ReferenceError: Cannot access 'User' before initialization
    at Object.get [as User] (/Users/mia/live-chat-stats/server/dist/users/entities/user.entity.js:1:140)
    at Object.<anonymous> (/Users/mia/live-chat-stats/server/dist/users/entities/photo.entity.js:1:1319)
    at Module._compile (node:internal/modules/cjs/loader:1566:14)
    at Object..js (node:internal/modules/cjs/loader:1718:10)
    at Module.load (node:internal/modules/cjs/loader:1305:32)
    at Function._load (node:internal/modules/cjs/loader:1119:12)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:220:24)
    at Module.require (node:internal/modules/cjs/loader:1327:12)
    at require (node:internal/modules/helpers:136:16)

2. 증상 파악

  1. 새롭게 추가한 relation을 주석 처리하면 정상적으로 동작했다. 즉, 엔티티 간의 관계가 이번 문제의 핵심이다.
  2. Cannot access 'User' before initialization라는 에러 메시지와 콜 스택에서 photo.entity.js:1:1319에서부터 오류가 시작된 것으로 보아, Photo entity에서의 null reference 문제인 것 같았다.
    • 🤔 아직 엔티티를 저장한 기록이 없는데도 문제가 발생하는 것은, 필요에 따라 연결하지 않고 초기화 시점에 이러한 연결을 수행하는 동작 때문인 것으로 예상된다. (eager / lazy 전략과 연관이 있을지 시도해보기)

3. 조치

  1. default:eager 상태에서 null을 허용하는 것 가능 ✅
  @ManyToOne(() => User, (user) => user.photos)
  owner: User | null;
  1. lazy를 적용하는 것 가능 ✅
    • TypeORM에서는 Promise<Entity> 타입으로 정의하면 자동으로 적용된다고 한다. 그래도 여기선 일단 명시적으로 옵션을 설정해두었다.
  @ManyToOne(() => User, (user) => user.photos, { lazy: true })
  owner: Promise<User>;

4. 마치며

이를 시작으로 저장하는 기능까지 성공적으로 구현 완료했다.

EntityManager를 통해 저장된 시점에 자동적으로 할당 받은 id를 가지고 있어야 명시적인 저장이 가능하다. 따라서, User를 저장함과 동시에 이와 연결된 photos를 저장하려면 cascade 옵션을 사용해야 한다.

0개의 댓글

관련 채용 정보