ABAP 데이터 타입과 변수 선언

ABAP 데이터 타입 개요

ABAP(Advanced Business Application Programming)에서 데이터를 다루려면 먼저 타입(Type)변수(Data Object)의 개념을 이해해야 합니다. 타입은 데이터의 형태를 정의하고, 변수는 해당 타입에 맞는 실제 값을 저장하는 메모리 공간입니다.

ABAP의 데이터 타입은 크게 기본 타입(Elementary Type), 구조체(Structure), 내부 테이블(Internal Table)로 나뉩니다.

기본 타입 (Elementary Types)

ABAP에서 제공하는 기본 데이터 타입은 다음과 같습니다.

타입설명기본 길이값 범위 / 예시
C문자(Character)1자리'ABAP', 'Hello'
N숫자 문자열(Numeric Text)1자리'001234' (숫자만 허용, 앞에 0 유지)
I정수(Integer)4바이트-2,147,483,648 ~ 2,147,483,647
P패킹 십진수(Packed Decimal)8바이트소수점 연산에 적합, DECIMALS 지정
D날짜(Date)8자리'20260506' (YYYYMMDD)
T시간(Time)6자리'143052' (HHMMSS)
STRING가변 길이 문자열가변길이 제한 없음
XSTRING가변 길이 바이트열가변바이너리 데이터

각 타입별 선언 예제

1REPORT Z_TYPE_EXAMPLE.
2
3" ── 문자 타입 ──
4DATA: lv_char   TYPE c LENGTH 10 VALUE 'ABAP',       " 고정 길이 문자
5      lv_numc   TYPE n LENGTH 8  VALUE '00012345',   " 숫자 문자열 (앞자리 0 유지)
6      lv_string TYPE string      VALUE 'Hello ABAP'. " 가변 길이 문자열
7
8" ── 숫자 타입 ──
9DATA: lv_int    TYPE i            VALUE 100,          " 정수
10      lv_pack   TYPE p LENGTH 8 DECIMALS 2 VALUE '1234.56'. " 패킹 십진수
11
12" ── 날짜/시간 타입 ──
13DATA: lv_date   TYPE d VALUE '20260506',  " 날짜 (YYYYMMDD)
14      lv_time   TYPE t VALUE '143000'.    " 시간 (HHMMSS)
15
16" ── 출력 ──
17WRITE: / '문자(C):', lv_char,
18       / '숫자문자(N):', lv_numc,
19       / '문자열(STRING):', lv_string,
20       / '정수(I):', lv_int,
21       / '패킹(P):', lv_pack,
22       / '날짜(D):', lv_date,
23       / '시간(T):', lv_time.
실행 결과:
문자(C): ABAP 숫자문자(N): 00012345 문자열(STRING): Hello ABAP 정수(I): 100 패킹(P): 1,234.56 날짜(D): 20260506 시간(T): 143000

P 타입의 소수점 연산

P 타입은 금액, 수량 등 정밀한 소수점 연산이 필요할 때 사용합니다.

1DATA: lv_price    TYPE p LENGTH 8 DECIMALS 2 VALUE '1500.00',
2      lv_quantity TYPE p LENGTH 8 DECIMALS 3 VALUE '2.500',
3      lv_total    TYPE p LENGTH 8 DECIMALS 2.
4
5lv_total = lv_price * lv_quantity.
6
7WRITE: / '단가:', lv_price,
8       / '수량:', lv_quantity,
9       / '합계:', lv_total.  " 결과: 3,750.00

DATA 선언

DATA 키워드

DATA는 변수를 선언하는 가장 기본적인 키워드입니다.

1" 단일 선언
2DATA lv_name TYPE string.
3
4" 연속 선언 (콜론 + 쉼표)
5DATA: lv_matnr TYPE c LENGTH 18,
6      lv_maktx TYPE c LENGTH 40,
7      lv_menge TYPE p LENGTH 13 DECIMALS 3.
8
9" DDIC 타입 참조 선언
10DATA: lv_bukrs TYPE bukrs,   " 회사코드 (DDIC 도메인 참조)
11      lv_werks TYPE werks_d. " 플랜트

