Spring Boot 4에서 외부 API 호출 무엇을 선택해야 할까?
·
Spring Boot
Spring Boot에서 외부 API를 호출해야 하는 경우 RestClient vs WebClient vs Feign Client vs WebFlux 중 무엇을 선택해야 좋을지 궁금해서 끄적여 보았습니다. 1. RestTemplate은 왜 고려하지 않는지?과거에는 RestTemplate이 기본 선택이었습니다. 하지만 현재는 유지보수 모드이며, Spring 공식 문서에서도 신규 프로젝트에서는 사용을 권장하지 않음따라서 Boot 4 기준에서는:RestTemplate → 구버전RestClient / WebClient / Feign Client / WebFlux → 사용 권장 2. RestClient란?RestClient는 Spring Framework 6.1부터 도입된 최신 동기 HTTP 클라이언트..
왜 UUID v7을 선택했는가? (Snowflake와 비교까지)
·
Spring Boot
대부분의 프로젝트는 기본 키로 다음 중 하나를 사용한다.AUTO_INCREMENT (Long)UUID v4 (랜덤)Snowflake (시간 기반 64bit ID)이번 프로젝트에서는 Postgres + Hibernate 환경에서 UUID v7을 선택했다.왜 굳이 v7을 선택했는지, 그리고 Snowflake와는 무엇이 다른지 정리해본다. 기존 UUID v4의 문제점 UUID v4는 완전 랜덤이다.550e8400-e29b-41d4-a716-446655440000장점충돌 확률 거의 없음분산 환경에서 안전중앙 서버 불필요단점완전 랜덤 → B-Tree 인덱스에 불리insert 시 page split 빈번인덱스 단편화 발생대량 트래픽 환경에서 성능 저하Postgres나 MySql 기본 인덱스는 B-Tree라 ..
🚚 허브 간 최단 경로 탐색 캐시 스탬피드 (Cache Stampede) 발생+해결
·
Spring Boot
이전 문제 상황출발지와 목적지 사이 허브 간 경로를 다익스트라 알고리즘으로 선정 후, Kakao Api를 호출해 허브 간 소요 시간 산출이때 Kakao Api 응답을 기다리는 방식의 경우 16 ~ 20 초의 많은 시간이 걸림 첫 번째 해결- Redis를 도입하여 TTL 5분이 지나지 않은 값은 Redis에 값을 꺼내 사용 (Redis TTL 5분, DB TTL 10분)- Redis TTL 5분이 지난 경우 DB 조회 후 Redis에 값 갱신 (이때 우선 Redis에 갱신 후 Kakao Api를 호출하여 최신 값으로 갱신)- Redis와 DB 모두 값이 없는 Cold Start의 경우 Kakao Api 호출 후 값 갱신 RedisHubEdgeCache@Component@RequiredArgsConstr..
라즈베리파이에 Loki + Grafana로 로그 수집 시스템 구축하기
·
Infra/LogBack
문제기존에는 EC2 환경에서 ELK 스택을 사용해 로그를 수집하고 있었다.하지만 개인 프로젝트와 홈 서버 성격의 서비스까지 포함되면서 다음 문제가 발생했다.ELK는 메모리 사용량이 너무 큼라즈베리파이의 RAM 용량은 4~8GB이지만 ELK를 가볍게 띄워도 3~4GB가 소요됨라즈베리파이의 디스크 IO 성능 제한 지금 환경에서 ELK는 기능은 충분하지만, 너무 무거우므로 “가벼운 로그 수집 시스템”이 필요하다.서비스별 로그 흐름 파악장애 발생 시 빠른 원인 추적저사양 환경에서도 안정적으로 동작운영 부담이 적을 것 Loki + Grafana + Promtail 조합기존 로그 시스템과 달리 로그 본문을 인덱싱 하지 않고 로그에 붙은 라벨(Label)만 인덱싱하는 구조메모리 사용량이 낮고디스크 IO 부담이 ..
🚚 허브 간 최단 경로 탐색 알고리즘 구현 + Kakao Map Api 연동 (Spring Boot)
·
Spring Boot
물류 관리 및 배송 시스템을 위한 MSA 기반 플랫폼 개발 프로젝트로 물류 관리 및 배송 시스템을 만들게 되었다. 그중 hub 파트를 맡게 되어 사용자가 주문을 완료하여 배송이 시작되면 특정 허브에서 도착 허브까지 가장 빠르고 효율적인 경로를 찾아 응답해 주는 코드를 구현해야 한다.처음에는 거리만 기준으로 정렬하는 단순 탐색을 고려했지만, 실제 배송에서는 다음 요소들을 모두 고려해야 했다. 즉 가중치 기반 최단 경로 문제였고, 자연스럽게 다익스트라(Dijkstra) 알고리즘을 채택하게 되었다.이동 거리 (distance)소요 시간 (duration)출발지의 위도 경도값, 도착지의 위도 경도값을 Kakao Map Api에 경로 탐색을 요청해 응답을 받아오며, 해당 결과가 있는 상태에서 동일 경로 탐색이 ..
DDD의 페이징 로직 (Spring Boot)
·
Spring Boot
문제 발생 - 헥사고날 아키텍처와 DDD 기반으로 허브 서버를 개발하면서, 페이징 로직을 어떻게 가져가야 할지에 대한 고민이 생겼다.- Spring Data JPA가 제공하는 Pageable, PageRequest, Page 같은 페이징 타입들은 매우 강력하고 편리하지만, 도메인 계층에 노출시키기에는 기술 의존성이 크다는 문제가 있다.- 도메인 계층에 그대로 사용하기에는 기술 의존성이 크다. 문제 예시- 헥사고날 아키텍처에서 도메인은 비즈니스 규칙만 알고 있어야 하고, 프레임워크나 기술에 종속되면 안되지만 페이징을 구현하려다 보니 자연스럽게 아래와 같은 코드가 만들어졌다.- Hub Repository 인터페이스에서 Page를 사용하게 된다면 도메인 부분이지만 Jpa에 의존하는 문제가 됨- 도메인은..
Spring Boot + Logback 구조적 JSON 로그 만들기 (Logging - 2)
·
Infra/LogBack
지난 글에서 Raspberry Pi + Elasticsearch + Kibana 환경을 기반으로 로그 분석 환경을 구축한 이유와 설치 과정을 다뤘다.이번 글에서는 스프링 애플리케이션에서 발생하는 로그를 Kibana가 이해할 수 있는 JSON 형식으로 변환하고, 모든 요청 로그에 TraceId를 자동 포함시키는 방법을 정리해보려 한다. 로그를 “정형화”해야 하는 이유 Spring Boot의 기본 로그는 다음과 같은 단순 문자열(Log Line) 형태이다:2025-11-21 13:11:02 INFO OrderService - 주문 생성 완료 user=100, order=50021 이러한 기본 방식에는 여러 문제점이 존재1. 검색의 어려움2. 에러 원친 추적 어려움3. MSA 같은 다중 서버 환경에 비효..
FileBeat를 활용해 로그 전송 (Loggin - 3)
·
Infra/LogBack
로그를 시각화하고 중앙에서 모니터링하려는 목적에서 Elasticsearch, Kibana을 사용한 로그 수집 및 시각화 시스템을 구축하려고 한다. 이를 위해, Spring 서버에서 생성된 로그를 통일화하여 ELK 시스템에 전송하는 두 가지 방법을 고려하였다. 방법 1: Spring → Logstash TCP 직결 Spring 애플리케이션에서 생성된 로그를 Logback을 사용하여 직접 TCP를 통해 Logstash로 전송하고, Logstash는 해당 로그를 받아 Elasticsearch에 삽입하는 방식구성:Spring에서 생성된 로그는 logback.xml 또는 logback-spring.xml에서 설정된대로 TCP를 통해 Logstash에 전달Logstash는 TCP로 받은 로그를 처리하고, 이를 J..
특정 이벤트 발생 시 Discord 실시간 알림 시스템 (Spring Boot)
·
Spring Boot
문제 발생특정 사용자가 질문을 위해 고객센터에 문의 게시물이 작성한다면 빠른 답변을 위해 관리자에게 알리는 알람을 울리는 알람 기능이 필요했다. 처음에는 웹 안에서 로그인 한 관리자에게 알림이 발생되게 구현했지만, 관리자가 페이지에 접속해야 알림을 확인해야만 하는 단점이 있어 실시간 모니터링이 불가능해 답변 지연이 잦아졌다. 원인 분석 관리자 접속 흐름의 비효율성 - 관리자는 페이지에 항상 접속해야만 문의 여부를 파악할 수 있음- 문의 답변을 위해서 24시간 모니터링은 사실상 불가능 관리자 알림 시스템 부재- 문의가 생성되었을 때 핸드폰으로 알림이 가는 기능이 없음- 이메일 기반 알림만으로는 반응 속도가 느리고 실시간성이 떨어짐 해결책 문제를 해결하기 위해 다음과 같은 방법들은 고민했다.방식..
Redis로 Refresh Token 검증 (Spring Boot)
·
Spring Boot
왜 Refresh Token을 사용하는가 JWT Access Token의 경우 토큰 자체에 인증 정보를 담고 있어 유출 위험이 있으므로, 5 ~ 15분 등 짧은 유효 기간을 가짐AccessToken만 사용하면 짧은 유효 시간에 따라 자동 로그아웃되어 재로그인을 자주 해야 하는 불편함 발생이러한 문제를 해결하기 위해 Access Token이 만료될 시 Refresh Token을 이용해 Access Token을 재발급Refresh Token은 며칠 ~ 일주일 등 긴 유효 기간을 가지므로 사용자는 로그인 상태를 오래 유지 가능해 편의성을 얻게 된다.예시 : 사용자는 앱을 껐다 켜도 백그라운드에서 토큰이 자동 갱신되어 재로그인 화면이 뜨지 않음 구현한 동작 방식첫 로그인 성공 시 AccessToken은..