2026. 7. 6. 16:40ㆍ부트캠프/TIL(Today I Learned)
주문 관리 플랫폼 프로젝트 3일차 - 명세서 피드백과 깃이슈 생성 및 깃 브랜치,PR,Merge 및 공통 API 로깅 코드 구현
팀 프로젝트 학습일지 (오늘의 회고)
오늘의 학습 키워드
- Soft Delete와 Unique 제약조건
- ERD / API 명세서 피드백
- GitHub Issue 기반 브랜치 생성
- Spring Boot Filter
- OncePerRequestFilter
- MDC(Mapped Diagnostic Context)
- Trace ID
- API 요청 로깅
오늘 배운 점
Soft Delete와 UNIQUE 제약조건에 대한 설계
오늘 명세서 리뷰를 받으면서 email 컬럼이 NOT NULL + UNIQUE인데 Soft Delete를 어떻게 처리할 것인지 고민해보라는 피드백을 받았다.
처음에는 단순히 deleted_at 컬럼만 추가하면 된다고 생각했지만, Soft-Delete를 적용하면 실제 데이터는 삭제되지 않기 때문에 기존 이메일이 계속 UNIQUE 제약조건을 차지하게 된다.
예를 들어서
test@test.com
회원이 탈퇴(Soft Delete)한 뒤에도 데이터는 남아 있으므로
test@test.com
으로는 다시 회원가입을 할 수 없다.
이를 해결하기 위해 회원 탈퇴 시 이메일을 변경하는 방식을 적용할 수 있다는 것을 배웠다.
예시
기존
test@test.com
↓
회원 탈퇴
↓
test@test.com_1751281234
또는
test@test.com_deleted_20260706
처럼 삭제 시간을 뒤에 붙여 이메일을 변경하면 UNIQUE 제약조건을 유지하면서 동일한 이메일로 재가입도 가능하다.
알게된 점
- Soft Delete는 단순히 삭제 여부만 관리하는 것이 아니라 데이터베이스의 제약조건까지 고려해야 한다.
- 설계 단계에서 DB 제약조건과 비즈니스 요구사항을 함께 생각해야 한다.
- UNIQUE 컬럼을 Soft Delete할 경우 값 변경, Partial Index 등 다양한 해결 방법이 존재한다.
- 구현은 코드 단계에서 진행하지만 설계 단계부터 이러한 문제를 미리 고려하는 것이 중요하다.
GitHub Issue 기반 브랜치 생성
오늘은 GitHub Issue를 생성한 뒤 브랜치를 만드는 과정을 익혔다.
기존에는
git checkout -b feature/login
처럼 직접 브랜치를 만들었지만,
GitHub에서
- Issue 생성
- Create Branch 클릭
만 하면 GitHub가 브랜치 이름까지 자동으로 만들어 주고
git fetch origin
git switch feature/#15-login
같은 명령어도 함께 제공한다.
덕분에 브랜치 네이밍 규칙을 맞추기 쉽고 Issue와 브랜치가 자동으로 연결되어 협업하기 훨씬 편리하다는 것을 배웠다.
기술적으로 배운 점
- GitHub Issue와 브랜치를 연결하면 작업 이력을 추적하기 쉽다.
- 브랜치 네이밍 규칙을 통일할 수 있다.
- 협업 시 어떤 브랜치가 어떤 작업인지 쉽게 파악할 수 있다.
공통 API 요청 로깅 필터 구현
오늘 팀 프로젝트에서는 공통 요청 로깅 필터(RequestLoggingFilter) 를 구현했다.
Spring Boot의
- OncePerRequestFilter
- MDC
- Logback
을 활용하여 모든 API 요청을 자동으로 기록하도록 만들었다.
구현한 기능
- 모든 요청에 Trace ID 생성
- 외부에서 전달된 X-Request-Id가 있으면 재사용
- 응답 헤더에도 Trace ID 추가
- 요청 종료 후
- HTTP Method
- URL
- Status Code
- 실행 시간
- Client IP
를 한 줄 로그로 출력
예시
[8a4fc321] POST /api/reviews
status=201
34ms
ip=127.0.0.1
왜 OncePerRequestFilter를 사용하는가?
일반 Filter는 DispatcherType에 따라 여러 번 실행될 수도 있다.
반면
OncePerRequestFilter
는 하나의 HTTP 요청당 한 번만 실행되므로 중복 로그를 방지할 수 있다.
공통 로깅 기능에는 가장 적합한 Filter라는 것을 배웠다.
MDC를 사용하는 이유
MDC(Mapped Diagnostic Context)는 하나의 요청 동안 사용할 공통 데이터를 저장하는 공간이다.
오늘은
MDC.put("traceId", traceId);
를 사용하여 Trace ID를 저장했다.
application.yml에서
logging.pattern.console:
에
%X{traceId}
를 추가하면
모든 로그 앞에
[8a4fc321]
처럼 Trace ID가 자동으로 출력된다.
덕분에 하나의 요청에서 발생한 여러 로그를 쉽게 추적할 수 있다.
finally에서 MDC.clear()를 하는 이유
Spring은 스레드를 재사용하는 Thread Pool 방식을 사용한다.
MDC를 비우지 않으면 이전 요청의 Trace ID가 다음 요청에도 남아 있을 수 있다.
그래서
finally {
MDC.clear();
}
를 통해 요청이 끝날 때 반드시 정리해야 한다는 것을 배웠다.
JWT를 고려한 확장성
현재는 인증 기능이 없어서 Trace ID만 저장한다.
하지만 이후 JWT 인증을 도입하면
MDC.put("userId", userId);
한 줄만 추가하면 된다.
즉, 로깅 필터는 수정하지 않고도 사용자 정보까지 함께 기록할 수 있도록 확장성을 고려하여 설계했다.
문제 해결
피드백
ERD 및 API 명세서 리뷰에서
email이 NOT NULL + UNIQUE인데 Soft Delete를 어떻게 처리할 것인가?
라는 질문을 받았다.
해결 방향
회원 탈퇴 시 이메일 뒤에 삭제 시각(Timestamp)을 붙여 이메일 값을 변경하는 방식으로 구현하기로 했다.
이를 통해
- Soft Delete 유지
- UNIQUE 제약 유지
- 동일 이메일 재가입 가능
이라는 요구사항을 모두 만족할 수 있다.
내일 할 일
- API 명세서 추가 설계
- 회원(User(Auth)) 도메인에 대해 팀원들과 설계 논의
- 회원 기능 구현 시작
- Soft Delete 처리 방식 코드 구현 검토
- 회원가입 및 로그인 API 개발 시작

