JPA 자동 스키마 관리에서 Flyway 기반 DB 마이그레이션
·
Backend/Trouble Shooting
배경프로젝트 초기에는 개발 속도를 우선시해JPA의 ddl-auto: update와 Java 기반 데이터 초기화 방식을 사용했다.이 방식은 빠른 개발에는 유리했지만,서비스 출시를 고려하면서 다음과 같은 한계를 명확히 인식하게 되었다.스키마 변경이 언제, 왜 발생했는지 추적하기 어려움애플리케이션 재기동 시 DB 상태가 달라질 수 있음개발 환경과 운영 환경의 데이터 경계가 흐려짐이 시점부터 데이터베이스를“프레임워크가 대신 관리해주는 영역”이 아니라“서비스 안정성을 좌우하는 핵심 시스템”으로 보게 되었다.문제 정의겉으로 드러난 문제는 ddl-auto 설정이었지만,본질적인 문제는 다음 질문으로 정리되었다.“DB 스키마 변경에 대한 책임은 어디에 있어야 하는가?”JPA의 자동 스키마 생성에 위임할 것인가아니면 애플..
[Spring Boot] Swagger(Springdoc)에서 제네릭 공통 응답 스키마가 꼬이는 문제 해결기
·
Backend/Trouble Shooting
1. 문제 상황 프로젝트에 공통 응답 포맷인 ApiResponseDto를 도입한 이후, Swagger UI에서 예상치 못한 문제가 발생했다.현상모든 API의 응답 데이터(data 필드)가 특정 DTO(예: UserResponseDto)로 고정되어 표시됨영향일기(Diary), 날씨(Weather) 등 서로 다른 도메인의 API 문서에서도 응답 예시가 전부 유저 정보로 출력되어공통 응답 래퍼를 쓰는 구조 자체는 문제가 없어 보였지만, 문서 자동화 도구(Springdoc) 와 결합되면서 문제가 표면화되었다.2. 원인 분석이 문제의 핵심 원인은Springdoc의 스키마 생성 방식과 제네릭 타입 정보가 문서화 과정에서 처리되는 방식에 있었다.2-1. Springdoc은 “스키마 이름”을 기준으로 동작한다Sprin..
[SpringBoot] UTC 시간 처리, 코드가 아니라 설정으로 정리하기 (Hibernate 6 & Jackson)
·
Backend/Trouble Shooting
1. 설정은 맞았지만, 최선은 아니었다지난 포스팅(https://wlals916.tistory.com/6)에서는DB와 서버의 타임존을 UTC로 통일하는 과정을 정리했다.당시에는 “이 정도면 충분히 잘 맞췄다”고 생각했다.하지만 코드 리뷰를 받으면서 생각이 바뀌었다.분명 동작은 하고 있었지만,같은 설정이 여러 곳에서 반복되고 있었고Hibernate 6에서 이미 제공하는 더 현대적인 해결책을 활용하지 못하고 있었다.이번 글에서는타임존을 안전하게 다루기 위해 내가 놓치고 있던 지점들과이를 정리하면서 얻은 설계적 통찰을 공유한다.2. 문제 제기: “왜 이 코드는 반복되는가?”다음은 실제 DTO에 존재하던 코드 일부다.@Schema(description = "일기 작성 날짜 및 시간 (UTC 기준, ISO-860..
스프링 핵심 원리 기본편 정리
·
Backend/Study Notes
김영한 강사의 스프링 핵심원리 - 기본편 강의 내용을 바탕으로 학습한 정리본입니다https://www.inflearn.com/course/스프링-핵심-원리-기본편#curriculum스프링의 진짜 얼굴: “프레임워크”가 아니라 “설계 철학”스프링을 처음 접하면 보통 이렇게 생각한다.“아, 웹 만들 때 쓰는 거지?”“스프링 부트가 스프링 아니야?” 절반만 맞다. 스프링은 웹 프레임워크 이전에 객체 지향 설계를 실현하기 위한 인프라다.웹, 데이터, 배치, 시큐리티는 그 위에 얹힌 옵션일 뿐이다.핵심은 딱 하나다.“객체 지향의 좋은 설계를 현실 세계에서 작동하게 만드는 것” 스프링은 하나가 아니다스프링은 마치 레고 세트 같다. 하나의 제품이 아니라 여러 박스의 조합이다.Spring Framework → 뼈대 (..
[SpringBoot] 검증 로직의 위치(@Valid vs Service) : 테스트 코드로 드러난 설계 문제
·
Backend/Trouble Shooting
실제 서비스를 개발하다 보면 “이건 분명 검증을 해놨는데 왜 이런 에러가 나지?”라는 순간을 자주 마주한다.이번 글은 검증 로직의 위치(@Valid vs Service) 에 대한 이야기이기도 하지만,검증 로직이 흩어졌을 때 생기는 문제Mock 기반 테스트가 왜 ‘허구의 안정감’을 줄 수 있는지그리고 왜 Service 레이어 단일 검증 전략을 선택하게 되었는지를 다룬다. 하지만 그보다 더 중요한 건“문제가 어떻게 드러났고, 왜 혼자서는 끝까지 발견하지 못했는가”에 대한 기록이다.1. 문제가 생기게 된 원인API 기능 구현을 마쳤을 때, 스스로는 이렇게 생각했다.요구사항은 모두 반영했다예외 처리도 했다공통 응답 포맷도 정리했다이제 남은 건 테스트 코드 작성뿐이라고 생각했다.하지만, 컨트롤러 / 서비스 테스트..
[SpringBoot] 날짜와 시간 처리를 UTC로 표준화하기
·
Backend/Trouble Shooting
최근 프로젝트에서 관련 테스트 코드를 작성하던 도중, 문득 시간 설정 방식에 큰 허점이 있다는 사실을 깨달았다. 여행 기록 서비스의 타겟은 한국인이지만, 서비스의 핵심은 해외 여행 기록이다. 사용자가 비행기를 타고 지구 반대편으로 떠나는 순간, 지금의 코드로는 감당할 수 없는 문제들이 기다리고 있었다.1️⃣ 무엇이 문제였을까? (기존 방식 분석)기존 코드는 당연하게 "한국(Asia/Seoul)" 시간대만을 바라보고 있었다. 이 코드는 해외 유저들의 타임라인은 엉망으로 만든다.A. Java 엔티티와 비즈니스 로직의 한계현재 Trip 엔티티는 LocalDate, Diary 엔티티는 LocalDateTime을 사용하고 있었다. 문제는 LocalDateTime에는 타임존(Timezone) 정보가 없다는 점이다..
[SpringBoot] 프로젝트에 SonarCloud 연동하기: Gradle + GitHub Actions
·
Backend/Trouble Shooting
개요지난 학기에 수강했던 DevOps 수업에서 SonarCloud를 처음 접했다. 당시에는 이미 개발이 완료된 프로젝트를 배포·운영하는 것이 목적이었기 때문에, 개발 과정에서 코드 품질을 지속적으로 관리하는 용도로 SonarCloud를 제대로 활용하지 못한 점이 아쉬움으로 남았다.이번에 진행한 여행기록 서비스 프로젝트에서는 이 아쉬움을 보완하고자 SonarCloud를 도입했다. 팀원들에게 SonarCloud의 목적과 장점을 공유하고, CI 파이프라인에 자연스럽게 녹여 코드 품질을 지속적으로 관리할 수 있도록 구성했다.이번 연동의 핵심 목표는 단순하다.“코드를 더 클린하게 유지하자.”이를 위해 dev 브랜치 기준으로 다음과 같은 파이프라인을 구성했다.테스트 실행SonarCloud 코드 품질 분석본 글에서는..