프로젝트
지마켓카드사 연동 · 공통 기능과 운영 도구

외부 파트너 제휴 연동 플랫폼

제휴사마다 반복할 기능을 공통화하고, 완료된 인증과 동의를 보존하면서 실패한 작업을 따로 다루는 연동 플랫폼을 개발했습니다. 2인 팀에서 구조 결정과 설계·구현·운영을 맡았습니다.

제휴사 설정 · 동의 조회·철회 · 처리 이력 관리

기간
2026.01 — 2026.06 개발, 이후 운영
팀
2인 팀
역할
설계 · 구현 · 운영 — 구조 결정 담당

제휴가 늘어도 같은 기능을 다시 만들지 않도록

제휴 연동에는 동의를 받는 기능만 있는 것이 아닙니다. 여러 경로에서 들어온 동의를 반영하고, 처리에 실패한 건을 확인하고, 고객에게 약속한 혜택도 전달해야 했습니다. 제휴사가 추가될 때 이 기능들을 다시 만드는 구조는 피하고 싶었습니다.

제휴사별 설정과 공통 처리 기능을 나눠 연동 플랫폼을 만들었습니다. 2인 팀에서 구조를 결정하고 설계·구현·운영을 맡았으며, 카드사 연동에 적용했습니다. 완료된 결과를 지키면서 실패한 부분을 따로 확인하고 처리하는 데 집중했습니다.

전체 아키텍처

사용자 화면은 member-web의 Spring MVC·Thymeleaf로 제공하고, OpenFeign으로 제휴 백엔드를 호출합니다. 운영 도구는 별도의 관리자 웹과 API로 나눴습니다. 화면에서 시작한 요청이 업무 처리와 저장소로 이어지는 구조, 카드사와 주고받는 경로를 차례로 보여줍니다.

고객 화면과 운영 화면이 제휴 백엔드와 저장소를 사용하는 구조

고객 화면과 운영 화면이 제휴 백엔드와 저장소를 사용하는 구조 고객 브라우저는 member-web을 이용합니다. member-web은 Spring MVC와 Thymeleaf로 페이지와 브라우저 스크립트를 제공하고 OpenFeign으로 제휴 백엔드를 호출합니다. 별도의 운영자는 Next.js 운영 웹과 브라우저 프록시를 거쳐 Spring 관리자 API를 이용합니다. 관리자 API는 Feign으로 제휴 백엔드를 호출하며 MongoDB의 오류·호출 이력도 직접 조회합니다. 제휴 백엔드는 Oracle RDB에서 설정·인증·동의·이력을 저장·조회하고 Redis에서 임시 인증 상태를 관리하며, MongoDB에는 오류·호출 이력을 남깁니다. 화살표는 논리적 호출과 저장소 접근 관계이며 서버 수나 물리적 배치를 나타내지 않습니다. 고객 브라우저 운영자 member-web Spring MVC + Thymeleaf 페이지·브라우저 JS 제공 운영 웹 Next.js 브라우저 프록시 포함 관리자 API Spring OpenFeign 호출 Feign 호출 제휴 백엔드 인증·동의 처리 카드사·쿠폰 연동 Oracle RDB 설정·인증·동의·이력 Redis 임시 인증 상태 MongoDB 오류·호출 이력 MongoDB 직접 조회 논리적 역할과 호출·저장소 접근 관계 고객 화면과 운영 화면이 제휴 백엔드와 저장소를 사용하는 구조 고객 브라우저는 member-web을 이용합니다. member-web은 Spring MVC와 Thymeleaf로 페이지와 브라우저 스크립트를 제공하고 OpenFeign으로 제휴 백엔드를 호출합니다. 별도의 운영자는 Next.js 운영 웹과 브라우저 프록시를 거쳐 Spring 관리자 API를 이용합니다. 관리자 API는 Feign으로 제휴 백엔드를 호출하며 MongoDB의 오류·호출 이력도 직접 조회합니다. 제휴 백엔드는 Oracle RDB에서 설정·인증·동의·이력을 저장·조회하고 Redis에서 임시 인증 상태를 관리하며, MongoDB에는 오류·호출 이력을 남깁니다. 화살표는 논리적 호출과 저장소 접근 관계이며 서버 수나 물리적 배치를 나타내지 않습니다. 고객 브라우저 member-web Spring MVC + Thymeleaf 페이지·브라우저 JS 제공 백엔드는 OpenFeign 호출 운영자 운영 웹 Next.js 브라우저 프록시 포함 관리자 API · Spring 제휴 백엔드 Feign 호출 MongoDB 이력 직접 조회 제휴 백엔드 인증·동의 처리 카드사·쿠폰 연동 Oracle RDB 설정·인증·동의·이력 Redis 임시 인증 상태 MongoDB 오류·호출 이력 논리적 역할과 호출 관계 서버 수·물리 배치를 나타내지 않음
대표적인 서버 호출과 저장소의 역할을 나타낸 논리 구성입니다. 관리자 API는 업무 처리를 백엔드에 요청하고, 일부 실패·호출 이력은 MongoDB에서 직접 조회합니다.

