분류 전체보기 14

오픈소스 기여: SpringDoc-OpenAPI에 기능 제안기

안녕하세요. Spring Boot 환경에서 API 문서를 위해 springdoc-openapi 라이브러리를 애용하는 개발자입니다. 이 라이브러리는 정말 훌륭하지만, API DTO에 Enum 타입 필드가 있을 때마다 항상 아쉬운 점이 있었습니다.바로 이 Enum이 어떤 값들을 가지고, 각 값이 무슨 의미인지 API 문서에 명확히 보여주는 작업이 너무 번거롭다는 것이었습니다.매번 @Operation의 description 속성에 Enum의 모든 값을 수동으로 복사-붙여넣기 하던 어느 날, "이 기능을 직접 만들어서 springdoc-openapi에 기여(Contribution)해 보면 어떨까?"라는 생각을 하게 되었습니다.이 포스트는 제가 springdoc-openapi에 **@EnumDescription*..

SPRING 2025.10.31

좋아요 버튼 뒤에 숨겨진 함정: 멱등성과 동시성 모두 잡는 API 설계

'좋아요'나 '찜하기' 기능은 대부분의 서비스에 있는 기본 기능입니다. 너무 기본적이라 "그냥 boolean 값 바꾸면 되는 거 아냐?"라고 생각하기 쉽죠.하지만 이 간단해 보이는 기능 뒤에는 **'동시성(Race Condition)'**과 **'멱등성(Idempotency)'**이라는 거대한 함정이 숨어있습니다. 사용자가 '좋아요' 버튼을 광클(더블 클릭)할 때, 우리 서버는 과연 안전할까요?오늘은 순진했던 첫 구현부터 시작해, 우리가 겪은 문제점과 이를 해결해 나가는 과정을 단계별로 정리해 보겠습니다.1. 순진한 구현: "먼저 확인하고, 실행한다" (Check-then-Act)가장 직관적인 코드는 "이미 찜했는지 확인하고, 없으면 생성하고, 있으면 삭제하는" 것입니다. // Controller (혹은..

SPRING 2025.10.27

트래픽에 따라 진화하는 조회수 기능: 동시성 문제부터 Redis 배치 업데이트까지

많은 웹 서비스에서 '조회수' 기능은 사용자의 반응을 보여주는 가장 기본적인 지표입니다. 간단해 보이지만, 이 조회수 기능은 트래픽이 몰리기 시작하면 **"데이터 불일치(Race Condition)"**와 **"DB 성능 저하"**라는 두 가지 큰 문제에 부딪히게 됩니다.오늘은 사용자가 거의 없는 초기 서비스부터 수백만 트래픽을 감당해야 하는 대규모 서비스까지, 트래픽 규모에 따라 조회수 기능을 어떻게 진화시켜야 하는지 3단계에 걸쳐 알아보겠습니다.Level 1. 초급: 순진한(Naive) 구현과 동시성 문제서비스를 처음 개발할 때, 우리는 가장 직관적인 방법으로 조회수 기능을 구현합니다.// Service.java@Transactionalpublic Board getBoard(Long boardId) ..

SPRING 2025.10.26

[Lombok] 상속받은 DTO 테스트 중 만난 @AllArgsConstructor의 함정과 @SuperBuilder로 해결하기

안녕하세요! 백엔드 개발을 하다 보면 공통된 요청 파라미터를 분리하기 위해 DTO 클래스 간 상속 구조를 자주 사용합니다. 예를 들어, 페이징 처리를 위한 PageRequest를 만들고, 실제 요청 DTO인 IdeaBoardListGetRequestDto가 이를 상속받게 하는 식이죠.저도 최근 이 구조를 사용해 DTO를 설계하고, 이에 대한 테스트 코드를 작성하고 있었습니다.1. 문제 상황: "그런 생성자는 없습니다"먼저 제가 작성한 DTO 클래스입니다.PageRequest (부모 클래스)import lombok.AllArgsConstructor;import lombok.NoArgsConstructor;import lombok.Setter;@Setter@NoArgsConstructor@AllArgsCon..

SPRING 2025.10.21

JPA Bulk Insert의 함정, 영속성 컨텍스트를 조심하세요

안녕하세요! 지난 JPA 1대N 관계 대량 INSERT, N+1 쿼리 대신 Bulk Insert로 성능 박살내기 🚀 포스팅에서는 JdbcTemplate을 이용해 엄청난 성능 향상을 이루는 방법을 알아봤습니다.하지만 이 강력한 기능에는 우리가 꼭 알아야 할 **'함정'**이 숨어있습니다. 바로 JPA 영속성 컨텍스트(Persistence Context)와의 단절 문제입니다.🤔 문제의 시작: 저장 직후, 데이터가 필요하다면?지난번 코드를 다시 보겠습니다. Board를 저장하고, JdbcTemplate으로 Tag들을 저장한 뒤 로직이 끝났습니다. 그런데 만약 저장 직후, 생성된 태그 정보를 이용해 알림을 보내는 로직이 추가된다면 어떨까요?// BoardService.java@Transactionalpubl..

