ABAP

ABAP OOP 실전 — CLASS, INTERFACE, INHERITANCE 완전 정복

▶ YouTube에서 보기

ABAP OOP 실전 — CLASS, INTERFACE, INHERITANCE 완전 정복

Moderator · 2026. 4. 27. · 조회 2

ABAP OOP 실전 — CLASS, INTERFACE, INHERITANCE 완전 정복

Moderator · 2026. 4. 27. · 조회 2

1. 개요 - ABAP OOP가 왜 중요한가

SAP S/4HANA와 BTP(Business Technology Platform) 시대에 접어들면서, ABAP 개발은 더 이상 절차적 프로그래밍만으로는 충분하지 않습니다. RAP(RESTful ABAP Programming Model), Clean ABAP, ABAP Cloud 등 모던 ABAP 개발 패러다임은 모두 객체지향(OOP) 기반 위에 설계되어 있습니다.

이 글에서는 ABAP OOP의 세 가지 핵심 축인 CLASS, INTERFACE, INHERITANCE를 체계적으로 다룹니다.

  • CLASS의 선언부와 구현부 구조를 이해하고 직접 작성할 수 있다
  • PUBLIC / PROTECTED / PRIVATE 가시성의 차이를 구분할 수 있다
  • 생성자(constructor)와 정적 생성자(class_constructor)를 활용할 수 있다
  • INHERITING FROM을 통한 상속과 메서드 재정의를 구현할 수 있다
  • INTERFACE를 정의하고 다형성을 실무에 적용할 수 있다
  • 업캐스트 / 다운캐스트의 원리와 안전한 사용법을 익힐 수 있다
학습 대상: ABAP 기본 문법(DATA, TYPES, SELECT 등)을 알고 있으며, 객체지향 개발로 전환하려는 ABAP 개발자. SAP S/4HANA 2021 이상 또는 SAP BTP ABAP Environment에서 실습할 수 있습니다.

2. CLASS 기본 구조 - 선언부와 구현부

ABAP 클래스는 크게 선언부(DEFINITION)구현부(IMPLEMENTATION)로 나뉩니다. 선언부에서는 클래스가 어떤 속성과 메서드를 가지는지 정의하고, 구현부에서는 메서드의 실제 로직을 작성합니다.

로컬 클래스 vs 글로벌 클래스

구분 로컬 클래스 글로벌 클래스
위치 프로그램/인클루드 내부 SE24 또는 ADT에서 별도 생성
접근 범위 해당 프로그램 내에서만 시스템 전체에서 사용 가능
선언 키워드 CLASS lcl DEFINITION. CLASS zcl DEFINITION PUBLIC.
용도 테스트, 헬퍼, 로컬 로직 재사용 가능한 비즈니스 로직

로컬 클래스의 기본 구조는 다음과 같습니다.

CLASS lcl_calculator DEFINITION.
  PUBLIC SECTION.
    METHODS: add IMPORTING iv_a TYPE i
                           iv_b TYPE i
                 RETURNING VALUE(rv_result) TYPE i.

  PRIVATE SECTION.
    DATA: mv_last_result TYPE i.
ENDCLASS.

CLASS lcl_calculator IMPLEMENTATION.
  METHOD add.
    rv_result = iv_a + iv_b.
    mv_last_result = rv_result.
  ENDMETHOD.
ENDCLASS.

글로벌 클래스는 추가로 CREATE PUBLIC, FINAL, ABSTRACT 등의 옵션을 지정할 수 있습니다.

  • FINAL - 이 클래스를 상속할 수 없도록 잠금
  • CREATE PUBLIC / CREATE PROTECTED / CREATE PRIVATE - 누가 인스턴스를 생성할 수 있는지 제어
  • ABSTRACT - 직접 인스턴스화 불가, 서브클래스를 통해서만 사용
핵심: 선언부(DEFINITION)는 "무엇을 할 수 있는가"를, 구현부(IMPLEMENTATION)는 "어떻게 하는가"를 담당합니다. 이 분리가 ABAP OOP의 기본 원칙입니다.

3. 가시성과 속성 - PUBLIC / PROTECTED / PRIVATE

클래스의 컴포넌트(속성, 메서드)는 가시성 섹션에 따라 접근 범위가 결정됩니다. 이것은 캡슐화(Encapsulation)의 핵심 메커니즘입니다.

섹션 클래스 내부 서브클래스 외부 호출자 Friend
PUBLIC O O O O
PROTECTED O O X O
PRIVATE O X X O

