개요: 이 글에서 얻어갈 것
ABAP에서 문자열을 조합할 때 아직도 CONCATENATE를 쓰고 있다면, 이 글이 코드 스타일을 바꾸는 계기가 될 것입니다. ABAP 7.02부터 도입된 String Template(|...{ }...|) 문법은 문자열 조합을 한 줄로, 그리고 훨씬 읽기 쉽게 만들어 줍니다. 이 글을 끝까지 읽으면 아래 항목을 스스로 할 수 있게 됩니다.
- String Template 기본 문법(
| |와{ })의 동작 원리 이해 - CONCATENATE 코드를 String Template으로 대체하는 3가지 실전 패턴 적용
- 변수 삽입, 조건 표현식(COND), 메서드 호출 결과를 템플릿 안에서 바로 사용
- 포맷 옵션(ALPHA, DATE, NUMBER 등)으로 출력 형식 제어
미리 알고 있으면 좋은 내용
ABAP 기본 데이터 타입(string, char, i, dats)과 변수 선언(DATA), 그리고 간단한 클래스/메서드 호출 경험이 있으면 충분합니다. CONCATENATE 문을 한 번이라도 써 봤다면 비교 포인트가 더 명확하게 보일 것입니다.
환경과 버전 준비
String Template은 ABAP 7.02(SAP NetWeaver 7.0 EhP2)부터 사용할 수 있고, 표현식 위치에서의 자유로운 활용(메서드 호출 결과 삽입, COND/SWITCH 결합 등)은 ABAP 7.40 이상에서 완전해집니다. 일반적으로 아래 환경이면 이 글의 모든 예제를 실행할 수 있습니다.
- SAP S/4HANA(온프레미스 또는 Cloud 에디션) — 전 릴리스에서 사용 가능
- SAP BTP ABAP Environment(Steampunk) — ABAP Cloud 개발 모델에서도 그대로 지원
- 구형 ECC라도 NetWeaver 7.40 이상이면 문제 없음
- 개발 도구: ADT(Eclipse) 권장, SE38/SE80도 가능
결과 확인은 온프레미스라면 cl_demo_output, ABAP Cloud라면 콘솔 인터페이스(if_oo_adt_classrun)를 쓰면 편리합니다.
핵심 개념: 왜 String Template인가
CONCATENATE는 "부품을 하나씩 조립하는" 방식입니다. 반면 String Template은 "완성된 문장 틀에 빈칸을 뚫어 놓고 값을 끼워 넣는" 방식입니다. 계약서 양식의 밑줄 빈칸을 채우는 것과 같아서, 코드만 봐도 최종 결과 문장이 그대로 눈에 들어옵니다. 기억할 기호는 두 가지뿐입니다.
| ... |— 파이프 기호 사이가 템플릿 리터럴 영역. 안의 텍스트(공백 포함)는 그대로 출력됩니다.{ ... }— 중괄호 안은 표현식 영역. 변수는 물론 연산식, 메서드 호출, COND/SWITCH 표현식까지 평가된 뒤 문자열로 변환됩니다.
CONCATENATE와 비교하면 차이가 명확합니다.
| 항목 | CONCATENATE | String Template |
|---|---|---|
| 결과 예측 | 변수 나열 순서를 따라가며 추론 | 문장 형태가 코드에 그대로 보임 |
| 공백 처리 | SEPARATED BY 별도 지정 | 템플릿 안에 그대로 입력 |
| 숫자/날짜 변환 | WRITE TO 등 사전 변환 필요 | 포맷 옵션으로 즉시 처리 |
| 표현식 삽입 | 불가(변수만 가능) | 연산·조건·메서드 호출 가능 |
또 하나 중요한 동작 원리는 자동 타입 변환입니다. 중괄호 안에 정수나 날짜를 넣으면 ABAP 런타임이 문자열로 변환해 주는데, 이때 ALPHA, DATE, TIME, NUMBER, WIDTH, PAD 같은 포맷 옵션으로 변환 규칙을 제어할 수 있습니다. 예를 들어 { lv_date DATE = USER }는 사용자 마스터의 날짜 형식으로, { lv_ebeln ALPHA = OUT }은 선행 0을 제거해 출력합니다. CONCATENATE 시절에는 CONVERSION_EXIT 함수나 WRITE TO 문으로 따로 처리하던 부분이 옵션 하나로 끝나는 것입니다.
실전 코드 3단계
구매발주(Purchase Order) 업무를 소재로, 기본 → 실무 → 프로덕션 순으로 난이도를 올려 보겠습니다.
1단계 — 기본: 변수 삽입으로 CONCATENATE 대체
구매발주 생성 확인 메시지를 만드는 가장 단순한 예제입니다. 예전 방식과 나란히 비교해 보세요.
" 예전 방식: CONCATENATE — 결과 문장을 머릿속으로 조립해야 함
DATA: lv_po_number TYPE ebeln VALUE '4500001234',
lv_vendor TYPE string VALUE '한빛물산',
lv_msg TYPE string.
CONCATENATE '구매발주' lv_po_number '(' lv_vendor ') 생성 완료'
INTO lv_msg SEPARATED BY space.
" 새 방식: String Template — 문장이 그대로 보임
lv_msg = |구매발주 { lv_po_number ALPHA = OUT } ({ lv_vendor }) 생성 완료|.
" 결과: 구매발주 4500001234 (한빛물산) 생성 완료
cl_demo_output=>display( lv_msg ).
ALPHA = OUT 옵션이 선행 0을 제거해 주므로 별도의 변환 함수 호출이 필요 없습니다. 괄호 앞뒤 공백도 템플릿에 쓴 그대로 유지됩니다. SEPARATED BY로 공백 위치를 짜맞추던 수고가 사라지는 것이 첫 번째 체감 포인트입니다.
2단계 — 실무: 조건 표현식 삽입과 로그 텍스트 포맷팅
실무에서는 상태 값에 따라 문구가 달라지는 경우가 많습니다. COND 표현식을 중괄호 안에 직접 넣으면 IF 분기 없이 한 문장으로 처리됩니다. 승인 처리 로그를 남기는 시나리오입니다.
DATA: lv_po_number TYPE ebeln VALUE '4500001234',
lv_status TYPE c LENGTH 1 VALUE 'E',
lv_amount TYPE p LENGTH 8 DECIMALS 2 VALUE '1250000.50',
lv_log_line TYPE string.
" 패턴 2: 조건 표현식(COND) 삽입 — 상태별 문구를 한 줄로
lv_log_line = |[{ sy-datum DATE = ISO } { sy-uzeit TIME = ISO }] |
&& |PO { lv_po_number ALPHA = OUT }: |
&& |{ COND string( WHEN lv_status = 'E' THEN '승인 반려'
WHEN lv_status = 'A' THEN '승인 완료'
ELSE '검토 대기' ) } |
&& |(금액: { lv_amount NUMBER = USER } KRW)|.
" 결과 예: [2026-07-20 09:30:15] PO 4500001234: 승인 반려 (금액: 1,250,000.50 KRW)
TRY.
" 실무에서는 Application Log 등에 전달
" lo_log->add_message( lv_log_line ).
CATCH cx_root INTO DATA(lx_error).
" 예외 텍스트도 템플릿으로 조합
lv_log_line = |로그 기록 실패: { lx_error->get_text( ) }|.
ENDTRY.
포인트를 정리하면 이렇습니다.
DATE = ISO,TIME = ISO는 로그에 적합한 표준 형식(YYYY-MM-DD, HH:MM:SS)을 즉시 적용NUMBER = USER는 사용자 설정의 소수점·천 단위 구분자를 따르므로 다국어 시스템에서 유용- 긴 템플릿은 연결 연산자
&&로 줄을 나누면 가독성이 유지됨
3단계 — 프로덕션: 메서드 호출 결과 삽입과 테스트 가능한 설계
세 번째 패턴은 중괄호 안에서 메서드 호출 결과를 바로 삽입하는 것입니다(ABAP 7.40+). 고객사 알림 메시지 생성 클래스를 예로 들면, 데이터 조회 로직과 문장 조립을 분리하면서도 최종 문장은 템플릿 한 곳에서 관리할 수 있습니다.
CLASS zcl_po_notification DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
METHODS build_message
IMPORTING iv_po_number TYPE ebeln
RETURNING VALUE(rv_message) TYPE string.
PRIVATE SECTION.
METHODS get_vendor_name
IMPORTING iv_po_number TYPE ebeln
RETURNING VALUE(rv_name) TYPE string.
ENDCLASS.
CLASS zcl_po_notification IMPLEMENTATION.
METHOD build_message.
" 패턴 3: 메서드 호출 결과를 템플릿에 직접 삽입
rv_message = |안녕하세요, { get_vendor_name( iv_po_number ) } 담당자님. |
&& |구매발주 { iv_po_number ALPHA = OUT }이(가) 발행되었습니다. |
&& |{ sy-datum DATE = USER } 기준 안내입니다.|.
ENDMETHOD.
METHOD get_vendor_name.
" 실제로는 I_Supplier 등 CDS 뷰 조회 — 예제에서는 고정값
rv_name = COND #( WHEN iv_po_number IS NOT INITIAL
THEN `한빛물산` ELSE `미지정 공급업체` ).
ENDMETHOD.
METHOD if_oo_adt_classrun~main.
out->write( build_message( '4500001234' ) ).
ENDMETHOD.
ENDCLASS.
프로덕션 관점의 체크 포인트입니다.
- 성능: String Template은 CONCATENATE와 사실상 동등한 성능을 보이는 것이 일반적입니다. 다만 대량 루프에서 중괄호 안 메서드는 매 반복마다 호출되므로, 값이 변하지 않는다면 루프 밖에서 변수로 받아 두는 편이 안전합니다.
- 보안: 사용자 입력을 템플릿에 넣어 동적 SQL이나 HTML을 만들 때는
cl_abap_dyn_prg의 escape 계열 메서드로 먼저 이스케이프 처리해야 인젝션을 막을 수 있습니다. - 테스트:
build_message처럼 문장 조립을 별도 메서드로 분리하면 ABAP Unit에서 결과 문자열을assert_equals로 검증하기 쉬워집니다.
흔한 실수와 트러블슈팅 FAQ
Q1. 템플릿 안에서 파이프(|)나 중괄호({)를 문자 그대로 쓰고 싶습니다.
이스케이프 문자 \를 사용합니다. |통화\{KRW\}: { lv_amount }|처럼 \{, \}, \|로 쓰면 기호 자체가 출력됩니다. 이스케이프 없이 쓰면 구문 오류가 발생합니다. 줄바꿈은 \n, 탭은 \t로 표현할 수 있습니다.
Q2. 값 뒤의 공백이 사라집니다.
중괄호 안의 문자형(char) 값은 변환 시 뒤 공백이 제거되는 것이 기본 동작입니다. 고정 폭 정렬이 필요하면 { lv_val WIDTH = 10 PAD = ` ` ALIGN = LEFT }처럼 WIDTH/PAD/ALIGN 옵션을 지정하세요. 참고로 텍스트 리터럴에서도 작은따옴표(' ')는 뒤 공백을 무시하므로, 공백 보존이 필요하면 백쿼트(` `) 사용이 권장됩니다.
Q3. 날짜가 20260720처럼 내부 형식 그대로 나옵니다.
포맷 옵션을 지정하지 않으면 내부 표현이 그대로 변환됩니다. { lv_date DATE = USER }(사용자 설정 형식) 또는 { lv_date DATE = ISO }(YYYY-MM-DD)를 명시하세요. 금액도 NUMBER = USER를 붙여야 로케일에 맞는 구분자가 적용됩니다.
Q4. 구버전 시스템에서 구문 오류가 납니다.
String Template 자체는 7.02부터 지원되지만, 중괄호 안 메서드 호출과 COND 결합은 7.40 이상이 필요합니다. 시스템 상태 메뉴 또는 SM51에서 릴리스를 먼저 확인하세요.
이어서 보면 좋은 주제
String Template에 익숙해졌다면 같은 계열의 모던 ABAP 문법으로 확장하는 것이 자연스럽습니다. COND/SWITCH 조건 표현식, VALUE/CORRESPONDING 생성자 표현식, 인라인 선언(DATA(...))은 String Template과 조합할 때 시너지가 큽니다. 문자열 처리 심화로는 find( ), replace( ), substring( ) 같은 내장 문자열 함수와 PCRE 정규식을 추천하며, ABAP Cloud에서 RAP 개발을 한다면 메시지 클래스와 예외 텍스트에 템플릿을 결합하는 설계도 함께 살펴보세요.
더 읽어볼 자료
댓글 0
아직 댓글이 없습니다.