왜 Embedded Steampunk가 등장했는가
S/4HANA Cloud Private Edition과 On-Premise 시스템에서 클린코어(Clean Core) 원칙을 강제하기 위해 도입된 개발 모델이 바로 Embedded Steampunk입니다. 기존의 Classic ABAP은 SAP 표준 테이블에 자유롭게 SELECT하고, 표준 Function Module을 호출하며, 심지어 표준 코드를 Implicit Enhancement로 수정할 수 있었습니다. 이런 자유는 단기적 생산성을 주었지만, 업그레이드 시점마다 수정자국이 발목을 잡는 기술부채로 누적되었습니다.
Embedded Steampunk는 BTP의 Pure Cloud ABAP 환경에서 검증된 ABAP for Cloud Development 언어 버전을 On-Stack(S/4HANA 시스템 내부)으로 가져온 것입니다. 즉 같은 시스템 안에서 살지만, Released API 컨트랙트로만 표준 자산에 접근하도록 컴파일러가 강제합니다. 결과적으로 향후 BTP ABAP Environment(Steampunk)로 코드를 이관할 때 거의 그대로 재사용 가능한 자산이 됩니다.
다음 항목을 점검 리스트로 활용할 수 있습니다.
- Language Version을 ABAP for Cloud Development로 전환했는가
- Released 컨트랙트(C1/C2)만 사용하는가
- RAP 기반으로 BO를 모델링했는가
- BTP 이관 시 Service Binding 교체만으로 동작하는가
사전에 알고 있으면 좋은 배경
ADT(ABAP Development Tools) 사용 경험, CDS View와 Annotation 기본 문법, OData/RAP의 Behavior Definition 개념, 그리고 객체지향 ABAP 클래스(CLASS ... DEFINITION) 문법에 익숙해야 합니다. 또한 S/4HANA의 Virtual Data Model(VDM) 계층 구조(Basic/Composite/Consumption)에 대한 이해가 있으면 Released View 선택 시 시행착오를 줄일 수 있습니다.
환경, 릴리스, 사전 준비
Embedded Steampunk는 S/4HANA 2022 이상(권장: S/4HANA 2023 FPS01 또는 그 이상)에서 안정적으로 사용 가능합니다. ABAP Cloud Development Model이 도입된 시점부터 본격적인 기능 확장이 이루어졌으며, 2023 릴리스부터 Custom Code Migration 도구와의 연계가 강화되었습니다.
- S/4HANA 릴리스: 2022 이상(On-Premise/Private Cloud), 2023 권장
- ADT: Eclipse 2024-03 기준 ABAP Development Tools 최신 버전
- 권한:
S_DEVELOP, ABAP Cloud Project 생성 권한 - 패키지: Software Component를
ZLOCAL대신 ABAP Cloud 호환으로 지정 - Tier 구분: 개발자 확장(Developer Extensibility) 패키지에서만 가능
BTP ABAP Environment(Pure Steampunk)는 별도의 SaaS 테넌트 형태로 제공되며, On-Stack과 달리 표준 트랜잭션 코드(SE80, SE16 등)는 사용할 수 없습니다. ADT만이 유일한 개발 진입점입니다.
핵심 개념: 컨트랙트 기반 격리 모델
전통적인 ABAP을 "열쇠가 모든 방에 통하는 마스터 키"라고 비유한다면, Embedded Steampunk는 "방마다 다른 출입증을 발급하고, 출입증은 SAP가 보증한 문에만 통한다"는 모델입니다. 이 출입증을 Released Contract라고 부르며, 세 가지 등급으로 나뉩니다.
- C0 Public: SAP가 안정성을 약속한 Public API. 클라우드/온프레미스 모두에서 호환
- C1 Key User / Developer Extensibility: 개발자 확장에서 사용 가능한 Released 자산. 가장 자주 사용되는 등급
- C2 SAP-internal: SAP 내부 컴포넌트 간 사용. 일반 고객은 직접 사용 불가
컴파일러는 Language Version이 ABAP for Cloud Development로 설정된 객체에서 다음을 차단합니다.
- 비공개 표준 테이블 직접 SELECT (예:
SELECT FROM bkpf) - Released되지 않은 Function Module 호출 (예:
CALL FUNCTION 'BAPI_...'중 일부) - Dynpro(Module Pool), 클래식 리스트, SAPGUI 종속 구문
- SUBMIT, CALL TRANSACTION 등 프로세스 점프
그렇다면 Released되지 않은 표준 BAPI가 꼭 필요한 경우는 어떻게 할까요? Wrapper 패턴을 사용합니다. Classic ABAP 패키지에서 표준 BAPI를 호출하고, 이를 Released Local API로 노출하여 Embedded Steampunk 코드가 호출하는 구조입니다. SAP는 이 방식을 ABAP Cloud 호환성 확보의 표준 패턴으로 권장하고 있습니다.
BTP ABAP(Pure Cloud)과 Embedded Steampunk의 가장 큰 차이는 실행 환경입니다. 전자는 SaaS 테넌트의 멀티테넌시 환경에서 동작하며 데이터베이스도 격리됩니다. 후자는 S/4HANA 시스템 내부에서 동작하므로 표준 데이터에 Released View를 통해 즉시 접근할 수 있습니다. 즉 같은 언어 버전이지만 데이터 접근 비용이 극명히 다릅니다.
실전 코드 1단계: ABAP Cloud 프로파일 적용
먼저 ADT에서 ABAP Project 생성 시 시스템이 클라우드 호환 모드를 지원하는지 확인하고, 개별 패키지/클래스의 Language Version을 명시적으로 설정합니다. 클래스 헤더에 ABAP Language Version 속성을 ABAP for Cloud Development로 지정하면 컴파일러가 즉시 검증을 시작합니다.
" ADT > Project Properties > ABAP Language Version
" = "ABAP for Cloud Development"
CLASS zcl_embedded_demo DEFINITION
PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
METHODS read_released_only
IMPORTING iv_agency TYPE /dmo/agency_id
RETURNING VALUE(rt_data) TYPE STANDARD TABLE OF zi_travel_m.
ENDCLASS.
CLASS zcl_embedded_demo IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
" 아래 코드는 컴파일 오류 - 비공개 테이블 직접 접근
" SELECT FROM bkpf FIELDS belnr INTO TABLE @DATA(lt_bkpf).
" Released CDS View 사용은 허용
DATA(lt_travel) = read_released_only( iv_agency = '70001' ).
out->write( lt_travel ).
ENDMETHOD.
METHOD read_released_only.
SELECT FROM zi_travel_m
FIELDS travel_id, agency_id, overall_status
WHERE agency_id = @iv_agency
INTO TABLE @rt_data.
ENDMETHOD.
ENDCLASS.
중요한 포인트는 if_oo_adt_classrun 인터페이스입니다. Classic ABAP에서 자주 쓰던 보고서 프로그램(REPORT)이 Embedded Steampunk에서는 허용되지 않기 때문에, ADT에서 직접 실행 가능한 콘솔 형태로 클래스를 만드는 것이 표준 패턴입니다.
실전 코드 2단계: CDS Released View와 EML 쓰기 작업
읽기는 Released CDS View를 통해 처리하고, 쓰기 작업은 절대 INSERT/UPDATE SQL 문으로 직접 하지 않습니다. 대신 EML(Entity Manipulation Language)을 사용하여 RAP의 Business Object 레이어를 거치도록 합니다. 이렇게 하면 BDEF에 정의된 Validation, Determination, Authorization Check가 모두 발동하므로 비즈니스 무결성이 보장됩니다.
METHOD update_travel_status.
" 1) Released CDS View로 사전 조회
SELECT FROM zi_travel_m
FIELDS travel_id, agency_id, overall_status
WHERE travel_id = @iv_travel_id
INTO TABLE @DATA(lt_current).
IF lt_current IS INITIAL.
RAISE EXCEPTION TYPE zcx_travel_not_found
EXPORTING textid = zcx_travel_not_found=>not_found
travel_id = iv_travel_id.
ENDIF.
" 2) EML로 BO 업데이트 (직접 UPDATE SQL 금지)
MODIFY ENTITIES OF zi_travel_m
ENTITY Travel
UPDATE FIELDS ( overall_status )
WITH VALUE #( ( travel_id = iv_travel_id
overall_status = 'A' ) )
FAILED DATA(ls_failed)
REPORTED DATA(ls_reported)
MAPPED DATA(ls_mapped).
" 3) 실패 시 로그 적재
IF ls_failed-travel IS NOT INITIAL.
LOOP AT ls_reported-travel INTO DATA(ls_msg).
cl_bali_message_setter=>create(
severity = if_bali_constants=>c_severity_error
text = ls_msg-%msg->if_message~get_longtext( ) ).
ENDLOOP.
RAISE EXCEPTION TYPE zcx_travel_update_failed.
ENDIF.
" 4) Save Sequence 명시 호출
COMMIT ENTITIES RESPONSES FAILED DATA(lt_commit_failed).
IF lt_commit_failed IS NOT INITIAL.
RAISE EXCEPTION TYPE zcx_travel_commit_failed.
ENDIF.
ENDMETHOD.
핵심은 변경 → COMMIT ENTITIES → 검증 시퀀스를 명시적으로 따르는 것입니다. Classic ABAP의 COMMIT WORK는 사용 가능하지만 RAP 트랜잭션 모델에서는 COMMIT ENTITIES가 BO 라이프사이클과 동기화되어 안전합니다. 또한 cl_bali_message_setter는 Released된 Business Application Log API로, BTP에서도 동일한 시그니처로 동작합니다.
실전 코드 3단계: RAP BDEF와 BTP 이관 대비 서비스 노출
Behavior Definition은 BO의 행동 계약입니다. 여기에 Validation, Determination, Action을 선언하면 RAP 런타임이 이를 자동 호출합니다. 운영 환경 배포 시에는 권한, 잠금, 락 모드까지 정의하여 다중 사용자 시나리오를 안전하게 처리해야 합니다.
managed implementation in class zbp_i_travel_m unique;
strict ( 2 );
with draft;
define behavior for ZI_TRAVEL_M alias Travel
persistent table /dmo/travel
draft table zdtravel_m
lock master total etag last_changed_at
authorization master ( instance )
etag master last_changed_at
{
create;
update;
delete;
field ( readonly ) travel_id;
field ( mandatory ) agency_id, customer_id;
validation validateStatus
on save { field overall_status; }
validation validateDates
on save { field begin_date, end_date; }
determination calculateTotal
on modify { field booking_fee, currency_code; }
action ( features : instance ) acceptTravel result [1] $self;
action ( features : instance ) rejectTravel result [1] $self;
draft action Edit;
draft action Activate optimized;
draft action Discard;
draft action Resume;
draft determine action Prepare {
validation validateStatus;
validation validateDates;
}
}
이 BDEF는 BTP ABAP Environment로 그대로 이관 가능합니다. 차이는 단 하나, persistent table이 BTP에서는 클라우드 전용 테이블(예: z_travel_cloud)을 가리키도록 변경해야 한다는 점뿐입니다. Service Definition과 Service Binding은 OData V4로 노출하면 Fiori Elements와 즉시 연동됩니다.
@EndUserText.label: 'Travel Service'
define service ZUI_TRAVEL_M {
expose ZI_TRAVEL_M as Travel;
expose ZI_BOOKING_M as Booking;
}
Service Binding을 OData V4 UI Service로 생성하면 즉시 Preview 가능하며, BTP 이전 시 Binding만 재생성하면 Fiori Launchpad의 타일까지 자동으로 연결됩니다. 권한 검사는 BDEF의 authorization master 절과 CDS Access Control의 DCL(Data Control Language) 파일을 함께 사용해야 합니다.
@EndUserText.label: 'Travel access control'
@MappingRole: true
define role ZI_TRAVEL_M {
grant select on ZI_TRAVEL_M
where (agency_id) = aspect pfcg_auth (/DMO/AGNCY, AGENCY_ID, ACTVT = '03');
}
흔한 실수와 트러블슈팅
Embedded Steampunk 도입 초기에 마주치는 실수는 대개 컨트랙트 위반과 트랜잭션 모델 혼동에서 발생합니다.
- Released 여부 확인 누락:
SELECT FROM mara처럼 표준 테이블을 직접 조회하면 컴파일 오류. ADT의 Repository Tree에서 객체 우클릭 → Released APIs로 확인하거나I_Product같은 VDM Released View로 우회 - Wrapper 패턴 미적용: 표준 BAPI가 Released되지 않은 경우, Classic ABAP 패키지에서 호출하는 Local Wrapper Class를 만들고 이를 Released로 표시
- COMMIT WORK 남용: RAP BO 내부에서
COMMIT WORK를 호출하면 트랜잭션 일관성이 깨질 수 있음. 반드시COMMIT ENTITIES사용
FAQ 1: Released API가 부족해서 막힐 때는? SAP for Me 또는 ADT의 API State 뷰에서 Release Request를 제출할 수 있습니다. 일반적으로 우선순위가 높은 BAPI는 분기별 릴리스에 포함됩니다.
FAQ 2: SE16N 대신 무엇을 쓰나요? ADT의 Data Preview(F8) 또는 RAP BO Test Class를 사용합니다. 데이터 분석은 CDS View Preview가 권장됩니다.
FAQ 3: 기존 Z-프로그램을 어떻게 이관하나요? Custom Code Migration 도구(ADT 내장)로 분석하면 Released되지 않은 호출 지점을 리스트업해 줍니다. 이를 기반으로 Wrapper를 만들거나 Released View로 대체합니다.
다음에 다뤄볼 만한 확장 주제
Embedded Steampunk에 익숙해졌다면 다음 단계로 Side-by-Side Extensibility(BTP에 별도 앱 배포), Event-Driven Architecture(SAP Event Mesh, ABAP Channels), Cloud Application Programming Model(CAP, Node.js/Java) 연동을 다뤄볼 수 있습니다. 특히 RAP 기반 OData 서비스를 SAP Build Apps와 연결하면 No-Code/Low-Code 프론트엔드까지 확장됩니다.
또한 ABAP Test Cockpit(ATC)에 ABAP Cloud 체크 변형을 적용하면, 모든 신규 코드에 자동으로 Released 컨트랙트 위반을 검증할 수 있어 거버넌스 측면에서 권장됩니다.
댓글 0
아직 댓글이 없습니다.