Kafka 찍먹해보기! : Kafka통한 서비스 경계를 넘는 이벤트 파이프라인을 구축기
·
Loopers/테크니컬 라이팅
더보기한줄요약 : Spring Boot로 만든 이커머스 API가 단일 애플리케이션의 한계에 부딪혔을 때, Kafka를 도입해서 서비스를 분리하고 확장 가능한 이벤트 파이프라인을 만든 과정을 단계별로 정리했습니다.Kafka가 뭐하는 놈이지 Kafka는 이름만 들어봤는데 한번 어떤방식으로 쓰는지 익히고자 들이박아봤다.@Service public class LikeFacade { @Transactional public void like(Long userId, Long productId, LikeType likeType) { // 1. 핵심 비즈니스: 좋아요 저장 (UPSERT로 중복 처리) int affected = likeRepository.upsert..
Spring 이벤트를 처음 써보며 깨달은 것들
·
Loopers/테크니컬 라이팅
더보기한줄요약 :무거워진 트랜잭션 문제를 해결하려고 Spring ApplicationEvent를 처음 도입하며 겪은 개념 학습, 설정 고민, 기존 로직 변경 과정과 마주친 문제들의 실전 기록문제의 시작: 기존 로직이 점점 무거워지고 있었다.도메인 주도 이커머스 프로젝트를 진행함에 따라 로직이 점점 무거워졌다.주문요청만 해도 5개의 도메인을 사용하고 있었다. @Transactional public Order placeOrder(OrderInfo orderInfo) { // 1. 재고 차감 (Product 도메인) productService.decreaseStock(items); // 2. 포인트 차감 (Point 도메인) pointService.usePoint(user..
DB 조회 및 정렬 성능 개선하기(비정규화, 인덱스, 캐시(Redis))
·
Loopers/테크니컬 라이팅
더보기한줄요약 :데이터가 증가함에 따라 JOIN과 GROUP BY를 사용하던 '좋아요 순 정렬' API의 성능이 급격히 저하되었다.비정규화로 JOIN을 제거하고, 조회 패턴에 맞는 복합 인덱스와 단일 인덱스를 전략적으로 설계하여 DB 정렬 부하(filesort)를 없애고 쿼리 성능을 대폭 개선했다. 문제의 시작: "좋아요 순으로 정렬해주세요" 기존에는 '좋아요' 정보를 가진 likes 테이블과 product 테이블을 JOIN하고, COUNT와 GROUP BY를 사용해'좋아요'가 많은 순서대로 상품을 정렬하는 쿼리를 사용했다.-- 가격순 정렬EXPLAIN SELECT * FROM product WHERE brand_id = 10 AND status = 'ACTIVE' ORDER BY price ASC LI..
동시성 테스트(Flaky Test 삽질기)
·
Loopers/테크니컬 라이팅
더보기한줄요약 :'좋아요 취소' 기능의 동시성 테스트가 간헐적으로 실패하는 'Flaky Test' 현상을 겪으며, '조회 후 삭제(Find-Then-Delete)' 패턴의 레이스 컨디션(Race Condition) 문제를 발견하고, 이를 해결할 방법으로 '소프트 삭제(Soft Delete)'와 낙관적 락을 찾은 일기 입니다.문제의 시작: 변덕스러운 테스트프로젝트에 동시성 제어 로직을 추가하고 자신 있게 전체 테스트를 실행했다. 하지만 결과는 당혹스러웠다. 분명 방금 전까지 단독으로 실행했을 땐 성공했던 '좋아요 취소' 동시성 테스트가, 전체 테스트에서는 실패했다. 더 이상한 건, 전체 테스트를 몇 번을 다시 돌려보면 어떨 땐 또 성공한다는 점이었다.// 문제가 발생했던 테스트 코드@Test@Displa..
뒤늦은 깨달음 Appication VS Domain
·
Loopers/WIL(What I Learned)
🧠 이번 주에 새로 배운 것이전까지 나는 계층형 아키텍처를 단순히 패키지 구조를 나누는 것이라고 막연하게 생각했다. Controller, Service, Repository... 늘 쓰던 구조였지만, "그래서 Service는 정확히 무슨 일을 해야 하는가?" 라고 물으면명확하게 답하기 어려웠다.그런데 이번 주 과제를 진행하면서 갑자기 머리속으로 Application Service와 Domain Service 에 대한 차이 및 역할에 대해생각하게 되었다.(왜 갑자기 각성한 것인지는 나도 잘 모르겠다.. 계속 생각하고 있어서 그런가..?)Application Service트랜잭션 관리, 여러 Repository 호출, DTO 변환 등 하나의 유스케이스 흐름을 조율하는 지휘자 역할.Domainproduct..
Loopers - 2 주차 : 설계
·
Loopers/WIL(What I Learned)
🧠 이번 주에 새로 배운 것 이번주는 코드를 작성하기 앞서 요구사항 명세서, 시퀀스 다이어그램, 클래스 다이어그램, ERD 를 어떤 관점과 고민을 가지고 해야하는지 배운거 같습니다. 요구사항 명세서는 낙관적 케이스, 제약 케이스, 실패 케이스 로 나누어 작성했고 다이어그램과 ERD는 .md 파일의 mermaid를 사용하여 작성했습니다.💭 이런 고민이 있었어요시퀀스 다이어그램을 그릴 때 가장 큰 고민은 "어디까지 표현해야 하는가" 였습니다.Repository 같은 DB 접근 계층까지 모두 그리자니 다이어그램이 너무 복잡해져서 핵심 흐름을 파악하기 어려웠습니다.반대로 너무 많이 생략하면, 중요한 정보를 누락한 부실한 설계처럼 보일까 봐 걱정이 되어'소통을 위한 명확성'과 '설계의 상세함' 사..
다들 이해하지?! 설계의 청사진 시퀀스 다이어그램
·
Loopers/테크니컬 라이팅
더보기한줄요약 : 이커머스 기능 요구사항을 분석하여, 각 도메인의 책임을 나누고 데이터 정합성을 고려한 ERD를 설계하며 겪은 고민과 선택의 과정을 담았습니다. 아이디어를 견고한 설계로 만드는 여정2주차 과제는 만들고 싶은 시나리오를 토대로 설계를 하는것이다.기능 요구명세서, 시퀀스 다이어그램, 클래스 다이어그램, ERD 를 작성하여 개발 전 토대를 만드는 것이다.최근 사용해본것은 ERD 뿐이고 앞의 3개는 한지 오래되서 기억도 잘 나지 않지만 갓-Alen 님의 Q&A 라이브 세션을 토대로 공부하며 해쳐 나가기로 했다. 그중에서 4개의 작업물 중 작업하는데 가장 고민을 많이했던 시퀀스 다이어그램에 대해 말해보고자 한다.시퀀스 다이어그램은 '책임 할당 계획서'다시퀀스 다이어그램을 그리면서 나에게는 한 가..
Loopers - 1 주차
·
Loopers/WIL(What I Learned)
더보기 아아.. 너무 빠른 1주였다... 7월 12일(토) 부터 시작된 루퍼스 생활처음 오프라인 모임에서부터 고수분들의 향기가 느껴진다. Controller - Service - Repository 구조만 알던 나에겐제공해준 템플릿 프로젝트 구조는 충격 그 자체였다.헥..헥사고날.. 아키텍쳐..? , record?, PR, ApiResponse는 또 뭐고 ApiSpec, Spy, Mock..?그 동안 우물안의 개구리였단걸 절실히 느끼고 쭈글쭈글 해졌다. 다행히 흐름은 얼추 때려맞추면서 과제 진행을 했지만 바쁜 1주..모르는건 배우고 적어가면서 따라가야겠다.🧠 이번 주에 새로 배운 것- TDD를 실행하면서 만난 에러를 통해 JPA의 영속성 컨텍스트에 대해서 찾아보는 계기가 되었습니다. 객체가 바로 D..
TDD, 실패하는 테스트가 알려준 것들: 아래에서 내려다보는 TDD
·
Loopers/테크니컬 라이팅
더보기한줄요약 : 테스트를 통과시키기 위해 JPA의 영속성 관리와 트랜잭션 범위, 올바른 예외 처리의 중요성을 깨달은 개발기. 새로운 아키텍처, 그리고 탑다운 테스트최근 새로운 부트캠프 프로젝트를 시작하며 interfaces-application-domain-infrastructure라는계층형 아키텍처를 처음 접하게 되었다. 익숙했던 Controller-Service-Repository 구조와는 사뭇 다른 이 구조에서, '포인트 충전 및 조회' 기능을 구현하는 과제를 받았다. 월요일에 진행한 Alen님의 TDD 라이브 코딩을 보면서 탑다운 방식의 TDD 접근 방식을 흉내 내 보기로 했다. 가장 바깥 계층인 API의 성공 시나리오인 E2E 테스트를 먼저 작성하는 것 부터 시작하였으며 그 중"존재하는 유저가..