ABAP 에서 인터널 테이블 두 개를 합치거나, 한 테이블의 내용을 다른 테이블 뒤에 이어 붙여야 하는 상황은 자주 나옵니다. 가장 쉬운 방법은 LOOP 안에서 한 줄씩 APPEND 하는 것이지만, 데이터 량이 많아지면 성능이 급격히 떨어집니다.
SAP 가 이런 경우를 위해 한 번에 통째로 추가하는 전용 구문 을 제공합니다. 두 테이블의 구조가 같으면 APPEND LINES OF, 구조가 달라 같은 이름 필드끼리만 옮기고 싶으면 MOVE-CORRESPONDING ... KEEPING TARGET LINES 로 처리합니다.
이 글은 인터널 테이블을 합치는 4가지 핵심 구문(APPEND LINES OF · MOVE-CORRESPONDING · INSERT LINES OF · ABAP 7.40+ 의 VALUE BASE) 과 선택 기준, 실무 함정을 정리한 메모입니다.
핵심 — 구조가 같으냐 다르냐가 첫 번째 분기점
테이블 합치기는 두 테이블의 구조 일치 여부 와 기존 데이터 유지 여부 에 따라 사용할 구문이 결정됩니다.
| 상황 | 사용 구문 | 동작 |
|---|---|---|
| 같은 구조 · 뒤에 이어 붙임 | APPEND LINES OF lt_a TO lt_b |
lt_a 의 모든 행이 lt_b 뒤에 한 번에 추가됨 |
| 다른 구조 · 같은 이름 필드만 추가 | MOVE-CORRESPONDING lt_a TO lt_b KEEPING TARGET LINES |
필드명 일치하는 컬럼만 매핑 후 lt_b 뒤에 추가 |
| 다른 구조 · 기존 데이터 덮어쓰기 | MOVE-CORRESPONDING lt_a TO lt_b |
lt_b 기존 행은 삭제되고 같은 이름 필드만 채워서 재구성 |
| 특정 위치에 끼워 넣기 | INSERT LINES OF lt_a INTO lt_b INDEX n |
n 번째 위치부터 lt_a 의 모든 행 삽입 |
| 구조가 같고 새 테이블 생성 | lt_b = lt_a. |
통째로 복사 (덮어쓰기) — 가장 빠름 |
핵심은 KEEPING TARGET LINES 옵션의 유무 입니다. 이 옵션을 빼면 대상 테이블의 기존 데이터가 모두 지워지고 새로 채워집니다. "추가" 가 목적이라면 반드시 옵션을 붙입니다.
1단계 — APPEND LINES OF (같은 구조 대량 추가)
가장 자주 쓰는 패턴. 두 테이블이 같은 라인 타입(또는 호환 가능한 구조) 일 때 한 줄로 처리됩니다.
DATA: lt_a TYPE STANDARD TABLE OF mara,
lt_b TYPE STANDARD TABLE OF mara.
" lt_a 에 데이터 채워졌다고 가정 (100건)
" lt_b 에도 기존 데이터 있음 (50건)
APPEND LINES OF lt_a TO lt_b.
" 결과: lt_b 는 150건 (기존 50건 + lt_a 100건)
부분 범위만 추가 — FROM ... TO 옵션
전체 대신 특정 행 범위만 추가할 수도 있습니다.
APPEND LINES OF lt_a FROM 10 TO 20 TO lt_b.
" lt_a 의 10번째 ~ 20번째 행만 lt_b 뒤에 추가
성능 비교 — LOOP + APPEND 와 차이
같은 결과를 얻는 두 가지 방식을 비교해 보면 차이가 큽니다.
" 방식 A — LOOP 반복 (느림)
LOOP AT lt_a INTO DATA(ls_a).
APPEND ls_a TO lt_b.
ENDLOOP.
" 방식 B — APPEND LINES OF (빠름)
APPEND LINES OF lt_a TO lt_b.
방식 B 는 SAP 가 메모리 블록 단위로 한 번에 복사하므로 대량(10,000건 이상) 에서 수십 배 빠릅니다. 대량 처리 코드에서는 반드시 방식 B 를 선택합니다.
2단계 — MOVE-CORRESPONDING ... KEEPING TARGET LINES (다른 구조)
두 테이블의 라인 타입이 다른데 같은 이름의 필드만 옮기고 싶을 때 사용합니다. KEEPING TARGET LINES 옵션이 핵심으로, 이걸 안 붙이면 기존 데이터가 모두 지워집니다.
DATA: lt_src TYPE STANDARD TABLE OF mara, " 자재 마스터
lt_dst TYPE STANDARD TABLE OF ty_simple. " { MATNR, MTART, MEINS } 만 있는 구조
" lt_dst 에 이미 100건 있음
" 같은 이름 필드(MATNR · MTART · MEINS) 만 매핑되어 lt_dst 뒤에 추가
MOVE-CORRESPONDING lt_src TO lt_dst KEEPING TARGET LINES.
" 결과: lt_dst 기존 100건 유지 + lt_src 매핑 데이터 추가
KEEPING TARGET LINES 없는 경우 — 덮어쓰기
MOVE-CORRESPONDING lt_src TO lt_dst.
" 결과: lt_dst 기존 100건 모두 삭제 + lt_src 의 매핑 데이터로 새로 채움
기존 데이터가 사라지므로 추가가 목적이라면 항상 KEEPING TARGET LINES 를 붙이는 습관 이 안전합니다.
EXPANDING NESTED TABLES 옵션
중첩 테이블(deep table) 이 있을 때 내부 테이블도 같이 복사하려면 옵션을 추가합니다.
MOVE-CORRESPONDING lt_src TO lt_dst
KEEPING TARGET LINES
EXPANDING NESTED TABLES.
3단계 — INSERT LINES OF (특정 위치 삽입)
테이블 끝이 아니라 중간 특정 위치에 끼워 넣고 싶을 때 사용합니다.
DATA: lt_a TYPE STANDARD TABLE OF mara,
lt_b TYPE STANDARD TABLE OF mara.
" lt_b 의 3번째 위치부터 lt_a 의 모든 행 삽입
INSERT LINES OF lt_a INTO lt_b INDEX 3.
" 결과: lt_b 의 기존 1·2번째 행 유지 → lt_a 의 행들 → 기존 3번째~ 마지막 행
APPEND LINES OF 가 무조건 끝에 붙이는 반면, INSERT LINES OF 는 위치 지정이 가능합니다. 위치 지정이 필요 없으면 APPEND 가 약간 더 빠릅니다(INSERT 는 이동 작업이 추가됨).
4단계 — ABAP 7.40+ 신택스 (VALUE BASE · CORRESPONDING)
ABAP 7.40 부터 함수형 신택스가 추가되어 같은 작업을 한 식으로 표현할 수 있습니다.
VALUE #( BASE ... ) — 기존 데이터 유지 + 추가
" 같은 구조 대량 추가의 7.40+ 버전
lt_b = VALUE #( BASE lt_b ( LINES OF lt_a ) ).
" 위 한 줄 = APPEND LINES OF lt_a TO lt_b 와 동일 결과
BASE lt_b 가 "KEEPING TARGET LINES" 와 같은 역할을 합니다.
CORRESPONDING #( ... ) — 필드 매핑 추가
" MOVE-CORRESPONDING ... KEEPING TARGET LINES 의 7.40+ 버전
lt_dst = CORRESPONDING #( BASE ( lt_dst ) lt_src ).
" 매핑 규칙 명시
lt_dst = CORRESPONDING #( BASE ( lt_dst ) lt_src
MAPPING matnr = material
mtart = type ).
" 같은 이름 필드 제외
lt_dst = CORRESPONDING #( BASE ( lt_dst ) lt_src
EXCEPT mtart ).
함수형 신택스는 한 줄에 의도가 명확히 드러나서 신규 코드에서 선호됩니다. 다만 디버깅 시 중간값 확인이 어렵다는 단점이 있어, 복잡한 매핑은 명령형 신택스(MOVE-CORRESPONDING) 가 더 편할 때도 있습니다.
흔히 빠뜨리는 함정
KEEPING TARGET LINES 누락 → 기존 데이터 사라짐
MOVE-CORRESPONDING 에서 옵션을 안 붙이면 대상 테이블의 기존 데이터가 모두 지워집니다. "왜 갑자기 결과가 절반밖에 안 되지" 하는 디버깅에서 가장 자주 발견되는 원인입니다. 추가가 목적이면 항상 KEEPING TARGET LINES 부터 쓰는 습관을 들입니다.
LOOP + APPEND 의 성능 함정
대량 데이터를 LOOP AT ... INTO ... APPEND 패턴으로 합치면 데이터 량이 늘수록 처리 시간이 기하급수적으로 증가합니다. 1,000건은 차이가 미미하지만 100,000건 이상에서는 APPEND LINES OF 대비 수십 배 느립니다. 동일 결과면 무조건 APPEND LINES OF 사용.
라인 타입 불일치 시 컴파일 에러
APPEND LINES OF 는 두 테이블의 라인 타입이 정확히 같거나 호환 가능해야 합니다. 다르면 컴파일 에러가 나며, 이때는 MOVE-CORRESPONDING 으로 전환하거나 LOOP 안에서 필드별로 매핑해야 합니다.
MOVE-CORRESPONDING 이 매핑 못 잡은 필드는 그대로 둠
MOVE-CORRESPONDING 은 같은 이름 필드만 매핑하므로, 대상 테이블에 새로 추가된 행의 매핑되지 않은 필드는 초기값(공백·0) 으로 남습니다. 의도된 동작이지만, "왜 이 컬럼만 비어있지" 라고 놀라기 쉽습니다.
INSERT LINES OF 의 인덱스 범위 초과
INDEX n 에서 n 이 대상 테이블 행 수보다 크면 런타임 에러가 발생합니다(예: 행이 10개인 테이블에 INDEX 100). 사전에 lines( lt_b ) 로 행 수 체크가 안전합니다.
SORTED / HASHED 테이블에서 APPEND 사용 시도
APPEND·APPEND LINES OF 는 STANDARD TABLE 에서만 사용 가능합니다. SORTED TABLE · HASHED TABLE 에는 INSERT LINES OF 를 사용합니다.
중복 행 처리 누락
APPEND LINES OF 는 중복을 검사하지 않고 모두 추가합니다. 키가 같은 행을 합산해야 한다면 COLLECT, 중복을 제거하고 싶다면 DELETE ADJACENT DUPLICATES 를 합쳐 사용합니다.
APPEND LINES OF lt_a TO lt_b.
SORT lt_b BY matnr.
DELETE ADJACENT DUPLICATES FROM lt_b COMPARING matnr.
전체 코드 — 복사용 통합본
4가지 방식을 한 프로그램에서 비교 실행하는 데모입니다. SE38 에 그대로 붙여 실행 가능합니다.
REPORT z_append_lines_demo.
TYPES: BEGIN OF ty_simple,
matnr TYPE matnr,
mtart TYPE mtart,
meins TYPE meins,
END OF ty_simple.
DATA: lt_a TYPE STANDARD TABLE OF ty_simple,
lt_b TYPE STANDARD TABLE OF ty_simple,
lt_src TYPE STANDARD TABLE OF mara,
lt_dst TYPE STANDARD TABLE OF ty_simple.
* 0) 테스트 데이터 준비
lt_a = VALUE #(
( matnr = 'M-001' mtart = 'FERT' meins = 'EA' )
( matnr = 'M-002' mtart = 'FERT' meins = 'EA' )
( matnr = 'M-003' mtart = 'HALB' meins = 'KG' )
).
lt_b = VALUE #(
( matnr = 'B-001' mtart = 'ROH' meins = 'L' )
).
* ★ 1) APPEND LINES OF — 같은 구조 대량 추가
APPEND LINES OF lt_a TO lt_b.
WRITE: / '=== 1) APPEND LINES OF — lt_b 결과 ==='.
LOOP AT lt_b INTO DATA(ls).
WRITE: / ls-matnr, ls-mtart, ls-meins.
ENDLOOP.
* ★ 2) APPEND LINES OF + FROM..TO — 부분 범위
CLEAR lt_b.
lt_b = VALUE #( ( matnr = 'KEEP-1' mtart = 'X' meins = 'Y' ) ).
APPEND LINES OF lt_a FROM 1 TO 2 TO lt_b.
WRITE: / / '=== 2) FROM 1 TO 2 만 추가 ==='.
LOOP AT lt_b INTO ls.
WRITE: / ls-matnr, ls-mtart, ls-meins.
ENDLOOP.
* ★ 3) MOVE-CORRESPONDING + KEEPING TARGET LINES — 다른 구조
SELECT matnr, mtart, meins
FROM mara
INTO TABLE @lt_src
UP TO 3 ROWS.
CLEAR lt_dst.
lt_dst = VALUE #( ( matnr = 'EXIST-1' mtart = 'A' meins = 'EA' ) ).
MOVE-CORRESPONDING lt_src TO lt_dst KEEPING TARGET LINES.
WRITE: / / '=== 3) MOVE-CORRESPONDING ... KEEPING TARGET LINES ==='.
LOOP AT lt_dst INTO ls.
WRITE: / ls-matnr, ls-mtart, ls-meins.
ENDLOOP.
* ★ 4) 7.40+ 신택스 — VALUE BASE / CORRESPONDING
DATA(lt_modern) = VALUE STANDARD TABLE OF ty_simple( BASE lt_b ( LINES OF lt_a ) ).
WRITE: / / '=== 4) VALUE #( BASE lt_b ( LINES OF lt_a ) ) ==='.
LOOP AT lt_modern INTO ls.
WRITE: / ls-matnr, ls-mtart, ls-meins.
ENDLOOP.
* ★ 5) INSERT LINES OF — 특정 위치 삽입
CLEAR lt_b.
lt_b = VALUE #(
( matnr = 'POS-1' mtart = 'X' meins = 'EA' )
( matnr = 'POS-2' mtart = 'X' meins = 'EA' )
).
INSERT LINES OF lt_a INTO lt_b INDEX 2.
WRITE: / / '=== 5) INSERT LINES OF ... INDEX 2 ==='.
LOOP AT lt_b INTO ls.
WRITE: / ls-matnr, ls-mtart, ls-meins.
ENDLOOP.
요약
| 단계 | 구문 | 선택 기준 |
|---|---|---|
| 1 | APPEND LINES OF |
같은 구조 · 끝에 한 번에 추가 (대량 시 필수) |
| 2 | MOVE-CORRESPONDING ... KEEPING TARGET LINES |
다른 구조 + 같은 이름 필드만 매핑 + 기존 유지 |
| 3 | INSERT LINES OF ... INDEX n |
특정 위치 삽입 · SORTED/HASHED 테이블도 가능 |
| 4 | VALUE #( BASE ... ) / CORRESPONDING #( BASE ... ) |
ABAP 7.40+ · 함수형 한 줄 표현 · 신규 코드 권장 |
| 5 | 피해야 할 패턴 | LOOP + APPEND 대량 처리 · KEEPING TARGET LINES 누락 |
인터널 테이블 합치기는 구조 일치 여부 와 기존 데이터 유지 여부 두 축으로 구문이 결정됩니다. 같은 구조면 APPEND LINES OF 가 가장 빠르고 단순하며, 다른 구조면 MOVE-CORRESPONDING 에 반드시 KEEPING TARGET LINES 를 붙여 기존 데이터를 보존합니다. 대량 처리에서 LOOP + APPEND 는 절대 피하고, 7.40+ 환경이라면 함수형 VALUE #( BASE ... ) · CORRESPONDING #( BASE ... ) 신택스가 더 간결한 선택지입니다.
Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다.
APPEND LINES OF · INSERT LINES OF · MOVE-CORRESPONDING 은 ABAP 표준 언어 기능으로 시스템 버전 의존 없이 동작합니다. 함수형 신택스(VALUE #( BASE ... ), CORRESPONDING #( BASE ... )) 는 ABAP 7.40 이상에서 사용 가능합니다. APPEND 계열은 STANDARD TABLE 전용이며, SORTED TABLE · HASHED TABLE 에는 INSERT LINES OF 를 사용해야 합니다. 대량 데이터 처리 시 LOOP 안에서 한 줄씩 APPEND 하는 패턴은 메모리 재할당이 반복되며 행 수에 비례해 시간이 증가하므로, 데이터 량과 무관하게 APPEND LINES OF 또는 함수형 신택스로 일괄 처리하는 것이 권장됩니다.