From Zero to SAP

ABAP 인터널 테이블 - TYPE vs LIKE / Work Area vs Header Line / LOOP WHERE / FILTER 초기화 / 정렬 본문

ABAP/이론

ABAP 인터널 테이블 - TYPE vs LIKE / Work Area vs Header Line / LOOP WHERE / FILTER 초기화 / 정렬

권쌥 2026. 4. 10. 17:13

[ABAP] 인터널 테이블 
TYPE vs LIKE, Work Area vs Header Line

인터널 테이블을 본격적으로 다루기 전에 기본적인 선언 문법부터 잡아야 한다. TYPELIKE는 처음 보면 둘 다 "타입을 참조하는 것 같은데?" 싶어서 헷갈리는데, 참조하는 대상이 명확히 다르다. 그리고 인터널 테이블을 실제로 다루려면 Work Area 개념도 반드시 이해해야 한다.


1. TYPE vs LIKE

두 키워드 모두 변수 선언 시 타입을 지정하는 데 쓰인다. 차이는 "무엇을 참조하느냐"다.

키워드 참조 대상 예시
TYPE 타입 이름
딕셔너리 타입, string·i 같은 기본 타입
TYPE string
TYPE TABLE OF ztemp
LIKE 이미 선언된 변수 또는 테이블 필드
변수명, 테이블명-필드명
LIKE ls_emp
LIKE ztemp-emp_id

 

코드로 직접 보면 이렇다.

"── TYPE : 타입 이름 참조 ─────────────────────────────────
DATA lv_name TYPE string.           " 기본 타입
DATA lt_emp  TYPE TABLE OF ztemp.  " 딕셔너리 테이블을 타입으로

"── LIKE : 이미 선언된 변수/필드 참조 ────────────────────
DATA ls_emp  TYPE ztemp.            " 먼저 ls_emp를 선언해두고
DATA ls_emp2 LIKE ls_emp.           " 그 변수와 동일한 타입으로 선언
DATA lv_id   LIKE ztemp-emp_id.    " 테이블 특정 필드 타입으로 선언

LIKE ztemp-emp_id처럼 선언하면, ztemp의 emp_id 필드가 CHAR 10이라면 lv_id도 자동으로 CHAR 10이 된다. 나중에 DB 테이블의 필드 타입이 바뀌어도 코드를 수정할 필요가 없다는 게 장점이다.

실무에서는 어떻게 쓰나

현대 ABAP(New Syntax)에서는 대부분 TYPE을 사용한다. LIKE는 레거시 코드에서 자주 보이기 때문에 읽을 수 있어야 하는 수준으로 알아두면 충분하다. 단, LIKE 테이블명-필드명 형태는 지금도 가끔 쓰이니 익혀두자.


2. 인터널 테이블이란?

본격적으로 Work Area를 설명하기 전에, 인터널 테이블이 무엇인지부터 짚고 가자.

인터널 테이블은 ABAP 프로그램이 실행되는 동안 메모리에 존재하는 임시 테이블이다.

DB에서 SELECT로 데이터를 가져온 다음, 그 데이터를 메모리 위에서 가공하고 처리할 때 담아두는 그릇이다.

Java로 따지면 List<Employee>, JavaScript로 따지면 객체 배열(Employee[])과 유사하다.

 

DB는 디스크에 있어서 접근할 때마다 I/O 비용이 발생하지만, 인터널 테이블은 이미 메모리에 올라와 있기 때문에 훨씬 빠르게 읽고 수정할 수 있다. 그래서 ABAP 성능 최적화의 핵심 원칙 중 하나가 "SELECT는 한 번, 이후 처리는 메모리(인터널 테이블)에서"다.

 

DB → SELECT → 인터널 테이블(메모리) → LOOP/READ → Work Area(1행씩 처리)


3. Work Area vs Header Line

인터널 테이블은 여러 행을 담는 그릇이다. 그런데 실제로 행을 처리할 때는 한 번에 한 행씩 꺼내서 읽거나 수정한다.

이때 꺼낸 1행짜리 임시 저장 공간을 Work Area라고 한다.

Work Area — 현재 권장 방식

테이블과 별도로 선언한 1행짜리 구조체다. 이름도 따로 있고, 테이블과 독립적으로 존재한다.

DATA lt_emp TYPE TABLE OF ztemp.  " 인터널 테이블 (여러 행)
DATA ls_emp TYPE ztemp.           " Work Area (1행짜리 구조체)

