# 올바로(Allbaro) OPEN API 연동 정본

| 항목 | 값 |
|---|---|
| Status | Active external API reference |
| Owner | Backend: 정정일 · APP contract counterpart: 주우철 |
| Last verified | 2026-07-15 KST |
| Supersedes | 올바로 연동 미확인 요구사항 메모 |

한국환경공단 올바로시스템 Open API의 실스펙 분석 정본이다. `docs/60-requirements/OPEN_QUESTIONS.md`의 올바로 스펙 미확보 항목을 해소한다.

분석 소스(공단 배포 자료 3종, repo에는 포함하지 않는다):

- 인터페이스 정의서(배포용) v1.9.5 (xlsx) — 인터페이스 41종 + 공통코드 21그룹
- 표준 Client 개발 가이드 v1.9.1 (pdf 49p, 2026-02-11, 공단 Allbaro 운영부)
- OpenAPIClient 표준 클라이언트 소스 (Java/Quartz, jar 포함)

주의: 업체 인증키·계정 등 크리덴셜 값은 이 문서를 포함해 repo 어디에도 기록하지 않는다(`docs/30-backend/WORKING_AGREEMENT.md`).

## 1. 연계 개요

- 기존 Active MQ 연계를 대체하는 RESTful(JSON) 방식이다.
- End-Point는 운영/테스트 공용 `https://api.allbaro.or.kr:27000/restApi`이며, 구분은 업체코드·인증키로만 한다. 별도 스테이징 도메인은 없다.
- 신청: 올바로 웹 `부가서비스관리 > OpenAPI 신청관리`에서 연계 신청 → 테스트용 임시 업체번호·임시 인증키 발급(30일 유효) → 기존 데이터와 대사 후 운영전환 → 실제 업체번호의 인증키 발급.
- Swagger 테스트 UI: `https://api.allbaro.or.kr:27000/swagger-ui.html` (업체 계정으로 접속).
- 매일 00:30~01:00은 공단 점검 시간으로 연계 불가.
- 명시적 rate limit 수치는 없으나 "허용량 이상의 요청이 잦으면 강제 연계취소" 경고가 있다. 과도 폴링 금지.

## 2. 인증

인증은 이중 구조다. 페이로드 자체 암호화는 없다(표준 클라이언트 jar 전수 확인 — Cipher/AES/서명 호출 전무). 전송 보안은 TLS에만 의존한다. 공단 가이드의 권장값(TLS 1.2 + `TLS_RSA_WITH_AES_128_CBC_SHA`)은 Forward Secrecy가 없는 레거시 스위트이므로, 재구현 시 최신 스위트(예: `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`)를 우선 협상하고 레거시 스위트는 서버가 거부할 때의 fallback으로만 둔다.

| 위치 | 내용 |
|---|---|
| HTTP Header | `Authorization: Basic base64(업체번호:비밀번호)` |
| Request Body | `API_CERT_KEY`(업체 인증키, String 24, 필수) + `ENTN_LKCD`(연계업체코드, String 10, 필수) |

업체(고객사)마다 크리덴셜 4종(업체코드/인증키/업체번호/비밀번호)을 안전 저장해야 한다. 테스트→운영 전환 시 업체코드·인증키가 교체된다. 표준 클라이언트는 서버 401 챌린지 후 Basic 재시도 방식이지만, 재구현 시 선제 전송이 낫다. 표준 클라이언트의 "모든 인증서 신뢰 TrustManager + HostnameVerifier 무력화"는 절대 따라 하지 않는다.

## 3. 프로토콜 규약