CONSTANTS

상수는 프로그램 실행 중 값이 변경되지 않는 데이터입니다.

1CONSTANTS: gc_max_rows TYPE i VALUE 1000,
2           gc_company  TYPE bukrs VALUE '1000',
3           gc_status_a TYPE c LENGTH 1 VALUE 'A'.
4
5" gc_max_rows = 2000.  " ← 컴파일 에러! 상수는 변경 불가

TYPES

TYPES는 사용자 정의 타입을 만들 때 사용합니다. 메모리를 할당하지 않으며, 이후 DATA로 변수를 선언할 때 참조합니다.

1" 단순 타입 정의
2TYPES: ty_matnr TYPE c LENGTH 18,
3       ty_menge TYPE p LENGTH 13 DECIMALS 3.
4
5" 정의한 타입으로 변수 선언
6DATA: lv_matnr TYPE ty_matnr,
7      lv_menge TYPE ty_menge.

LIKE vs TYPE 비교

구분TYPELIKE
참조 대상타입(Type) 참조기존 변수(Data Object) 참조
사용 예시DATA lv_a TYPE iDATA lv_b LIKE lv_a
DDIC 참조DATA lv_c TYPE bukrsDATA lv_d LIKE mara-matnr (필드 참조 가능)
권장 여부권장레거시 코드에서 주로 사용
1DATA: lv_count TYPE i VALUE 10.
2DATA: lv_copy  LIKE lv_count.    " lv_count와 동일한 타입(I)으로 선언
3
4" 현재는 TYPE 사용이 표준으로 권장됩니다.
5DATA: lv_count2 TYPE i VALUE 20. " 권장 방식

초기값과 CLEAR

각 데이터 타입은 선언 시 자동으로 초기값이 할당됩니다.

타입초기값
C공백(Space)
N'0...0' (0으로 채움)
I0
P0
D'00000000'
T'000000'
STRING빈 문자열('')

CLEAR 구문을 사용하면 변수를 초기값으로 되돌릴 수 있습니다.

1DATA: lv_name TYPE string VALUE 'ABAP',
2      lv_num  TYPE i VALUE 999.
3
4WRITE: / '초기화 전:', lv_name, lv_num.
5
6CLEAR: lv_name, lv_num.
7
8WRITE: / '초기화 후:', lv_name, lv_num.
9" 결과: lv_name = '', lv_num = 0

구조체 (Structure)

구조체는 서로 다른 타입의 필드를 하나로 묶은 복합 데이터 타입입니다. 데이터베이스 테이블의 한 행(Row)과 유사합니다.

BEGIN OF ~ END OF

1" ── 구조체 타입 정의 ──
2TYPES: BEGIN OF ty_material,
3         matnr TYPE matnr,    " 자재번호
4         maktx TYPE maktx,    " 자재내역
5         mtart TYPE mtart,    " 자재유형
6         menge TYPE menge_d,  " 수량
7         meins TYPE meins,    " 단위
8       END OF ty_material.
9
10" ── 구조체 변수 선언 ──
11DATA: ls_material TYPE ty_material.
12
13" ── 값 할당 ──
14ls_material-matnr = '000000001000000001'.
15ls_material-maktx = '테스트 자재'.
16ls_material-mtart = 'FERT'.
17ls_material-menge = '100.000'.
18ls_material-meins = 'EA'.
19
20WRITE: / '자재번호:', ls_material-matnr,
21       / '자재내역:', ls_material-maktx,
22       / '자재유형:', ls_material-mtart.

INCLUDE STRUCTURE

DDIC에 정의된 구조체를 포함하여 확장할 수 있습니다.

