📖 개요 — 이 글에서 다루는 내용
ABAP 시스템에서 외부 REST API를 호출해야 하는 순간은 반드시 옵니다. 환율 조회, 배송 추적, 사내 미들웨어 연동까지, 온프레미스 SAP ECC / S/4HANA(온프레미스) 환경에서는 CL_HTTP_CLIENT가 사실상 표준 진입점입니다. 이 글은 "어디서 본 것 같은데 막상 짜면 막히는" HTTP 클라이언트 코드를 GET/POST 실전 예제로 정리합니다.
- ✅
CL_HTTP_CLIENT의 생성 방식 3가지(URL / Destination / Proxy) 구분 - ✅ GET으로 JSON 응답 받아 파싱하는 기본 흐름
- ✅ POST + JSON Body + 에러 처리 + 로깅이 들어간 실무 코드
- ✅ SM59 Destination, 타임아웃, SSL, 커넥션 정리 등 프로덕션 체크포인트
📚 미리 알아두면 좋은 배경
ABAP OO 문법(클래스, 메서드 호출, 예외 처리 TRY...CATCH)과 HTTP 기본 개념(메서드, 상태 코드, 헤더, Body)을 알고 있다면 충분합니다. JSON 직렬화는 /UI2/CL_JSON을 사용하므로 별도 파서 지식은 필요 없습니다.
🔧 환경 · 버전 · 준비물
- 시스템: SAP NetWeaver AS ABAP 7.40 SP08 이상 (ECC 6.0 EHP7+, S/4HANA 온프레미스 전 버전에서 동일 패턴 적용 가능)
- 클래스:
CL_HTTP_CLIENT(구현),IF_HTTP_CLIENT(인터페이스) — ICM(Internet Communication Manager) 기반 - HTTPS 호출 시: 트랜잭션
STRUST에서 대상 서버의 CA 인증서를 SSL Client(Anonymous 또는 표준) PSE에 등록 - 권장 사전 설정:
SM59에서 Type G(HTTP to External Server) Destination 생성 — URL 하드코딩 대신 운영 표준으로 일반적으로 권장됩니다 - 참고로 SAP BTP ABAP Environment(Steampunk)에서는
CL_HTTP_CLIENT가 릴리스되지 않아CL_WEB_HTTP_CLIENT_MANAGER를 사용해야 합니다. 이 글은 온프레미스 기준입니다.
💡 핵심 개념 — ICM 위에 올라탄 우체국 창구
CL_HTTP_CLIENT를 우체국 창구에 비유하면 구조가 쉽게 잡힙니다. 개발자는 편지(Request)를 쓰고 창구(클라이언트 인스턴스)에 접수하면, 실제 배달은 ICM이라는 우체부가 수행합니다. 즉 ABAP 코드는 소켓을 직접 다루지 않고, 커널 레벨의 ICM에 위임합니다.
흐름은 항상 5단계로 고정됩니다.
- 생성:
create_by_url(테스트·간단 호출) 또는create_by_destination(운영 권장) — Destination 방식은 URL·인증·프록시·SSL 설정을 SM59로 외부화하므로 이관 시 코드 수정이 필요 없습니다. - 요청 구성:
request객체(IF_HTTP_REQUEST)에 메서드·헤더·Body 설정 - 전송:
send( )— 이 시점에 ICM이 실제 TCP 연결을 열고 요청을 내보냄 - 수신:
receive( )— 응답이 올 때까지 대기(타임아웃 적용 지점) - 정리:
response에서 상태 코드·Body를 읽고close( )로 커넥션 반납
자주 혼동하는 포인트 두 가지. 첫째, send와 receive는 반드시 쌍으로 호출해야 하며 각각 별도의 예외를 던집니다. 둘째, 예외는 클래스 기반이 아니라 클래식 예외(EXCEPTIONS 절 + sy-subrc)라는 점입니다. 그래서 TRY...CATCH가 아니라 호출 직후 sy-subrc 분기가 필요합니다. 이 두 가지만 지켜도 "왜 응답이 비어 있지?" 류의 문제 대부분이 사라집니다.
💻 실전 코드 — 3단계로 완성하기
1단계: GET 기본 예제 — 환율 조회
공개 환율 API에서 USD 기준 환율 JSON을 받아오는 최소 코드입니다.
DATA: lo_client TYPE REF TO if_http_client,
lv_json TYPE string,
lv_status TYPE i.
cl_http_client=>create_by_url(
EXPORTING url = 'https://api.frankfurter.app/latest?from=USD&to=KRW'
IMPORTING client = lo_client
EXCEPTIONS argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
IF sy-subrc <> 0.
MESSAGE '클라이언트 생성 실패' TYPE 'E'.
ENDIF.
lo_client->request->set_method( if_http_request=>co_request_method_get ).
lo_client->request->set_header_field( name = 'Accept' value = 'application/json' ).
lo_client->send( EXCEPTIONS OTHERS = 1 ).
lo_client->receive( EXCEPTIONS OTHERS = 1 ).
lo_client->response->get_status( IMPORTING code = lv_status ).
lv_json = lo_client->response->get_cdata( ).
lo_client->close( ).
cl_demo_output=>display( |HTTP { lv_status }: { lv_json }| ).
get_cdata는 문자 데이터, 바이너리(파일 다운로드 등)는 get_data를 사용합니다.
2단계: 실무 시나리오 — POST + 에러 처리 + 로깅
판매오더 확정 결과를 외부 물류 시스템에 POST로 전송하는 시나리오입니다. JSON 직렬화, 상태 코드 분기, 실패 로그를 포함합니다.
TYPES: BEGIN OF ty_shipment_req,
sales_order TYPE vbeln_va,
ship_to TYPE string,
total_weight TYPE p LENGTH 13 DECIMALS 3,
END OF ty_shipment_req.
DATA(ls_req) = VALUE ty_shipment_req(
sales_order = '0000012345'
ship_to = 'Busan DC-02'
total_weight = '148.500' ).
" ABAP 구조 → JSON (camelCase 변환)
DATA(lv_body) = /ui2/cl_json=>serialize(
data = ls_req
pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
DATA lo_client TYPE REF TO if_http_client.
cl_http_client=>create_by_destination(
EXPORTING destination = 'ZLOGISTICS_API' " SM59 Type G
IMPORTING client = lo_client
EXCEPTIONS OTHERS = 1 ).
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE zcx_api_error MESSAGE e001(zapi).
ENDIF.
lo_client->request->set_method( if_http_request=>co_request_method_post ).
lo_client->request->set_header_field( name = 'Content-Type'
value = 'application/json; charset=utf-8' ).
lo_client->request->set_cdata( lv_body ).
lo_client->send( EXCEPTIONS http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4 ).
IF sy-subrc = 0.
lo_client->receive( EXCEPTIONS http_communication_failure = 1
OTHERS = 2 ).
ENDIF.
IF sy-subrc <> 0.
lo_client->get_last_error( IMPORTING message = DATA(lv_errtext) ).
zcl_app_log=>get( object = 'ZAPI' )->add_error( lv_errtext )->save( ).
lo_client->close( ).
RETURN.
ENDIF.
lo_client->response->get_status( IMPORTING code = DATA(lv_code) ).
DATA(lv_resp) = lo_client->response->get_cdata( ).
lo_client->close( ).
CASE lv_code.
WHEN 200 OR 201.
/ui2/cl_json=>deserialize( EXPORTING json = lv_resp
CHANGING data = DATA(ls_result) ).
WHEN 401 OR 403.
" 인증 문제 → SM59 인증 설정 점검 유도
WHEN OTHERS.
zcl_app_log=>get( object = 'ZAPI'
)->add_error( |HTTP { lv_code }: { lv_resp }| )->save( ).
ENDCASE.
3단계: 프로덕션 체크 — 타임아웃 · 재시도 · 테스트 가능 설계
" (1) 타임아웃: receive 무한 대기 방지 — 초 단위
lo_client->set_timeout( timeout = 10 ).
" (2) 압축 응답 허용으로 대역폭 절감
lo_client->request->set_header_field( name = 'Accept-Encoding' value = 'gzip' ).
" (3) 인증 토큰은 하드코딩 금지 — SM59 or SSF/시크릿 테이블에서 조회
lo_client->request->set_header_field(
name = 'Authorization'
value = |Bearer { zcl_token_store=>get( 'ZLOGISTICS' ) }| ).
" (4) 일시 오류(429/503) 백오프 재시도 골격
DO 3 TIMES.
DATA(lv_try) = sy-index.
" ... send / receive / get_status ...
IF lv_code <> 429 AND lv_code <> 503. EXIT. ENDIF.
WAIT UP TO lv_try SECONDS.
ENDDO.
테스트 관점에서는 if_http_client 타입 참조를 생성자 주입으로 받도록 래퍼 클래스(ZCL_LOGISTICS_GATEWAY 등)를 만들어 두면, ABAP Unit에서 테스트 더블로 교체해 실제 네트워크 없이 상태 코드별 분기를 검증할 수 있습니다.
⚠️ 흔한 실수와 트러블슈팅
- close( ) 누락: 대량 배치에서 커넥션이 고갈되어 ICM 큐가 밀립니다. 성공/실패 모든 경로에서
close를 호출하세요. - sy-subrc 미확인: 클래식 예외라서 확인하지 않으면 오류가 조용히 지나가고 빈 응답만 남습니다.
- Content-Type 누락 POST: 상당수 API가 415 또는 400을 반환합니다. charset=utf-8까지 명시하는 편이 안전합니다.
Q1. HTTPS 호출 시 "SSL handshake failed"가 발생합니다.
A. 대상 서버 인증서 체인(루트 CA 포함)이 STRUST의 SSL Client PSE에 없기 때문입니다.
Q2. 사내 프록시 뒤에서 외부 API가 안 나갑니다.
A. SM59 Destination의 HTTP Proxy 설정을 사용하거나create_by_url의 proxy 파라미터를 지정하세요.
Q3. 응답 한글이 깨집니다.
A.response->get_data( )로 xstring을 받아cl_abap_conv_in_ce(UTF-8)로 직접 변환하면 해결됩니다.
Q4. receive에서 세션이 멈춥니다.
A.set_timeout미설정이 원인입니다. 코드에서 명시적으로 지정하세요.
🚀 이후 확장해볼 주제
- REST 라이브러리 계층:
CL_REST_HTTP_CLIENT로 리소스 중심 호출 추상화 - OAuth 2.0:
OA2C_CONFIG기반 클라이언트 자격증명 플로우 연동 - Clean Core 대비: BTP ABAP Environment의
CL_WEB_HTTP_CLIENT_MANAGER+ Communication Arrangement 패턴으로 마이그레이션 - 인바운드 방향: SICF 핸들러(
IF_HTTP_EXTENSION)로 ABAP을 REST 서버로 노출
📚 더 깊이 볼 자료
- SAP Help Portal — HTTP Client in ABAP (IF_HTTP_CLIENT)
- SAP Help Portal — Internet Communication Framework(ICF) 개요
- SAP Help Portal — Trust Manager(STRUST)와 SSL 구성
- SAP Help Portal — RFC/HTTP Destination(SM59) 관리
댓글 0
아직 댓글이 없습니다.