DEVELOPER GUIDE

API 개발 가이드

토큰을 받아 첫 호출을 성공시키기까지 필요한 절차를 순서대로 정리했습니다. 각 서비스의 정확한 필드 스펙은 Swagger 문서에서 Try it out으로 직접 확인하세요.

01

인증 — API 토큰

모든 호출은 Authorization: Bearer <토큰> 헤더가 필요합니다. 토큰은 JWT가 아니라 opaque 문자열입니다 - 탈취돼도 그 안에 아무 정보도 들어있지 않고, 서버가 저장해 둔 해시와 대조해서만 유효성을 판단합니다.

  1. 사용자 등록에서 업체명·담당 업무·연락처를 입력해 가입합니다.
  2. 관리자가 신청을 검토해 승인하면, 그 순간의 승인 응답에 토큰 원문이 1회만 노출됩니다 - 이후에는 서버 어디에도 원문이 남지 않으므로(해시만 저장) 잃어버리면 재발급만 가능합니다.
  3. 발급받은 토큰을 요청마다 헤더에 실어 보냅니다.
curl
# Authorize 창에는 Bearer 접두사 없이 토큰 값만 넣습니다.
curl -H "Authorization: Bearer <토큰>" \
  https://호스트/api/services/AC_ADDRAT_L1/call \
  -X POST -H "Content-Type: application/json" \
  -d '{"isPatNo":"00012345"}'

헤더가 아예 없으면 401 missing Authorization: Bearer <token> header, 토큰이 틀렸거나 폐기/만료됐으면 401 invalid or revoked API token이 오는데 - 이때 hint 필드에 "URL을 넣은 건 아닌지", "Bearer가 중복된 건 아닌지", "폐기됐는지 만료됐는지"를 서버가 진단해서 알려줍니다. 값 자체는 절대 되비추지 않으니 hint만 보고 원인을 좁히세요.

02

서비스 찾기

이 게이트웨이는 병원 tmax 도메인의 서비스를 이름 그대로 노출합니다 - 서비스명은 업무그룹 머릿글자로 시작합니다(예: 원무업무는 A, 진료업무는 M). 어떤 서비스가 있는지는 세 가지 경로로 찾을 수 있습니다.

  • GET /docs — Swagger UI. 필드까지 완전히 문서화된 파일럿 서비스는 여기서 바로 Try it out으로 실행해볼 수 있습니다.
  • GET /api/services?q=&group=&status=RDY&limit=&offset= — 이름/업무그룹/기동상태로 검색·페이징 조회.
  • GET /api/services/{svcName} — 서비스 하나의 상세 스펙 (입출력 필드, requires_tx, accepts_multi_row_input, has_binary_field)을 반환합니다. 아래 03~06 항목은 이 값들을 보고 판단합니다.
토큰에 ROLE(서비스 접근 범위)이 지정돼 있다면, 이 조회 결과들도 그 범위로 자동으로 필터링됩니다 - 카탈로그 검색만으로 권한 밖 서비스명이 노출되지 않습니다.
03

호출하기

모든 서비스 호출은 하나의 엔드포인트를 씁니다.

POST /api/services/{svcName}/call
// body: 별칭(alias) 필드로 채운 평면 JSON 객체
{ "isPatNo": "00012345" }

// -> 200 응답: 응답도 별칭으로 번역돼 돌아옵니다
{ "success": true, "sPatname": "…", "tBirthday": "…", … }

필드명은 원래 tmax FML 이름(예: S_STRING1)이 아니라, Pro*C 소스에서 자동 추출한 읽기 쉬운 별칭(isPatNo)을 씁니다. 어떤 별칭이 있는지는 02의 서비스 스펙 조회로 확인하세요. 값은 문자열·숫자·불리언 같은 평면 스칼라만 가능합니다 - 중첩 객체는 FML로 표현할 수 없어 400 invalid_request_body로 거절됩니다.

언어별 호출 예제 (모두 같은 요청을 보냅니다):

curl -X POST "https://호스트/api/services/AC_ADDRAT_L1/call" \
  -H "Authorization: Bearer <토큰>" \
  -H "Content-Type: application/json" \
  -d '{"isPatNo":"00012345"}'
04

트랜잭션(tx=true)

일부 서비스는 여러 테이블에 걸친 쓰기를 하나의 글로벌 트랜잭션(XA)으로 묶어야 합니다. 그런 서비스는 02의 스펙 조회에서 requires_tx: true로 표시되며, 호출 시 쿼리스트링에 ?tx=true를 붙여야 합니다.

curl
curl ... -X POST ".../api/services/AC_ADDRAT_U1/call?tx=true" -d '{"...": "..."}'

requires_tx: false인 서비스에 tx=true를 붙여도 해가 되진 않지만, 필요 없는 서비스에는 붙이지 않는 편이 트랜잭션 오버헤드가 없어 유리합니다.

