00-foundations
이 챕터가 답하는 질문: TypeORM은 도대체 무엇이고, 다른 ORM(Prisma·Drizzle·Sequelize…)과 어떻게 다르며, 왜 데코레이터에 모든 것을 걸었는가? 한 줄 답 (Pyramid Top): “TypeORM은 데코레이터로 클래스에 메타데이터를 박아 컴파일 타임 타입과 런타임 메타를 동시에 얻는 DataMapper ORM이다 — 그 한 줄 트릭이 매력과 한계의 출발점이다.”
한 문장 답 (Pyramid Top)
‘TypeORM’이라는 단어는 세 개의 다른 것을 동시에 가리킨다 — ① 데코레이터로 메타데이터를 박는 패러다임, ② 그 메타를 SQL로 번역하는 런타임, ③ Repository와 DataMapper 패턴이 박힌 API 표면. 이 챕터는 셋을 분리해서 이름을 붙이고, 다른 ORM과 어디가 다른지, 왜 2016년에 태어났는지를 한 층씩 벗긴다.
챕터 지도 (Mermaid)
Why — 왜 이 챕터부터 시작하나
“TypeORM은 TypeScript용 ORM이다”라는 한 줄 정의가 거의 모든 오해의 출발점이다. 이 정의는 세 가지를 동시에 흐린다 — TypeScript 전용이 아니라 데코레이터 + reflect-metadata에 묶여 있고, ORM이라는 한 카테고리 안에서도 ActiveRecord와 DataMapper가 갈리며, Prisma·Drizzle 같은 후발주자가 같은 자리에 있는 것이 아니라 다른 트레이드오프를 산다.
상위 챕터에서 만나게 될 거의 모든 헷갈림이 여기서 출발한다.
- “왜
@Entity한 줄로 테이블이 만들어지지?” →01-what-is-typeorm.mdx - “왜 TypeORM 0.3.x로 올리면서 코드가 다 깨졌나?” →
02-history-and-ecosystem.mdx - “Prisma로 갈아탈까 말까?” →
03-typeorm-vs-other-orms.mdx - “데코레이터 한 줄로 뭐가 어떻게 박히는 거지?” →
04-decorator-and-metadata.mdx - “결국 TypeORM을 어떻게 머릿속에 그려야 하나?” →
05-mental-model.mdx
이 챕터는 ‘TypeORM’이라는 단어 안에 숨어 있는 5개의 분리된 개념에 각각 이름을 붙인다. 이름을 붙이고 나면, 위 질문들이 자동으로 풀린다.
How — 어떻게 읽나
다음 5개 문서를 순서대로 읽으면 한 시간 정도 걸린다. 각 문서는 독립적으로도 읽히지만, 순서가 누적적이다.
| # | 파일 | 읽는 데 | 핵심 키워드 |
|---|---|---|---|
| 01 | 01-what-is-typeorm.mdx | 12분 | decorator, reflect-metadata, DataMapper, ActiveRecord, EntityManager |
| 02 | 02-history-and-ecosystem.mdx | 12분 | 2016, NestJS, 0.2.x → 0.3.x, TC39 Stage, lerna monorepo |
| 03 | 03-typeorm-vs-other-orms.mdx | 14분 | Prisma, Drizzle, MikroORM, Sequelize, Kysely, 데코레이터 vs 스키마 vs SQL |
| 04 | 04-decorator-and-metadata.mdx | 14분 | experimentalDecorators, emitDecoratorMetadata, reflect-metadata, design:type |
| 05 | 05-mental-model.mdx | 10분 | 컴파일 타임 vs 런타임 이중 신원, MetadataArgsStorage, single source of truth |
의존성: 02는 01을, 03은 0102를, 04는 01을, 05는 14 모두를 통합한다.
What — 한 페이지 요약 (모든 문서의 핵심 한 줄)
| 문서 | 한 줄 결론 |
|---|---|
| 01 | TypeORM은 데코레이터 + reflect-metadata에 기댄 DataMapper ORM이고, ActiveRecord 모드는 권장하지 않는 호환 옵션에 가깝다. |
| 02 | TypeORM은 2016년 Umed Khudoiberdiev가 시작했고, NestJS가 기본 ORM으로 채택하며 사실상 표준이 됐다 — 그러나 0.3.x 전환이 조용한 분기점이었다. |
| 03 | Prisma는 스키마 우선, Drizzle은 SQL 우선, MikroORM은 Unit of Work 우선, TypeORM은 클래스 우선. 같은 자리에 있는 게 아니라 다른 트레이드오프를 산다. |
| 04 | @Column은 마법이 아니다 — Reflect.metadata로 클래스 prototype에 메타 객체를 박는 평범한 함수이고, TS가 emitDecoratorMetadata로 타입까지 넣어준다. |
| 05 | TypeORM의 핵심 멘탈모델은 “클래스 = 테이블 = 메타데이터 묶음” — 한 클래스가 컴파일 타임 타입과 런타임 메타라는 이중 신원을 동시에 가진다. |
What-if — 이 챕터를 건너뛰면
- 데코레이터를 마법으로 보면:
experimentalDecorators를 끄거나 SWC/esbuild로 옮길 때 모든 엔티티가 조용히 망가지는데 원인을 모른다. - DataMapper와 ActiveRecord를 같은 것으로 보면:
BaseEntity를 상속해user.save()로 짜다가 도메인 객체가 영속성을 알아버리는 누수가 생긴다. - 다른 ORM과 비교 없이 TypeORM부터 배우면: 모든 한계가 데코레이터 패러다임의 본질적 비용임을 모르고 *“TypeORM 버그”*라고 부르게 된다.
- 0.2.x와 0.3.x를 구분 못 하면: 인터넷 글의 절반은 deprecated된 사용법이라 그대로 따라 하면
findOne(id)부터 깨진다.
Insight — 한 단락 이야기
“TypeORM은 데코레이터 spec이 살아 있을 때 태어난 ORM이다”
2016년, TypeScript는 막 1.8을 지나 2.0으로 가는 길목이었고, TC39 데코레이터 제안서는 Stage 1이었다. Angular 2가 데코레이터로 메타프로그래밍을 정착시키고 있었고, Umed Khudoiberdiev라는 한 개발자가 Hibernate를 TypeScript로 가져오자는 발상을 깃허브에 올렸다. 같은 해 NestJS가 Angular 스타일 백엔드 프레임워크로 등장하며 TypeORM을 기본 ORM으로 채택한다. 두 프로젝트는 같은 한 줄에 운명을 걸었다 — “TypeScript는 데코레이터로 의존성을 표현한다.” 9년이 지난 지금, 데코레이터 제안서는 여전히 Stage 3 어딘가를 떠돌고 있고 — TypeORM의 매력과 한계 모두 그 한 줄에 묶여 있다. 이 챕터가 하는 일은 그 한 줄을 다섯 층으로 분해해 이름을 붙이는 것.
한 단락 요약
TypeORM은 데코레이터 + reflect-metadata(
01) 위에 역사와 NestJS 결혼(02), 다른 ORM과의 위치 차이(03), 메타데이터가 박히는 메커니즘(04), 클래스 = 테이블 멘탈모델(05)이 차례로 쌓인 구조다. 이 챕터를 끝내면 “TypeORM이 뭐냐”라는 질문 대신 *“내 팀의 코드가 데코레이터 패러다임의 비용을 감당할 만한가, 아니면 스키마/SQL 우선 도구가 더 맞는가”*라는 질문을 던지게 된다. 다음 챕터(01-entity-decorators)는 이 패러다임으로 클래스 한 개를 실제로 테이블로 만드는 일을 다룬다.