Spring
-
CPU는 남는데 서비스가 멈추는 현상: DB 커넥션 병목Spring 2026. 2. 1. 13:26
백엔드 서버를 운영하다 보면 CPU 사용률은 10%도 안 되는데 서비스가 먹통이 되는 이상한 상황을 만나게 된다. 얼핏 보면 모순처럼 느껴지지만, 이것은 전형적인 DB 커넥션 병목 현상이다. 문제 상황상황을 한 문장으로 요약하면 이렇다:DB 커넥션 병목으로 웹 쓰레드가 BLOCKED 상태가 되어 CPU는 유휴 상태지만 서비스는 정지된 상황 왜 CPU는 놀고 있는가?CPU는 기본적으로 RUNNABLE 상태의 쓰레드만 실행한다. 그런데 이 상황에서는:웹 쓰레드 대부분이 DB 커넥션을 기다리며 BLOCKED/WAITING 상태BLOCKED 상태의 쓰레드는 CPU 스케줄링 대상이 아님결과적으로 CPU는 실행할 쓰레드가 없어서 유휴 상태따라서 CPU가 놀고 있다는 건 일이 없다는 뜻이 아니라, 실행 가능한 일이 ..
-
[Spring Study] 토비의 스프링 3주차 스터디 회고: 예외를 던지는 이유를 이해Spring 2025. 11. 18. 16:57
3주차 스프링 스터디에서 토비의 스프링 4장 예외를 공부하면서, 기존에 예외(Exception)라고 생각했던 개념이 얼마나 얕았는지 깨닫게 되었다. 처음에는 그냥 try-catch 정도로 생각했지만, 책과 실무 경험을 함께 고민하면서왜 스프링은 거의 모든 예외를 언체크로 통일하려 하는지,왜 입력값 오류조차 언체크인지,왜 필터에서 발생하는 예외는 @RestControllerAdvice가 받지 못하는지 같은 내용들을 깊이 이해하게 되었다.이건 단순히 예외 문법을 공부한 게 아니라, 예외가 설계에 미치는 영향까지 이해한 시간이었다. 흔한 예외 처리try { ...} catch (SQLException e) { e.printStackTrace();}이 코드는 개발자가 가장 많이 쓰는 예외 처리이다..
-
[Spring Study] 토비의 스프링 2주차 스터디 회고: JDBC 리팩토링과 JdbcTemplate의 발전Spring 2025. 11. 5. 16:58
"스프링의 철학은 결국 코드 중복을 줄이고, 변하지 않는 부분과 변하는 부분을 명확히 분리하는 것."이다. 이번 스터디에서는 이 철학이 JDBC 리팩토링 과정을 통해 어떻게 코드로 녹아드는지를 살펴보았다. 배경: JDBC 리팩토링JDBC를 이용해 DAO를 작성하다 보면 항상 비슷한 코드가 반복된다.Connection c = dataSource.getConnection();PreparedStatement ps = c.prepareStatement(sql);ps.executeUpdate();ps.close();c.close(); 이 구조의 문제점은 명확하다.반복되는 코드 (Connection, Statement, close())예외 처리 복잡도 (try/catch/finally 중첩)유지보수 어려움 (SQL..
-
[Spring Study] 토비의 스프링 1주차 스터디 회고: 스프링의 핵심 철학Spring 2025. 11. 3. 16:50
스터디를 시작하며혼자서 스프링을 공부하며 프로젝트를 진행해왔지만, 개념을 깊이 이해하기보다는 일단 작동하게 만드는 데 집중했던 것 같다.그러다 문득 이런 생각이 들었다.스프링은 왜 이런 구조를 택했을까? 왜 스프링에서는 이런 기능들을 제공할까? 이런 근본적인 의문을 해소하기 위해, 동기, 선배들과 함께 토비의 스프링 Vol.1을 교재로 하는 스터디를 시작했다. 스터디는 스프링의 바이블로 불리는 토비의 스프링 Vol.1로 진행되며, 각 주차별로 정해진 범위를 읽고, 발표자가 내용을 정리해 발표한 뒤 각자 읽으며 인상 깊었던 부분이나 궁금했던 점을 함께 토론하는 방식으로 진행된다.발표는 매주 돌아가면서 진행한다. 오늘의 목표오늘 스터디는 토비의 스프링 Vol.1 1장: 오브젝트와 의존관계. 겉보기엔 단순히 ..
-
@MemberId 도입기: 스프링 MVC 요청 흐름과 커스ArgumentResolver 활용Spring 2025. 9. 8. 18:15
서론최근 진행한 프로젝트에서 컨트롤러에서 사용자 ID를 매번 직접 꺼내서 처리하는 중복을 줄이고, 비즈니스 로직과 요청 파싱을 분리하기 위해 @MemberId 커스텀 애노테이션과 이에 대응하는 ArgumentResolver 패턴을 도입하기로 결정했습니다. 간단히 말하면 컨트롤러는 현재 로그인한 사용자 ID만 받는다는 의도를 명확히 하고, 그 값을 어디서 어떻게 얻는지는 필터/리졸버가 책임지게 한 것입니다. 이 과정에서 헷갈리는 스프링 MVC의 요청 흐름의 개념을 다시 공부하고, 제가 @MemberId 커스텀 애노테이션을 사용하는지 정리하려고 합니다. 스프링 MVC의 전체 요청 흐름클라이언트 → 서블릿 컨테이너(Tomcat) → 서블릿 필터 체인 → DispatcherServlet → HandlerMa..
-
왜 ResponseEntity를 써야 할까?Spring 2025. 8. 5. 11:49
서론Spring으로 REST API를 개발하다 보면 한 번쯤 이런 의문이 듭니다.그냥 DTO를 리턴하면 되는데, 굳이 ResponseEntity를 써야 할까?처음에는 단순히 JSON 데이터만 리턴하면 충분해 보입니다. 하지만 프로젝트가 커지고, 예외 상황과 상태코드, 헤더 설정 등 다양한 조건을 처리해야 할수록 단순한 리턴만으로는 한계에 겪습니다. 이 글에서는 ResponseEntity가 왜 필요하고, 무엇을 해결해 주며, 내부적으로는 어떻게 동작하는지까지 하나의 흐름으로 정리합니다. 응답 방식의 기본: DTO 직접 리턴 방식Spring MVC에서는 컨트롤러가 DTO를 직접 리턴해도, 내부에서 Jackson(ObjectMapper)을 통해 JSON으로 변환되고, 응답 바디로 클라이언트에 전송됩니..
-
JPA 기반 스프링 애플리케이션에서의 CQRS 패턴 적용Spring 2025. 7. 14. 00:13
CQRS란?CQRS(Command Query Responsibility Segregation)는 명령(Command)과 조회(Query)의 책임을 분리하는 설계 패턴입니다. 이 개념은 단순한 객체지향 원칙을 넘어서 어플리케이션 아키텍처 수준에서의 분리를 의미합니다. CQRS가 필요한 이유는?제가 개발한 JPA 기반의 서비스 클래스는 다음과 같은 작업을 모두 처리합니다.@Service@Transactionalpublic class OrderService { public Order createOrder(...) { ... } public void cancelOrder(...) { ... } public OrderDto getOrderDetail(Long orderId) { ... }} 이..