- URL: 조회 = `POST {base}/select{인터페이스ID}`, 제출 = `PUT {base}/insert{인터페이스ID}`. 명칭상 "GET"인 조회도 HTTP는 POST다. 경로 세그먼트는 `T200_4001_01` 형식의 인터페이스 ID다.
- `Content-Type: application/json;charset=utf-8`. 길이는 한글 2Byte 기준.
- 응답 공통: `ifid`, `txid`, `resultCode`(4), `resultMessage`, `errorMessage`, `totalPageNo`(조회만), `dataList`(조회만). 대장 생성 PUT만 `startDate`/`endDate` 추가.
- `TX_ID` = `IF_ID + "-" + YYYYMMDDHHmmss + "-" + 증가번호 4자리`.
- 조회 범위 `REQ_TYPE`: `N`(신규, default — 서버가 미조회분 커서 관리, 인계번호·페이지·기간 동봉 금지) / `A`(전체 — `TOTAL_PAGE_NO` 페이징 루프, 인계서·업체 계열 2,000행·대장 업체 조회 4,000행 단위).
- 기간 조회: `PERIOD_FROM_DATE`는 "직전 요청일 +1일", `PERIOD_TO_DATE`는 당일. 인터페이스·업체별 마지막 성공 조회일(watermark)을 우리 쪽에 영속해야 한다(표준 클라이언트의 `client.notify.date` 자동갱신은 주석뿐, 실구현 없음).
- `SUBCD_INCLUDE_YN`(하위업체 포함)은 대장 계열(T200_6001_01~04)에만 유효.
- 2024/2025 확장분(대장 6001 계열)은 요청 파라미터가 2020 공통 8필드와 다르다(`WSTE_CODE`/`GNTP`/`REMK`/`WSTE_TYPE`/`FIRM_NAME` 등 필터형). 인터페이스별 정의서 확인 필수.
- PUT은 전부 동기 결과회신이다(응답에 결과 즉시 포함, 비동기 재조회 아님). 수시 1건씩 제출한다.

## 4. 인터페이스 카탈로그 (유효 41종)

정의서 표지의 "43종"과 달리 고유 인터페이스는 41종이다(`T400_5001_01` 중복 등재 1건, 색인 결번은 폐기 인터페이스).

### 공통 (CMMN)

| ID | 이름 | 방식 | 주기 |
|---|---|---|---|
| T100_3001_00 | 공지사항 조회 | 조회 | 매일 3회 07/12/19시 |
| T100_3001_02 | 공통 코드 조회 | 조회 | 주 1회 일요일 |

### 배출자 (EMIS)

| ID | 이름 | 방식 | 주기 |
|---|---|---|---|
| T200_4001_01 | 배출 및 처리계획 조회 | 조회 | 매일 03:40 |
| T200_4001_05 | 업체정보 조회 | 조회 | 매일 03:41 |
| T200_4001_06 | 차량정보 조회 | 조회 | 매일 03:42 |
| T200_4001_08 | 인계번호 조회(발번 풀 수신) | 조회 | 매일 3회 |
| T200_4001_09 | 인계서 정보 조회(반려 정보 포함) | 조회 | 매일 3회 |
| T200_4001_10 | 발생량·자가처리내역 조회 | 조회 | 매일 03:44 |
| T200_4001_12 | 오류 인계서 조회 | 조회 | 매일 08:00 |
| T200_6001_01/02 | 사업장폐기물 대장 처리내역/월계 | 조회 | 매일 21:00/21:40 |
| T200_6001_03/04 | 건설폐기물 대장 처리내역/월계 | 조회 | 매일 21:20/21:50 |
| T200_6001_05/06 | 대장 운반/처리업체 조회 | 조회 | 매일 22:00/22:05 |
| T200_5001_01 | 인계서 정보 수집(등록) | 제출 | 수시 1건 |
| T200_5001_02 | 발생량·자가처리내역 수집 | 제출 | 수시 1건 |
| T200_7001_01 | 대장 처리내역 입력 | 제출 | 수시 1건 |
| T200_7001_02 | 대장 생성/해제(월 단위) | 제출 | 수시 1건 |

### 운반자 (TRAN)