카드사 연동의 송신·수신 경로

카드사 연동의 송신·수신 경로보내는 요청은 제휴 백엔드에서 Nginx를 거쳐 카드사로 갑니다. 받는 요청은 카드사에서 Nginx와 API Gateway를 거쳐 제휴 백엔드로 들어옵니다. API Gateway는 요청을 인증합니다. 송신 경로에 API Gateway가 포함된다는 의미는 아닙니다. 반복된 Nginx 표시는 각 경로의 역할이며 인스턴스 수나 배포 구성을 나타내지 않습니다. 보내는 요청 제휴 백엔드 Nginx 카드사 받는 요청 카드사 Nginx API Gateway 요청 인증 제휴 백엔드 Nginx는 경로별 역할 표시이며, 인스턴스 수를 뜻하지 않습니다. 카드사 연동의 송신·수신 경로보내는 요청은 제휴 백엔드에서 Nginx를 거쳐 카드사로 갑니다. 받는 요청은 카드사에서 Nginx와 API Gateway를 거쳐 제휴 백엔드로 들어옵니다. API Gateway는 요청을 인증합니다. 송신 경로에 API Gateway가 포함된다는 의미는 아닙니다. 반복된 Nginx 표시는 각 경로의 역할이며 인스턴스 수나 배포 구성을 나타내지 않습니다. 보내는 요청 제휴 백엔드 Nginx 카드사 받는 요청 카드사 Nginx API Gateway 요청 인증 제휴 백엔드 Nginx는 경로별 역할 표시입니다. 인스턴스 수를 뜻하지 않습니다.
카드사와의 송신·수신은 Nginx를 거칩니다. 수신 경로에는 요청 인증을 위한 API Gateway를 두었습니다. 주소와 인증 값 등 운영 설정은 생략했습니다.

쿠폰 발급 실패가 혜택 누락으로 남지 않도록

인증과 동의를 마쳐도 외부 연동 문제로 쿠폰 발급이 실패할 수 있었습니다. 고객이 앞선 절차를 다시 밟게 하는 대신, 인증·동의와 쿠폰 발급의 처리 흐름을 나눴습니다.

발급 실패를 기록하고 재처리할 수 있게 해, 누락된 혜택을 후속 처리로 전달했습니다. 실패 기록이 중복해서 쌓이지 않도록 관리하고, 운영자가 남아 있는 실패와 처리 결과를 확인하도록 했습니다. 재처리로 해결되지 않은 건도 이력에서 추적할 수 있게 했습니다.

쿠폰 발급 실패를 이력으로 남기고 다시 처리하는 흐름

쿠폰 발급 실패를 이력으로 남기고 다시 처리하는 흐름인증과 동의가 이미 완료된 뒤의 별도 쿠폰 발급 흐름입니다. 쿠폰 발급 요청이 성공하면 완료합니다. 실패하면 실패 이력을 남기고 재시도하며, 재시도 결과는 성공하거나 실패 상태로 남을 수 있습니다. 모든 실패의 자동 복구, 외부 발급의 멱등성이나 정확히 한 번 실행, 분산 원자성을 보장한다는 의미가 아닙니다. 인증·동의 완료는 유지 · 쿠폰은 별도 처리 쿠폰 발급 요청 성공 발급 완료 실패 실패 이력 재시도 성공 실패 실패 상태 유지 재시도 결과에 따라 완료하거나 실패 상태로 남습니다. 쿠폰 발급 실패를 이력으로 남기고 다시 처리하는 흐름인증과 동의가 이미 완료된 뒤의 별도 쿠폰 발급 흐름입니다. 쿠폰 발급 요청이 성공하면 완료합니다. 실패하면 실패 이력을 남기고 재시도하며, 재시도 결과는 성공하거나 실패 상태로 남을 수 있습니다. 모든 실패의 자동 복구, 외부 발급의 멱등성이나 정확히 한 번 실행, 분산 원자성을 보장한다는 의미가 아닙니다. 인증·동의 완료는 유지 쿠폰은 별도 처리 쿠폰 발급 요청 실패 성공 실패 이력 발급 완료 재시도 성공 실패 실패 상태 유지 재시도 결과에 따라 완료하거나 실패 상태로 남습니다.
실패 이력을 기준으로 쿠폰 발급을 재처리합니다. 완료된 인증·동의는 별도로 유지합니다.