인스턴스 속성 vs 정적 속성

  • 인스턴스 속성 (DATA) - 각 객체마다 독립적으로 존재하는 데이터. 객체가 생성될 때마다 새로운 사본이 만들어집니다.
  • 정적 속성 (CLASS-DATA) - 클래스 전체에서 공유하는 데이터. 모든 인스턴스가 동일한 값을 참조합니다.
  • 상수 (CONSTANTS) - 변경 불가능한 고정 값.
  • READ-ONLY - PUBLIC SECTION에 선언 시 외부에서 읽기만 허용하고 쓰기는 차단합니다.

비유하자면, 인스턴스 속성은 "각 직원의 개인 사물함"이고, 정적 속성은 "부서 공용 게시판"과 같습니다. 모든 직원(인스턴스)이 각자의 사물함을 갖지만, 게시판은 부서(클래스) 하나에 하나만 존재합니다.

설계 원칙: 가능한 한 PRIVATE으로 선언하고, 필요한 것만 PUBLIC으로 노출하세요. "최소 권한 원칙"은 유지보수성과 안정성을 높여줍니다.

4. 메서드와 생성자

메서드는 클래스의 행위(Behavior)를 정의합니다. ABAP OOP에서는 인스턴스 메서드정적 메서드, 그리고 두 종류의 생성자를 구분해야 합니다.

파라미터 종류

키워드 방향 설명
IMPORTING 입력 호출자가 메서드에 전달하는 값
EXPORTING 출력 메서드가 호출자에게 반환하는 값
CHANGING 입출력 전달받아 변경 후 반환
RETURNING 반환 함수형 메서드, 메서드 체이닝에 필수
RAISING 예외 발생 가능한 예외 클래스 선언

생성자(Constructor)

  • 인스턴스 생성자 (constructor) - 객체가 생성될 때마다 자동 호출됩니다. PUBLIC SECTION에 선언하며, IMPORTING 파라미터를 가질 수 있습니다.
  • 정적 생성자 (class_constructor) - 클래스가 세션 내에서 최초로 사용될 때 단 1회만 호출됩니다. 파라미터를 가질 수 없습니다.
CLASS lcl_employee DEFINITION.
  PUBLIC SECTION.
    METHODS constructor IMPORTING iv_name   TYPE string
                                  iv_emp_id TYPE i.
    CLASS-METHODS class_constructor.
    METHODS get_info RETURNING VALUE(rv_info) TYPE string.

  PRIVATE SECTION.
    DATA: mv_name   TYPE string,
          mv_emp_id TYPE i.
    CLASS-DATA: sv_counter TYPE i.
ENDCLASS.

CLASS lcl_employee IMPLEMENTATION.
  METHOD class_constructor.
    sv_counter = 0.
    " 클래스 최초 사용 시 1회 실행 (예: 로그 초기화)
  ENDMETHOD.

  METHOD constructor.
    mv_name   = iv_name.
    mv_emp_id = iv_emp_id.
    sv_counter = sv_counter + 1.
  ENDMETHOD.

  METHOD get_info.
    rv_info = |사원번호: { mv_emp_id } / 이름: { mv_name } / 전체 직원 수: { sv_counter }|.
  ENDMETHOD.
ENDCLASS.
주의: class_constructor는 파라미터를 받을 수 없고, 반드시 PUBLIC SECTION에 선언해야 합니다. 정적 속성의 초기화나 환경 설정 로딩에 주로 사용됩니다.

5. 객체 생성과 사용 - NEW, ->, =>

ABAP 7.40 이후부터 NEW 연산자인라인 선언을 활용하여 간결하게 객체를 생성할 수 있습니다.

객체 생성 방법

" 방법 1: 전통적 방식
DATA lo_emp TYPE REF TO lcl_employee.
CREATE OBJECT lo_emp
  EXPORTING iv_name   = '김개발'
            iv_emp_id = 1001.

" 방법 2: NEW 연산자 (ABAP 7.40+)
DATA lo_emp2 TYPE REF TO lcl_employee.
lo_emp2 = NEW #( iv_name = '박설계' iv_emp_id = 1002 ).

" 방법 3: 인라인 선언 + NEW (가장 간결)
DATA(lo_emp3) = NEW lcl_employee( iv_name = '이분석' iv_emp_id = 1003 ).

" 인스턴스 멤버 접근: -> 사용
DATA(lv_info) = lo_emp3->get_info( ).

" 정적 멤버 접근: => 사용
DATA(lv_count) = lcl_employee=>sv_counter.

