100년 가는 프론트엔드 코드, SDK (새 탭에서 열림)

토스페이먼츠는 결제 연동의 복잡성을 해결하기 위해 SDK를 제공하고 있으며, 최근 V1의 한계를 극복하고 안정성과 확장성을 극대화한 V2 SDK를 구축했습니다. 가맹점의 다양한 런타임 환경과 예측 불가능한 요구사항에 대응하기 위해 단순한 기능 구현을 넘어 체계적인 아키텍처와 모니터링 시스템을 도입했습니다. 결과적으로 개발자에게는 쉬운 연동 경험을, 비즈니스에는 견고한 신뢰성을 제공하는 결제 생태계를 완성했습니다.

SDK 개발의 특수성과 V1의 한계

  • 환경의 의존성: SDK는 가맹점의 코드 내에서 실행되므로, 가맹점의 호출 빈도나 네트워크 상태에 직접적인 영향을 받습니다. 일례로 사용량 분석을 위해 추가한 로그 코드가 특정 가맹점의 잦은 호출과 맞물려 네트워크 병목 현상을 일으키고 서비스 전체를 다운시키는 사례가 발생했습니다.
  • 런타임 예측 불가능성: 가맹점에서 잘못된 데이터 타입(예: String 대신 Number)을 전달할 경우 startsWith 같은 표준 메서드에서 에러가 발생하는 등, 일반적인 프론트엔드 개발보다 훨씬 방어적인 코딩이 요구됩니다.
  • 커뮤니케이션의 접점: SDK는 단순히 API를 호출하는 도구가 아니라 가맹점 개발자와 만나는 기술적 창구이며, 가맹점의 수많은 커스텀 요구사항을 수용해야 하는 복잡성을 안고 있습니다.

안정성 확보를 위한 테스트와 모니터링

  • 촘촘한 테스트 체계: 로직 검증을 위한 300개 이상의 단위 테스트와 다양한 유즈케이스를 반영한 500개 이상의 E2E 통합 테스트를 통해 코드 수준의 안정성을 확보했습니다.
  • Global Trace ID: 프론트엔드부터 백엔드까지 결제 전 과정을 하나의 식별자로 추적하는 체계를 도입하여, 장애 발생 시 시스템 레이어 전체를 쉽게 파악할 수 있도록 했습니다.
  • 모니터링 CLI: 배포 전후의 결제 성공률을 가맹점 및 런타임 환경(OS, 브라우저, 웹뷰 등)별로 비교 분석하는 자체 도구를 개발했습니다. 이를 통해 특정 환경에서 발생하는 결제 중단 현상을 실시간으로 탐지하고 즉각 대응합니다.

확장성을 위한 레이어드 아키텍처

  • 조립 가능한 구조: 특정 가맹점만을 위한 예외 처리가 if문으로 산재되어 코드 복잡도가 올라가는 문제를 해결하기 위해, 기능을 레고 블록처럼 독립적으로 구성했습니다.
  • 3계층 분리: "변경의 원인"을 기준으로 코드의 경계를 명확히 나누어 관리합니다.
    • Public Interface Layer: 가맹점과 약속한 인터페이스를 검증하고 도메인 언어로 번역하는 역할
    • Domain Layer: 핵심 비즈니스 로직과 결제 정책을 담당하는 중심부
    • External Service Layer: 서버 API나 Web API 등 외부 의존성과의 통신을 담당하는 계층
  • 관심사 격리: 이러한 계층화를 통해 가맹점별 커스텀 요구사항이 추가되더라도 기존의 핵심 로직에 영향을 주지 않고 특정 블록만 교체하거나 확장할 수 있는 유연성을 확보했습니다.

성공적인 SDK 개발을 위해서는 단순히 편리한 기능을 제공하는 것을 넘어, 타사의 코드 환경에서도 견고하게 동작할 수 있는 방어적인 설계와 문제 발생 시 즉시 원인을 파악할 수 있는 관측성(Observability) 확보가 필수적입니다. 가맹점별 특이 케이스를 코드 전반에 흩뿌리기보다는, 명확한 레이어 구분을 통해 비즈니스 로직과 커스텀 로직을 분리하는 설계 원칙을 권장합니다.