제휴사마다 반복할 기능을 공통화하고, 완료된 인증과 동의를 보존하면서 실패한 작업을 따로 다루는 연동 플랫폼을 개발했습니다. 2인 팀에서 구조 결정과 설계·구현·운영을 맡았습니다.
제휴사 설정 · 동의 조회·철회 · 처리 이력 관리
기간
2026.01 — 2026.06 개발, 이후 운영
팀
2인 팀
역할
설계 · 구현 · 운영 — 구조 결정 담당
제휴가 늘어도 같은 기능을 다시 만들지 않도록
제휴 연동에는 동의를 받는 기능만 있는 것이 아닙니다. 여러 경로에서 들어온 동의를 반영하고, 처리에 실패한 건을 확인하고, 고객에게 약속한 혜택도 전달해야 했습니다. 제휴사가 추가될 때 이 기능들을 다시 만드는 구조는 피하고 싶었습니다.
제휴사별 설정과 공통 처리 기능을 나눠 연동 플랫폼을 만들었습니다. 2인 팀에서 구조를 결정하고 설계·구현·운영을 맡았으며, 카드사 연동에 적용했습니다. 완료된 결과를 지키면서 실패한 부분을 따로 확인하고 처리하는 데 집중했습니다.
전체 아키텍처
사용자 화면은 member-web의 Spring MVC·Thymeleaf로 제공하고, OpenFeign으로 제휴 백엔드를 호출합니다. 운영 도구는 별도의 관리자 웹과 API로 나눴습니다. 화면에서 시작한 요청이 업무 처리와 저장소로 이어지는 구조, 카드사와 주고받는 경로를 차례로 보여줍니다.
고객 화면과 운영 화면이 제휴 백엔드와 저장소를 사용하는 구조
대표적인 서버 호출과 저장소의 역할을 나타낸 논리 구성입니다. 관리자 API는 업무 처리를 백엔드에 요청하고, 일부 실패·호출 이력은 MongoDB에서 직접 조회합니다.
카드사 연동의 송신·수신 경로
카드사와의 송신·수신은 Nginx를 거칩니다. 수신 경로에는 요청 인증을 위한 API Gateway를 두었습니다. 주소와 인증 값 등 운영 설정은 생략했습니다.
쿠폰 발급 실패가 혜택 누락으로 남지 않도록
인증과 동의를 마쳐도 외부 연동 문제로 쿠폰 발급이 실패할 수 있었습니다. 고객이 앞선 절차를 다시 밟게 하는 대신, 인증·동의와 쿠폰 발급의 처리 흐름을 나눴습니다.
발급 실패를 기록하고 재처리할 수 있게 해, 누락된 혜택을 후속 처리로 전달했습니다. 실패 기록이 중복해서 쌓이지 않도록 관리하고, 운영자가 남아 있는 실패와 처리 결과를 확인하도록 했습니다. 재처리로 해결되지 않은 건도 이력에서 추적할 수 있게 했습니다.
쿠폰 발급 실패를 이력으로 남기고 다시 처리하는 흐름
실패 이력을 기준으로 쿠폰 발급을 재처리합니다. 완료된 인증·동의는 별도로 유지합니다.
제휴사 추가는 설정과 공통 기능의 조합으로
동의 처리와 이력 관리처럼 반복되는 기능은 공통으로 두고, 제휴사마다 달라지는 값은 설정으로 분리했습니다. 운영자가 관리자에서 제휴사와 연동 설정을 관리하도록 해, 같은 명세의 제휴사를 추가할 때 기존 기능을 활용할 수 있게 했습니다.
확장성은 설계에 반영했지만 실제 구현과 운영은 한 제휴사에 집중했습니다. 서로 다른 명세까지 설정만으로 처리하는 범용 엔진을 만든 것은 아닙니다. 공통화할 수 있는 부분과 추가 개발이 필요한 경계를 나눴습니다.
제휴사 설정을 바꿔 공통 연동 기능을 재사용하는 설계
새 제휴사의 설정을 공통 처리 기능에 연결하는 흐름입니다.
인증 완료와 동의 저장의 실패를 분리
동의 저장이 실패했다고 이미 끝난 인증까지 되돌리면 고객은 같은 절차를 다시 거쳐야 합니다. 인증 완료 이후 동의 항목을 각각 별도 트랜잭션으로 저장하도록 나눠, 한 항목의 실패가 완료된 인증과 다른 동의에 영향을 주지 않도록 했습니다.
대신 일부만 성공한 상태를 이력과 함께 관리해야 했습니다. 완료된 결과는 유지하고 실패한 항목은 구분해 확인했습니다. 커밋 이후 이벤트 처리는 트랜잭션을 나누기 위한 선택이며, 그 자체로 영속적인 전달이나 모든 실패의 복구까지 보장하지는 않습니다.
B가 실패한 뒤에도 인증과 A의 커밋은 유지됩니다
인증을 커밋한 뒤 각 동의 항목을 별도 트랜잭션으로 처리합니다. 한 항목이 실패해도 완료된 인증과 다른 항목의 커밋은 남습니다. 시간축의 순서와 간격은 설명용입니다.
카드사 동의를 묶음으로 받다
카드사에서 받은 동의는 여러 묶음으로 나뉘어 들어왔습니다. 같은 묶음이 다시 도착하거나 도착 순서가 바뀌어도 처리 현황을 잘못 판단하지 않도록 해야 했습니다.
집계 정보의 생성 충돌은 별도 트랜잭션에서 처리하고, 같은 배치의 중복 확인과 누적 갱신은 하나의 잠금 범위 안에 뒀습니다. 단순히 마지막 순번이 도착했다고 완료로 판단하지 않고, 수신 묶음 수와 누락 여부를 함께 확인했습니다. 같은 집계에 대한 요청이 몰리면 잠금 대기가 생기는 비용도 있었습니다.
도착 순서와 중복을 고려한 묶음 집계
처음 받은 묶음만 집계하고, 수신 순서와 무관하게 누락 여부를 확인합니다.
데이터 오류와 작업 실패를 구분하다
Spring Batch를 사용해 제휴 데이터를 검증하고 필요한 형태로 반영하는 별도 처리 흐름을 구성했습니다. 개별 데이터의 오류와 작업 자체의 실패를 구분해, 어느 범위까지 처리됐고 무엇을 다시 확인해야 하는지 알 수 있도록 했습니다.
정상 처리와 오류 내역을 남겨 후속 업무에서 결과를 확인할 수 있게 했습니다. 데이터가 들어왔다는 사실만으로 작업이 끝났다고 보지 않고, 처리 결과까지 운영할 수 있는 상태를 만들었습니다.
개별 데이터의 처리 결과와 작업의 종료 상태
Spring Batch로 구현한 처리 흐름입니다. 개별 오류를 건너뛰고 작업이 완료될 수도 있어, 작업 상태와 개별 데이터의 처리 결과를 따로 확인합니다.
만들고 끝이 아니라 운영까지
개발자가 로그를 대신 찾아줘야만 운영할 수 있는 구조는 피하고 싶었습니다. 제휴사 설정, 동의 조회·철회, 배치 처리 현황과 쿠폰 실패 이력을 관리자 화면에서 확인할 수 있도록 개발했습니다.
완료된 건과 추가 확인이 필요한 건을 구분하고, 처리 이력을 따라갈 수 있게 했습니다. 연동 기능과 운영 도구를 함께 만들어, 문제가 생겼을 때 어디부터 확인해야 하는지 드러나도록 했습니다.
구현 범위 · 사용 기술
상세 기능과 사용 기술 보기
Java 21
Spring Boot 3.2
WebFlux
Spring Batch
Oracle
MongoDB
Next.js
OpenShift · ArgoCD
동의 연동서비스와 카드사에서 받은 동의 처리
묶음 수신중복 집계 방지 · 누락과 처리 결과 확인
데이터 처리입력 검증 · 오류 구분 · 결과 확인
제휴사 추가같은 명세에서 설정과 공통 기능 재사용
쿠폰 발급실패 기록 · 재처리 · 결과 확인
운영 관리동의 조회·철회 · 처리 이력 · 모니터링
돌아보면
제휴 연동에서 중요했던 것은 연결 자체보다 실패 이후의 처리였습니다. 완료된 결과는 보존하고, 중복된 입력과 실패한 작업은 따로 다뤘습니다. 공통 기능과 제휴사 설정을 나눈 구조 위에 운영자가 상태를 확인할 도구까지 함께 만들었습니다.
회사 프로젝트의 소스 코드는 공개하지 않습니다. 구조도는 업무 흐름을 설명하기 위한 개념도입니다.