self-reference: me

인스턴스 메서드 내부에서 me->를 통해 자기 자신의 속성이나 메서드를 명시적으로 참조할 수 있습니다. 로컬 변수와 인스턴스 속성의 이름이 동일할 때 구분하는 데 유용합니다.

메서드 체이닝

RETURNING 파라미터가 자기 자신의 레퍼런스를 반환하면, 메서드를 연속으로 호출하는 체이닝 패턴을 구현할 수 있습니다. 빌더(Builder) 패턴 등에서 자주 활용됩니다.

권장: 모던 ABAP 개발에서는 NEW 연산자와 인라인 선언을 사용하는 것이 일반적입니다. CREATE OBJECT는 레거시 코드에서 주로 볼 수 있습니다.

6. 상속(INHERITANCE) - 코드 재사용과 특화

상속은 기존 클래스(슈퍼클래스)의 속성과 메서드를 물려받아 새로운 클래스(서브클래스)를 만드는 메커니즘입니다. INHERITING FROM 키워드로 상속 관계를 선언합니다.

상속 규칙 요약

  • 서브클래스는 슈퍼클래스의 PUBLICPROTECTED 컴포넌트를 상속받습니다
  • PRIVATE 컴포넌트는 상속되지 않습니다 (friend 관계 제외)
  • 메서드 재정의는 REDEFINITION 키워드를 사용합니다
  • 재정의된 메서드에서 슈퍼클래스 원본 로직을 호출하려면 super->를 사용합니다
  • 정적 메서드는 접근 가능하지만 재정의할 수 없습니다
  • FINAL로 선언된 클래스는 상속할 수 없습니다
" 슈퍼클래스: 일반 문서
CLASS lcl_document DEFINITION.
  PUBLIC SECTION.
    METHODS constructor IMPORTING iv_title TYPE string.
    METHODS get_description RETURNING VALUE(rv_desc) TYPE string.

  PROTECTED SECTION.
    DATA: mv_title      TYPE string,
          mv_created_at TYPE timestamp.
ENDCLASS.

CLASS lcl_document IMPLEMENTATION.
  METHOD constructor.
    mv_title = iv_title.
    GET TIME STAMP FIELD mv_created_at.
  ENDMETHOD.

  METHOD get_description.
    rv_desc = |문서: { mv_title }|.
  ENDMETHOD.
ENDCLASS.

" 서브클래스: 승인 문서 (상속 + 확장)
CLASS lcl_approval_doc DEFINITION INHERITING FROM lcl_document.
  PUBLIC SECTION.
    METHODS constructor IMPORTING iv_title    TYPE string
                                  iv_approver TYPE string.
    METHODS get_description REDEFINITION.

  PRIVATE SECTION.
    DATA: mv_approver TYPE string,
          mv_status   TYPE string VALUE 'PENDING'.
ENDCLASS.

CLASS lcl_approval_doc IMPLEMENTATION.
  METHOD constructor.
    super->constructor( iv_title = iv_title ).  " 슈퍼클래스 생성자 호출 필수
    mv_approver = iv_approver.
  ENDMETHOD.

  METHOD get_description.
    rv_desc = |승인문서: { mv_title } / 승인자: { mv_approver } / 상태: { mv_status }|.
  ENDMETHOD.
ENDCLASS.

" 사용 예시
DATA(lo_doc) = NEW lcl_approval_doc( iv_title = '구매요청서' iv_approver = '김부장' ).
DATA(lv_desc) = lo_doc->get_description( ).
" 결과: 승인문서: 구매요청서 / 승인자: 김부장 / 상태: PENDING

업캐스트와 다운캐스트

업캐스트(Upcast)는 서브클래스 레퍼런스를 슈퍼클래스 레퍼런스에 할당하는 것으로, 자동으로 수행됩니다. 반면 다운캐스트(Downcast)는 슈퍼클래스 레퍼런스를 서브클래스 레퍼런스로 변환하는 것이며, 반드시 CAST 연산자를 사용해야 합니다.

" 업캐스트: 서브 -> 슈퍼 (자동)
DATA lo_base TYPE REF TO lcl_document.
DATA(lo_approval) = NEW lcl_approval_doc( iv_title = '견적서' iv_approver = '이팀장' ).
lo_base = lo_approval.  " 업캐스트 - 자동 변환