| ID | 이름 | 방식 | 주기 |
|---|---|---|---|
| T300_4001_05 | 업체정보 조회 | 조회 | 매일 03:45 |
| T300_4001_12 | 오류 인계서 조회 | 조회 | 매일 08:10 |
| T300_4001_20 | 인계서(배출자) 정보 조회 | 조회 | 매일 3회 |
| T300_4001_21 | 인계서(운반자 인수) 정보 조회 | 조회 | 매일 3회 |
| T300_4001_34 | 차량정보 조회 | 조회 | 매일 03:46 |
| T300_6001_01~04 | 수집운반관리대장(일반/건설, 내역/월계) | 조회 | 매일 21:00~21:50 |
| T300_6001_05/06 | 대장 배출/처리업체 조회 | 조회 | 매일 22:00/22:05 |
| T300_5001_01 | 인계서 정보 수집(인수/인계 등록) | 제출 | 수시 1건 |
| T300_7001_01 | 수집운반대장 처리내역 입력 | 제출 | 수시 1건 |
| T300_7001_02 | 수집운반대장 생성/해제 | 제출 | 수시 1건 |

### 처리자 (TRTM)

| ID | 이름 | 방식 | 주기 |
|---|---|---|---|
| T400_4001_05 | 업체정보 조회 | 조회 | 매일 03:47 |
| T400_4001_12 | 오류 인계서 조회 | 조회 | 매일 08:20 |
| T400_4001_20 | 인계서(배출자) 정보 조회 | 조회 | 매일 3회 |
| T400_4001_21 | 인계서(처리자 인수) 정보 조회 | 조회 | 매일 3회 |
| T400_4001_22 | 처리실적 정보 조회 | 조회 | 매일 3회 |
| T400_4001_35 | 차량정보 조회 | 조회 | 매일 03:48 |
| T400_5001_01 | 인계서·계량증명 정보 수집(인수+계근) | 제출 | 수시 1건 |
| T400_5001_02 | 처리실적 정보 수집 | 제출 | 수시 1건 |

처리자 대장 PUT은 정의서에 없다.

## 5. 핵심 제출(PUT) 페이로드

전 필드 String(snake_case 그대로 JSON 키). 수량은 값 + 단위코드(A6) 쌍이다. null 값 필드는 JSON에 싣지 않는다(직렬화에서 제외 — 표준 클라이언트의 gson 기본 동작과 동일). 재구현 시에도 null 제외 직렬화를 규칙으로 강제한다.

### T200_5001_01 — 배출자 인계서 등록 (22필드)

`ENTN_LKCD`(PK1), `MANF_NUMS`(PK2 — T200_4001_08에서 발번받은 번호, 임의 생성 불가), `EMIS_CHRG`, `WSTE_CODE`(A0), `GNTP`(A2), `GIVE_QUNT`/`GIVE_QUNT_UNIT`(인계량), `TRAN_CHRG`, `TRTM_CHRG`, `GIVE_DATE`(14), `GIVE_CHRG_NAME`, `TRTM_WAYS`(A3), `CMPT_AUTH`(A1), `CERTFORM_INFO`(AI), `CERT_PDATE`, `CERT_PINFO`, `TRTM_SITE`, `VEHC_NUMS`(null이면 예약입력), `WSTE_REMK`, `MANB_TYPE`(**0 예약등록 / 1 확정등록 / 2 삭제**), `WSTE_TYPE`(AJ).

예약(0) 시 배출량 0이어야 하고(오류 1017), 확정(1) 시 배출량 > 0이어야 한다(오류 1018).

### T300_5001_01 — 운반자 인수/인계 등록 (12필드)

`ENTN_LKCD`(PK1), `MANF_NUMS`(PK2), `TRAN_CHRG`, `TRAN_NUMS`(차량번호), `RECV_DATE`, `RECV_QUNT`/`RECV_UNIT`(인수량), `DPST_YSNO`(보관장소 경유 0/1), `GIVE_DATE`, `GIVE_CHRG_NAME`, `MANB_TYPE`(**3 인수/인계등록 / 2 삭제**).

### T400_5001_01 — 처리자 인수 + 계량증명 (18필드)