제휴사 추가는 설정과 공통 기능의 조합으로

동의 처리와 이력 관리처럼 반복되는 기능은 공통으로 두고, 제휴사마다 달라지는 값은 설정으로 분리했습니다. 운영자가 관리자에서 제휴사와 연동 설정을 관리하도록 해, 같은 명세의 제휴사를 추가할 때 기존 기능을 활용할 수 있게 했습니다.

확장성은 설계에 반영했지만 실제 구현과 운영은 한 제휴사에 집중했습니다. 서로 다른 명세까지 설정만으로 처리하는 범용 엔진을 만든 것은 아닙니다. 공통화할 수 있는 부분과 추가 개발이 필요한 경계를 나눴습니다.

제휴사 설정을 바꿔 공통 연동 기능을 재사용하는 설계

제휴사 설정을 바꿔 공통 연동 기능을 재사용하는 설계실제 운영은 한 제휴사입니다. 같은 명세의 제휴사를 추가할 때 제휴사 설정을 통해 공통 동의 처리, 처리 이력, 운영 기능을 재사용하도록 설계한 확장 지점입니다. 여러 제휴사를 실제 운영했다는 뜻이 아니며 다른 명세는 추가 구현이 필요합니다. 같은 명세의 제휴사 추가 설계한 확장 지점 제휴사 설정 공통 연동 기능 동의 처리 처리 이력 운영 기능 실제 운영은 한 제휴사입니다. 같은 명세는 공통 기능 재사용 · 다른 명세는 추가 구현 필요 제휴사 설정을 바꿔 공통 연동 기능을 재사용하는 설계실제 운영은 한 제휴사입니다. 같은 명세의 제휴사를 추가할 때 제휴사 설정을 통해 공통 동의 처리, 처리 이력, 운영 기능을 재사용하도록 설계한 확장 지점입니다. 여러 제휴사를 실제 운영했다는 뜻이 아니며 다른 명세는 추가 구현이 필요합니다. 같은 명세의 제휴사 추가 설계한 확장 지점 제휴사 설정 공통 연동 기능 동의 처리 처리 이력 운영 기능 실제 운영은 한 제휴사입니다. 같은 명세는 공통 기능 재사용 다른 명세는 추가 구현 필요
새 제휴사의 설정을 공통 처리 기능에 연결하는 흐름입니다.

인증 완료와 동의 저장의 실패를 분리

동의 저장이 실패했다고 이미 끝난 인증까지 되돌리면 고객은 같은 절차를 다시 거쳐야 합니다. 인증 완료 이후 동의 항목을 각각 별도 트랜잭션으로 저장하도록 나눠, 한 항목의 실패가 완료된 인증과 다른 동의에 영향을 주지 않도록 했습니다.

대신 일부만 성공한 상태를 이력과 함께 관리해야 했습니다. 완료된 결과는 유지하고 실패한 항목은 구분해 확인했습니다. 커밋 이후 이벤트 처리는 트랜잭션을 나누기 위한 선택이며, 그 자체로 영속적인 전달이나 모든 실패의 복구까지 보장하지는 않습니다.

B가 실패한 뒤에도 인증과 A의 커밋은 유지됩니다

