개요 및 이 글에서 얻어갈 것
ABAP에서 타입 변환은 가장 빈번하게 일어나는 작업이지만, 동시에 가장 많은 런타임 오류(CX_SY_CONVERSION_NO_NUMBER, CX_SY_CONVERSION_OVERFLOW)를 일으키는 영역입니다. 7.40 이전에는 MOVE 또는 단순 대입(=)으로 처리했지만, 7.40 SP02부터 도입된 CONV 생성자 연산자(constructor operator)는 인라인 선언과 결합되어 코드 안정성과 가독성을 동시에 끌어올립니다. 이 글에서는 CONV의 내부 동작, MOVE 대비 장점, 그리고 실무에서 자주 마주치는 함정을 다룹니다.
- CONV 연산자의 문법과 컴파일 타임 타입 추론 방식 이해
- MOVE/직접 대입과 CONV의 동작 차이 비교
- 판매오더, 자재마스터 등 실무 시나리오에 CONV 적용
- 변환 실패 시 예외 처리(
CONV ... ( ... )+ TRY-CATCH) 패턴 정착 - 흔한 오버플로/문자→숫자 변환 함정 회피
이 글을 읽기 전 알아두면 좋은 것
ABAP 7.40 이상의 인라인 선언(DATA(...)), 기본 데이터 타입(C, N, P, I, STRING, DECFLOAT), 클래스 기반 예외 처리(TRY/CATCH/CX_ROOT) 개념을 익혀두시기 바랍니다. RAP나 CDS 작업 중 BAPI/RFC 반환값을 ABAP 내부 타입으로 옮길 때 CONV가 자주 등장하므로, ABAP Dictionary의 도메인·데이터 엘리먼트 구조도 함께 알면 도움이 됩니다.
환경·버전·준비물
CONV 연산자는 ABAP 7.40 SP02 이상에서 사용할 수 있으며, 본 글의 예제는 SAP S/4HANA 2022 FPS02(ABAP Platform 2022) 환경의 ADT(ABAP Development Tools for Eclipse 2025-03)에서 검증되었습니다. SAP BTP ABAP Environment(Steampunk)와 on-premise NetWeaver 7.50 이상에서도 동일하게 동작합니다. 실습용으로는 사용자 정의 패키지($TMP 또는 로컬 객체)와 SE38 클래식 리포트 또는 ADT의 Class/Report 객체가 필요합니다. 컴파일 옵션은 Unicode 활성화 상태가 일반적으로 권장됩니다.
참고: 7.40 미만 시스템에서는 CONV가 컴파일 오류를 내므로, 마이그레이션 전 시스템 코드 점검(ATC)에서
SLIN_ABAP_RELEASE_CHECK를 활성화해 두는 것이 안전합니다.
CONV는 어떻게 동작하는가
CONV는 "타입을 명시적으로 지정해 임시 변수를 만든 뒤 거기에 값을 변환해 담는" 생성자 연산자입니다. 문법은 CONV dtype|#( expression ) 형태로, dtype 자리에는 데이터 타입명이나 데이터 엘리먼트가 오고, #은 컨텍스트에서 타입을 자동 추론하라는 의미입니다.
비유하자면 MOVE/대입은 "값을 그냥 옮겨라"고 시스템에 맡기는 방식이고, CONV는 "이 값을 정확히 이 타입의 임시 컨테이너에 담아서 넘겨라"고 명시하는 방식입니다. 차이는 다음에서 두드러집니다.
- 인라인 선언과의 결합:
DATA(x) = some_string.은 x가 자동으로 STRING이 됩니다. 하지만 함수 시그니처가 C(10)을 요구하면 타입 충돌이 발생합니다. CONV는DATA(x) = CONV char10( some_string ).한 줄로 의도된 타입을 부여합니다. - 메서드 파라미터 전달: IMPORTING 파라미터가
P DECIMALS 2인데 호출부에 STRING을 가지고 있을 때, MOVE는 별도 변수 선언이 필요하지만 CONV는 호출식 안에서 즉시 변환 가능합니다. - 표현식 평가 시점: CONV는 컴파일 타임에 타입이 결정되므로, 코드를 읽는 사람이 변환 의도를 즉시 파악할 수 있습니다. MOVE는 런타임에 좌변 타입을 보고 변환하므로 의도가 묻힙니다.
내부적으로 CONV는 일반 대입(=) 규칙과 동일한 변환 표를 따릅니다. 즉 C → N 변환 시 비숫자 문자가 있으면 CX_SY_CONVERSION_NO_NUMBER, P → I 변환 시 범위를 넘으면 CX_SY_CONVERSION_OVERFLOW가 발생합니다. CONV가 "안전한 변환"을 보장하는 것이 아니라, "변환 지점을 명확히 드러내 예외 처리를 강제"하는 도구라는 점이 핵심입니다.
1단계 — 기본 형태 익히기
판매오더 번호 문자열을 숫자형 도메인에 담아야 하는 가장 단순한 케이스부터 보겠습니다.
REPORT zr_conv_basic.
DATA: lv_order_text TYPE string VALUE '0000045231',
lv_order_num TYPE n LENGTH 10.
" 7.40 이전 방식
MOVE lv_order_text TO lv_order_num.
WRITE: / 'MOVE 결과 :', lv_order_num.
" CONV 방식 — 동일 결과, 의도 명확
DATA(lv_converted) = CONV n( lv_order_text ).
WRITE: / 'CONV 결과 :', lv_converted.
" 메서드 호출부에서 인라인 변환
DATA(lv_amount_str) = '1234.56'.
DATA(lv_amount) = CONV p( lv_amount_str ). " 타입 추론 대신 명시
WRITE: / 'Amount :', lv_amount.
위 코드에서 핵심은 마지막 두 줄입니다. DATA(lv_amount) = lv_amount_str로 썼다면 lv_amount는 STRING으로 추론되었을 것입니다. CONV로 감싸는 순간 P 타입으로 고정되며, 이후 산술 연산에서 의도하지 않은 문자열 연결 같은 사고를 막을 수 있습니다.
2단계 — 실무 시나리오와 예외 처리
판매오더 헤더 BAPI를 호출한 뒤, 반환된 문자열 금액을 내부 P 타입 필드로 옮기는 상황입니다. 외부 데이터는 신뢰할 수 없으므로 반드시 예외 처리를 동반해야 합니다.
CLASS zcl_so_amount_parser DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES: BEGIN OF ty_so_input,
order_id TYPE string,
net_amount TYPE string,
currency TYPE string,
END OF ty_so_input.
TYPES: BEGIN OF ty_so_parsed,
order_id TYPE vbeln_va,
net_amount TYPE netwr,
currency TYPE waers,
END OF ty_so_parsed.
METHODS parse
IMPORTING is_input TYPE ty_so_input
RETURNING VALUE(rs_parsed) TYPE ty_so_parsed
RAISING cx_sy_conversion_no_number
cx_sy_conversion_overflow.
ENDCLASS.
CLASS zcl_so_amount_parser IMPLEMENTATION.
METHOD parse.
rs_parsed-order_id = CONV vbeln_va( is_input-order_id ).
rs_parsed-net_amount = CONV netwr( is_input-net_amount ).
rs_parsed-currency = CONV waers( is_input-currency ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(lo_parser) = NEW zcl_so_amount_parser( ).
TRY.
DATA(ls_result) = lo_parser->parse(
VALUE #( order_id = '0000045231'
net_amount = '15000.75'
currency = 'EUR' ) ).
WRITE: / ls_result-order_id, ls_result-net_amount, ls_result-currency.
CATCH cx_sy_conversion_no_number INTO DATA(lx_no_num).
MESSAGE |숫자 변환 실패: { lx_no_num->get_text( ) }| TYPE 'E'.
CATCH cx_sy_conversion_overflow INTO DATA(lx_ovf).
MESSAGE |오버플로: { lx_ovf->get_text( ) }| TYPE 'E'.
ENDTRY.
MOVE 기반 코드와 비교하면, 어느 라인에서 어떤 타입으로 변환이 일어나는지가 한눈에 드러납니다. 트러블슈팅 시 ST22 덤프의 호출 스택과 코드 라인을 1:1로 맞추기가 쉬워집니다.
3단계 — 프로덕션 품질: 로깅, 단위 테스트, 안전 변환
실제 운영 코드에서는 변환 실패를 단순 덤프가 아닌 애플리케이션 로그로 남기고, ABAP Unit으로 회귀 테스트까지 작성합니다.
CLASS zcl_safe_converter DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS to_amount
IMPORTING iv_text TYPE string
iv_default TYPE netwr DEFAULT 0
RETURNING VALUE(rv_amount) TYPE netwr.
ENDCLASS.
CLASS zcl_safe_converter IMPLEMENTATION.
METHOD to_amount.
TRY.
rv_amount = CONV netwr( iv_text ).
CATCH cx_sy_conversion_no_number
cx_sy_conversion_overflow INTO DATA(lx_conv).
cl_bali_log_db=>get_instance(
)->save_log( EXPORTING io_log = NEW cl_bali_log(
iv_subobject = 'CONV_FAIL' ) ).
rv_amount = iv_default.
ENDTRY.
ENDMETHOD.
ENDCLASS.
CLASS ltcl_converter DEFINITION FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS:
valid_decimal FOR TESTING,
invalid_text FOR TESTING,
overflow_value FOR TESTING.
ENDCLASS.
CLASS ltcl_converter IMPLEMENTATION.
METHOD valid_decimal.
cl_abap_unit_assert=>assert_equals(
act = zcl_safe_converter=>to_amount( '999.99' )
exp = CONV netwr( '999.99' ) ).
ENDMETHOD.
METHOD invalid_text.
cl_abap_unit_assert=>assert_equals(
act = zcl_safe_converter=>to_amount( 'ABC' )
exp = CONV netwr( 0 ) ).
ENDMETHOD.
METHOD overflow_value.
cl_abap_unit_assert=>assert_equals(
act = zcl_safe_converter=>to_amount(
'99999999999999999999' iv_default = 0 )
exp = CONV netwr( 0 ) ).
ENDMETHOD.
ENDCLASS.
이 패턴의 장점은 (1) 호출부가 예외 처리 없이도 안전한 기본값을 받을 수 있고, (2) 변환 실패 통계를 BAL로 집계해 데이터 품질 모니터링이 가능하며, (3) 단위 테스트로 회귀를 막을 수 있다는 점입니다. 성능 측면에서 CONV는 컴파일 시점 타입 결정이라 런타임 오버헤드가 사실상 없습니다.
실무에서 자주 밟는 지뢰와 FAQ
Q1. DATA(x) = CONV i( '12.7' ).의 결과는? — 12가 아닌 13입니다. P → I 변환은 반올림(commercial rounding) 규칙을 따릅니다. 절사하고 싶다면 FLOOR( ) 같은 내장 함수를 함께 사용해야 합니다.
Q2. CONV로 감쌌는데도 변환 오류가 안 잡힙니다. — CONV는 변환 규칙 자체를 바꾸지 않습니다. C → STRING처럼 손실 없는 변환은 절대 예외를 던지지 않습니다. 반대로 STRING → I, STRING → P처럼 데이터 손실 가능성이 있는 경로에서만 예외가 발생합니다.
Q3. CONV #( ... )를 어디서나 써도 되나요? — 컨텍스트에서 타입 추론이 가능한 자리(메서드 파라미터, RETURNING, ASSIGN 대상)에서만 작동합니다. 인라인 DATA(...) 우변에 CONV #( ... )를 쓰면 추론 컨텍스트가 없어 컴파일 오류가 납니다.
그 외 자주 발생하는 실수: ① 통화 필드(WAERS)에 소문자를 넣는 경우 — CONV는 변환만 할 뿐 도메인 변환 루틴(CONVERSION_EXIT)은 자동 호출되지 않으므로 별도 함수 모듈을 거쳐야 합니다. ② 날짜 변환 — STRING '20260619'을 DATS로 CONV하면 잘 되지만, '2026-06-19'는 실패합니다. 외부 포맷은 cl_abap_datfm 또는 cl_abap_tstmp를 먼저 거치는 것이 권장됩니다. ③ AMDP나 CDS에서 받은 결과를 CONV로 좁히는 경우, HANA 측 타입(NVARCHAR vs ABAP STRING) 차이로 길이 잘림이 발생할 수 있습니다.
여기서 더 나아가려면
CONV를 익혔다면 자연스럽게 다른 생성자 연산자도 함께 다루게 됩니다. 값 생성에는 VALUE, 참조 변환에는 CAST(다운캐스팅, CX_SY_MOVE_CAST_ERROR), 객체 생성에는 NEW, 조건 평가에는 COND·SWITCH가 있습니다. 특히 CAST는 CONV와 이름이 비슷하지만 참조 타입 변환이라 동작이 완전히 다르므로 분리해서 학습하시기 바랍니다.
댓글 0
아직 댓글이 없습니다.