`ENTN_LKCD`, `MANF_NUMS`, `TRTM_CHRG`, `RECV_DATE`, `RECV_QUNT`/`RECV_QUNT_UNIT`(필수), `RECV_CHRG_NAME`, `TRAN_NUMS`, **`WEIT_NUMS`(계량번호, 업체 발급, PK3)**, **`SEQX`(발송순번, PK4)**, `FULL_WEIT_DATE`/`FULL_QUNT`(총중량), `EMTY_WEIT_DATE`/`EMTY_QUNT`(공차중량), `LOAD_QUNT`(실중량), `ORGL_LOAD_QUNT`(실중량 측정원본 — 단위변환 전), `MANB_TYPE`(**3 인수등록 / 5 계량증명 / 2 삭제**).

계근 자연키는 `WEIT_NUMS + SEQX`다. 실중량은 원본(`ORGL_LOAD_QUNT`)과 변환값(`LOAD_QUNT`)을 분리 보존한다.

### T400_5001_02 — 처리실적 (11필드)

`ENTN_LKCD`(PK1), `MANF_NUMS`(PK2), `TRTM_CHRG`(PK3), `TRTM_DATE`(PK4), `NUMS`(실적 순번, PK5), `TRTM_WAYS`(A3), `TRTQ`/`TRTQ_UNIT`(처리량), `LEFT_QUNT`(잔량), `MANB_TYPE`(**1 입력 / 2 삭제**). 인계서 1건에 처리실적 다건(중간→최종)이 순번으로 누적되고 잔량으로 추적된다.

### T*_7001_01/02 — 대장 처리내역 입력 / 대장 생성

- 처리내역 입력 키: `ENTN_LKCD + ENTN + MANB_DATE + WSTE_CODE + GNTP + NUMS`. 수정/삭제 시 이 키는 변경 불가. `WSTE_CODE`에 따라 일반/건설 대장이 자동 분기되고 해당 허가증(AI) 미보유 시 오류 1037.
- 처리방법 접두 규칙: 자가중간 = 10XX/11XX, 자가최종 = 12XX/13XX/15XX. 위반 시 오류 1022.
- `RPT_GB`(AK): 배출자 대장 = 1(사업장)/16(건설), 운반자 대장 = 3(수집운반)/17(건설 수집운반).
- 대장 생성은 월 단위(`MANB_TYPE` 1), 해제는 전체 해제(`MANB_TYPE` 2, `PCLS_DATE` null 시). 성공 코드 0004(당월)/0005(전체).

## 6. MANB_TYPE 상태 전이와 ZERRO 매핑

`MANB_TYPE`(공통코드 AA: 0 예약, 1 확정/입력, 2 삭제, 3 인수/인계등록, 4 인계등록, 5 계량증명)이 인계서 협업 문서의 전이 키다.

```
배출자 예약(0) → 배출자 확정(1) → 운반자 인수/인계(3) → 처리자 인수(3) → 처리자 계량증명(5) → 처리실적 입력(1, 잔량 소진까지 반복)
```

ZERRO handover 라이프사이클과의 대응:

| ZERRO 단계 | 올바로 제출 |
|---|---|
| 배출 신청 접수(차량 미정) | T200_5001_01 `MANB_TYPE=0` (예약) |
| 배차 확정 + 상차 | T200_5001_01 `MANB_TYPE=1` (확정, 차량번호 포함) |
| 운반 완료(하차) | T300_5001_01 `MANB_TYPE=3` |
| 처리장 입고 | T400_5001_01 `MANB_TYPE=3` |
| 계근 등록 | T400_5001_01 `MANB_TYPE=5` |
| 처리 실적 | T400_5001_02 `MANB_TYPE=1` |

HALF MODE(당일 배차)는 가이드·정의서에 직접 언급이 없다. 예약(0)→확정(1) 2단계가 그 대응 후보이나 문서 근거로 단정할 수 없어, 공단 확인 전까지 미확정으로 둔다(후속 open question).

