전체 글 썸네일형 리스트형 Spring Data JPA에서 미리 집계된 카운트를 활용한 팔로우 목록 조회 최적화 문제 상황팔로우 시스템을 구현할 때 많은 개발자들이 팔로잉 수와 팔로워 수를 미리 User 엔티티에 집계해서 저장합니다. 하지만 정작 팔로우 목록을 조회할 때는 여전히 COUNT 쿼리가 발생하여 집계 데이터의 의미가 퇴색되는 경우가 많습니다. 기존 방식의 문제점1. 불필요한 COUNT 쿼리 발생// 기존 Repository 메서드@Query("SELECT u FROM User u WHERE u.id IN (...)")List findFollowingsByUserId(@Param("userId") Long userId, Pageable pageable);// 실제 실행되는 쿼리:// 1. SELECT u FROM User u WHERE ... LIMIT 20 OFFSET 0// 2. SELECT COUNT.. 더보기 Java Record 클래스: 올바른 예외처리와 역할 분담 들어가며Java 14에서 도입된 Record 클래스는 데이터 전송 객체(DTO)를 간결하게 작성할 수 있는 강력한 기능입니다. 하지만 Record에서 예외처리를 어떻게 해야 할지, 그리고 Service Layer와의 역할을 어떻게 분담해야 할지에 대해서는 많은 개발자들이 고민하고 있습니다. 이번 글에서는 Record 클래스의 기본 개념부터 올바른 예외처리 방법까지 자세히 알아보겠습니다.Record 클래스란?Record는 "데이터만 담는 불변 클래스"를 간단하게 만들어주는 문법입니다. 기존에 DTO를 만들 때 필요했던 반복적인 코드들을 컴파일러가 자동으로 생성해줍니다. 기존 방식과의 비교기존 방식public class UserInfoResponseDto { private final Long id; .. 더보기 Spring Boot JPA 연관관계 및 애그리거트 경계 설계: 연관관계 vs 키 값 들어가며모임 플랫폼을 개발하면서 User 도메인의 연관관계 설계에 대해 깊이 고민하게 되었습니다. Users, UserCategories, UserFollow, UserRatings 엔티티 간의 관계를 어떻게 설정할지에 대한 여러 접근법을 공유합니다.초기 요구사항 분석사용자 도메인에서 관리해야 할 엔티티들은 다음과 같았습니다:Users: 기본 사용자 정보UserCategories: 사용자의 관심 카테고리UserFollow: 사용자 간 팔로우 관계UserRatings: 사용자에 대한 평가 (모임 후 상호 평가) 설계 과정의 여러 시행착오1단계: ManyToOne 단방향 접근처음에는 성능을 고려하여 ManyToOne 단방향 관계를 고려했습니다.// UserCategories@ManyToOne(fetch = .. 더보기 데이터베이스 커넥션 풀 최적화 - 성능과 안정성 향상 들어가며데이터베이스 커넥션은 애플리케이션에서 가장 중요하면서도 제한적인 자원 중 하나입니다. 커넥션을 효율적으로 관리하지 못하면 성능 저하, 응답 지연, 심지어 서비스 장애까지 발생할 수 있습니다. 이번 포스트에서는 커넥션 풀의 개념부터 실제 최적화 방법까지 상세히 알아보겠습니다. 커넥션 풀의 이해커넥션 풀이란커넥션 풀은 데이터베이스 연결을 미리 생성해서 풀에 저장해두고, 필요할 때마다 재사용하는 메커니즘입니다. 매번 새로운 커넥션을 생성하고 종료하는 비용을 절약할 수 있습니다. 커넥션 풀 없이 사용할 때의 문제점// 문제가 되는 코드 - 매번 새로운 커넥션 생성public List getUsers() { Connection conn = null; try { // 1. 커넥션 생성.. 더보기 파일 저장소 분리와 CDN 활용 - 대용량 파일 처리 최적화 들어가며현대의 웹 애플리케이션에서는 이미지, 동영상, 문서 등 다양한 형태의 파일을 처리해야 합니다. 이러한 파일들을 애플리케이션 서버나 데이터베이스에 직접 저장하면 성능 저하와 확장성 문제가 발생할 수 있습니다. 이번 포스트에서는 파일 저장소를 분리하고 CDN을 활용하여 효율적으로 파일을 관리하는 방법을 알아보겠습니다. 파일 저장소 분리의 필요성기존 방식의 문제점1. 데이터베이스에 파일 저장-- 문제가 되는 구조CREATE TABLE posts ( id BIGINT PRIMARY KEY, title VARCHAR(255), content TEXT, image_data LONGBLOB -- 이미지를 직접 저장); 문제점:데이터베이스 크기 급속 증가백업 및 복원 시간 증가메모리 사용.. 더보기 백엔드 성능 최적화 - Redis를 활용한 리모트 캐싱 들어가며백엔드 애플리케이션에서 성능 병목 현상이 발생하는 가장 흔한 원인 중 하나는 데이터베이스 조회입니다. 특히 동일한 데이터를 반복적으로 조회하거나, 복잡한 연산이 필요한 데이터를 매번 새로 계산하는 것은 시스템 전체의 성능을 크게 저하시킬 수 있습니다. 이런 문제를 해결하기 위한 핵심 기술이 바로 캐싱입니다. 캐싱이란 무엇인가캐싱은 자주 사용되거나 계산 비용이 높은 데이터를 임시로 저장해두었다가, 동일한 요청이 들어올 때 빠르게 응답할 수 있도록 하는 기술입니다. 데이터베이스 조회 대신 메모리에서 데이터를 가져오므로 응답 속도가 현저히 빨라집니다. Redis란Redis(Remote Dictionary Server)는 메모리 기반의 키-값 저장소로, 다음과 같은 특징을 가지고 있습니다.인메모리 데이터.. 더보기 Spring Boot에서 RestTemplate 내부 API 호출 시 JWT 토큰 전달하기 문제 상황Spring Boot 프로젝트에서 한 도메인이 다른 도메인의 API를 호출할 때 발생할 수 있는 인증 문제를 해결한 경험을 공유하고자 합니다. 프로젝트 구조HotDeal API 서버 (localhost:8080)├── Stock Domain (재고 관리)├── Product Domain (상품 관리) └── Auth Domain (인증/인가) 발생한 문제재고 관리 API에서 상품 검증을 위해 상품 조회 API를 호출하는 상황에서 에러가 발생했습니다. 문제 분석핵심 문제: RestTemplate을 통한 내부 API 호출 시 원본 요청의 JWT 토큰이 전달되지 않음해결책 비교방법 1: 매번 수동으로 토큰 전달public SearchProductResponse getProduct(Long produ.. 더보기 도메인 간 의존성 낮추기 : API 호출 및 스프링 이벤트 구독을 위한 Common 패키지 설계 문제 상황: 도메인 간 강한 결합프로젝트가 커지면서 도메인 간 협력이 복잡해졌습니다.1. API 호출 중복// EventService.java - 상품 정보 조회private List productSearch(List productIds) { // 13줄의 RestTemplate 코드...}// OrderService.java - 또 상품 정보 조회 private List productSearch(List productIds) { // 거의 동일한 13줄 코드 반복...}// SubscribeService.java - 또또 상품 정보 조회private SearchProductResponse getProductInfo(Long productId) { // 또 다른 형태의 RestTempl.. 더보기 이전 1 2 3 4 ··· 14 다음