05

다건 입력(rows)

accepts_multi_row_input: true인 서비스는 한 번의 호출로 여러 행을 보낼 수 있습니다. 최상위 필드 대신 rows 배열에 행 객체를 나열하세요.

POST body
{ "rows": [
  { "isPatNo": "00012345", "sItemCd": "A001" },
  { "isPatNo": "00012345", "sItemCd": "A002" }
] }

모든 행은 정확히 같은 필드 구성이어야 합니다. 행마다 키가 다르면 브릿지가 열을 순차로 쌓는 방식(fbput) 특성상 값이 한 칸씩 밀려버릴 수 있어, 서버는 이 경우를 조용히 처리하는 대신 400으로 명시적으로 거절합니다. 같은 필드를 최상위와 rows 양쪽에 중복 지정해도 마찬가지로 거절됩니다.

06

바이너리 필드(base64)

has_binary_field: true인 서비스는 이미지·첨부파일 필드를 포함합니다. 값은 base64로 인코딩한 문자열로 보내고 받습니다 - 별도 multipart 업로드는 지원하지 않습니다.

필드당 크기 한도는 약 1MB(1,048,512바이트, 디코딩 후 기준)입니다. 초과하면 tmax까지 가지 않고 그 자리에서 413 payload_too_large로 거절되며, 응답에 어느 필드가 몇 바이트였고 한도가 얼마인지 정확한 수치가 함께 옵니다 - 브릿지 stderr을 뒤질 필요 없이 바로 원인을 알 수 있습니다.

07

에러 코드

HTTP 상태 코드로 "성공/업무 실패/시스템 오류"를 구분합니다 - 재시도 전략이 코드마다 다릅니다.

코드의미대처
200성공 (업무 로직까지 정상 처리)—
400요청 본문 형식 오류 (중첩 객체, rows 필드 불일치 등)재시도 전에 요청 본문을 고쳐야 함 - 그대로 재시도해도 동일하게 실패
401토큰 없음/무효/만료/폐기hint 필드 확인 후 토큰 재확인 또는 관리자에게 재발급 요청
403토큰의 ROLE에 이 서비스가 포함되지 않음관리자에게 ROLE 할당 요청
404존재하지 않거나(오탈자) ROLE 밖이라 "없음"으로 응답한 서비스서비스명 재확인
413바이너리 필드가 한도(약 1MB) 초과압축하거나 분할 - 응답의 size_bytes/limit_bytes 참고
422업무 실패 (tmax 도메인은 정상 응답했지만 업무 조건 불충족 - 예: 대상 없음, 입력값 오류)그대로 재시도해도 결과 동일 - 응답 필드로 원인 확인
502게이트웨이-tmax 브릿지 오류 (타임아웃 15초 기본값, 브릿지 실행 실패, tmax 도메인 응답 불가 등)일시적 장애일 가능성 - 백오프 후 재시도 가능

200과 422 둘 다 tmax 도메인이 정상적으로 응답했다는 뜻입니다(둘 다 "요청은 잘 갔다") - 차이는 응답 본문의 success 필드가 가리는 업무 결과입니다. 다만 조회 결과가 0건인 경우는 실패로 보지 않고 서버가 success: true, no_data_found: true로 자동 정규화해 돌려줍니다.

08

모범 사례

  • 토큰은 서버 사이드에만 보관하세요. 브라우저/모바일 클라이언트에 직접 심으면 그대로 노출됩니다 - 프런트엔드는 여러분의 백엔드를 거쳐 호출하세요.
  • 422는 재시도하지 마세요. 같은 입력이면 같은 업무 결과가 나옵니다 - 입력을 고치거나 사용자에게 알리는 것이 맞는 대응입니다.
  • 502는 짧은 backoff 후 재시도가 합리적입니다. 다만 쓰기 성격의 호출(특히 tx=true)을 재시도할 때는 중복 처리 가능성을 염두에 두고 멱등하게 설계하세요 - 게이트웨이 쪽에서 중복 방지를 대신해주지 않습니다.
  • 02에서 얻은 스펙을 캐시하세요. requires_tx/ accepts_multi_row_input/has_binary_field는 서비스가 바뀌지 않는 한 고정값이라, 매 호출 전에 다시 조회할 필요는 없습니다.
  • 호출 전 카탈로그로 status가 RDY인지 확인하면, 유지보수로 잠시 내려간 서비스를 부르는 헛수고를 줄일 수 있습니다.
막히면 연동 신청 시 등록한 연락처로 관리자에게 문의하거나, Swagger 문서의 Try it out으로 먼저 재현해 보세요 - 어떤 요청이 나갔는지부터 확인하면 원인의 절반은 좁혀집니다.