SPRING 2025.10.14

JPA 1대N 관계 대량 INSERT, N+1 쿼리 대신 Bulk Insert로 성능 박살내기

안녕하세요! 오늘은 JPA를 사용하면서 많은 분들이 한 번쯤 마주쳤을 1대N(One-to-Many) 관계에서의 대량 데이터 INSERT 성능 문제에 대해 이야기해보려고 합니다.게시글(Board)을 작성할 때 여러 개의 태그(Tag)를 함께 저장하는 기능을 구현한다고 가정해봅시다. 아마 많은 분들이 아래와 같이 코드를 작성하실 겁니다. 🤔 흔히 사용하는 방식 (JPA 연관관계 메소드 활용)// BoardService.java@Transactionalpublic Board createIdeaBoard(..., List tagList) { Board board = Board.createIdeaBoard(...); // 태그 추가 if (tagList != null && !tagLis..

SPRING 2025.10.14

INNER JOIN vs. OUTER JOIN

데이터베이스에서 관계형 데이터를 조회할 때 JOIN은 필수적인 SQL 구문이다. 그중 가장 기본이 되는 INNER JOIN과 OUTER JOIN은 조회 결과에 결정적인 차이를 만들기 때문에, 개발자는 두 조인 방식의 메커니즘을 명확히 이해하고 목적에 맞게 사용해야 한다.본 포스트에서는 두 JOIN 방식의 핵심적인 차이점을 예제와 함께 기술적으로 분석한다.## 분석을 위한 예제 테이블아래의 EMPLOYEE(사원) 테이블과 DEPARTMENT(부서) 테이블을 기준으로 설명한다.[EMPLOYEE 테이블]EMP_IDEMP_NAMEDEPT_ID101김개발10102이서버20103박클라10104최데이터NULLSheets로 내보내기[DEPARTMENT 테이블]DEPT_IDDEPT_NAME10개발팀20인프라팀30기획팀S..

DB 2025.10.12

static 이란 뭘까?

안녕하세요! 개발하다 보면 원인 모를 오류에 static 키워드 하나 붙였더니 해결되는 마법 같은 순간, 다들 경험해보셨죠? 특히 Entity를 DTO로 변환하는 메소드나, main 메소드에서 다른 메소드를 호출할 때 자주 마주치게 되는데요.오늘은 바로 그 static이 도대체 무슨 역할을 하고, 왜 오류를 해결해 주는지 쉽고 명확하게 파헤쳐 보겠습니다! ## 비유로 시작하기: 대학교와 학생 🎓static을 가장 쉽게 이해하는 방법은 '대학교'와 '학생'의 관계를 떠올리는 거예요.class = 대학교 (설계도, 개념)new로 만든 객체(인스턴스) = 학생 한 명 한 명 (설계도로 만들어진 실체)👤 1. static이 없는 멤버 (학생 개인의 것)static이 붙지 않은 변수나 메소드는 '학생 개인' ..

JAVA 2025.10.12

Spring boot + AWS ec2 windows 를 활용한 프로젝트 배포

이번 시간엔 클라우드 플랫폼 중 하나인 아마존 웹 서비스(AWS) 를 이용한 간단한 spring boot 프로젝트를배포해보는 시간을 가져보겠다. 일단 배포할 프로젝트는 docker 테스트 시 쓰였던 프로젝트를 그대로 활용하겠다.https://github.com/TAEWOOKK/docker GitHub - TAEWOOKK/docker: 도커를 이용해서 배포가 되는 스프링 프로젝트 기본 툴도커를 이용해서 배포가 되는 스프링 프로젝트 기본 툴. Contribute to TAEWOOKK/docker development by creating an account on GitHub.github.com @RestControllerpublic class MainController { @GetMapping("/")..

AWS 2024.09.26

SpringBoot + docker 를 통한 서버 실행(3)

2024.09.24 - [Docker] - SpringBoot + docker 를 통한 서버 실행(2) SpringBoot + docker 를 통한 서버 실행(2)2024.09.24 - [Docker] - SpringBoot + docker 를 통한 서버 실행(1 SpringBoot + docker 를 통한 서버 실행(1)이번엔 도커를 통해 간단한 스프링 부트 프로젝트를 생성해서 도커를 통해프로젝트를 실행시켜 보도록wookpro.tistory.com이전 게시물에서 도커를 이용해서 서버를 실행 시키는걸 진행해 보았다.이번엔 빌드를 성공한 도커이미지를 저장할 수 있는 도커허브에 저장(push) 해보고 pull 해서 저장소에 있는 도커이미지를 local에 불러와서 실행해보겠다. docker images 이 명..

Docker 2024.09.26
반응형