" 다운캐스트: 슈퍼 -> 서브 (명시적 CAST 필요)
TRY.
    DATA(lo_back) = CAST lcl_approval_doc( lo_base ).
    DATA(lv_info) = lo_back->get_description( ).
  CATCH cx_sy_move_cast_error INTO DATA(lx_error).
    " 캐스팅 실패 시 예외 처리
    DATA(lv_msg) = lx_error->get_text( ).
ENDTRY.

" IS INSTANCE OF 로 안전한 타입 검사
IF lo_base IS INSTANCE OF lcl_approval_doc.
  " 안전하게 다운캐스트 가능
ENDIF.
실무 팁: 다운캐스트 전에는 항상 IS INSTANCE OF 또는 TRY-CATCH를 사용하세요. 런타임에 CX_SY_MOVE_CAST_ERROR 예외가 발생할 수 있습니다.

7. 인터페이스(INTERFACE) - 계약과 다형성

인터페이스는 "무엇을 해야 하는가"만 정의하고, "어떻게 하는가"는 구현 클래스에 맡기는 계약(Contract)입니다. ABAP 인터페이스의 주요 특징은 다음과 같습니다.

  • 인터페이스 내부의 모든 컴포넌트는 PUBLIC입니다 (가시성 섹션이 없음)
  • 속성(DATA), 상수(CONSTANTS), 메서드(METHODS) 모두 선언 가능
  • 하나의 클래스가 여러 인터페이스를 구현할 수 있어, 다중 상속의 한계를 극복
  • 구현 클래스에서 인터페이스 컴포넌트는 intf~component 형식으로 접근
  • ALIASES로 별칭을 만들어 간결하게 사용 가능
" 인터페이스 정의
INTERFACE lif_printable.
  METHODS print RETURNING VALUE(rv_output) TYPE string.
ENDINTERFACE.

INTERFACE lif_exportable.
  METHODS export_to_csv RETURNING VALUE(rv_csv) TYPE string.
ENDINTERFACE.

" 두 개의 인터페이스를 동시에 구현하는 클래스
CLASS lcl_sales_order DEFINITION.
  PUBLIC SECTION.
    INTERFACES: lif_printable,
                lif_exportable.
    ALIASES print FOR lif_printable~print.    " 별칭 설정

    METHODS constructor IMPORTING iv_order_id TYPE string
                                  iv_amount   TYPE p.
  PRIVATE SECTION.
    DATA: mv_order_id TYPE string,
          mv_amount   TYPE p LENGTH 13 DECIMALS 2.
ENDCLASS.

CLASS lcl_sales_order IMPLEMENTATION.
  METHOD constructor.
    mv_order_id = iv_order_id.
    mv_amount   = iv_amount.
  ENDMETHOD.

  METHOD lif_printable~print.
    rv_output = |주문번호: { mv_order_id } / 금액: { mv_amount }|.
  ENDMETHOD.

  METHOD lif_exportable~export_to_csv.
    rv_csv = |{ mv_order_id };{ mv_amount }|.
  ENDMETHOD.
ENDCLASS.

" 다형성 활용: 인터페이스 레퍼런스로 다양한 객체를 동일하게 처리
DATA lt_printables TYPE TABLE OF REF TO lif_printable.
DATA(lo_order1) = NEW lcl_sales_order( iv_order_id = 'SO-001' iv_amount = '15000.00' ).
DATA(lo_order2) = NEW lcl_sales_order( iv_order_id = 'SO-002' iv_amount = '28500.00' ).

APPEND lo_order1 TO lt_printables.
APPEND lo_order2 TO lt_printables.

LOOP AT lt_printables INTO DATA(lo_item).
  DATA(lv_output) = lo_item->print( ).
  WRITE: / lv_output.
ENDLOOP.

인터페이스 메서드 옵션

인터페이스를 구현하는 클래스에서 다음 옵션을 활용할 수 있습니다.

옵션 설명
ABSTRACT METHODS 지정한 메서드를 추상으로 선언 (서브클래스에서 구현)
ALL METHODS ABSTRACT 인터페이스의 모든 메서드를 추상으로 설정
FINAL METHODS 지정한 메서드를 재정의 불가로 잠금
DEFAULT IGNORE 구현하지 않아도 에러 없이 무시
DEFAULT FAIL 미구현 메서드 호출 시 런타임 에러 발생
상속 vs 인터페이스: 상속은 "A는 B의 한 종류다(IS-A)" 관계에, 인터페이스는 "A는 B를 할 수 있다(CAN-DO)" 관계에 적합합니다. 일반적으로 인터페이스를 먼저 고려하고, 코드 재사용이 필요할 때 상속을 추가하는 것이 권장됩니다.

