[Optimization-4] JPA: N+1 모니터링 시스템 구축하기
·
Spring/JPA
1. 들어가며 앞선 장들에서는 JPA의 연관 관계, 로딩 전략, 그리고 N+1 문제가 왜 발생하는지를 이론과 코드 예제를 통해 살펴보았다. 하지만 실제 현업에서 중요한 질문은 여기서 한 단계 더 나아간다. “그래서 이 문제를 어떻게 발견했고, 어떻게 개선했으며, 이 경험을 어떻게 설명할 수 있는가?” 이번 장에서는 N+1 문제를 실무 환경에서 모니터링하고 추적하는 방법, 그리고 그 경험을 설득력 있게 녹여내는 과정을 중심으로 이야기를 풀어보려 한다.2. N+1 문제, 어떻게 모니터링할까? 실제 운영 중인 서비스에서는 수많은 API가 동시에 호출된다. 각 API는 서로 다른 비즈니스 로직을 가지고 있고, 그 내부에서는 여러 개의 SQL 쿼리가 실행된다. 문제는 이 쿼리들이 눈에 잘 보이지 않는다는 데 있다..
[Optimization-3] N+1 문제 - 대표적인 사례와 해결 전략
·
Spring/JPA
1. 들어가며 앞서 우리는 JPA의 기본 개념과 프록시, 그리고 로딩 전략(LAZY / EAGER)이 무엇인지 살펴보았다. 이제부터는 이 개념들이 실제 서비스 코드에서 어떤 문제를 만들어내는지, 그리고 그 문제를 어떻게 해결할 수 있는지를 본격적으로 다뤄보려 한다. 이번 장의 핵심 주제는 JPA를 사용하는 개발자라면 반드시 한 번쯤은 마주하게 되는 N+1 문제다. 2. N+1 문제란 무엇인가 N+1 문제는 JPA에서 연관 관계를 가진 엔티티를 조회할 때, 의도보다 훨씬 많은 SQL이 실행되는 현상을 의미한다. 이름 그대로 한 번의 조회 쿼리(1) 이후에, 연관된 엔티티를 가져오기 위해 N번의 추가 쿼리가 실행되는 구조다. 가장 전형적인 흐름은 다음과 같다.특정 엔티티 목록을 조회하는 쿼리가 1번 실행된..
[Optimization-2] 기초(2) - 성능 최적화의 열쇠, 프록시와 로딩 전략
·
Spring/JPA
1. 들어가며JPA를 사용하다 보면 단순한 CRUD를 넘어서 “왜 쿼리가 이렇게 많이 나가지?”,“분명 한 번 조회했는데 또 SELECT가 나간다” 같은 의문을 마주치게 된다. 이 문제의 중심에는 항상 프록시(Proxy) 와 로딩 전략(Fetch Strategy) 이 존재한다. 이번 글에서는 JPA 내부 동작을 이해하는 데 꼭 필요한 두 개념을 비유 → 내부 구조 → 실제 코드 → 실행 쿼리 흐름 순서로 이해해보자.2. 프록시(Proxy)의 이해2.1. 프록시란 무엇인가? 프록시(Proxy)는 사전적으로 ‘대리인’ 을 의미한다. 즉, 실제 객체가 해야 할 일을 대신 수행하거나, 필요할 때 실제 객체에게 위임하는 객체다. JPA에서는 이 프록시 개념이 단순한 디자인 패턴을 넘어, 지연 로딩(LAZY)을 ..
[Optimization-1] 기초(1) - 현대 백엔드 개발의 표준, JPA의 본질
·
Spring/JPA
1. JPA(Java Persistence API)의 정의JPA는 Java 진영의 영속성 관리 및 객체-관계 매핑(ORM, Object-Relational Mapping)을 위한 표준 기술이다. 이는 자바 객체와 관계형 데이터베이스의 테이블을 자동으로 매핑하여 데이터 불일치 문제를 해결한다. 핵심 요약인터페이스: JPA는 그 자체로 동작하는 것이 아닌 인터페이스의 집합이다.구현체: 실제 동작은 구현체에 의해 이루어지며, Hibernate가 가장 대표적이다.Spring Boot 환경: 기본 설정만으로도 Hibernate를 쉽게 사용할 수 있도록 지원하며, 실무에서의 JPA 사용은 대개 Hibernate 기반 환경을 의미한다.2. JPA의 주요 특징과 장점JPA의 도입은 개발의 패러다임을 SQL 중심에서 객..
[Practice-6] 단뱡향/양방향 선택 기준 (⭐⭐⭐)
·
Spring/JPA
기준 1. 데이터의 개수 (Cardinality)"리스트에 담았을 때 메모리가 터질 가능성이 있는가?"ProductOption (옵션):한 상품에 옵션이 몇 개나 붙을까요? 색상, 사이즈 조합해봤자 보통 10개 내외, 많아도 100개를 넘지 않습니다.이 정도는 List에 담아서 메모리에 올려도 서버에 전혀 부담이 없습니다.Review (리뷰):인기 상품은 리뷰가 수천, 수만 개가 달립니다.이걸 List에 담는 순간, 상품 하나 조회하려고 리뷰 1만 개를 메모리에 퍼올리는 대형 사고가 터집니다. 그래서 리뷰는 페이징(Slice/Page)이 필수이고, 양방향을 끊어야 합니다.2. 생명주기 (Lifecycle)와 종속성"부모가 죽을 때 자식도 같이 죽어야 하는가? 그리고 함께 관리되는가?"ProductOpti..
[Practice-5] 일대다/다대일 관계 정의
·
Spring/JPA
결론부터 말하면 방향(누가 누구를 바라보느냐)에 따라 이름이 달라지기 때문이다. 네가 헷갈려하는 부분은 "관계의 전체적인 그림"과 "객체 입장에서의 시선"을 혼동했기 때문일 가능성이 크다. JPA 어노테이션(@ManyToOne, @OneToMany)은 항상 "나(현재 필드를 가진 객체)"를 기준으로 "너(상대방 객체)"가 몇 개인지를 정의한다. 아래 설명을 통해 오해를 풀어보자.1. 관계를 정의하는 공식JPA 어노테이션은 항상 @MeToYou (나 To 너) 순서로 읽어야 한다.Left (Me): 이 어노테이션이 붙은 클래스 (또는 인스턴스)Right (You): 이 필드가 가리키는 대상2. 자식 입장 (CategoryEntity -> parent)@ManyToOne // (Me = Many, You =..
[Practice-3] Spring Core: 깔끔하고 확장성 있는 예외 처리
·
Spring/Core
1. 들어가며 웹 애플리케이션을 개발할 때 정상적인 성공 응답만큼이나 중요한 것이 에러 상황을 클라이언트에게 어떻게 전달할 것인가이다. Spring Boot를 사용하면 기본적으로 White Label Error Page 또는 단순한 에러 JSON이 내려가지만, 이는 프론트엔드나 모바일 클라이언트가 사용하기에는 정보가 부족하고 형식 또한 일관되지 않다. 특히 REST API 환경에서는 에러 응답 역시 하나의 계약(Contract) 이다. 어떤 에러가 발생하더라도 항상 동일한 구조의 JSON을 내려주어야 클라이언트는 예외 케이스를 예측 가능하게 처리할 수 있다. 본 글에서는 @RestControllerAdvice를 활용해 예외 처리를 중앙화하고, ErrorCode, BusinessException, Er..
[Practice-4] Spring Data: 무한 깊이 조회 패턴 (댓글/대댓글, 카테고리)
·
Spring/JPA
1. 들어가며 개발을 하다 보면 카테고리, 회사의 조직도, 혹은 게시판의 댓글/대댓글이나 카테고리처럼 '계층 구조(Hierarchy)'를 가진 데이터를 다뤄야 할 때가 있다. 만약 이 계층의 깊이가 1단계나 2단계로 고정되어 있다면 설계가 간단하겠지만, 요구사항에 따라 깊이가 5단계, 10단계, 혹은 그 이상으로 무한히 늘어나야 한다면 어떻게 데이터베이스를 설계해야 할까? 본 글에서는 이러한 무한 계층 구조를 유연하게 처리하기 위한 표준적인 설계 방식인 자기 참조(Self-Referencing) 모델링에 대해 정리한다.1. 가장 흔한 실수: 컬럼 나열 방식 (Legacy)계층형 데이터를 처음 접할 때 가장 직관적으로 떠올리는 방식은 깊이(Depth)별로 컬럼을 만드는 것이다.[구조 예시]depth1_id..