낙서장이자 오답 노트이자 컨닝 페이퍼
패스트캠퍼스 환급챌린지 14일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기 본문
패스트캠퍼스 환급챌린지 14일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기
NangIn 2025. 4. 14. 21:22본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.
강의 내용 정리
Entity Embedding & Entity Inheritance 실습
실습 목표
- Movie 엔티티에 공통 메타데이터 필드 도입
- 필드: createdAt, updatedAt, version
- 방식 2가지 비교:
- Entity Embedding
- Entity Inheritance
Entity Embedding 방식
- BaseEntity 클래스 생성
-
class BaseEntity { @CreateDateColumn() createdAt: Date; @UpdateDateColumn() updatedAt: Date; @VersionColumn() version: number; }
-
- Movie 엔티티에 임베딩 적용
-
@Entity() class Movie { @PrimaryGeneratedColumn() id: number; @Column() title: string; @Column() genre: string; @Column(() => BaseEntity) base: BaseEntity; }
-
- 결과 (DB 및 응답)
- DB에는 칼럼: baseCreatedAt, baseUpdatedAt, baseVersion 형태로 생성됨
- JSON 응답에서는 네스팅되어 응답
-
{ "id": 1, "title": "Inception", "genre": "Sci-Fi", { "base": { "createdAt", "updatedAt", "version" } } } - 장점: 구조적으로 명확함
- 단점: 응답 시 불필요한 중첩 구조
Entity Inheritance 방식
- BaseEntity 클래스 생성
-
class BaseEntity { @CreateDateColumn() createdAt: Date; @UpdateDateColumn() updatedAt: Date; @VersionColumn() version: number; }
-
- Movie 클래스에서 상속 적용
-
@Entity() class Movie extends BaseEntity { @PrimaryGeneratedColumn() id: number; @Column() title: string; @Column() genre: string; }
-
- 결과 (DB 및 응답)
- DB에는 칼럼: createdAt, updatedAt, version 으로 깔끔하게 생성
- JSON 응답도 중첩 없이 1단계로 바로 출력
-
{ "id": 1, "title": "Inception", "genre": "Sci-Fi", "createdAt": "...", "updatedAt": "...", "version": 1 } - 장점: 깔끔한 응답 구조, 직관적인 설계
- 단점: OOP에 익숙하지 않으면 상속 구조가 다소 생소할 수 있음
결론 요약
| 항목 | Entity Embedding | Entity Inheritance |
| 응답 구조 | 중첩됨 (base.createdAt) | 평평하게 노출 (createdAt) |
| DB 칼럼 | 접두어 붙음 (baseCreatedAt) | 필드명 그대로 생성 |
| 코드 구조 | 컴포지션 구조 | 상속 구조 |
| 주 용도 | 필드 그룹화 | 공통 프로퍼티 재사용 |
| 선호도 | 단순 재사용 시 적합 | 실무에서 더 많이 사용 |
팁
- 기존 DB에 데이터가 있는 상태에서 칼럼 변경 시 에러 발생 가능 → 이럴 땐 테이블 드랍 후 재생성 필요
- 실무에서는 BaseEntity를 common 디렉토리로 분리해 재사용
- 상속 방식이 실제 사용성과 유지보수 측면에서 더 유리함
Single Table Inheritance 실습
Single Table Inheritance 설계 개념
- 목적: Movie와 Series를 하나의 테이블(Content)로 관리하기 위한 구조 구성
- 전제:
- Movie → runtime 필드 보유 (예: 상영 시간)
- Series → seriesCount 필드 보유 (예: 총 몇 부작인지)
- 둘 다 Content라는 상위 개념으로 묶기
- 실무에선 STI는 잘 사용하지 않지만 교육 목적상 실습 진행
STI 구현 과정
- 공통 상위 클래스 정의
-
@Entity() @TableInheritance({ column: { type: 'varchar', name: 'type' } }) export class Content extends BaseEntity { @PrimaryGeneratedColumn() id: number; @Column() title: string; @Column() genre: string; }- @Entity()는 부모(Content)에만 붙임
- @TableInheritance()로 상속 전략 정의
- 공통 필드: id, title, genre (BaseEntity에서 메타필드 상속)
-
- 하위 자식 클래스 정의
-
@ChildEntity() export class Movie extends Content { @Column({ nullable: true }) runtime: number; } @ChildEntity() export class Series extends Content { @Column({ nullable: true }) seriesCount: number; }- @ChildEntity()를 붙여 상속 선언
- 자식 고유 컬럼은 반드시 nullable: true 설정
-
- 모듈에 등록
-
TypeOrmModule.forFeature([Content, Movie, Series])- AppModule 또는 해당 모듈에 3개 엔티티 모두 등록
-
테이블 생성 결과
- 테이블 이름: content
- 포함된 컬럼:
- 공통 필드: id, title, genre, type (STI 구분용)
- Movie 전용: runtime
- Series 전용: seriesCount
- 실제 데이터:
- Movie → type = 'Movie', runtime = 100, seriesCount = null
- Series → type = 'Series', seriesCount = 16, runtime = null
요약
- STI는 복잡한 상속 구조를 하나의 테이블로 관리 가능하나, 유연성 부족 및 nullable 필드 증가 단점 존재
- 실무에선 보통 Entity Inheritance(테이블 분리) 방식 선호
- 강의에서는 교육 목적상 STI 구조를 직접 구현 → 테스트 → 제거하는 흐름으로 마무리됨
학습 후기
이번 실습에서는 Entity Embedding, Entity Inheritance, Single Table Inheritance라는 세 가지 설계 방식을 직접 구현해보며 각각의 특징과 장단점을 비교해볼 수 있었습니다.
먼저 Entity Embedding 방식은 공통 필드를 컴포지션 방식으로 묶어 재사용할 수 있다는 장점이 있었지만, 실제 응답 데이터 구조가 중첩되고 DB 칼럼에도 접두어가 붙어 실무에서는 다소 번거롭게 느껴졌습니다. 특히 프론트엔드와 데이터 구조를 협의할 때 불필요한 깊이로 인해 직관성이 떨어질 수 있다는 점이 단점으로 다가왔습니다.
반면 Entity Inheritance 방식은 OOP스럽게 공통 필드를 상속받아 사용할 수 있고, 응답에서도 별도 중첩 없이 평탄화된 구조로 제공되어 유지보수와 협업 측면에서 훨씬 더 효율적이라고 느껴졌습니다. 중복 없이 코드 재사용도 가능하고, 구조적으로도 깔끔하게 관리된다는 점에서 실무에 적합한 방식임을 체감할 수 있었습니다.
STI 방식은 하나의 테이블에 상속받은 자식 엔티티들을 모두 넣어 관리할 수 있다는 점은 흥미로웠지만, 자식 엔티티마다 nullable 필드가 생기고 테이블이 불필요하게 비대해지는 구조라 유연성이 떨어졌습니다. 강의에서도 언급했듯 실제로는 잘 사용되지 않으며, 학습 목적으로 개념만 이해하고 넘어가는 것이 좋다고 판단됩니다.
이번 과정을 통해 ORM을 설계할 때 단순히 코드 작성이 아닌, 실제로 어떤 방식이 데이터 구조와 서비스 아키텍처에 적절한지 고민해야 한다는 점을 배울 수 있었습니다. 특히 관계형 설계에서의 중복 제거, 응답 구조의 일관성, 유지보수성까지 모두 고려해야 하는 점에서 큰 인사이트를 얻었습니다.
학습 인증샷



