본문 바로가기

전체 글

(19)
👀 @TransactionalEventListener: 학습테스트로 동작 방식 확인해보기 트랜잭션이 롤백될 때 발행된 이벤트를 처리하지 않도록 하여 문제를 해결했다. 하지만 문제 해결에 그치고 싶지 않았고 사용했던 @TransactionalEventListener 어노테이션의 동작 방식을 더 깊게 학습하고 싶었다. 그 여정을 공유하는 글이다. @TransactionalEventListener 이벤트 처리 시점아래와 같이 @TransactionalEventListener 어노테이션의 phase 옵션을 통해 이벤트가 처리되는 시점을 지정할 수 있다.BEFORE_COMMIT트랜잭션이 커밋되기 이전에 이벤트를 처리한다.AFTER_COMMIT트랜잭션이 성공적으로 커밋된 후 이벤트를 처리한다. (default)AFTER_ROLLBACK트랜잭션이 롤백될 때 이벤트를 처리한다.AFTER_COMPLETION..
트랜잭션이 롤백될 때 이미 발행된 이벤트를 어떻게 처리할까: @TransactionalEventListener 1. 문제: 발행된 이벤트는 무조건 처리된다.동시성 이슈를 해결하기 위해 낙관적 잠금을 구현하고 있었다. 충돌을 방지하기 위해 낙관적 잠금을 걸게 되면 애플리케이션 단에서 버저닝 필드를 검증한다. 그 후 버저닝 필드가 일치하지 않으면 트랜잭션 충돌로 판단하여 아래와 같이 낙관적 잠금 예외를 발생시키게 된다. 이 예외는 트랜잭션이 커밋되는 시점에 발생하는데, 그렇다면 예외가 발생해 트랜잭션이 롤백된다면 트랜잭션 내부에서 이전에 발행된 이벤트는 어떻게 처리될까? 총대마켓의 기존 코드에서는 트랜잭션이 롤백되어도 이미 발행된 이벤트는 실행되었다. 즉, 사용자가 참여하려고 할 때 공동구매가 마감되어 참여하지 못했는데(동시성 이슈로 인한 트랜잭션 롤백), "에버님이 공동구매에 참여했어요!"라는 알림이 전송(이벤트 ..
동시성 이슈 해결 과정: 트랜잭션 격리 수준, 낙관적 잠금, 비관적 잠금 문제 상황채팅방 목록을 조회할 때 500 예외가 반환되어 데이터가 조회되지 않고 앱에서 빈 화면이 출력되었습니다.LoggingErrorResponse[identifier=ceedb3fa-300d-4ee4-852d-c9d83826132e, memberIdentifier={"sub":"1010","exp":1729660386}, httpMethod=GET, uri=/comments, requestBody=, statusCode=500, errorMessage=, latency=24ms, stacktrace=org.springframework.dao.IncorrectResultSizeDataAccessException: Query did not return a unique result: 2 results we..
FCM 푸시알림 트러블슈팅: 비동기 처리로 동시성 이슈 방지하기 상황 성공적으로 푸시알림 기능을 구현하였습니다. 2024.11.20 - [우아한테크코스 6기] - [프로젝트] FCM 푸시알림 도입기 | 백엔드 자바 [프로젝트] FCM 푸시알림 도입기 | 백엔드 자바상황공동구매 서비스 '총대마켓'에는 총대와 여러 참여자가 소통하는 채팅방이 있습니다. 하지만 서비스 초기에 알림 기능을 MVP로 보지 않았기 때문에, 채팅을 전송해도 알림을 수신하지 못하helenason.tistory.com ..인 줄 알았으나 QA 과정에서 두 가지 문제를 발견하였습니다.유효하지 않은 기기 토큰에 대한 예외API 중복 호출, 일명 `따닥` 문제위 두 가지 문제 원인을 파악하고, 해결 과정까지 공유하겠습니다. 그중에서도 두 번째 문제인 `따닥` 문제를 비동기로 해결한 과정을 중점적으로 포스팅..
FCM 푸시알림 도입기 (with 안드로이드 코틀린 & 백엔드 자바) 상황 공동구매 서비스 '총대마켓'에는 총대와 여러 참여자가 소통하는 채팅방이 있습니다. 하지만 서비스 초기에 알림 기능을 MVP로 보지 않았기 때문에, 채팅을 전송해도 알림을 수신하지 못하는 상황이었습니다. 직접 총대마켓의 사용자가 되어 거래를 진행해 본 결과, 아래 불편함이 크게 다가왔습니다.- 즉각적인 소통이 어려워, 거래 날짜와 장소를 빠르게 확정할 수 없다.- 거래의 진행 상황과 참여 사실을 앱에 접속하지 않는 이상 알기 어렵다.- 채팅 확인을 위해 불필요하게 앱에 접속하는 상황이 많아지거나, 반대로 앱에 접속하지 않게 된다. 위 불편함을 이유로 푸시알림은 해당 시점에 꼭 필요한 기능이라고 생각했습니다. 하지만 다른 팀원들은 우선순위가 높은 기능이라고 생각하지 않거나, 많은 리소스 투여로 구현 시..
쿼리 최적화와 인덱스로 API Latency 30배 개선하기 문제 총대마켓 서비스의 메인페이지 필터링 및 검색 조회 API Latency가 100만 건 더미데이터 기준, 약 25초에 근접했습니다. 사용자가 메인페이지에서 30초간 아무런 데이터도 확인할 수 없는 것과 마찬가지죠. 조회 성공 시 API Latency 약 23초2024-10-10 20:35:23 [http-nio-8080-exec-4] INFO c.z.c.l.config.LoggingInterceptor - LoggingInfoSuccessResponse[identifier=e472b64f-5b04-4ce4-ab08-0c96c43fdd45, memberIdentifier=Not Found, httpMethod=GET, uri=/read-only/offerings, requestBody=, status..
인덱스는 만능인가 이 글은 인덱스가 무엇인지 아는 독자를 타겟으로 작성하였으며, MySQL을 기준으로 설명합니다. 목차인덱스란인덱스는 데이터를 어떻게 탐색할까인덱스 성능 비교인덱스 적용 실패 사례알게된 점 인덱스는 테이블 조회 성능 개선에 유용하다. 누구나 이론적으로 이해하고 있는 인덱스의 장점입니다. 하지만 저는 아직 이 장점을 체감하지 못했습니다. 많은 데이터를 관리한 경험이 없기 때문입니다. 따라서 직접 1억건의 데이터를 쌓고 실험해보고자 합니다. 그 여정을 여러분께 공유합니다. 인덱스란인덱스는 데이터베이스에서 데이터를 효율적으로 검색할 수 있도록 도와주는 데이터 구조입니다. 일반적으로 테이블의 컬럼에 대해 설정되며, 해당 컬럼을 기준으로 데이터의 위치를 빠르게 찾을 수 있게 합니다. 아래는 MySQL 공식문서에서 ..
개발 환경 CI/CD 파이프라인 구축기 | Github Actions, Self-hosted Runner, Docker 기술 선택 이유 CI/CD 필요성작년 여름 참여했던 북링크 프로젝트에서, 백엔드 코드에 변경 사항이 발생할 때마다 깃허브 pull, 빌드, 서버 내리고 올리기 과정을 반복했다. 모든 자잘한 작업들을 수동으로 진행했기 때문에 명령어를 입력할 때 잦은 실수가 있었고, 가끔은 배포 과정을 잊어 프론트엔드 팀원들에게 미안한 상황도 종종 발생했다. CI/CD에 무지했기 때문에 발생했던 불편함이었다. 덕분에 지속적으로 코드를 통합하고 배포하는 과정이 꼭 필요함을 체감했다. 이번에 진행하는 총대마켓 프로젝트에서는 실수를 줄이기 위해 배포를 자동화해보자!사용 기술Github Actions + Self-hosted RunnerDockerGithub Actions 선택 이유총대마켓 서비스가 Github Actions를 CI/CD 구축 도..