8. 실무 활용 팁 - 설계 원칙과 실습 방법

설계 원칙

  • 인터페이스 우선 설계 - 구체 클래스 대신 인터페이스에 의존하면 테스트와 교체가 용이합니다
  • 생성자에서 초기화 - 객체 생성 시 필요한 의존성과 데이터를 constructor에서 주입하세요
  • RETURNING 파라미터 활용 - 함수형 메서드로 작성하면 체이닝이 가능하고 코드가 간결해집니다
  • 상속 깊이 제한 - 상속 계층이 3단계를 넘어가면 복잡도가 급격히 증가합니다. 구성(Composition)을 함께 검토하세요
  • ABAP Unit으로 테스트 - FOR TESTING 키워드와 인터페이스 기반 모킹으로 단위 테스트를 작성하세요

SE24 / ADT에서 실습하기

  • SE24 (Class Builder) - SAP GUI에서 글로벌 클래스를 시각적으로 생성하고 관리합니다. 메서드, 속성, 이벤트를 탭으로 관리할 수 있어 초보자에게 직관적입니다.
  • ADT (ABAP Development Tools) - Eclipse 기반 개발 환경으로, 코드 기반으로 클래스를 작성합니다. Clean ABAP 스타일에 적합하며, S/4HANA 및 BTP 개발의 표준 도구입니다.
  • ABAP 콘솔 앱 - IF_OO_ADT_CLASSRUN~MAIN 인터페이스를 구현하면 ADT에서 콘솔 출력으로 빠르게 테스트할 수 있습니다.

흔한 실수와 트러블슈팅

실수 원인 해결
super->constructor 미호출 서브클래스 constructor에서 슈퍼클래스 constructor를 빠뜨림 서브클래스 constructor의 첫 줄에서 반드시 super->constructor( ) 호출
CX_SY_MOVE_CAST_ERROR 덤프 다운캐스트 시 실제 타입과 불일치 IS INSTANCE OF 또는 TRY-CATCH로 사전 검사
정적 메서드 REDEFINITION 시도 정적 메서드는 재정의 불가 인스턴스 메서드로 변경하거나, 서브클래스에서 동명의 새 정적 메서드 선언
PRIVATE 속성 상속 기대 PRIVATE은 서브클래스에서 접근 불가 서브클래스 접근이 필요하면 PROTECTED로 변경
인터페이스 메서드명 틸데(~) 누락 lif~method 형식을 사용하지 않음 구현부에서 반드시 인터페이스명~메서드명 형식 사용, 또는 ALIASES 활용
FAQ:
  • Q: ABSTRACT 클래스와 INTERFACE의 차이는? - ABSTRACT 클래스는 일부 메서드를 구현할 수 있지만, INTERFACE는 구현을 포함하지 않습니다. ABSTRACT 클래스는 단일 상속만 가능하고, INTERFACE는 여러 개를 동시에 구현할 수 있습니다.
  • Q: class_constructor는 언제 실행되나요? - 해당 클래스가 세션 내에서 최초로 사용되는 시점(객체 생성, 정적 메서드 호출, 정적 속성 접근 등)에 자동으로 1회 실행됩니다.
  • Q: 메서드 체이닝은 어떻게 구현하나요? - RETURNING 파라미터의 타입을 자기 자신의 클래스 레퍼런스(REF TO)로 설정하고, 메서드 마지막에 result = me를 반환합니다.

더 파볼 주제

ABAP OOP의 기초를 익혔다면, 다음 주제로 학습을 확장할 수 있습니다.

  • ABAP Unit 테스팅 - 인터페이스 기반 Test Double 작성과 자동화 테스트
  • RAP (RESTful ABAP Programming Model) - S/4HANA 확장 및 BTP 개발의 표준 아키텍처
  • Design Patterns in ABAP - Factory, Singleton, Observer 등 실무 패턴
  • Clean ABAP - SAP 공식 코딩 가이드라인에 따른 읽기 좋은 코드 작성법
  • ABAP Cloud - Released API만 사용하는 클라우드 개발 모델

더 읽어볼 자료


⚠️ 비공식 콘텐츠 안내

본 게시글은 btpstacks.com의 독립 학습 콘텐츠이며 SAP SE와 무관합니다. 공식 문서는 help.sap.com을 참고하세요.

SAP, ABAP, SAP BTP, SAPUI5, SAP Fiori는 독일 및 기타 국가에서 SAP SE의 상표 또는 등록상표입니다.

댓글 0

아직 댓글이 없습니다.