모든 태그

# API Gateway

2개의 글

전문·TCP와 JSON·REST 사이에 통역기를 세운 아홉 단계, 관문(gwanmun) 총정리

은행 계정계는 고정길이 전문(電文)과 TCP로만, 모바일 앱은 JSON과 HTTP REST로만 말합니다. 둘 다 못 고치니 가운데에 통역기를 세웁니다. 전문과 JSON을 변환하는 연계층, 그리고 그 통로를 지키는 API 게이트웨이층입니다. 이 글은 그 통역기를 목업 계정계까지 세워 직접 만든 9단계의 총정리입니다. 계정계를 실제로 죽여 서킷이 OPEN으로 열리고 503으로 격리하는 과정, RuntimeException 하나(풀 고갈)가 서킷을 열고 원장 4건을 증발시킨 감사 결함과 그 수정(503과 원장 완결), 부하가 서킷 stale 레이스를 staleResultsTotal=197로 실증한 기록, 한계 약 10~12k req/s와 게이트웨이 오버헤드 약 0.21ms, 죽은 백엔드에서 서킷 off 351 vs on 9,425 req/s, 같은 멱등키를 두 번 보내도 계정계 호출 1회에 원장 1행으로 이중거래가 0이었던 것까지 담았습니다. 전부 VERIFICATION에 명령과 출력이 남은 실측이고, 안 만든 것은 왜 안 만들었는지 적었습니다.

완제품 없이 세운 문지기, 인증·라우팅·유량제어 필터 체인부터 가변 프레이밍과 커넥션 풀까지

전문↔JSON 왕복 통로는 열렸지만 아무나 드나들 수 있었습니다. 1부에서 /api/gateway/** 앞에 문지기를 손으로 세웁니다. 인증(X-API-Key, 없으면 401·잘못되면 403), 라우팅(모르는 경로 404), 유량제어(클라이언트별 토큰버킷, 용량 5 초과 시 6번째 429 + Retry-After)입니다. 완제품 프레임워크 없이 GatewayFilter 인터페이스와 체인 실행기, 서블릿 브릿지로 직접 짰고, 직접 짜는 유량제어의 두 함정(벽시계로 인한 시간 역행, 같은 버킷을 치는 스레드 경쟁)을 단조 시계와 버킷 단위 동기화로 막았습니다. 겸사겸사 코드베이스를 Spring Modulith 모듈러 모놀리스로 재정렬해 모듈 경계를 verify()가 강제하게 했습니다. 2부는 통로에 남은 두 구멍을 메웁니다. 거래내역 조회 응답처럼 레코드가 건수만큼 붙어 길이가 매번 다른 전문은 4byte 길이 헤더의 2단계 프레이밍으로 자르고(가변 309B 왕복, 비정상 길이는 fail-closed 거절), 요청마다 소켓을 새로 열던 것은 최대 크기·유휴 반납·검증·고갈 거절을 갖춘 스레드 안전 커넥션 풀로 바꿨습니다. 순차 6회 조회에 소켓 1개 재사용, 동시 10건 폭주에도 created=4(==max)·reused=12를 진짜 실행으로 남겼습니다.