개요
우선 나는 NestJS + TypeORM으로 약 2년 넘게 개발해왔으며, 최근엔 회사를 다니며 drizzle을 사용중이다.
이 글을 작성하게 된 계기는 Service와 Domain 계층간 관계에 대해 어떻게 정의하고 개발할 수 있을까를 고민하다가, 문득 drizzle에 대해 든 생각을 정리하기 위해 작성했다.
1. 우선 우리는 왜 orm을 쓸까?
ORM의 풀 네임은 다음과 같다.
Object-Relational Mapping
프로그래밍 언어와 데이터베이스 테이블을 자동으로 매핑해주는 기술.
정의만 봐도 목적을 어느정도 알 수 있다.
- 사람이 쓰기 힘든 sql을 메서드 호출을 통해 데이터를 쉽게 다룬다.
orm이 sql로 자동으로 변환해주기 때문. - 그러면 코드 가독성이 올라간다.
- 그리고 스키마 변경이 발생해도 코드 변경이 적다.
- 마이그레이션 기능을 제공한다. 그것이 스키마 변경 로그가 되기도 한다.
2. orm은 이미 차고도 넘치는데 왜 drizzle이 나온걸까?
https://orm.drizzle.team/docs/overview
➡️ drizzle orm 문서를 들어가면 나오는 첫 페이지
아래는 그 페이지에 적힌 내용중 일부이다.
Drizzle ORM is a headless TypeScript ORM with a head. 🐲
headless한 orm이라고 한다.
typeorm처럼 dataSource를 정의하거나, 데코레이터를 사용하여 객체 중심적인 코딩을 하는 대신, drizzle은 스키마를 함수로 정의하고 상속, 데코레이터도 없다. 그냥 어디서든 import해서 쓰는 도구다.
It’s the only ORM with both relational and SQL-like query APIs, providing you the best of both worlds when it comes to accessing your relational data. Drizzle is lightweight, performant, typesafe, non-lactose, gluten-free, sober, flexible and serverless-ready by design.
사실 대부분의 ORM은 SQL을 추상화해서 감춰버리는데, Drizzle은 오히려 SQL이 드러나게 하는 것을 지향하는 것 같다. 내가 짠 코드가 실제로 어떤 쿼리를 날리는지 예측 가능해야 한다는 철학이다.
예전에 typeorm의 getOne 함수 동작을 모르고 Lock을 걸었다가 전체 스캔이 된 줄 모르고, 디버깅하는데 애먹은 경험이 있다.
3. 그렇다면 typeorm과 prisma는 별로일까?
결론은 orm을 사용하는 사람의 취향차이, 즉 어떤 개발 철학에 공감하느냐에 따라 갈릴 것 같다는 개인적인 생각이다.
typeorm은?
데코레이터 기반이고 굉장히 객체지향적인 orm이다. oop에 익숙하다면 진입장벽이 낮을 것이다. 또한 typeorm 1.0.0이 정식 출시한지 이제 3개월이 지났다. 2016년부터 시작되고 계속된 검증 끝에 안정적인 버전으로 출시하게 된 것이다. 그만큼 신뢰성이 두껍고 많이 애용한다는 의미일 것이다.
하지만, getOne 사고와 같은 sql 추상화에 의해 메서드의 동작을 에상할 수 없다는 것이 한계가 아닐까 라는 생각이다.
prisma는?
스키마 파일 하나가 SSOT(Single Source of Truth) 이다. 스키마와 코드가 어긋나는 사고도 구조적으로 잘 일어나지 않고, 마이그레이션도 diff를 계산해서 drop, delete 등(위험한 변경) 사전에 경고해준다. 문서화, VSCode 확장, Prisma Studio 등 DX를 극대화하여 팀 온보딩 속도에도 빠르다.
sql을 몰라도 완벽한 DX와 타입 안정성으로 비즈니스 로직에만 집중할 수 있다. 즉 typeorm 보다 더 가려져있다.
4. 그래서?
사실 본인은 가려진 것을 더 싫어하는 편이다.
복잡한 sql 문법을 몰라도 코드를 짤 수 있다는 강력한 기능들이 있지만, 적어도 코드를 한 줄 쓰는데 그것이 정확히 어떻게 실행되고 영향을 미치는가를 설명할 줄 알아야 한다는 것이 개발자의 기본 소양이라고 생각한다.
그렇다고 drizzle이 무조건 좋아! 라고 찬양하지는 않는다.
- 기획이 자주 바뀌는 초기 개발에는 prisma가 더 유용할 수도 있다.
- 아니면 nestjs의 호환성이나 oop를 엄격히 따를 때 typeorm을 사용할 수도 있다.
- 성능 최적화가 필요하거나 sql을 깊게 이해하여 원하는 쿼리를 쓰고 싶다면 drizzle을 선택할 수도 있다.
실제로 성능 퍼포먼스는 drizzle이 더 우세하다고 한다.
(이것저것 무거운 도구가 없으니 당연할만도 하다)
아래는 어떤 개발자가 세 도구를 비교하며 작성한 글이다. 참고해보면 좋을 듯 하다. https://navanathjadhav.medium.com/prisma-vs-drizzle-vs-typeorm-the-modern-orm-battle-618694d6361c
5. 개요에 적은 Service와 Domain은 무슨 상관인데?
typeorm은 사실 repository 패턴을 강제한다. getRepository를 거치에 만듦으로써 데이터 접근은 repository에서 도메인/비즈니스 로직은 다른 계층에서 구현하라는 경계는 orm이 어느정도 그어준다. (prisma도 마찬가지)
drizzle은 이런 걸 아무것도 강제하지 않는다. pgTagle로 정의한 스키마는 그냥 평범한 ts 객체라서 서비스 코드 어디에서든 바로 import한다.
- 쿼리를 어디에 두어 실행되게 할 것인가?
- 서비스 계층이 스키마를 직접 알아도 되는건가?
- 도메인 로직과 데이터 접근을 어떻게 분리할까?
이런 질문에 아무도 답을 안해준다는 것이다.
즉, 온전히 직접 설계해야 하는 과제는 이 orm을 사용하는 개발자에게 남겨진 것이다.