이태랑
Next.js 15NestJS 11MikroORMPostgreSQLTanStack Query

Smart Reserve

뷰티 살롱/네일 숍 예약 관리 SaaS

Smart Reserve

역할

CTO / Full-Stack Engineer

기간

2025

클라이언트

일본 뷰티 살롱 체인 (Narimoto)

01문제

다중 매장 뷰티 살롱에서 예약, 직원 관리, 재고, 매출 집계가 수기/엑셀로 처리되어 실시간 관리가 불가능. POS/CRM/HR이 통합된 시스템이 필요했음.

02판단

ORM 선택: TypeORM vs MikroORM

선택

MikroORM

이유

Unit of Work 패턴으로 트랜잭션 안정성 확보. 70+ 엔티티 관리에 적합

트레이드오프

TypeORM 대비 커뮤니티 작지만, 데이터 정합성이 더 중요한 도메인

데이터 격리: 애플리케이션 필터링 vs PostgreSQL RLS

선택

PostgreSQL RLS

이유

DB 레벨에서 강제적 테넌트 데이터 격리. 애플리케이션 버그로도 타사 데이터 노출 방지

서버 상태 관리: SWR vs TanStack Query

선택

TanStack Query

이유

stale-while-revalidate 전략으로 대시보드 쿼리 최적화. 복잡한 캐시 무효화 제어

03결과

예약 대기 시간 70% 단축

매장 운영 효율 45% 개선

Next.js 15 App Router 서버 컴포넌트로 초기 로딩 40% 개선

04아키텍처

graph TB subgraph Client["클라이언트"] Web["Next.js 15<br/>App Router"] end subgraph API["API Layer"] NestJS["NestJS 11<br/>REST API"] Auth["JWT Auth<br/>Guard"] end subgraph DB["데이터베이스"] PG["PostgreSQL<br/>+ RLS"] MikroORM["MikroORM<br/>Unit of Work"] end subgraph Infra["인프라"] CloudRun["Google<br/>Cloud Run"] Vercel["Vercel"] end Web -->|TanStack Query| NestJS NestJS --> Auth Auth --> MikroORM MikroORM --> PG Web --> Vercel NestJS --> CloudRun

05기술 스택

frontend

Next.js 15 (App Router), TanStack Query, Radix UI

backend

NestJS 11, MikroORM, TypeScript 5

database

PostgreSQL (RLS)

infra

Google Cloud Run, Vercel