오늘의 회고
오늘은 단순히 기능을 구현하는 것보다 설계 단계에서 발생할 수 있는 문제를 미리 고려하는 것의 중요성을 느낀 하루였다. 특히 Soft Delete와 UNIQUE 제약조건처럼 데이터베이스 설계와 비즈니스 요구사항이 충돌할 수 있다는 점을 배웠고, 구현 이전에 이를 해결할 방향을 고민하는 과정이 중요하다는 것을 알게 되었다.
또한 GitHub Issue 기반 브랜치 생성과 공통 로깅 필터를 구현하면서 협업과 운영을 고려한 개발 방식도 경험했다. 특히 OncePerRequestFilter와 MDC를 활용한 로깅은 단순히 로그를 남기는 것이 아니라 요청을 추적하고, 이후 JWT 인증과도 자연스럽게 연계할 수 있도록 확장성을 고려한 설계라는 점이 인상 깊었다.
오늘은 협업을 위한 개발 프로세스와 유지보수를 고려한 설계 방식까지 함께 배울 수 있었던 의미 있는 시간이었다.
'부트캠프 > TIL(Today I Learned)' 카테고리의 다른 글
| [내일배움캠프_사전캠프_8기]_Days_13 TIL_ 팀 프로젝트-Day5 (0) | 2026.07.08 |
|---|---|
| [내일배움캠프_사전캠프_8기]_Days_12 TIL_ 팀 프로젝트-Day4 (0) | 2026.07.07 |
| [내일배움캠프_사전캠프_8기]_Days_9 TIL_ 팀 프로젝트 OT (0) | 2026.07.03 |
| [내일배움캠프_단기심화_8기]_Days-7-TIL (0) | 2026.06.30 |
| [내일배움캠프_단기심화_8기]_Days-6-TIL (0) | 2026.06.29 |