728x90

springboot 15

[Backend] 유저 프로필 모듈 구현5편: 응답 DTO 최적화와 Kafka 연동 흐름 정리

유저 프로필 기술 블로그 5편: 응답 DTO 최적화와 Kafka 연동 흐름 정리1. UserProfileResponse DTO란?유저의 공개 프로필 정보를 클라이언트에게 전달할 때 사용하는 응답 객체이다.@Getter@Builderpublic class UserProfileResponse { private Long userId; private String nickname; private String profileImageUrl; private String introduction; private String gender; private String location; private List genres; private List interests;}장르 및 관심사는 ..

BindProject 2025.06.23

[Backend] 유저 프로필 모듈 구현4-1편 N+1 문제 완전 정복: 유저 프로필 조회 최적화 여정

## 들어가며유저 프로필 조회 기능은 필터 조건이 다양하고, 관심사/장르 같은 N:M 관계가 얽혀 있어 **쿼리 성능 이슈가 빈번히 발생**합니다. 이 글에서는 실무에서 자주 마주치는 **N+1 문제**를 집중 분석하고, **QueryDSL + 페이징 최적화 전략**을 통해 이를 어떻게 극복했는지 상세히 설명합니다.## 1. N+1 문제란?> 엔티티 A를 1번 조회한 뒤, 관련된 B 엔티티를 N번 추가 조회하는 현상### 예시 상황```javaList profiles = userProfileRepository.findAll();for (UserProfile profile : profiles) { for (UserInterest interest : profile.getUserInterests()..

BindProject 2025.06.23

[Backend] 유저 프로필 모듈 구현4편 - DSL 기반 검색 기능과 응답 모델 설계

목차도입 - DSL을 선택한 이유전체 아키텍처 흐름DSL 쿼리 설계응답 모델 구조페이징 최적화 방식정리 및 다음 편 예고1. 도입 - DSL을 선택한 이유우리는 사용자 프로필을 다음 조건들로 검색해야 합니다:닉네임 (like 검색)성별지역관심사 (Instrument)선호 장르 (Genre)이러한 조건은 모두 **선택적(optional)**이고, 동시에 다중 값도 허용됩니다. 이를 만족하기 위한 쿼리 조건 생성과 join이 필요한데,Spring Data JPA의 기본 Repository만으로는 아래와 같은 제약이 있습니다:방식장점단점Method Query간단한 조건 처리복잡한 조합 불가Specification동적 조합 가능연관 관계 Join Fetch 어렵고 DSL보다 VerboseQuerydsl타입 안정..

BindProject 2025.06.23

[Backend] 유저 활동 로그 수집 모듈 개발기 5편 : 마무리 회고