1" MARA 테이블 구조를 포함하고 추가 필드를 덧붙임
2TYPES: BEGIN OF ty_material_ext.
3         INCLUDE STRUCTURE mara.
4TYPES:   maktx TYPE maktx,   " 추가 필드: 자재내역
5         status TYPE c LENGTH 1, " 추가 필드: 상태
6       END OF ty_material_ext.
7
8DATA: ls_mat_ext TYPE ty_material_ext.

내부 테이블 (Internal Table)

내부 테이블은 구조체의 집합으로, 프로그램 실행 중 메모리에 여러 행의 데이터를 저장합니다. 데이터베이스 테이블과 달리 프로그램이 종료되면 사라집니다.

테이블 종류 비교

SSTANDARD TABLE

🔍 검색: 순차 (Linear)
📊 성능: O(n)
🔑 키 중복: 허용
📋 정렬: 미정렬
📌 접근: 인덱스 / 키

용도: 일반적인 데이터 처리, 순서 유지

1000건 → 최대 1000번 비교

OSORTED TABLE

🔍 검색: 이진 (Binary)
📊 성능: O(log n)
🔑 키 중복: 선택 가능
📋 정렬: 자동 정렬
📌 접근: 인덱스 / 키

용도: 정렬 필요, READ TABLE 빈번

1000건 → 최대 10번 비교

HHASHED TABLE

🔍 검색: 해시 (Hash)
📊 성능: O(1)
🔑 키 중복: 불허 (UNIQUE)
📋 정렬: 없음
📌 접근: 키만 가능

용도: 대량 데이터 빠른 검색

1000건 → 1번에 접근

테이블 선언

1" ── 라인 타입 정의 ──
2TYPES: BEGIN OF ty_employee,
3         empno TYPE n LENGTH 8,   " 사원번호
4         name  TYPE c LENGTH 40,  " 이름
5         dept  TYPE c LENGTH 20,  " 부서
6         salary TYPE p LENGTH 8 DECIMALS 0, " 급여
7       END OF ty_employee.
8
9" ── STANDARD TABLE (가장 일반적) ──
10DATA: lt_emp_std TYPE STANDARD TABLE OF ty_employee
11        WITH DEFAULT KEY.
12
13" ── SORTED TABLE ──
14DATA: lt_emp_sort TYPE SORTED TABLE OF ty_employee
15        WITH UNIQUE KEY empno.
16
17" ── HASHED TABLE ──
18DATA: lt_emp_hash TYPE HASHED TABLE OF ty_employee
19        WITH UNIQUE KEY empno.
20
21" ── 간단한 선언 (STANDARD TABLE이 기본값) ──
22DATA: lt_employees TYPE TABLE OF ty_employee.
23
24" ── Work Area (구조체) ──
25DATA: ls_employee TYPE ty_employee.

주요 조작 구문

APPEND: 테이블 끝에 행 추가

1" Work Area에 값을 채운 후 테이블에 추가
2ls_employee-empno  = '00000001'.
3ls_employee-name   = '홍길동'.
4ls_employee-dept   = '개발팀'.
5ls_employee-salary = 5000000.
6APPEND ls_employee TO lt_employees.
7
8ls_employee-empno  = '00000002'.
9ls_employee-name   = '성춘향'.
10ls_employee-dept   = '기획팀'.
11ls_employee-salary = 4800000.
12APPEND ls_employee TO lt_employees.
13
14" 인라인 추가 (7.40+)
15APPEND VALUE #( empno = '00000003'
16                name  = '이몽룡'
17                dept  = '개발팀'
18                salary = 5200000 ) TO lt_employees.

READ TABLE: 특정 행 읽기

1" 키로 검색
2READ TABLE lt_employees INTO ls_employee
3  WITH KEY empno = '00000002'.
4
5IF sy-subrc = 0.
6  WRITE: / '찾음:', ls_employee-name. " 결과: 성춘향
7ELSE.
8  WRITE: / '데이터 없음'.
9ENDIF.
10
11" 인덱스로 검색
12READ TABLE lt_employees INTO ls_employee INDEX 1.
13WRITE: / '첫 번째:', ls_employee-name. " 결과: 홍길동

