백엔드/API설계 과거 주차 조회에서 '그 당시 최신 스프린트'는 뭐였나: weekEnd 기준 latest sprint 설계 주간 리포트 API가 '이번 주의 latest sprint' 개념으로 태스크를 골라왔는데, 과거 주차를 조회하면 '그 당시'가 아닌 '지금의' latest sprint가 튀어나왔다. carry-over 없이 버려진 태스크까지 리포트에 다시 나타나는 버그였다.
백엔드/Prisma 순차 루프를 10배 빠르게: Promise.all 병렬화 + findMany distinct 배치화로 API 응답 시간 잡기 주간 리포트 API가 과제 수에 비례하여 느려졌다. for 루프의 sprint+task 쿼리를 Promise.all로 병렬화해 10배, findFirst N회를 findMany(distinct) + createMany 2쿼리로 바꿔 50배. 두 최적화를 한 커밋에 담은 기록.
백엔드/Prisma 과거의 진실을 기록하는 법: Append-only ProjectStatusLog로 구현한 historical 주간 리포트 이번 주 주간 리포트를 보는데, 지난 달에 완료된 과제가 목록에서 사라졌다. 현재 상태(status=완료)로 필터하면 과거 주차 리포트가 오염된다 — 이 문제를 append-only 로그로 해결한 방법.
백엔드/Prisma findUnique → create의 함정: Prisma get-or-create 패턴의 P2002 레이스 컨디션과 3줄짜리 해법 '없으면 만들어'는 간단해 보이지만 동시 요청 2개가 들어오면 둘 다 'findUnique가 없다'를 거쳐 둘 다 create를 호출합니다. unique constraint에 걸려 P2002가 터지는 전형적인 get-or-create 레이스. try/catch 3줄로 우아하게 풀었습니다.
백엔드/API설계 Docker는 UTC, 사용자는 KST: Intl.DateTimeFormat만으로 만든 tz-aware ISO Week 유틸리티 주간 리포트의 주차 경계가 서버 컨테이너(UTC)와 사용자(KST) 사이에서 어긋났다. date-fns-tz나 luxon을 도입하는 대신, Node 22의 full-ICU Intl.DateTimeFormat만으로 IANA 타임존 ISO week 유틸리티를 구현한 기록.
백엔드/API설계 API 에러 처리 표준화: withErrorHandler 패턴으로 중앙집중화하기 API 엔드포인트가 늘어나면서 에러 처리 코드가 중복되고 응답 형식도 제각각이었습니다. withErrorHandler 래퍼와 세분화된 에러 클래스로 문제를 해결한 경험을 공유합니다.
백엔드/API설계 TypeScript Branded Types로 타입 안전성 높이기 모든 ID가 string 타입이라 인자 순서를 바꿔도 컴파일 에러가 안 났습니다. Branded Types 패턴으로 런타임 오버헤드 없이 타입 안전성을 확보한 방법을 공유합니다.
백엔드/API설계 Promise.all vs Promise.allSettled: 부분 실패를 허용하는 벌크 처리 100명에 대해 데이터를 생성하는데 1명이 실패하면 전체 99명도 실패로 처리되었습니다. Promise.allSettled로 부분 실패를 허용하는 벌크 처리를 구현한 방법을 공유합니다.
백엔드/API설계 API 에러 추적 개선하기: errorId 패턴으로 디버깅 시간 단축 "서버 오류가 발생했습니다" 메시지만으로는 어떤 에러인지 특정할 수 없었습니다. errorId 패턴으로 디버깅 시간을 90% 단축한 방법을 공유합니다.
백엔드/API설계 JavaScript 타임존 함정 피하기: UTC vs Local 날짜 처리 1월 31일을 선택했는데 1월 30일로 저장되는 버그를 발견했습니다. JavaScript Date 생성자의 타임존 해석 방식을 이해하고, 정오(12:00) 패턴으로 해결한 방법을 공유합니다.
백엔드/API설계 Next.js API에 Rate Limiting 구현하기 (메모리 기반) API 보안을 위해 Rate Limiting이 필요했습니다. Redis 없이 메모리 기반으로 구현하고 HTTP 429 표준을 준수한 방법을 공유합니다.