렌더링 구조를 정리한 글에서 "앱이 있거나 팀이 나뉘면 별도 API 서버를 둔다"고 적었다. 그러면 바로 다음 질문이 온다. API 서버는 무엇으로 만들 것인가. 이 글은 새 백엔드를 시작할 때 쓰려고 만들어 둔 템플릿 저장소들을 고르며 정리한 기준이다.

먼저 밝혀 두면, 프레임워크 선택에서 성능 차이는 생각보다 늦게 문제가 된다. 대부분의 API 서버에서 응답 시간을 결정하는 것은 프레임워크가 아니라 쿼리와 인덱스, 커넥션 풀, 캐시다. 그래서 이 글은 성능 순위보다 "어떤 철학의 도구인가"와 "DB를 어떤 방식으로 다루는가"를 중심에 둔다.

프레임워크는 두 갈래로 나뉜다

구조 중심 프레임워크

정해진 구조와 아키텍처를 따라 개발한다. 모듈, 컨트롤러, 서비스, 의존성 주입 같은 규칙이 프레임워크에 들어 있다.

  • NestJS (Node.js)
  • Spring Boot (Java·Kotlin)

팀원이 여러 명이고 오래 유지보수할 서비스라면 이 "강제된 규칙"이 가장 큰 장점이다. 누가 작성해도 파일 위치와 계층이 비슷해서 코드 리뷰와 인수인계가 쉽다. 대신 작은 서비스에서는 보일러플레이트가 부담스럽다.

경량 프레임워크

라우팅과 요청 처리만 제공하고, 필요한 구조는 직접 설계한다.

  • Fastify, Hono, Elysia (Node.js·Bun)
  • Ktor (Kotlin)
  • Gin, Fiber (Go)
  • FastAPI (Python)

자유도가 높고 불필요한 기능이 적어 가볍다. 작은 프로젝트에서 시작해 큰 서비스까지 가는 경우도 많지만, 그만큼 계층 구조와 에러 처리 규칙을 팀이 스스로 정하고 지켜야 한다.

두 갈래의 대응 관계를 표로 보면 이렇다.

성격 Java·Kotlin Node.js·Bun Go Python
구조 중심 Spring Boot NestJS — —
경량 Ktor Fastify, Hono, Elysia Gin, Fiber FastAPI

DB에 접근하는 방식 네 가지

프레임워크보다 더 오래 영향을 주는 선택이 DB 접근 방식이다. 이름은 전부 "ORM"으로 뭉뚱그려 부르지만, 실제로는 철학이 꽤 다르다.

분류 한 줄 설명 대표 라이브러리
ORM DB를 객체처럼 다룬다 Hibernate(JPA), MikroORM, GORM
SQL DSL SQL을 코드처럼 안전하게 작성한다 Drizzle, jOOQ, Exposed DSL, SQLAlchemy Core
Query Client DB를 SDK처럼 호출한다 Prisma
SQL 코드 생성기 SQL에서 타입 안전한 코드를 생성한다 SQLC

ORM: 엔티티 중심

테이블을 엔티티 객체에 매핑하고, 객체를 바꾸면 변경 감지(Dirty Checking)가 UPDATE를 만들어 준다. 연관 관계는 지연 로딩(Lazy Loading)으로 필요할 때 가져온다. 도메인 모델이 복잡하고 객체지향 설계를 중시할 때 강하다.

대신 실제로 어떤 SQL이 몇 번 나가는지 코드만 보고 알기 어렵다. 목록을 돌며 연관 엔티티에 접근하는 순간 N+1 쿼리가 생기는 것이 대표적이다. ORM을 쓴다면 개발 환경에서 실행 SQL 로그를 켜 두는 습관이 필요하다.

SQL DSL: SQL이 그대로 보인다

SQL 구조를 숨기지 않고 코드로 옮긴다. Drizzle로 쓰면 이런 모양이다.

const rows = await db
  .select({ id: users.id, name: users.name, postCount: count(posts.id) })
  .from(users)
  .leftJoin(posts, eq(posts.authorId, users.id))
  .where(eq(users.active, true))
  .groupBy(users.id);

SQL을 아는 사람이라면 실행될 쿼리를 그대로 예측할 수 있고, 컬럼 이름이나 타입이 틀리면 컴파일 단계에서 잡힌다. 복잡한 JOIN과 집계가 많은 서비스에서 특히 편하다.

Query Client: CRUD 생산성 최우선

Prisma는 스키마 파일에서 타입이 붙은 클라이언트를 생성하고, prisma.user.findMany({ include: { posts: true } })처럼 SDK를 호출하듯 쓴다. 자동완성과 마이그레이션 도구가 좋아서 CRUD 위주 서비스의 초기 개발 속도는 가장 빠르다. 복잡한 쿼리는 결국 raw SQL로 내려가야 하는 경우가 생기고, 추상화 계층만큼의 오버헤드가 있다.