MODIFY: 행 수정

1" 인덱스로 수정
2ls_employee-salary = 5500000.
3MODIFY lt_employees FROM ls_employee INDEX 2.
4
5" 키로 수정 (TRANSPORTING 사용)
6ls_employee-dept = '경영지원팀'.
7MODIFY lt_employees FROM ls_employee
8  TRANSPORTING dept
9  WHERE empno = '00000002'.

DELETE: 행 삭제

1" 인덱스로 삭제
2DELETE lt_employees INDEX 3.
3
4" 조건으로 삭제
5DELETE lt_employees WHERE dept = '기획팀'.

INSERT: 특정 위치에 삽입

1" 인덱스 위치에 삽입
2ls_employee-empno = '00000004'.
3ls_employee-name  = '심청이'.
4ls_employee-dept  = '인사팀'.
5ls_employee-salary = 4500000.
6INSERT ls_employee INTO lt_employees INDEX 1.

LOOP AT ~ WHERE

1" ── 전체 순회 (INTO 방식) ──
2LOOP AT lt_employees INTO ls_employee.
3  WRITE: / ls_employee-empno, ls_employee-name, ls_employee-dept.
4ENDLOOP.
5
6" ── 조건부 순회 ──
7WRITE: / '── 개발팀만 조회 ──'.
8LOOP AT lt_employees INTO ls_employee WHERE dept = '개발팀'.
9  WRITE: / ls_employee-empno, ls_employee-name, ls_employee-salary.
10ENDLOOP.
11
12" ── ASSIGNING 방식 (메모리 복사 없이 직접 접근) ──
13FIELD-SYMBOLS: <ls_emp> TYPE ty_employee.
14
15LOOP AT lt_employees ASSIGNING <ls_emp>.
16  " Field Symbol로 직접 수정 가능 (MODIFY 불필요)
17  <ls_emp>-salary = <ls_emp>-salary * '1.1'. " 10% 인상
18ENDLOOP.

실무 예제: 구매오더 데이터 구조 설계

실제 SAP 업무에서 사용하는 구매오더(Purchase Order) 데이터를 구조체와 내부 테이블로 설계하고, 데이터를 추가/조회/집계하는 전체 예제입니다.