LOOP AT lt_emp INTO ls_emp.
  " ls_emp에 현재 행이 담긴다
  " ls_emp-emp_id, ls_emp-name 등으로 접근 가능
ENDLOOP.

New Syntax에서는 Work Area를 미리 선언하지 않고 DATA() 인라인 선언으로 바로 쓸 수도 있다.

LOOP AT lt_emp INTO DATA(ls_emp).  " 인라인 선언 — ls_emp 타입이 자동 추론됨
  " ls_emp-emp_id, ls_emp-name ...
ENDLOOP.

Header Line — 구버전 방식 (읽기 전용으로 알아두기)

테이블에 자동으로 딸려오는 1행짜리 버퍼다. 선언 시 WITH HEADER LINE을 붙이면 생긴다. 테이블명 자체가 Work Area 역할을 겸한다. -> 헤더 라인 버퍼가 필드 하나씩 순회한다고 생각하면 된다.

DATA lt_emp TYPE TABLE OF ztemp WITH HEADER LINE.

LOOP AT lt_emp.              " INTO 없이 쓴다
  lt_emp-emp_id ...          " 테이블명 자체가 Work Area처럼 동작
ENDLOOP.
Header Line, 왜 지금은 쓰지 않나

Header Line 방식은 ABAP OO(클래스 내부)에서 사용할 수 없다.
RAP(RESTful ABAP Programming) 역시 OO 기반이라 동일하게 지원하지 않는다.

따라서 레거시 코드를 읽을 때 "아, 이렇게도 썼구나" 하고 이해하는 수준으로 알아두면 된다.

새로 작성하는 코드에서는 항상 Work Area를 별도로 선언하자.


4. LOOP AT … WHERE vs FILTER

조건에 맞는 데이터만 처리해야 할 때 두 가지 방법을 쓸 수 있다. 둘 다 "조건 필터링"이지만 동작 방식과 목적이 다르다.

LOOP AT … WHERE — 조건 맞는 행만 처리

전체를 순회하면서 조건에 맞지 않는 행은 건너뛴다. 원본 테이블은 그대로 유지되고, 조건에 맞는 행만 루프 안에서 처리된다.

LOOP AT lt_emp INTO DATA(ls_emp) WHERE dept_cd = 'D001'.
  " 이 블록 안에는 dept_cd가 'D001'인 행만 들어온다
  " lt_emp 전체를 돌긴 하지만, 조건 불일치 행은 자동 스킵
ENDLOOP.

FILTER — 조건에 맞는 행만 새 테이블로 추출

조건에 맞는 행만 골라서 새로운 인터널 테이블을 만든다. 원본 테이블(lt_emp)은 변하지 않는다.

DATA lt_d001 TYPE TABLE OF ztemp.

" lt_emp에서 dept_cd = 'D001'인 행만 뽑아 lt_d001에 담기
lt_d001 = FILTER #( lt_emp WHERE dept_cd = 'D001' ).

" lt_emp는 여전히 전체 데이터를 가지고 있다
" lt_d001은 D001 부서 행만 갖고 있다
구문 내부 동작 결과 사용 시점
LOOP WHERE 전체 순회, 불일치 스킵 원본 유지, 조건 행만 처리 조건 행만 처리하고 끝낼 때
FILTER 조건 행만 추출 새 테이블 생성, 원본 유지 부분 집합을 별도로 계속 써야 할 때
언제 뭘 쓸까

"D001 부서 데이터를 별도로 여러 군데서 참조해야 한다"면 FILTER로 새 테이블을 만들어두는 게 낫다. "딱 한 번, 조건 맞는 것만 루프 돌면서 처리하면 된다"면 LOOP WHERE가 코드가 더 간결하다.


5. 인터널 테이블 초기화 — CLEAR / FREE

인터널 테이블의 데이터를 날려야 할 때 CLEARFREE 두 가지를 주로 쓴다.

(과거에는 헤더 라인 있는 테이블을 사용했었기에 CLEAR를 사용하면 헤더라인 한 줄만 초기화됐었다.
그래서 Body를 모두 초기화하기 위해 등장한 것이 REFRESH인데, 지금은 폐기된 구문이다. -> 헤더라인 사용X)

"── Header Line 없는 일반 인터널 테이블 ──────────────────
CLEAR   gt_itab.   " 테이블 전체를 비운다 (FREE와 동일)
FREE    gt_itab.   " 테이블을 비우고 메모리도 해제한다

