본문 바로가기
ABAP 문법 & 기법

[SAP ABAP] 동적 TABLE & ITAB 생성하기 — RTTS(RTTI + RTTC) 활용

by Song.sh 2026. 5. 12.

ABAP 개발을 하다 보면 컴파일 타임에 구조를 알 수 없는 테이블을 다뤄야 할 때가 있습니다. 예를 들면 사용자가 화면에서 선택한 SAP 테이블 이름으로 그 테이블 데이터를 조회해서 ALV로 표시해야 한다거나, 외부에서 받은 임의의 데이터 구조를 받아 처리해야 하는 경우죠.

 

이런 상황에서 사용하는 게 RTTS(Runtime Type Services) 입니다. RTTI 로 타입 정보를 조회하고, RTTC 로 런타임에 동적 테이블을 만드는 두 가지 작업으로 나뉩니다.


RTTS의 두 축 — RTTI vs RTTC

구분 풀어쓰기 역할
RTTI Runtime Type Identification 기존 타입·데이터의 구조 정보 조회
RTTC Runtime Type Creation 런타임에 새 타입·데이터 객체 생성

두 작업 모두 같은 클래스 계층을 사용합니다.

클래스 설명
CL_ABAP_TYPEDESCR 모든 타입 디스크립터의 최상위 베이스
CL_ABAP_STRUCTDESCR 구조체(structure) 타입 정보·생성
CL_ABAP_TABLEDESCR 내부 테이블(itab) 타입 정보·생성
CL_ABAP_ELEMDESCR 기본 요소(char, int, packed 등) 타입 정보·생성

패턴 1 — RTTI로 구조체 정보 조회

이미 정의된 구조체에서 필드 이름과 타입 정보를 런타임에 추출하는 패턴.

*str의 정보찾기*
TYPES: BEGIN OF gs_data,
         vbeln TYPE vbak-vbeln,
         erdat TYPE vbak-erdat,
         erzet TYPE vbak-erzet,
       END OF gs_data.

DATA: component TYPE abap_compdescr.   " cl_abap_structdescr의 속성
DATA: lr_str TYPE REF TO cl_abap_structdescr.

" types만 가능, data는 안 됨
lr_str ?= cl_abap_typedescr=>describe_by_name( 'GS_DATA' ).

LOOP AT lr_str->components INTO component.
  " gs_data의 이름과 타입속성을 불러옴
  WRITE: / component-type_kind, component-name.
ENDLOOP.

핵심 포인트

  • describe_by_nameTYPES 선언만 받음. 일반 DATA 변수를 넘기면 동작하지 않음.
  • 데이터 변수의 타입 정보가 필요하면 describe_by_data( lv_var ) 사용.
  • ?= (Casting Down)으로 베이스 타입을 구조체 디스크립터로 다운캐스팅.
  • components 속성은 필드 이름·타입·길이가 들어 있는 테이블.

패턴 2 — RTTC로 동적 테이블 생성

사용자가 런타임에 선택한 SAP 테이블 이름으로 그 테이블과 동일한 구조의 내부 테이블을 동적으로 만드는 패턴. 가장 자주 쓰는 RTTS 활용 예입니다.

TYPE-POOLS: abap.

DATA: lv_str   TYPE REF TO cl_abap_structdescr,
      lv_table TYPE REF TO cl_abap_tabledescr.

PARAMETERS: r_data  RADIOBUTTON GROUP gr1 USER-COMMAND uc1,
            r_data2 RADIOBUTTON GROUP gr1,
            r_data3 RADIOBUTTON GROUP gr1.

DATA(lv_test) = 'SFLIGHT'.   " 동적으로 테이블 이름 결정

" 1) 구조체 타입 정보 가져오기
lv_str   ?= cl_abap_typedescr=>describe_by_name( lv_test ).

" 2) 그 구조체로 테이블 타입 생성
lv_table  = cl_abap_tabledescr=>create( lv_str ).

" 3) 동적 데이터 객체 생성
DATA: ref_dynamic_table TYPE REF TO data.
CREATE DATA ref_dynamic_table TYPE HANDLE lv_table.

" 4) FIELD-SYMBOL에 연결
FIELD-SYMBOLS: <fs_table> TYPE ANY TABLE.
ASSIGN ref_dynamic_table->* TO <fs_table>.

" 5) 동적 SELECT
IF r_data = 'X'.
  SELECT *
    FROM (lv_test)
    INTO CORRESPONDING FIELDS OF TABLE <fs_table>.

ELSEIF r_data2 = 'X'.
  SELECT *
    FROM (lv_test)
    UP TO 30 ROWS
    INTO CORRESPONDING FIELDS OF TABLE <fs_table>.