1REPORT Z_PO_DATA_EXAMPLE.
2
3" ==============================
4" 1. 타입 정의
5" ==============================
6TYPES: BEGIN OF ty_po_item,
7         ebeln     TYPE c LENGTH 10,  " 구매오더 번호
8         ebelp     TYPE n LENGTH 5,   " 항목번호
9         matnr     TYPE c LENGTH 18,  " 자재번호
10         maktx     TYPE c LENGTH 40,  " 자재명
11         menge     TYPE p LENGTH 8 DECIMALS 3,  " 수량
12         netpr     TYPE p LENGTH 8 DECIMALS 2,  " 단가
13         netwr     TYPE p LENGTH 8 DECIMALS 2,  " 금액
14         waers     TYPE c LENGTH 5,   " 통화
15         lifnr     TYPE c LENGTH 10,  " 공급업체
16       END OF ty_po_item.
17
18TYPES: ty_po_items TYPE STANDARD TABLE OF ty_po_item
19         WITH DEFAULT KEY.
20
21" ==============================
22" 2. 데이터 선언
23" ==============================
24DATA: lt_po_items TYPE ty_po_items,
25      ls_po_item  TYPE ty_po_item.
26
27DATA: lv_total_amount TYPE p LENGTH 10 DECIMALS 2,
28      lv_item_count   TYPE i.
29
30" ==============================
31" 3. 데이터 추가
32" ==============================
33ls_po_item-ebeln = '4500000001'.
34ls_po_item-ebelp = '00010'.
35ls_po_item-matnr = 'MAT-001'.
36ls_po_item-maktx = 'A4 복사용지'.
37ls_po_item-menge = '100.000'.
38ls_po_item-netpr = '25000.00'.
39ls_po_item-netwr = ls_po_item-menge * ls_po_item-netpr.
40ls_po_item-waers = 'KRW'.
41ls_po_item-lifnr = 'V-1001'.
42APPEND ls_po_item TO lt_po_items.
43
44CLEAR ls_po_item.  " 재사용 전 초기화
45
46ls_po_item-ebeln = '4500000001'.
47ls_po_item-ebelp = '00020'.
48ls_po_item-matnr = 'MAT-002'.
49ls_po_item-maktx = '토너 카트리지'.
50ls_po_item-menge = '10.000'.
51ls_po_item-netpr = '85000.00'.
52ls_po_item-netwr = ls_po_item-menge * ls_po_item-netpr.
53ls_po_item-waers = 'KRW'.
54ls_po_item-lifnr = 'V-1001'.
55APPEND ls_po_item TO lt_po_items.
56
57CLEAR ls_po_item.
58
59ls_po_item-ebeln = '4500000002'.
60ls_po_item-ebelp = '00010'.
61ls_po_item-matnr = 'MAT-003'.
62ls_po_item-maktx = '사무용 의자'.
63ls_po_item-menge = '5.000'.
64ls_po_item-netpr = '320000.00'.
65ls_po_item-netwr = ls_po_item-menge * ls_po_item-netpr.
66ls_po_item-waers = 'KRW'.
67ls_po_item-lifnr = 'V-2001'.
68APPEND ls_po_item TO lt_po_items.
69
70" ==============================
71" 4. 데이터 조회 및 출력
72" ==============================
73WRITE: / '====================================================='.
74WRITE: / '구매오더', 15 '항목', 22 '자재명', 45 '수량', 58 '단가', 75 '금액'.
75WRITE: / '====================================================='.
76
77LOOP AT lt_po_items INTO ls_po_item.
78  WRITE: / ls_po_item-ebeln,
79         15 ls_po_item-ebelp,
80         22 ls_po_item-maktx,
81         45 ls_po_item-menge,
82         58 ls_po_item-netpr,
83         75 ls_po_item-netwr.
84
85  " 합계 누적
86  lv_total_amount = lv_total_amount + ls_po_item-netwr.
87  lv_item_count   = lv_item_count + 1.
88ENDLOOP.
89
90WRITE: / '====================================================='.
91WRITE: / '총 항목 수:', lv_item_count.
92WRITE: / '총 금액:', lv_total_amount, ls_po_item-waers.
93
94" ==============================
95" 5. 특정 구매오더만 필터링
96" ==============================
97WRITE: / ''.
98WRITE: / '── 4500000001 구매오더 상세 ──'.
99
100LOOP AT lt_po_items INTO ls_po_item
101  WHERE ebeln = '4500000001'.
102  WRITE: / ls_po_item-ebelp, ls_po_item-maktx, ls_po_item-netwr.
103ENDLOOP.
실행 결과:
===================================================== 구매오더 항목 자재명 수량 단가 금액 ===================================================== 4500000001 00010 A4 복사용지 100.000 25,000.00 2,500,000.00 4500000001 00020 토너 카트리지 10.000 85,000.00 850,000.00 4500000002 00010 사무용 의자 5.000 320,000.00 1,600,000.00 ===================================================== 총 항목 수: 3 총 금액: 4,950,000.00 KRW ── 4500000001 구매오더 상세 ── 00010 A4 복사용지 2,500,000.00 00020 토너 카트리지 850,000.00

이 예제에서는 TYPES로 구매오더 구조체를 정의하고, DATA로 내부 테이블과 Work Area를 선언한 뒤, APPEND, LOOP, WHERE 등을 활용하여 실무에서 자주 접하는 구매 데이터 처리 패턴을 구현했습니다.

Disclaimer — 이 포스트는 AI(Claude)를 활용하여 작성된 초안을 바탕으로 검수 및 보완하여 작성되었습니다. 내용 중 오류나 오타가 있다면 댓글로 알려주시면 감사하겠습니다.