ABAP

문자열 루프 그만 — SPLIT + STRING TABLE #shorts #SAP #ABAP

▶ YouTube에서 보기

개요 및 이 글에서 다루는 범위

ABAP에서 문자열을 다루다 보면 CSV 한 줄을 컬럼별로 쪼개거나, 쉼표로 구분된 코드 목록을 내부 테이블로 변환해야 하는 상황이 매우 자주 발생합니다. 이때 가장 직관적이고 강력한 도구가 바로 STRING TABLE과 SPLIT 명령어의 조합입니다. 이 글에서는 단순 분리부터 실무 CSV 파싱, 필드 심볼을 활용한 고성능 처리까지 단계별로 다룹니다.

  • STRING TABLE 타입을 선언하고 사용하는 두 가지 방식 익히기
  • SPLIT AT ... INTO TABLE과 INTO v1 v2 v3 구문의 차이 이해
  • FIELD-SYMBOLS와 LOOP로 라인 복사 없이 수정하기
  • CSV 라인을 구조체로 매핑하는 실무 패턴 구현
  • SPLIT과 정규식(REGEX) 사용 시점 구분

먼저 알고 있으면 좋은 내용

이 글은 ABAP 기본 문법(DATA 선언, LOOP, IF), 내부 테이블의 기본 개념(STANDARD TABLE, WORK AREA)을 알고 있는 독자를 가정합니다. ABAP 7.40 이상의 인라인 선언(DATA(...)) 문법을 사용하므로 NetWeaver 7.40 SP08 이상 환경을 권장합니다.

환경 및 준비물

  • SAP NetWeaver AS ABAP 7.50 이상 (S/4HANA 2022 / BTP ABAP Environment 포함)
  • ABAP Development Tools(ADT) for Eclipse 또는 SAP GUI SE38/SE80
  • 별도 외부 라이브러리 필요 없음 — 표준 ABAP 명령어만 사용

핵심 개념 — STRING TABLE과 SPLIT의 동작 원리

STRING TABLE은 ABAP이 표준으로 제공하는 사전 정의 타입으로, 각 라인이 하나의 string인 내부 테이블입니다.

" WITH EMPTY KEY — 키 비교 비용 없음, 순회 작업에 권장
DATA lt_lines TYPE STANDARD TABLE OF string WITH EMPTY KEY.

" STRING_TABLE 타입 직접 사용 (표준 제공)
DATA lt_csv TYPE string_table.

SPLIT은 한 문자열을 특정 구분자 기준으로 나누는 명령어입니다. 결과를 어디에 담느냐에 따라 두 가지 형태가 있습니다.

  • INTO TABLE itab: 분리된 조각 개수가 가변적일 때 (CSV 한 줄, 태그 목록 등)
  • INTO v1 v2 v3: 분리될 조각 수가 고정되어 있을 때 (예: "이름|나이|도시")

구분자는 단일 문자뿐 아니라 여러 문자(예: cl_abap_char_utilities=>cr_lf)도 가능하며, 빈 라인도 결과 테이블에 포함되어 데이터 누락이 없습니다.

실전 예제 1단계 — 도시 목록 분리 기본

REPORT z_split_basic.

DATA: lv_cities TYPE string,
      lt_city   TYPE STANDARD TABLE OF string WITH EMPTY KEY.

lv_cities = 'Seoul,Busan,Incheon,Daegu,Gwangju'.

SPLIT lv_cities AT ',' INTO TABLE lt_city.

LOOP AT lt_city INTO DATA(lv_one).
  WRITE: / sy-tabix, lv_one.
ENDLOOP.

" 결과:
" 1 Seoul  2 Busan  3 Incheon  4 Daegu  5 Gwangju

분리할 조각 수가 정해져 있다면 변수에 직접 받을 수도 있습니다.

DATA: lv_record TYPE string,
      lv_name   TYPE string,
      lv_age    TYPE string,
      lv_city   TYPE string.

lv_record = 'Hong Gildong|35|Seoul'.
SPLIT lv_record AT '|' INTO lv_name lv_age lv_city.

WRITE: / 'Name:', lv_name, / 'Age:', lv_age, / 'City:', lv_city.

고정 분리 방식에서 실제 조각 수가 변수 수보다 많으면 남는 조각이 마지막 변수에 들어갑니다. 가변 길이는 반드시 INTO TABLE 방식을 사용하세요.

실전 예제 2단계 — CSV 파일 파싱과 구조체 매핑

REPORT z_csv_parser.

TYPES: BEGIN OF ty_employee,
         empno TYPE string,
         name  TYPE string,
         dept  TYPE string,
         sal   TYPE p LENGTH 10 DECIMALS 2,
       END OF ty_employee,
       tt_employee TYPE STANDARD TABLE OF ty_employee WITH EMPTY KEY.

DATA: lv_csv    TYPE string,
      lt_lines  TYPE STANDARD TABLE OF string WITH EMPTY KEY,
      lt_emp    TYPE tt_employee,
      lt_errors TYPE STANDARD TABLE OF string WITH EMPTY KEY.

