-
🥗 [NestJS/Prisma] 식단 관리 서비스의 꽃, 주간 리포트 API 구현 및 트러블슈팅프로젝트/개인프로젝트 2026. 3. 5. 11:52
1. 개요: 왜 주간 리포트인가?
사용자가 매일 식단을 기록하는 이유는 결국 '내가 잘하고 있는가?'를 확인하기 위함입니다. 단순히 리스트를 보여주는 CRUD를 넘어, 지난 7일간의 데이터를 집계하여 성취도를 시각화해 주는 리포트 API를 구현했습니다.
2. 주요 구현 포인트: "데이터가 없는 날은 어떻게 하죠?"
✅ 시계열 데이터의 완전성 보장 (Zero-filling)
가장 큰 고민은 식단을 기록하지 않은 날이었습니다. DB 쿼리 결과만 그대로 반환하면 차트에서 해당 날짜가 통째로 빠져버려 흐름이 끊기게 됩니다.
- 해결: 서버에서 최근 7일치 빈 객체를 포함한 Map을 미리 생성(dailyMap)하여 0으로 채워두고, DB에서 가져온 데이터를 덮어쓰는 방식을 채택했습니다.
- 결과: 프론트엔드 차트 구현이 훨씬 단순해지고, 사용자에게도 '기록 누락'을 명확히 인지시킬 수 있게 되었습니다.
✅ 비즈니스 로직: "성공"의 정의
단순히 목표 칼로리를 안 넘으면 성공일까요?
- 결정: 건강한 식습관을 위해 목표치의 90% ~ 110% 사이를 섭취했을 때만 isGoalAchieved: true를 반환하도록 설계했습니다.
- 이유: 다이어트 식단 관리는 과식뿐만 아니라 극단적인 절식도 지양해야 하기 때문입니다.
3. 🔥 트러블슈팅: 개발은 역시 에러와의 싸움
오늘 개발 중 가장 진땀 뺐던 두 가지 에러와 해결 과정입니다.
❌ 이슈 1: DTO 클래스 중복 및 필드 누락 (TS2300, TS2339)
- 현상: DailyNutritionDto 클래스가 중복 정의되었다는 에러와 함께, 서비스 로직에서 추가한 achievementRate 필드를 인식하지 못하는 문제가 발생했습니다.
- 원인: 코드 복사 과정에서 클래스가 두 번 선언되었고, DTO 정의에 새로운 분석용 필드들이 누락되어 TypeScript가 타입을 엄격하게 체크했기 때문입니다.
- 해결: 중복 클래스를 제거하고, 응답 객체에 필요한 모든 통계 필드를 @ApiProperty와 함께 명시적으로 추가하여 해결했습니다.
❌ 이슈 2: Prisma 스키마와 서비스 로직의 불일치 (TS2353)
- 현상: targetCalories 필드를 찾을 수 없다는 에러가 발생했습니다.
- 원인: 서비스 로직에서는 targetCalories라는 변수명을 썼지만, 실제 Prisma 스키마(DB 필드명)는 **goalCalories**로 명명되어 있었습니다.
- 해결: select 절에서 실제 필드명인 goalCalories를 가져온 뒤, 코드 내에서 사용할 변수에 매핑하여 데이터 정합성을 맞췄습니다.
🔍 [추가 섹션] API 기능 검증 및 Postman 테스트 결과

설계한 주간 리포트 로직이 의도대로 동작하는지 확인하기 위해 Postman을 사용한 통합 테스트를 진행했습니다. 주요 검증 포인트는 다음과 같습니다.
1. 데이터 집계 및 기간 필터링 검증
- 테스트 케이스: 최근 7일 이내의 식단 데이터가 있는 날과 없는 날이 섞여 있는 경우.
- 결과: 3월 4일에 기록한 데이터가 weeklyTotals에 정확히 합산되었으며, 기록이 없는 다른 날짜들은 0으로 채워져(Zero-filling) 총 7개의 객체가 반환됨을 확인했습니다.
2. 목표 달성 로직 및 수치 정확도 확인
- 테스트 케이스: 섭취 칼로리가 목표 칼로리(2000kcal)의 25%인 상황.
- 결과: achievementRate가 25%로 정확히 산출되었고, 목표 범위(90~110%)를 벗어났으므로 isGoalAchieved가 false로 올바르게 표시되었습니다.
3. 보안 및 인증 연동
- 테스트 케이스: JWT 토큰을 Header에 포함하여 요청.
- 결과: 200 OK 응답과 함께 현재 로그인한 유저의 데이터만 정확히 집계되어 반환되었습니다.
4. 마치며: ADR의 중요성
이번 개발 과정을 통해 ADR(Architecture Decision Record) 작성의 소중함을 다시 느꼈습니다. 왜 90~110%를 기준으로 잡았는지, 왜 실시간 집계를 선택했는지를 기록해두니 협업이나 나중에 코드를 다시 볼 때 큰 확신을 가질 수 있었습니다.
"코드는 사라질 수 있어도, 왜 그렇게 짰는지에 대한 고민의 흔적은 기술 블로그와 ADR에 남는다."
'프로젝트 > 개인프로젝트' 카테고리의 다른 글
🚀 [NestJS] Saga 패턴의 시작: RabbitMQ와 함께하는 비동기 메뉴 분석 API 구현기 (0) 2026.03.08 [NestJS] 회원가입부터 사용자 취향 설정까지: 인증 및 유저 모듈 통합기 (F-03, F-04) (0) 2026.03.07 Meal API Troubleshooting(API 보안 강화) (0) 2026.03.04 [NestJS/Prisma] 식단 관리 서비스 백엔드 고도화 및 트러블슈팅 기록 (0) 2026.03.04 [NestJS] Prisma 7과 JWT로 철벽 보안 로그인 구현하기 (feat. 드라이버 어댑터의 늪) (0) 2026.03.02