도입앞선 글들에서는 Outbox 패턴을 통한 신뢰성 있는 로그 발행, Kafka 기반 로그 수집 처리, 그리고 분석 최적화를 위한 수신 시스템 설계까지 다루었습니다.이제 마지막으로, BFF 모듈에서의 로그 발행 흐름과 전체 서비스 구성 흐름을 정리하고 마무리하겠습니다.BFF에서의 로그 발행 흐름클라이언트 요청이 들어오면, 다음과 같은 구조로 로그를 발행합니다.@Slf4j@RestController@RequiredArgsConstructorpublic class PostController { private final LogEventPublisher logPublisher; @GetMapping("/posts/{id}") public ResponseEntity getPost(@PathVari..

BindProject 2025.06.22

[Backend] 유저 활동 로그 수집 모듈 개발기 3편 : 로그 메타데이터 구현

1. 도입: 단순 로그를 넘어서서비스에서 유저가 어떤 행동을 했는지를 기록하는 건 단순한 기능 같지만, 실제로는 시스템의 인사이트와 회복력을 좌우하는 핵심 관측 지표가 된다. 예를 들어 다음과 같은 시나리오를 상상해보자.어떤 유저가 로그인에 실패한 후 탈퇴 페이지로 이동한다.게시글을 클릭했는데 500 에러가 발생한다.예약 시스템에서 요청이 들어왔으나 Kafka에 전송되지 않았다.이런 상황을 파악하기 위해선 단순한 “누가 무엇을 했다” 수준의 로그로는 부족하다. 우리는 유저의 행동을 시간, 플랫폼, 처리 결과 등 **맥락(Context)**과 함께 수집해야 한다.2. 로그 시스템 설계 목표이번 로그 수집 시스템은 다음의 목표를 달성하고자 설계되었다:항목설명표준화로그 데이터에 공통적으로 포함되어야 할 필드를..

BindProject 2025.06.22

[Backend] 유저 활동 로그 수집 모듈 개발기 2-2편 :Kafka 전송 최적화를 위한 배치 전송 구조 개선기

설계 동기앞서 1편에서는 boolean 기반 sent 필드로 Kafka 전송 여부를 관리하는 기존 구조의 한계를 진단했습니다. 특히 다음 세 가지 문제를 해결하고자 리팩토링이 시작되었습니다:전송 결과의 모호함: 실패와 성공을 구분할 수 없음재시도 전략 부재: Kafka 전송 실패 시 복구 불가배치 최적화 미흡: Kafka로 단일 이벤트를 순차 처리 → TPS 병목설계 목표이번 개선의 핵심 목표는 다음과 같습니다.목표 항목개선 전개선 후상태 표현 방식boolean sentenum OutboxStatusKafka 전송 전략단일 전송배치 전송 + 상태 기반오류 처리실패 감지 불가실패 정보 저장 및 재시도 가능전송 주기없음스케줄러로 관리삭제 정책수동 삭제SENT + 시간 조건 기반 자동 삭제상태 모델링 - Ou..

BindProject 2025.06.21

[Backend] 유저 활동 로그 수집 모듈 개발기 2-1편 : Kafka Outbox 패턴 기반 유저 활동 로그 수집기 리팩토링기(문제 확인)

도입서비스에 유저 활동 로그를 남기기로 결정한 이후, 나는 곧 중요한 딜레마에 부딪혔다. "유저 활동 로그는 쓰기 트래픽이 압도적으로 많고, 유실되어서는 안 되며, 속도도 중요하다." 이 세 가지 요구사항을 만족하기 위해 기존 Outbox 구조를 되돌아보게 되었다.기존의 Outbox는 단건 이벤트를 즉시 저장하고, Kafka로 전송하는 방식으로 구성되어 있었다. 하지만 로깅 시스템은 본질적으로 다르다. 수많은 작은 이벤트가 순식간에 쏟아지기 때문에, 기존 구조로는 병목이 생기고, 네트워크 사용량 또한 비효율적으로 늘어난다.기존 Outbox 구조의 한계초기 Outbox 구조는 단순하고 직관적이다.OutboxEventEntity에는 sent: boolean만 존재Kafka 전송은 개별 이벤트 단위상태 관리나..

BindProject 2025.06.21

[Backend] 유저 활동 로그 수집 모듈 개발기 2편 – 메모리 버퍼 기반 로그 수집기 설계와 구현

1. 도입 – 로그를 Kafka로 바로 보내면 안 되는 이유1편에서 우리는 왜 유저 활동 로그를 수집해야 하는지, 그리고 Kafka를 도입하기로 결정한 이유를 설명했다.하지만 Kafka를 도입한다고 해서 모든 게 해결되진 않았다.유저 요청이 올 때마다 Kafka로 바로 전송한다면?요청 응답 속도에 영향을 줄 수 있다.Kafka에 대한 의존성이 높아지며, 장애에 취약해진다.로그가 수백 TPS로 들어오는 경우, Kafka 자체도 부하를 받는다.그래서 우리는 메모리 버퍼 기반 로그 수집기를 직접 만들기로 했다.2. 설계 목표 – 단순히 "버퍼에 쌓기"가 아니다우리가 만든 수집기는 단순한 List 저장소가 아니다.아래 세 가지 요구사항을 만족해야 했다.1. 로그 유실 없이, 빠르게 저장→ 버퍼는 비동기로 데이터..

BindProject 2025.06.21

[Backend] 유저 활동 로그 수집 모듈 개발기 1편 유저 활동 로그 수집기 구상하기

"왜 우리는 로그 수집기를 직접 만들기로 했을까?"1. 도입플랫폼이 성장하고 트래픽이 늘어나면서, 단순한 서버 로그만으로는 부족해지는 순간이 온다.우리는 사용자와 플랫폼 간의 상호작용을 정밀하게 추적하고 싶었다.사용자가 어떤 합주실을 둘러보는지어떤 경로로 예약까지 이어지는지비정상 요청이 반복되는 경로는 어디인지이 모든 것을 알기 위해선, 단순 로그가 아닌 행동 기반 이벤트 수집기가 필요했다.2. 설계 목표처음부터 무리한 대시보드나 통계 시스템을 만들 생각은 없었다.우리의 목표는 다음 세 가지였다.유저의 주요 활동을 놓치지 않고 수집한다플랫폼 장애나 지연에도 유실되지 않도록 설계한다추후 분석 시스템과도 유연하게 연동할 수 있게 한다→ 이 목표를 만족하기 위해선,단순한 DB INSERT 또는 파일 로깅 방식..

BindProject 2025.06.21

[초안] 합주실 탐색 기능의 설계: 정렬에서 표기로, 현실적인 MVP를 위한 선택

1. 도입음악인들을 위한 합주실 예약 플랫폼을 설계하면서, 우리는 사용자들이 합주실 이름, 주소, 이용 가능 시간을 기준으로 손쉽게 탐색할 수 있는 기능이 필요하다는 것을 확인했다.이에 따라, **합주실을 운영하는 관리자(사장님)**가 정보를 등록하고, **클라이언트(사용자)**가 다양한 기준으로 합주실을 탐색할 수 있도록 하는 모듈을 설계하게 되었다.2. 설계 목표운영자 입장: 합주실의 이름, 주소, 연락처, 운영시간, 방(Room) 정보 등을 등록사용자 입장: 특정 시간에 예약 가능한 합주실을, 이름/주소를 기반으로 쉽게 검색MVP 우선: 너무 많은 복잡도를 초기에 가져가지 않도록 기능과 구조를 분리하고, 확장 가능한 형태로 시작3. 초기 고민: 정렬 기준을 어떻게 할 것인가?초기에는 사용자 편의성을..

BindProject 2025.06.20
728x90