ELSE.
  SELECT *
    FROM (lv_test)
    UP TO 20 ROWS
    INTO CORRESPONDING FIELDS OF TABLE <fs_table>.
ENDIF.

" 6) 결과 출력
cl_demo_output=>display( <fs_table> ).

단계별 정리

단계 코드
1 describe_by_name 으로 구조체 디스크립터 획득
2 cl_abap_tabledescr=>create 로 테이블 디스크립터 생성
3 CREATE DATA ... TYPE HANDLE 로 데이터 객체 생성
4 ASSIGN ref->* 으로 FIELD-SYMBOL에 매핑
5 SELECT * FROM (lv_test) 처럼 테이블 이름도 동적으로
6 cl_demo_output=>display 등으로 출력

이렇게 만들어진 <fs_table> 은 일반 내부 테이블처럼 LOOP, READ, SORT, DELETE 등 모든 ABAP 명령이 작동합니다.


활용 케이스

케이스 1 — 임의의 SAP 테이블 데이터 뷰어

사용자가 입력 화면에서 SAP 테이블 이름(예: MARA, VBAK, BSEG)을 입력하면 해당 테이블 구조 그대로 데이터 조회. SE16N 같은 표준 도구의 간이 버전을 직접 만드는 셈.

케이스 2 — 엑셀 업로드 시 컬럼 수가 매번 다른 경우

엑셀 시트의 컬럼 수가 케이스마다 달라서 한 가지 고정 구조로 안 잡힐 때, 첫 행 헤더를 읽어 동적으로 ITAB 구조를 만들고 그 위에 데이터를 채워 넣는 패턴.

케이스 3 — 인터페이스 송수신 시 가변 구조

EAI/RFC로 다른 시스템과 데이터 교환할 때, 한 함수로 여러 종류의 메시지 타입을 처리해야 한다면 RTTC로 매번 다른 구조의 ITAB을 동적으로 생성해서 받는다.

케이스 4 — 동적 ALV 그리드

ALV 그리드를 표시할 때 컬럼 구성이 사용자 선택에 따라 바뀌어야 한다면, cl_abap_structdescr=>create 로 컬럼별 component 리스트를 직접 만들어서 동적 ALV로 표시.


주의사항

describe_by_name vs describe_by_data

메소드 입력
describe_by_name( 'TYPE_NAME' ) TYPES 이름 또는 DDIC 객체 이름
describe_by_data( lv_var ) 데이터 변수 (실제 DATA로 선언된 객체)

DATA로 선언한 변수에 describe_by_name을 쓰면 동작 안 합니다. 반대 케이스도 마찬가지.

CREATE DATA로 만든 객체는 메모리 직접 관리

REF TO data 변수가 가리키는 메모리는 ABAP 가비지 컬렉터가 관리합니다. 변수가 스코프를 벗어나면 자동 해제되지만, 큰 데이터를 다룰 땐 메모리 사용 모니터링 권장.

INTO CORRESPONDING FIELDS OF TABLE 필수

동적 SELECT에서 INTO TABLE 만 쓰면 필드 매핑이 깨질 수 있습니다. 동적 테이블에는 항상 INTO CORRESPONDING FIELDS OF TABLE <fs_table> 사용.

성능 — 정적 ITAB보다 느림

동적 테이블은 컴파일 시 타입 체크가 불가능해서 런타임 비용이 약간 더 듭니다. 매 LOOP마다 동적 생성하는 패턴은 피하고, 한 번 만든 객체를 재사용하는 게 좋습니다.

TYPE HANDLE 안에는 데이터 디스크립터만

CREATE DATA ... TYPE HANDLE lr_descr 의 lr_descr 위치에는 cl_abap_datadescr 의 하위(structdescr / tabledescr / elemdescr 등)만 올 수 있습니다.


요약

필요한 것 사용할 클래스 / 명령
구조체 필드 정보 조회 cl_abap_typedescr=>describe_by_name?= cl_abap_structdescrcomponents 루프
동적 ITAB 생성 cl_abap_tabledescr=>createCREATE DATA TYPE HANDLEASSIGN ref->*
동적 SELECT SELECT * FROM (lv_name) INTO CORRESPONDING FIELDS OF TABLE <fs_table>
출력 cl_demo_output=>display 또는 동적 ALV

RTTS는 한 번 익혀두면 활용 범위가 매우 넓은 ABAP 기법입니다. 처음에는 클래스 캐스팅과 데이터 레퍼런스 개념이 헷갈리지만, 위 6단계 패턴만 정확히 외워두면 어떤 동적 시나리오든 같은 틀로 해결할 수 있습니다.


Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다. SAP NetWeaver 버전에 따라 일부 클래스 메소드의 동작이 다를 수 있으므로 적용 전 테스트 시스템에서 검증하시기 바랍니다.