B가 실패한 뒤에도 인증과 A의 커밋은 유지됩니다설명용 시간축. 인증을 먼저 커밋하고 AFTER_COMMIT 이후 동의 A와 B를 각각 REQUIRES_NEW로 처리합니다. A 성공, B 실패의 예에서 앞선 커밋은 유지됩니다. A와 B의 순서와 시간 간격은 예시입니다.설명용 논리 시간순서·간격은 예시AFTER_COMMIT인증먼저 커밋동의 A독립 TX동의 B독립 TX인증 처리커밋결과 유지REQUIRES_NEW동의 A 처리커밋결과 유지REQUIRES_NEW동의 B 처리실패B가 실패한 뒤에도 인증과 A의 커밋은 유지됩니다설명용 시간축. 인증을 먼저 커밋하고 AFTER_COMMIT 이후 동의 A와 B를 각각 REQUIRES_NEW로 처리합니다. A 성공, B 실패의 예에서 앞선 커밋은 유지됩니다. A와 B의 순서와 시간 간격은 예시입니다.인증먼저 커밋인증 트랜잭션✓ 커밋 완료동의 AREQUIRES_NEW동의 A 처리✓ 커밋 완료동의 BREQUIRES_NEW동의 B 처리× 실패AFTER_COMMIT
인증을 커밋한 뒤 각 동의 항목을 별도 트랜잭션으로 처리합니다. 한 항목이 실패해도 완료된 인증과 다른 항목의 커밋은 남습니다. 시간축의 순서와 간격은 설명용입니다.

카드사 동의를 묶음으로 받다

카드사에서 받은 동의는 여러 묶음으로 나뉘어 들어왔습니다. 같은 묶음이 다시 도착하거나 도착 순서가 바뀌어도 처리 현황을 잘못 판단하지 않도록 해야 했습니다.

집계 정보의 생성 충돌은 별도 트랜잭션에서 처리하고, 같은 배치의 중복 확인과 누적 갱신은 하나의 잠금 범위 안에 뒀습니다. 단순히 마지막 순번이 도착했다고 완료로 판단하지 않고, 수신 묶음 수와 누락 여부를 함께 확인했습니다. 같은 집계에 대한 요청이 몰리면 잠금 대기가 생기는 비용도 있었습니다.

도착 순서와 중복을 고려한 묶음 집계

도착 순서와 중복을 고려한 묶음 집계 카드사 동의를 여러 묶음으로 받을 때 도착 순서와 중복을 고려해 집계하는 일반 개념도입니다. 수신한 묶음이 중복인지 확인하고 처음 받은 묶음만 집계합니다. 이미 받은 묶음은 집계에서 제외합니다. 그 결과로 전체 수신 여부와 누락을 확인합니다. 이 그림은 묶음 수신 집계의 개념이며 전체 동의 반영의 단 한 번 처리를 보장한다는 의미가 아닙니다. 도착 순서와 중복을 고려한 집계 카드사 동의 수신 여러 묶음으로 도착 묶음 중복 여부 확인 새 묶음 처음 받은 묶음만 집계 중복 묶음 이미 받은 묶음은 집계에서 제외 수신 현황 확인 전체 수신 여부 · 누락 확인 묶음 집계의 개념 · 전체 동의 반영 보장과는 구분 도착 순서와 중복을 고려한 묶음 집계 카드사 동의를 여러 묶음으로 받을 때 도착 순서와 중복을 고려해 집계하는 일반 개념도입니다. 수신한 묶음이 중복인지 확인하고 처음 받은 묶음만 집계합니다. 이미 받은 묶음은 집계에서 제외합니다. 그 결과로 전체 수신 여부와 누락을 확인합니다. 이 그림은 묶음 수신 집계의 개념이며 전체 동의 반영의 단 한 번 처리를 보장한다는 의미가 아닙니다. 도착 순서와 중복을 고려한 집계 카드사 동의 수신 여러 묶음으로 도착 묶음 중복 여부 확인 새 묶음 처음 받은 묶음만 집계 중복 묶음 이미 받은 묶음 집계에서 제외 수신 현황 확인 전체 수신 여부 · 누락 확인 묶음 집계에 대한 개념도 전체 동의 반영 보장과는 구분
처음 받은 묶음만 집계하고, 수신 순서와 무관하게 누락 여부를 확인합니다.

데이터 오류와 작업 실패를 구분하다

Spring Batch를 사용해 제휴 데이터를 검증하고 필요한 형태로 반영하는 별도 처리 흐름을 구성했습니다. 개별 데이터의 오류와 작업 자체의 실패를 구분해, 어느 범위까지 처리됐고 무엇을 다시 확인해야 하는지 알 수 있도록 했습니다.

정상 처리와 오류 내역을 남겨 후속 업무에서 결과를 확인할 수 있게 했습니다. 데이터가 들어왔다는 사실만으로 작업이 끝났다고 보지 않고, 처리 결과까지 운영할 수 있는 상태를 만들었습니다.

개별 데이터의 처리 결과와 작업의 종료 상태