"── Header Line 있는 테이블에서는 동작이 달라진다 ─────────
CLEAR   gt_itab.   " 헤더라인(Work Area 역할)만 비운다! 바디는 살아있음
FREE    gt_itab.   " 바디 전체를 비운다
핵심 정리

Header Line 없는 현대 방식에서는 CLEARFREE가 테이블 바디를 비운다는 점에서 동일하다.

단, FREE는 메모리까지 해제하므로 더 이상 쓸 일 없는 테이블을 명시적으로 해제할 때 쓴다.

REFRESH는 구버전 코드에서 볼 수 있지만 새로 쓸 필요는 없다.


6. 인터널 테이블 정렬 — SORT / STABLE SORT

기본 SORT

SORT는 Standard 또는 Hashed 타입의 인터널 테이블을 정렬할 때 쓴다.

(Sorted Table은 이미 정렬 상태를 유지하기 때문에 SORT를 쓰면 오류가 발생한다.)

"── 키 기준 정렬 ──────────────────────────────────────────
SORT gt_itab ASCENDING.
SORT gt_itab DESCENDING.

"── 컬럼을 직접 지정해서 정렬 ───────────────────────────
SORT gt_itab BY f1 ASCENDING  f2 DESCENDING.
" → f1은 오름차순, f2는 내림차순

"── 전체 컬럼에 동일한 방향 적용 ────────────────────────
SORT gt_itab DESCENDING BY f1, f2.
" → f1, f2 모두 내림차순

"── 잘못된 예 (이렇게 쓰면 안 됨) ─────────────────────
" SORT gt_itab BY f1, f2 DESCENDING
" → f1은 오름차순(ASCENDING 기본), f2만 내림차순이 됨

STABLE SORT — 동일 키값의 원래 순서를 보장

일반 SORT는 같은 키값을 가진 행들 사이에서 순서를 보장하지 않는다. STABLE SORT는 같은 키값이면 원래 입력 순서가 유지된다는 것을 보장한다.

이해를 위해 상황을 가정해보겠다.

학교에서 달리기 시합을 하는데, 학생A가 10초로 전교 신기록을 경신했다.

그러고나서, 그 다음 시합에서 학생B가 10초로 현재 1등과 같은 기록을 달성했다.

이런 상황에서 STABLE을 사용하면 가장 먼저 신기록을 경신한 학생A가 앞 순서로 보장되고, 그 다음 학생B가 위치한다.

SORT gt_itab STABLE BY score DESCENDING.

 

실무에서 왜 중요한가

"먼저 주문한 고객이 동일 등급이면 우선 처리"되는 시스템을 구현할 때, 일반 SORT를 쓰면 나중 주문이 앞으로 올 수 있어 선착순 로직에서 버그가 생긴다. 주문 순서가 비즈니스 로직에 영향을 준다면 항상 STABLE SORT를 써야 한다.

LINES — 테이블 행 수 구하기

LINES()는 인터널 테이블의 현재 행 수를 반환한다. 데이터 존재 여부 체크나 진행률 계산에 쓴다.

"── 데이터 존재 여부 체크 ────────────────────────────────
IF LINES( gt_orders ) = 0.
  MESSAGE '처리할 데이터가 없습니다.' TYPE 'I'.
  RETURN.
ENDIF.

"── 진행률 계산 ─────────────────────────────────────────
DATA(gv_total)   = LINES( gt_itab ).
DATA(gv_current) = 1.

LOOP AT gt_itab INTO DATA(ls_data).
  " gv_current / gv_total * 100 → 진행률(%)
  gv_current += 1.
ENDLOOP.

마무리 정리

개념 핵심 요약
TYPE 타입 이름을 참조해서 선언 (딕셔너리 타입, string 등)
LIKE 이미 선언된 변수 또는 테이블 필드를 참조해서 선언
Work Area 테이블과 분리된 1행짜리 구조체 — OO/RAP에서 필수
Header Line 테이블에 붙어있는 1행짜리 버퍼 — 구버전, OO에서 사용 불가
LOOP WHERE 전체 순회하되 조건 불일치 행 스킵 — 원본 유지
FILTER 조건 행만 추출해서 새 테이블 생성 — 원본 유지
CLEAR / FREE 테이블 초기화. FREE는 메모리까지 해제
SORT / STABLE SORT STABLE은 동점 행의 원래 순서 보장

다음 포스팅에서는 인터널 테이블 3종(Standard / Sorted / Hashed)의 내부 구조와 성능 차이를 다룬다.