lv_csv = |E001,Kim Junho,Sales,4500.00| && cl_abap_char_utilities=>cr_lf
      && |E002,Lee Mira,HR,3800.50|     && cl_abap_char_utilities=>cr_lf
      && |E003,Park Soo,IT,5200.00|.

" 1) 줄 단위 분리
SPLIT lv_csv AT cl_abap_char_utilities=>cr_lf INTO TABLE lt_lines.

" 2) 라인별 컬럼 분리 후 구조체 채우기
LOOP AT lt_lines INTO DATA(lv_line).
  IF lv_line IS INITIAL. CONTINUE. ENDIF.

  DATA lt_cols TYPE STANDARD TABLE OF string WITH EMPTY KEY.
  SPLIT lv_line AT ',' INTO TABLE lt_cols.

  IF lines( lt_cols ) < 4.
    APPEND |Line { sy-tabix }: column mismatch - { lv_line }| TO lt_errors.
    CONTINUE.
  ENDIF.

  APPEND VALUE ty_employee(
    empno = lt_cols[ 1 ]
    name  = lt_cols[ 2 ]
    dept  = lt_cols[ 3 ]
    sal   = lt_cols[ 4 ]
  ) TO lt_emp.
ENDLOOP.

LOOP AT lt_emp INTO DATA(ls_row).
  WRITE: / ls_row-empno, ls_row-name, ls_row-dept, ls_row-sal.
ENDLOOP.

핵심은 두 단계 SPLIT입니다. 먼저 줄바꿈으로 라인을 분리하고, 라인별로 다시 쉼표로 컬럼을 분리합니다. lines() 함수로 컬럼 수를 검증해 잘못된 라인을 에러 테이블에 누적하면 디버깅이 수월해집니다.

실전 예제 3단계 — FIELD-SYMBOLS 기반 고성능 처리

REPORT z_split_production.

DATA: lv_input    TYPE string,
      lt_codes    TYPE STANDARD TABLE OF string WITH EMPTY KEY,
      lt_filtered TYPE STANDARD TABLE OF string WITH EMPTY KEY,
      lv_output   TYPE string.

lv_input = 'MAT-001;MAT-002;TMP-099;MAT-003;OBS-050;MAT-004'.

" 1) 세미콜론으로 분리
SPLIT lv_input AT ';' INTO TABLE lt_codes.

" 2) FIELD-SYMBOL로 라인 직접 수정 (복사 없음)
LOOP AT lt_codes ASSIGNING FIELD-SYMBOL().
  CONDENSE  NO-GAPS.
  TRANSLATE  TO UPPER CASE.
ENDLOOP.

" 3) 조건 필터링 — 'MAT-'로 시작하는 항목만 누적
LOOP AT lt_codes ASSIGNING .
  IF  CP 'MAT-*'.
    APPEND  TO lt_filtered.
  ENDIF.
ENDLOOP.

" 4) 다시 하나의 문자열로 결합
CONCATENATE LINES OF lt_filtered INTO lv_output SEPARATED BY ','.
WRITE: / 'Result:', lv_output.

ASSIGNING FIELD-SYMBOL은 복사가 없어 대용량에서 성능 차이가 큽니다. CP 연산자는 와일드카드 매칭에 사용되며 SPLIT 결과 필터링과 잘 어울립니다. CONCATENATE LINES OF는 내부 테이블 전체를 한 번에 합치므로 LOOP 반복보다 빠릅니다.

SPLIT vs REGEX — 선택 기준

상황권장 방식
단순 구분자 하나로 분리SPLIT AT
공백/탭 등 다양한 구분자 패턴FIND ALL OCCURRENCES OF REGEX
따옴표 안 쉼표 포함 CSVCL_RSDA_CSV_CONVERTER 사용

흔한 실수와 트러블슈팅

  • Q1. 분리 결과에 빈 라인이 잔뜩 들어옵니다. 문자열 끝에 구분자가 있거나 연속 구분자가 있으면 빈 항목이 들어옵니다. DELETE lt_lines WHERE table_line IS INITIAL.로 정리하세요.
  • Q2. 줄바꿈 구분자가 안 먹습니다. Windows는 CR+LF, Unix는 LF만 사용합니다. REPLACE ALL OCCURRENCES로 정규화 후 분리하세요.
  • Q3. INTO v1 v2 v3에서 마지막 변수에 값이 합쳐집니다. 가변 컬럼 수는 반드시 INTO TABLE 방식을 사용하세요.
  • Q4. 따옴표 안 쉼표를 처리할 수 없습니다. SPLIT은 단순 분리이므로 RFC 4180 CSV는 CL_RSDA_CSV_CONVERTER를 활용하세요.

이어서 확인하면 좋은 주제

STRING TABLE과 SPLIT 패턴이 익숙해졌다면 REDUCE/FOR 등 ABAP 7.40+ 표현식 기반 테이블 구성, CL_ABAP_GZIP으로 압축 처리, ABAP Unit Test로 파서 단위 테스트 자동화로 확장해보세요. 또한 RAP 모델에서 문자열 입력 검증 구현도 살펴보길 권장합니다.

댓글 0

아직 댓글이 없습니다.