전체 글
-
외부 서비스 호출 시 트랜잭션 전략운영 중인 서비스/Leather-Studio 2026. 3. 5. 22:26
배경소분컷 재고 추가 기능을 구현하면서, 외부 서비스(naver-server)를 두 번 호출해야 하는 상황이 발생했다.studio-server → naver-server: 롤 재고 차감studio-server → naver-server: 소분컷 재고 추가이 두 호출은 하나의 논리적 트랜잭션이다. 롤에서 1개를 빼고 소분컷에 N개를 넣는 건 원자적이어야 한다.하지만 외부 서비스 호출은 DB처럼 ROLLBACK 한 방으로 되돌릴 수 없다.문제 정의실패 시나리오시나리오롤 차감소분컷 추가상태정상성공성공OK1번 실패실패미실행변경 없음, 안전2번 실패성공실패데이터 불일치핵심은 "1번 성공 후 2번 실패" 시나리오다. 롤 재고만 줄어들고 소분컷은 그대로인 상태가 된다.고려할 수 있는 옵션1. 단순 예외 전파await..
-
Kafka 로 두 마리 토끼 잡기: 일관성과 처리량Work Experience/차량 위치 및 온도 관제 서비스 2025. 12. 14. 11:58
5일의 워킹데이와 4일의 주말을 통째로 쏟아서 작업한 새로운 아키텍쳐 적용기 입니다! 목차모든 것의 시작은 Loki로부터해결하고자 했던 문제문제 해결과정만났던 문제들고민해볼 내용들1. 모든 것의 시작은 Loki로부터마지막 남은 인프라팀 동료직원이 떠나고,, 최근에 홀로 떠있던 Loki 가 고장이 나버렸습니다.살려도 며칠을 못가도 자꾸 죽기를 반복해서, Loki 컴포넌트들과 데이터 흐름을 뜯어보게 되었는데 뜻밖의 깨달음이 있었습니다. 어? 이거 우리 서비스와 완전 동일한 목적을 위한 아키텍쳐구나! [ Write Path (Ingestion) ] ┌──────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │ Promtail │───▶..
-
확장 가능하면서 단순한 CI/CD를 목표로!운영 중인 서비스/Developer-Growth-Protocol 2025. 11. 27. 23:57
최근에 회사에서 인프라 작업을 하면서, 브랜치로 환경을 나눠서 gitops 관리하는 ci/cd 플로우를 마이그레이션했습니다.환경별로 EKS 클러스터가 나눠져 있어서 격리는 확실하게 되었으나, 여러 레포에 브랜치 명이 달라서 고생했던 경험이 있습니다.고민했던 다른 방식들을 DGP에 적용해봅니다. 1. K8S 환경에서 환경별 운영 전략여러 개의 클러스터를 운영하는 방식으로 환경별로 완벽한 격리를 가져갈 수도 있겠으나, 사용자가 많지 않은 서비스이기 때문에 루트앱을 환경별로 나누고, namespace 수준에서 분리를 해주었습니다. 2. CI/CD 플로우 ArgoCD의 App of Apps 패턴이 편리하다는 느낌이 있어서 적용하려고 합니다.요즘 Github Action 위주의 설정을 너무 많이 사용하기도 했고..
-
홈 서버 구성완!OFF THE RECORD/홈서버 2025. 11. 27. 23:34
컴퓨터를 구매하고 2년이 다 되어서야,, 개인용 서버로 역할을 하게 되었습니다. 1. Overview/16 대역을 기본 의미 단위로 나눠서 구축을 해보았습니다.오른쪽에서부터 첫번째 대역은 on promise 서버 관리와 모니터링을 위한 Devops 대역입니다. 그리고 두번째 대역은 K8S 위에서 서비스 구축을 이어나가기 위한 공간이고, 마지막 공간은 클로드 코드로 빠르게 만들어본 프로젝트를 바로바로 띄워 볼 수 있는 공간으로 꾸려보았습니다ㅎㅎ 2. ArgoCD는 사랑입니다.리소스도 한정적이고, 손도 많이가서 K8S 구성은 꼭 필요하지 않다면 1개의 대역에서만 운영하려고 합니다.그래서 다른 VM 위에 떠있는 애플리케이션들은 도커 컴포즈로 운영하고 있는데, 변경 사항이 생길 때 마다 재실행 해줘야하는..
-
Metal LB 와 Spoofing !OFF THE RECORD/홈서버 2025. 11. 12. 00:40
k8s 설정 중에 어떻게 Metal LB가 어떻게 동작하는지 살펴보고, Spoofing을 직접 구현해 보는 글입니다. 1. 아니 어떻게 응답이 올 수가 있는거지? 이 테스트의 시작은 아래와 같습니다 ㅎㅎ특정 domain으로 들어온 요청을 k8s 로 프록싱 하는데, 실제로 클러스터가 떠잇지 않은 ip로 요청을 보내도록 metal lb가 설정이 됩니다. 아니, 10.0.0.100 에 요청을 날렸는데, 어떻게 10.0.0.5에 떠잇는 Metal LB가 받을 수 있는 것일까요? 아래와 같이 arp 로 누가 Who is 10.0.0.100 이라고 물었더니, 10.0.0.5가 내가 10.0.0.100 이라고 응답하는 상황입니다. 2. Metal LB의 Speaker저는 1개의 마스터와 2개의 워커를 사용해서 ..
-
Type1 하이퍼바이저로 갈아타기OFF THE RECORD/홈서버 2025. 10. 26. 15:56
새롭게 작업하는 서비스들을 운영하기 위해서, 24년 초에 사서 세팅해놓고 사용하지 않고 있던 홈서버를 다시 살려봅니다.당장 띄울 서비스가 많지 않지만, 확장성을 고려하여 OS 위에서 Containered 기반으로 나눠 둔 것을 vm 기반으로 변경하였습니다. 1. Type1으로 전환! ( feat. Proxmox )최근에 회사에서 v2 마그레이션을 위한 Infra를 업무를 진행하였습니다.서비스별로, 환경별로 어떻게 격리를 가져가는게 좋을지 고민을 많이 하였는데,, 회사에서 선택하지 못한 방법을 개인 환경에서 구현해보려고 했습니다. 기존에 Rocky Linux 위에 도커를 사용해서 구성하려고 했던 전략을 버리고, 서비스 단위로 VM을 가져가는 전략을 선택하려고 합니다.사용하지 않게되는 서비스를 정리할 때..
-
레거시 시스템을 안전하게 v2로 마이그레이션하기Work Experience/차량 위치 및 온도 관제 서비스 2025. 10. 25. 23:09
1. "이 코드... 정말 건드려도 될까요?"외주사에서 인수받은 시스템을 살펴보니 예상했던 것보다 상황이 심각했습니다:운영 DB에 테스트용 컬럼들이 혼재되어 있어 어떤 데이터가 실제 서비스용인지 구분이 어려웠습니다스테이징 환경이 부재했고, 실시간 기능을 테스트할 수 있는 방법이 전혀 준비되어있지 않은 상태였습니다복사-붙여넣기로 만들어진 유사한 코드들이 곳곳에 있어서 실제로 사용되는 로직인지 파악하기 힘들었습니다if문으로 연명하는 아슬아슬한 비즈니스 로직들로 인해 작은 수정에도 사이드 이펙트가 우려되었습니다 2. 현실적 제약사항들1. 서비스 연속성의 중요성운영 중인 서비스를 중단할 수 없었습니다. 사용자들이 실제로 이용하고 있는 서비스이기 때문에 다운타임 없는 마이그레이션이 필수였습니다.2. 비즈니스 요..
-
근본적인 문제해결 방법을 고민하기 (feat. NPE)운영 중인 서비스/Developer-Growth-Protocol 2025. 10. 6. 17:26
1. 들어가며DGP(Developer Growth Protocol) 프로젝트에서 UC-03(문제 발송 이력 등록) 유스케이스 테스트를 작성하던 중 흥미로운 문제를 발견했습니다. 테스트는 DomainException을 기대했지만 NullPointerException이 발생했고, 처음엔 Java의 auto-unboxing 문제로 보였습니다. 하지만 깊이 분석해보니 진짜 문제는 시스템 전반의 null 처리 정책 부재였습니다. 2. 문제 상황실패한 테스트@Test@DisplayName("구독자 ID가 null일 때 DELV-SUB-001 에러가 발생해야 한다")void registerDeliveryHistoryWithNullSubscriberId() { // Given: 구독자 ID를 null로 설정 ..