반려 인계서는 API로 수정 불가(오류 1028/1029 — 올바로 웹에서만 처리), 재제출은 삭제 후 새 인계번호가 필요하다(1030). 반려 정보는 인계서 조회 응답의 `TRAN_RETURN_*`/`TRTM_RETURN_*` 8필드로 읽는다.

## 7. 공통코드 (T100_3001_02, 21그룹 1,315행)

| 그룹 | 이름 | 값 수 | ZERRO 사용 |
|---|---|---|---|
| A0 | 폐기물코드 | 647 | 계약·인계서·대장. 신코드(6자리)와 구코드("(구)" 표기) 병존 — 미러 시 legacy 구분 필요 |
| A1 | 관할관청 | 324 | 인계서 필드 |
| A2 | 성상 | 4 (고상/기타/액상/액상고상) | 계약·인계서·대장 키 |
| A3 | 처리방법 | 92 (0000 발생량, 1XXX 자가, 2XXX 위탁, 9000 재위탁) | 계약·처리실적·대장 |
| A4/A5 | 처리/운반구분 | 각 2 (위탁/자가) | 처리계획 |
| A6 | 단위코드 | 3 (01 Ton / 02 kg / 03 g) | 모든 수량 필드의 짝 |
| A7 | 업체구분 | 9 (배출/운반/처리 복합 역할 포함) | 업체 마스터 |
| A8 | 업체상태 | 24 (01 정상, 02 폐업 등) | 업체 마스터 |
| A9 | 차량종류 | 5 | 차량 마스터 (ZERRO 자체 5종과 별개 체계) |
| AA | 연계실적구분 | 6 | MANB_TYPE (6절) |
| AB | 연계오류코드 | 62 | 오류 처리 (8절) |
| AC | 폐기물분류 | 5 (지정/일반/의료/지정·일반/건설) | 차량·업체 |
| AD | 처리업구분 | 8 | 처리자 차량 조회 |
| AE~AH | 해역배출 계열 | 2/40/4/19 | 해역배출 시나리오만 |
| AI | 필증정보 | 31 (D/M/T + IE 계열) | 대장 생성 자격 검증 |
| AJ | 사업장폐기물구분 | 2 | 대장 분기 플래그 |
| AK | 대장구분 | 24 (주력: 1/3/16/17) | 대장 PUT `RPT_GB` |

주 1회 폴링으로 로컬 코드 테이블에 미러링한다. `FMAN_TYPE`(04/05), `SRVC_TYPE`(O/T), `DPST_YSNO`, `AUTO_GENE_YSNO` 등 코드그룹 미등재 값은 앱 상수로 관리한다.

## 8. 에러 처리

`RESULT_CODE` 주요 값(전체 62종은 공통코드 AB):

| 코드 | 의미 | 처리 |
|---|---|---|
| 0000 | 정상 | — |
| 0001/0002/0003 | 예약/확정/삭제 정상 | — |
| 0004/0005 | 당월/전체 대장생성 완료 | — |
| 1004 | 이미 사용된 인계번호 | 발번 풀 재조회 |
| 1011 | 처리실적 중복입력 | 멱등 처리(성공 간주 검토) |
| 1017/1018 | 예약 시 배출량 존재 / 확정 시 배출량 없음 | 제출 전 검증 |
| 1022 | 허용 안 된 처리방법 접두 | 제출 전 검증 |
| 1028/1029/1030 | 반려 인계서(수정 불가/재작성 필요) | 재시도 금지, 사용자 안내 |
| 1037 | 허가증 미보유(대장 생성 불가) | 고객사 자격 사전 검증 |
| 9001~9005 | 연계 미등록/휴면/인증키 오류 | 재시도 금지, 크리덴셜 점검 알림 |
| 9010 | 조회 성공·0건 (클라이언트 관용 코드) | 정상 처리, watermark 전진 |
| 9011 | 요청 파라미터 오류 (클라이언트 판정) | 즉시 실패(버그) |
| 9999 | 예상치 못한 오류 | TX_ID 기록, 보수적 재시도 |

