02 — History and Ecosystem
이 문서가 답하는 질문: TypeORM은 언제 누가 만들었고, 왜 NestJS 진영의 사실상 표준이 됐으며, 왜 0.3.x로 올리는 순간 코드가 깨졌는가? 한 줄 답 (Pyramid Top): “TypeORM은 2016년 Umed Khudoiberdiev가 시작했고, 같은 해 등장한 NestJS가 기본 ORM으로 채택하며 사실상 표준이 됐다 — 그러나 2022년 0.3.x 전환은 API의 절반을 바꾸는 조용한 분기점이었다.”
한 문장 답 (Pyramid Top)
TypeORM의 역사는 세 시기로 나뉜다 — ① 2016~2018 출발기: Hibernate를 TS로 가져오자는 한 개발자의 실험, ② 2018~2022 황금기: NestJS와 결혼하며 사실상 표준이 됨, ③ 2022~ 분기기: 0.3.x 전환의 충격, Prisma·Drizzle의 위협, TC39 데코레이터 spec 정체. 각 시기에서 결정된 것들이 지금 TypeORM의 모든 매력과 한계를 만든다.
챕터 지도 (Mermaid)
Why — 왜 역사를 알아야 하나
TypeORM 인터넷 자료의 절반은 deprecated된 0.2.x 시절 문법이다. 검색 상위에 뜨는 블로그를 그대로 따라 하면 findOne(id)부터 깨진다. 또한 왜 이 ORM이 이렇게 생겼는가에 대한 거의 모든 답은 “2016년에 데코레이터 spec이 어디까지 와 있었나”와 “NestJS와 어떻게 결혼했나”라는 두 사실에 묶여 있다.
| 잘못된 직관 | 실제 |
|---|---|
| ”TypeORM은 안정적이다” | 0.2.x → 0.3.x에서 DataSource 도입·findOne 시그니처 변경·EntityManager API 일부 deprecated — 마이그레이션 비용 큼 |
| ”NestJS가 만든 ORM이다” | 별개 프로젝트. NestJS가 *adapter(@nestjs/typeorm)*로 감싸 쓸 뿐 |
| ”TypeORM 팀이 크다” | 핵심 maintainer는 수 명 수준, GitHub 이슈 트래커는 수천 개의 open issue를 들고 있음 |
이 셋을 분리하면 “왜 우리 코드의 findOne(1)이 안 되지?”(0.2.x 문법), “왜 NestJS 가이드와 TypeORM 공식 문서가 달라 보이지?”(adapter 레이어가 있다), “왜 issue가 풀리지 않지?”(maintainer 인원의 현실) 같은 질문이 동시에 풀린다.
How — 어떻게 흘러왔나
1) 2016 — 한 개발자의 실험
Umed Khudoiberdiev가 처음 만든 것은 TypeORM이 아니라 typeorm-core라는 작은 실험이었다. 그는 이전에 typeodm(MongoDB용)을 만들고 있었고, 같은 아이디어를 관계형 DB로 확장한 것이 시작이었다.
| 사건 | 날짜 |
|---|---|
| 첫 GitHub 커밋 | 2016년 초 |
npm typeorm 첫 출시 | 2016년 봄 |
| 0.0.x 시리즈 (실험) | 2016 ~ 2017 |
| 0.1.x (첫 안정) | 2017 후반 |
같은 해 TypeScript는 2.0~2.1을 지나며 디스크리미네이티드 유니온·null 안정성을 도입하고 있었고, Angular 2는 데코레이터 기반 컴포넌트 시스템으로 정착하던 시기였다.
2) 2017 — NestJS와의 결혼
NestJS 1.0이 2017년 출시되면서 기본 ORM 추천으로 TypeORM을 채택한다. NestJS 자체가 Angular 스타일 데코레이터 백엔드였기 때문에 데코레이터 ORM과 사상이 완벽히 일치했다. @nestjs/typeorm 패키지는 NestJS의 DI 시스템 위에 Repository를 inject할 수 있게 감싼 얇은 adapter다.
// NestJS에서의 TypeORM 사용 (시그니처는 0.3.x 기준)
@Module({
imports: [TypeOrmModule.forRoot({ /* DataSource 옵션 */ }),
TypeOrmModule.forFeature([User])],
})
export class AppModule {}
@Injectable()
export class UserService {
constructor(
@InjectRepository(User) private readonly userRepo: Repository<User>
) {}
}이 결합은 양쪽 모두에 결정적이었다 — NestJS는 공식 ORM 후보가 생겼고, TypeORM은 기본 채택자를 얻었다.
3) 2018~2021 — 황금기
이 시기 TypeORM은 GitHub 스타 30,000+ 를 넘기며 TypeScript 진영의 사실상 표준이 된다. 같은 시기 경쟁자들의 위치:
| ORM | 2020년 위치 |
|---|---|
| Sequelize | JavaScript 시대의 강자, TS 지원 약함 |
| Prisma | 2019년 Prisma 2 preview, 아직 production 적게 쓰임 |
| MikroORM | 2018년 출범, 사용자 수 적음 |
| Drizzle | 존재하지 않음 |
| Kysely | 존재하지 않음 |
→ 이 시기엔 데코레이터 ORM = TypeORM이 거의 자명한 등식이었다.
4) 2022 — 0.3.0의 조용한 분기점
2022년 3월, TypeORM 0.3.0이 출시된다. breaking change의 폭이 컸다.
| 변경 | 0.2.x | 0.3.x |
|---|---|---|
| 연결 진입점 | createConnection() / getConnection() | new DataSource(...) + dataSource.initialize() |
| findOne 시그니처 | repo.findOne(1) 가능 | repo.findOne({ where: { id: 1 } }) 필수 |
| findOneOrFail | 결과 또는 throw | 같음, 하지만 시그니처도 강제됨 |
select 옵션 | 배열 또는 객체 혼용 | 객체로 통일 |
| 마이그레이션 CLI | typeorm migration:run | typeorm migration:run -d ./datasource.ts 필수 |
@Transaction 데코레이터 | 사용 가능 | deprecated, 명시적 트랜잭션 권장 |
EntityManager.find 옵션 | 일부 alias 허용 | 엄격해짐 |
문서는 일부만 업데이트됐고, Stack Overflow와 블로그 자료의 절반은 0.2.x 시절이었다. 결과 — 2022~2023년 마이그레이션 작업이 NestJS 팀들 사이에서 흔한 고통이 됐다.
5) 2022~ 현재 — 추격당하는 위치
같은 시기에 세 가지 위협이 동시에 왔다.
| 위협 | 무엇이 다른가 |
|---|---|
| Prisma | 스키마 우선 + 코드젠 → 데코레이터 우회. 마이그레이션 워크플로 더 매끄러움 |
| Drizzle (2022~) | SQL DSL + 컴파일 타임 타입 → 데코레이터·메타데이터 없이 강한 타입 |
| MikroORM 5.x | Unit of Work + Identity Map → TypeORM에 없는 추상 보유 |
| Kysely | SQL DSL 전용, ORM 아님 — raw SQL의 타입 안정성만 |
TypeORM은 여전히 NestJS 가이드에 첫 번째로 등장하지만, 새 프로젝트에서 Prisma·Drizzle을 채택하는 비율이 지속적으로 늘고 있다 (State of JS 2023 등 설문).
6) TC39 데코레이터 spec 정체
데코레이터 제안서는 Stage 0 → 1 → 2 → 3을 9년에 걸쳐 떠돌았다. 2023년 TC39가 새로운 데코레이터 제안서(2022 Stage 3)을 발표했지만 — TypeORM이 의존하는 emitDecoratorMetadata 동작은 새 spec에서 정의되지 않는다.
즉 TC39가 데코레이터를 표준화하면, 오히려 TypeORM이 그 위에서 동작하지 않는다는 역설.
What — 구체 사양·연표
주요 버전 연표
| 버전 | 출시 | 핵심 변경 |
|---|---|---|
| 0.0.x | 2016 | 실험 |
| 0.1.x | 2017 | 첫 안정, ActiveRecord/DataMapper 양립 |
| 0.2.0 | 2018.01 | 안정 API, 마이그레이션 CLI 도입 |
| 0.2.x (~2021) | 2018~2021 | 사실상 표준 시기 |
| 0.3.0 | 2022.03 | DataSource 도입, findOne 시그니처 강제 |
| 0.3.x | 2022~ | 점진 개선, Spanner·Better-SQLite3 등 추가 |
0.2.x → 0.3.x 마이그레이션 핵심 diff
// 0.2.x
import { createConnection, getRepository } from "typeorm";
const conn = await createConnection({ /* ... */ });
const userRepo = getRepository(User);
const user = await userRepo.findOne(1);
// 0.3.x
import { DataSource } from "typeorm";
const AppDataSource = new DataSource({ /* ... */ });
await AppDataSource.initialize();
const userRepo = AppDataSource.getRepository(User);
const user = await userRepo.findOne({ where: { id: 1 } });세 줄 같지만 프로젝트 전반의 모든 파일이 영향을 받는다.
생태계 위치
| 도구 | TypeORM과의 관계 |
|---|---|
@nestjs/typeorm | NestJS adapter — DI 통합 |
typeorm-extension | 시드 데이터 + CLI 확장 |
typeorm-naming-strategies | snake_case ↔ camelCase 명명 규칙 |
class-validator | 같은 maintainer, 같은 데코레이터 철학 |
class-transformer | 같은 maintainer, 객체 변환 |
routing-controllers | 같은 maintainer, 데코레이터 라우팅 |
class-validator·class-transformer·routing-controllers는 모두 Umed가 만든 라이브러리들로, 데코레이터 메타 철학을 공유한다.
What-if — 잘못 알면
1) 0.2.x 자료를 그대로 따라 하면
→ repo.findOne(1)이 “Object literal may only specify known properties” 또는 런타임 에러로 깨진다.
대응: 모든 자료 확인 시 공식 docs (typeorm.io) 의 버전 표기를 본다. 검색 상위가 0.2.x인 경우가 흔하다.
2) NestJS와 TypeORM 문서를 같은 것으로 보면
→ NestJS는 forFeature([])로 Repository를 등록하는 adapter 패턴을 쓴다. TypeORM 직접 사용 방식과 다르다.
대응: NestJS 프로젝트면 NestJS 문서를 우선, 그 다음 TypeORM 문서로 깊이 들어간다.
3) “TypeORM은 활발히 개발된다”고 믿으면
→ 핵심 maintainer가 제한적이라 PR이 수개월 안 머지되는 경우가 흔하다. 대응: 의존성을 불멸의 것으로 보지 말 것. Prisma·Drizzle로의 탈출 경로를 항상 열어둔다.
4) TC39 데코레이터가 표준화되면 자동으로 좋아질 거라 생각하면
→ 오히려 지금 동작이 안 될 수 있다. 새 spec은 메타데이터를 다르게 다룬다.
대응: TypeORM의 메이저 다음 버전이 어떻게 새 spec을 흡수할지 공식 RFC를 추적. 그동안 experimentalDecorators를 유지.
Insight — 흥미로운 이야기
”Umed의 데코레이터 패밀리”
Umed Khudoiberdiev가 만든 라이브러리 목록을 보면 하나의 일관된 비전이 드러난다 — typeorm(ORM), class-validator(검증), class-transformer(변환), routing-controllers(라우팅), typedi(DI). 모두 데코레이터로 메타를 박고 그 메타로 동작하는 라이브러리들이다. 2016~2018년 사이 그는 TypeScript에서 데코레이터 기반 메타프로그래밍의 가능성을 거의 혼자 증명했고, 같은 시기 NestJS의 Kamil Myśliwiec이 그 도구들을 모아 백엔드 프레임워크를 만들었다. 두 사람의 작업이 합쳐져 NestJS + TypeORM 스택이 된 셈이다.
”왜 0.3.x로 못 올리는 팀이 많은가”
0.3.x 출시 후 2년이 지난 2024년에도 여전히 0.2.x를 쓰는 팀이 흔하다. 이유는 findOne(id) 같은 호출이 프로젝트 전체에 흩어져 있어서 한 번에 옮기기 어렵기 때문. 대안으로 Prisma·Drizzle로 점진적 이주를 택하는 팀이 많아졌다 — 어차피 코드를 다 고쳐야 한다면, 다른 ORM으로 가는 게 낫다는 판단.
”GitHub 이슈 트래커의 무게”
TypeORM 레포의 open issue 수는 2,000개를 넘긴 적이 있다 (시점에 따라 변동). Maintainer 인원의 한계와 오래된 결정들의 누적이 그 숫자의 정체다. Prisma는 이 학습을 흡수해 issue triage를 회사 차원에서 운영한다 — 오픈소스 ORM의 지속가능성은 코드보다 조직 구조의 문제임이 드러난 사례.
요약 + 다이어그램
TypeORM은 2016년 한 개발자의 실험에서 시작해, 2017년 NestJS와 결혼하며 사실상 표준이 됐다. 2022년 0.3.x 전환이 조용한 분기점이었고, 같은 시기 Prisma·Drizzle·MikroORM이 다른 트레이드오프로 추격해 왔다. TypeORM의 운명은 TC39 데코레이터 spec의 운명과 묶여 있다.
다음 문서:
03-typeorm-vs-other-orms.mdx— Prisma·Drizzle·MikroORM·Sequelize·Kysely는 같은 자리에 있나, 다른 자리에 있나?