개별 데이터의 처리 결과와 작업의 종료 상태두 흐름은 개별 데이터와 작업 전체를 서로 다른 단위로 비교합니다. 정상 데이터는 반영하고, 허용된 유형과 한도 안의 개별 오류는 기록한 뒤 건너뛰어 다음 데이터를 처리합니다. 모든 오류를 건너뛰는 것은 아닙니다. 입력 전체 검증 실패나 처리를 계속할 수 없는 오류는 작업 실패로 이어집니다. 작업 완료 여부와 개별 오류는 따로 확인하며, 실패한 작업은 원인과 처리 범위를 확인합니다. 개별 오류가 있어도 작업은 완료될 수 있습니다. 자동 복구나 데이터 한 건마다의 독립 트랜잭션을 나타내는 그림은 아닙니다. 개별 데이터 · 무엇을 반영했는가 데이터 처리 정상 반영 오류 기록 건너뛰기 허용 시 다음 데이터 건너뛰기는 정해 둔 오류 유형과 한도 안에서만 허용 작업 상태 · 실행을 마쳤는가 전체 처리 작업 완료 작업 실패 개별 오류는 별도로 확인 실패 원인과 처리 범위 확인 입력 전체 검증 실패 등, 처리를 이어갈 수 없는 경우는 작업 실패 개별 데이터의 처리 결과와 작업의 종료 상태두 흐름은 개별 데이터와 작업 전체를 서로 다른 단위로 비교합니다. 정상 데이터는 반영하고, 허용된 유형과 한도 안의 개별 오류는 기록한 뒤 건너뛰어 다음 데이터를 처리합니다. 모든 오류를 건너뛰는 것은 아닙니다. 입력 전체 검증 실패나 처리를 계속할 수 없는 오류는 작업 실패로 이어집니다. 작업 완료 여부와 개별 오류는 따로 확인하며, 실패한 작업은 원인과 처리 범위를 확인합니다. 개별 오류가 있어도 작업은 완료될 수 있습니다. 자동 복구나 데이터 한 건마다의 독립 트랜잭션을 나타내는 그림은 아닙니다. 개별 데이터 무엇을 반영했는가 데이터 처리 정상 반영 오류 기록 건너뛰기 허용 시 다음 데이터 건너뛰기는 정해 둔 오류 유형과 한도 안에서만 허용 작업 상태 실행을 마쳤는가 전체 처리 작업 완료 작업 실패 개별 오류는 별도로 확인 실패 원인과 처리 범위 확인 입력 전체 검증 실패 등 계속 처리할 수 없으면 작업 실패
Spring Batch로 구현한 처리 흐름입니다. 개별 오류를 건너뛰고 작업이 완료될 수도 있어, 작업 상태와 개별 데이터의 처리 결과를 따로 확인합니다.

만들고 끝이 아니라 운영까지

개발자가 로그를 대신 찾아줘야만 운영할 수 있는 구조는 피하고 싶었습니다. 제휴사 설정, 동의 조회·철회, 배치 처리 현황과 쿠폰 실패 이력을 관리자 화면에서 확인할 수 있도록 개발했습니다.

완료된 건과 추가 확인이 필요한 건을 구분하고, 처리 이력을 따라갈 수 있게 했습니다. 연동 기능과 운영 도구를 함께 만들어, 문제가 생겼을 때 어디부터 확인해야 하는지 드러나도록 했습니다.

구현 범위 · 사용 기술

상세 기능과 사용 기술 보기
  • Java 21
  • Spring Boot 3.2
  • WebFlux
  • Spring Batch
  • Oracle
  • MongoDB
  • Next.js
  • OpenShift · ArgoCD
  • 동의 연동서비스와 카드사에서 받은 동의 처리
  • 묶음 수신중복 집계 방지 · 누락과 처리 결과 확인
  • 데이터 처리입력 검증 · 오류 구분 · 결과 확인
  • 제휴사 추가같은 명세에서 설정과 공통 기능 재사용
  • 쿠폰 발급실패 기록 · 재처리 · 결과 확인
  • 운영 관리동의 조회·철회 · 처리 이력 · 모니터링

돌아보면

제휴 연동에서 중요했던 것은 연결 자체보다 실패 이후의 처리였습니다. 완료된 결과는 보존하고, 중복된 입력과 실패한 작업은 따로 다뤘습니다. 공통 기능과 제휴사 설정을 나눈 구조 위에 운영자가 상태를 확인할 도구까지 함께 만들었습니다.

회사 프로젝트의 소스 코드는 공개하지 않습니다. 구조도는 업무 흐름을 설명하기 위한 개념도입니다.