반응형
에러 메세지
ReferenceError: Cannot access 'User' before initialization at Module.User (webpack-internal:///(api)/./src/models/user.ts:3:51) at eval (webpack-internal:///(api)/./src/models/user-info.ts:24:129)
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, OneToMany, CreateDateColumn, UpdateDateColumn } from 'typeorm';
import { UserInfo } from '@/models/user-info';
import { Task } from '@/models/task';
import { TaskLabel } from '@/models/task_label';
@Entity({ name: 'user_orm_v2' })
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
...중략...
@OneToOne(() => UserInfo, (userInfo) => userInfo.user, { cascade: true })
user_info: UserInfo; // UserInfo와 1:1 관계
}
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn, UpdateDateColumn } from 'typeorm';
import { User } from '@/models/user';
@Entity({ name: 'user_info_orm_v2' })
export class UserInfo {
@PrimaryGeneratedColumn('uuid')
id: string;
@OneToOne(() => User, (user) => user.user_info)
@JoinColumn()
user: User; // User와 1:1 관계
..중략..
}
원인
순환 참조(circular reference) 문제로 인해 발생하는 것입니다. User와 UserInfo 두 엔티티가 서로를 참조하는 과정에서, 한쪽이 아직 초기화되지 않았을 때 다른 쪽에서 접근하려고 하면서 발생하는 문제입니다. TypeORM에서 두 엔티티가 서로를 동시에 참조할 때 자주 발생하는 문제
해결 방법: 지연 로딩(Lazy Loading)
TypeORM에서는 람다 함수를 사용하여 참조가 필요할 때 해당 엔티티를 불러오도록 지연 로딩을 설정할 수 있습니다. 이 방법을 사용하면 순환 참조 문제를 해결할 수 있다.
또한 서로 참조하는 양방향 관계이기 때문에 User 쪽도 Promise<UserInfo>로 바꿔주는 게 좋음.
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, OneToMany, CreateDateColumn, UpdateDateColumn } from 'typeorm';
import { UserInfo } from '@/models/user-info';
import { Task } from '@/models/task';
import { TaskLabel } from '@/models/task_label';
@Entity({ name: 'user_orm_v2' })
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
..중략..
@OneToOne(() => UserInfo, (userInfo) => userInfo.user, { cascade: true })
user_info: UserInfo; // UserInfo와 1:1 관계
}
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn, UpdateDateColumn } from 'typeorm';
import { User } from '@/models/user';
@Entity({ name: 'user_info_orm_v2' })
export class UserInfo {
@PrimaryGeneratedColumn('uuid')
id: string;
// 지연 로딩으로 순환 참조 문제 해결
@OneToOne(() => User, (user) => user.user_info, { lazy: true })
@JoinColumn({ name: 'userId' })
user: Promise<User>; // User와 1:1 관계
..중략..
}
// user.ts
@OneToOne(() => UserInfo, (userInfo) => userInfo.user, { cascade: true, lazy: true })
user_info: Promise<UserInfo>;
// user-info.ts
@OneToOne(() => User, (user) => user.user_info, { lazy: true })
@JoinColumn({ name: 'userId' })
user: Promise<User>;
💡 지연 로딩을 사용할 경우, 해당 필드는 Promise<Entity> 타입으로 정의됩니다.
즉, user.user_info에 바로 접근하는 것이 아니라 await user.user_info처럼 비동기 방식으로 접근해야 합니다.
결론
- TypeORM에서 서로를 참조하는 엔티티끼리 `ReferenceError`가 나면 순환 참조 문제일 가능성이 높습니다.
- 이 경우 지연 로딩(lazy loading)을 사용하면, 참조를 `Promise<Entity>` 형태로 바꾸어 문제를 해결할 수 있습니다.
- 지연 로딩 사용 시 `await` 키워드를 사용해야 실제 데이터에 접근할 수 있습니다.
반응형
'Dev > Nextjs' 카테고리의 다른 글
[React-hook-form] controller-checkbox 반복문을 사용한 방식과 개별 작성 방식의 차이 (0) | 2024.10.10 |
---|---|
[Nextjs]useMemo 를 이용하여 불필요한 리렌더링 문제 해결 (0) | 2024.10.05 |
[Nextjs] Nextjs + nprogress 구현 (0) | 2024.09.30 |
[React] React.FC vs React.ButtonHTMLAttributes - 공통컴포넌트 제작방식 (0) | 2024.09.25 |
[Nextjs] 공통 인터페이스를 이용해서 컴포넌트 생성하기 (0) | 2024.09.25 |