SQL 코드 생성기: SQL을 직접 관리

SQLC는 반대 방향이다. .sql 파일에 쿼리를 직접 쓰면 그 쿼리를 실행하는 타입 안전한 Go 함수를 생성한다. 런타임 추상화가 없어서 오버헤드가 사실상 raw SQL과 같고, 쿼리 자체가 리뷰 대상이 된다. SQL을 잘 다루는 팀에게는 가장 투명한 방식이다.

조합별 성격

같은 프레임워크라도 DB 접근 방식에 따라 성격이 달라진다. 아래는 단순 CRUD + DB 쿼리 1회를 기준으로 본 상대적인 경향이다. 실제 처리량은 하드웨어, 쿼리 복잡도, 커넥션 풀 설정에 따라 몇 배씩 달라지므로 절대값으로 읽으면 안 된다.

조합 처리량 경향 개발 경험 한 줄 평가
Go + Fiber/Gin + SQLC 가장 높은 쪽 보통 raw SQL 수준의 낮은 오버헤드, 가장 검증된 조합
Bun + Elysia/Hono + Drizzle 높음 매우 좋음 JS 계열에서 가장 빠른 축. Hono는 런타임 이식성이 강점
Node.js + Fastify + Drizzle 높음 매우 좋음 Express 이후의 사실상 표준
Kotlin + Ktor + Exposed/jOOQ 높음 좋음 코루틴 기반, SQL 중심의 타입 안정성
Node.js + NestJS + Drizzle 중상 매우 좋음 구조와 성능의 균형
Kotlin + Spring Boot + jOOQ 중상 매우 좋음 대규모 서비스에 적합
Node.js + NestJS + Prisma 중간 최고 DX 최우선, ORM 오버헤드 감수
Kotlin/Java + Spring Boot + JPA 중간 매우 좋음 엔터프라이즈 표준, 리플렉션 오버헤드
Python + FastAPI + SQLAlchemy 중간 좋음 AI·데이터 연동에 최적, GIL 영향 존재

표에서 읽어야 할 것은 순위가 아니라 패턴이다. 같은 프레임워크 안에서도 ORM을 SQL DSL로 바꾸는 것만으로 체감 차이가 생긴다. NestJS + Prisma와 NestJS + Drizzle의 차이가 그 예다. 프레임워크를 갈아엎기 전에 DB 접근 계층부터 보는 편이 비용이 적다.

언어별 기본 조합

새 프로젝트에서 특별한 제약이 없을 때 먼저 꺼내는 조합이다.

언어 프레임워크 DB 접근 이유
Node.js Fastify Drizzle 성능, 생산성, 타입 안정성의 균형
Kotlin Ktor jOOQ SQL 중심 + 높은 타입 안정성
Go Fiber SQLC 최고 수준의 성능과 투명한 SQL
Python FastAPI SQLAlchemy AI·LLM 생태계와의 연동

여기에 팀 상황을 얹는다. 팀이 여러 명이고 규칙이 중요하면 Node.js는 NestJS, JVM은 Spring Boot로 올라간다. 이미 조직에 Spring 운영 경험이 쌓여 있다면 그 경험이 어떤 벤치마크보다 크다.

템플릿으로 미리 만들어 두기

결정을 반복하지 않으려고, 자주 쓰는 조합은 인증·에러 형식·로그·Swagger까지 붙인 템플릿 저장소로 만들어 두었다.

  • nestjs-prisma: 구조화된 Node 백엔드, DX 최우선
  • nestjs-drizzle: 같은 구조에서 DB 계층만 성능 개선판
  • springboot-jpa-querydsl: 엔터프라이즈·대규모 조직 표준
  • bun-elysia-drizzle: Bun 단일 환경, 경량·실험적 서비스

이 템플릿들이 공통으로 갖추는 항목(인증, 에러 형식, 로그, 스케줄러 등)은 다음에 체크리스트로 따로 정리할 예정이다.

이 조합들이 다루지 못하는 영역도 있다. 클라우드 네이티브 도구나 CLI, 극단적인 저지연이 필요한 시스템 레벨 작업, 그리고 WebSocket·gRPC 위주의 실시간 스트리밍 서비스는 별도 스택을 검토하는 것이 맞다.

정리

  • 프레임워크는 **구조 중심(NestJS, Spring)**과 경량(Fastify, Ktor, Gin, FastAPI) 중 팀 규모와 유지보수 기간으로 고른다.
  • DB 접근은 ORM, SQL DSL, Query Client, SQL 코드 생성기 네 갈래이고, 성능과 디버깅 경험에 프레임워크보다 큰 영향을 준다.
  • 성능 표는 방향성으로만 읽고, 실제 병목은 쿼리와 인덱스에서 먼저 찾는다.

참고 자료