자동 재시도·백오프 규약은 문서에 없다. 자체 정의하되 rate 경고(강제 연계취소)를 고려해 보수적으로 설계한다.

오류 인계서는 역할별 T*_4001_12로 매일 아침(08:00/08:10/08:20) 폴링한다. 응답: `MANF_NUMS`, `START_DATE`/`END_DATE`(최초·최종 발생), `FMAN_ITMS`(오류 내역), `FMAN_TYPE`(**04 불일치 / 05 기한초과**). 미해결 오류 인계서 알림·재처리 큐의 원천이다. PC "올바로 오류" 화면이 이 데이터를 표시한다.

## 9. 폴링 스케줄 규약

- 각 조회 인터페이스는 "지정 시간창 내 랜덤 1회" 실행이 규약이다(부하 분산). 표준 클라이언트도 Quartz cron의 초/분을 부팅 시 랜덤 생성한다.
- 시간대 설계: 새벽 03:40~03:48 = 업체·차량·처리계획, 07/12/19시 = 인계서·인계번호 인트라데이, 08:00~08:20 = 오류 인계서, 21:00~22:05 = 대장, 일요일 = 공통코드.
- 00:30~01:00 점검창은 스케줄에서 제외한다.
- PUT은 수시(이벤트 드리븐, ZERRO 상태 전이 시 즉시 제출).

## 10. ZERRO 백엔드 설계 시사점

1. **동기화 스케줄러**: Spring Scheduler + 시간창 내 지터. 다중 인스턴스는 ShedLock 등 분산 락으로 중복 호출 방지(중복 폴링 = 강제취소 리스크). 고객사 수만큼 크리덴셜별 호출이 발생하므로 창 내 오프셋 분산.
2. **sync 커서 테이블**: 인터페이스 × 고객사(연계업체코드)별 watermark(마지막 성공 조회일)·페이지 진행 상태를 DB에 영속. 전체(A) 조회는 전 페이지 순회 완료 후에만 watermark 전진(부분 유실 방지).
3. **요청/응답 로그**: 기존 `olbaro_request_log`(append-only) 설계와 부합. TX_ID·resultCode·errorMessage 저장, 인증키는 마스킹.
4. **크리덴셜**: 고객사별 4종 시크릿, 기존 `olbaro_credential` 테이블의 암호화 저장·회전(테스트→운영 교체) 설계와 부합.
5. **코드 미러**: `olbaro_code`(code_type, code, code_name, legacy 여부) 테이블 신설, 주 1회 갱신.
6. **외부 식별자 컬럼**: 업체 = `ENTN_LKCD`(연계코드)/`ENTN`(업체번호), 인계 = `MANF_NUMS`(발번 풀 수신 후 사용), 계근 = `WEIT_NUMS + SEQX`, 처리실적 = `MANF_NUMS + TRTM_DATE + NUMS`.
7. **수량 표현**: 값(numeric) + 단위코드(A6) 쌍. 계근은 총중량/공차/실중량/측정원본 4값 보존.
8. **반려 상태 모델링**: 반려 인계서는 재시도 루프에 넣지 않는 터미널 상태 + 신규 인계번호 재작성 플로우.
9. **업체 전화·이메일은 올바로가 제공하지 않는다** — ZERRO 자체 수집 필수.

## 11. 후속 open questions

- HALF MODE ↔ 예약(0)/확정(1) 매핑 검증 (공단 문의 또는 테스트 계정 실측).
- T300_6001_06(대장 처리업체 조회)의 DataList 첫 필드가 `TRAN_CHRG`로 표기된 정의서 내부 불일치 — 실응답으로 확인.
- 자동 재시도 정책 자체 확정 (문서 규약 없음).
- 테스트 계정 신청 시점 결정 (30일 유효 제약 — backend scaffold와 맞물려 신청).
