Project (16) 썸네일형 리스트형 Kakao API를 사용하여 키워드로 장소 검색하기 1. 왜 Kakao API를 썼는가?오먹추 프로젝트의 목표는 사용자의 음식 선택을 도와주는 추천 기능을 만드는 것이었다.이때 가장 중요했던 건 장소 정보였다.예를 들어 사용자들이 '김밥', '떡볶이'처럼 투표한 메뉴를 기반으로 사용자 주변에 있는 관련 식당들을 알려줘야 했다. 그래서 생각났던 것이 Kakao Maps였는데 한국 기반 서비스 + 개발 문서가 깔끔 + 손쉬운 REST API를 제공 해서 선택을 하게 되었다.2. 연동을 위한 사전 준비개발자 등록 & 키 발급Kakao Devlopers 접속로그인 후 내 애플리케인션에서 애플리케이션 추가하기왼쪽 대시보드에 앱 설정 -> 앱 키에 들어가서 REST API 키 사용3. Kakao API 호출을 위한 Client 클래스일단 Kakao Maps의 키워드.. 복합 유니크 제약 조건의 필요성 1. 문제상황오먹추 프로젝트에서 "사용자가 하루에 한 번 특정 카테고리의 메뉴에만 투표할 수 있다"는 요구사항이 있었다.예를 들어 BREAKFAST 카테고리에서 투표는 1번만 진행 가능, 하지만 LUNCH 때는 투표를 다시 1회 가능.그래서 다음과 같은 제약을 의도했다한 유저는 하루에 한 번만 투표할 수 있어야 한다같은 날 같은 카테고리에 중복 투표가 불가능해야 한다.왜 이 제약 조건이 중요한가?예를 들어 오먹추에서 투표 결과를 집계할 때 user_id + category + vote_date가 중복되면 잘못된 순위 계산이나 추천 음식의 왜곡이 발생할 수 있다. 처음엔 이 제약을 서비스 로직에서만 체크했다.if (voteRepository.existsByUSerIdAndCategoryAndVoteDate.. Spring Security와 JWT로 로그인 구현하기 1. 왜 JWT와 Spring Security를 선택했는가?프로젝트에서 인증 기능이 필요했고, 다음 한 가지 조건이 있었다.프론트엔드 없이 백엔드 단독으로도 테스트 가능한 인증 방식이 필요했다.그래서 내가 선택한 방법은 Spring Security + JWT를 직접 구현하는 구조였다.세션을 서버에 저장하지 않아도 되니 구조가 단순해졌다. 2. 세션이나 쿠키를 사용하지 않은 이유는?이유1 : 백엔드 단독 실행 및 테스트의 편의성프론트 없이 Postman, Swagger 등에서 직접 요청을 보낼 수 있어야 했다.세션 기반 인증은 보통 쿠키 기반 요청을 전제로 하므로 브라우저 기반에서 테스트가 편하지만, Postman에서 매번 JSESSIONID를 수동 저장하거나 쿠키를 관리해야 함.이유2 : 서버가 상태를 .. 스프링 프로젝트에서 공통 응답 + 페이징 + 전역 예외처리 1. 통일된 응답 포맷 만들기 : ApiResponseAPI 마다 응답 형태가 다르면 프론트 개발자는 매번 if (response.data) {...}else if (response.content) {...}이런 식으로 응답을 파싱해야 한다. 그래서 프로젝트에서는 모든 응답을 하나의 포맷으로 통일하기로 했다.{ "status" : 200, "message" : "성공 메시지", "data" : {...}}해결 방법 : 제네릭 기반 응답 래퍼 만들기@AllArgsConstructorpublic class ApiResponse { private int status; private String message; private T data; public static ApiRe.. 결제 시나리오 3. 악의적 선점 - 데이터 정합성 문제(2) 문제 상황이전 트러블 슈팅을 통해 스케줄러가 조회한 후 결제 상태가 변경되었을 가능성을 고려하여 최신 상태를 다시 조회하는 로직을 추가함으로써 데이터 정합성 문제를 해결할 수 있었습니다.그러나 여전히 결제 승인 요청과 스케줄러가 동시에 실행되는 경우 아주 짧은 시간 간격으로 정합성이 깨질 가능성이 남아있었습니다.→ 여전히 발생할 수 있는 문제사용자가 9분 5x초에 결제 진행 → CONFIRMING 상태로 변경동일한 시점에 스케줄러 실행 → 기존 IN_PROGRESS 상태를 조회 후 취소 처리 시도스케줄러가 findById()로 최신 상태를 다시 조회했지만, 아주 미세한 타이밍 차이로 CONFIRMING 상태 변경이 반영되기 직전이면 여전히 취소 진행결제 승인 요청이 완료되었음에도, 결제 내역이 취소되는 .. 결제 시나리오 3. 악의적 선점 - 데이터 정합성 문제(1) 문제 상황Spring Scheduler를 활용하여 10분이 지난 IN_PROGRESS 상태의 결제를 자동으로 취소하는 방식으로 구현하면서 트러블 슈팅이 발생했습니다.(악의적 사용자가 아닌)일반 사용자가 어떠한 사유로 9분 5x초에 결제를 진행하면 결제 요청과 스케줄러의 실행이 동시에 이루어질 수 있습니다. 이로 인해 실제 결제는 성공했지만 시스템에서는 결제가 취소되는 데이터 정합성 문제가 발생했습니다.[문제 상황 설명]사용자가 결제 페이지에 진입Payment 상태 : IN_PROGRESS사용자는 결제 정보 입력 후, 9분 5x초에 결제 진행TossPayments에 결제 요청TossPayments에서 /success 엔드포인트로 PaymentKey, orderId, amount(가격) 정보와 함께 POST.. 결제 시나리오 3. 악의적 예약 선점 배경악의적인 사용자가 여러 좌석을 선점한 후 결제를 진행하지 않을 경우 다른 이용자가 좌석을 예약할 수 없는 심각한 문제가 발생할 수 있습니다. 이를 해결하기 위해 결제 대기 상태에서 일정 시간이 지나면 자동으로 예약이 취소되는 시스템을 구현해야 합니다.선택지[RabbitMQ를 활용한 방법]RabbitMQ는 메시지 브로커로 TTL과 DLQ(Dead Letter Queue) 기능을 활용하면 메시지를 특정 시간 동안 보관하고, 시간이 지나면 자동으로 만료되도록 설정할 수 있습니다.구현 방식사용자가 항공권을 예매하면 예약 메시지를 RabbitMQ의 큐에 저장하며 TTL을 설정하여 N분 후 자동 만료되도록 설정TTL이 만료되면 메시지는 Dead Letter Queue로 이동DLQ에서 메시지를 감지한 Consum.. 결제 시나리오 2. 중복 결제 방지 배경중복 결제에 대해 고민을 하게된 이유는 처음 결제 시스템을 개발할 때 중복 결제가 실제로 발생할 가능성이 있을까? 라는 질문에서 시작했습니다. 아직 서비스가 운영되지 않았기 때문에 실제 사례는 없었지만 한 번이라도 중복 결제가 발생하면 사용자 신뢰도에 치명적인 영향을 미칠 수 있다 생각했습니다.결제는 단순한 API 호출이 아니라 사용자의 돈이 직접적으로 움직이는 중요한 프로세스 입니다. 따라서 이런 문제가 발생할 수도 있다는 가정만으로도 사전 대비가 필요했다고 판단했습니다.특히 토스페이먼츠를 연동하는 과정에서 짧은 시간 안에 동일한 결제 요청이 여러 번 들어올 경우 어떻게 처리될까? 라는 의문이 들었습니다.사용자가 실수로 결제 버튼을 여러 번 클릭하면?네트워크 지연으로 인해 서버가 응답을 받지 못하고.. 이전 1 2 다음