[RAP] ABAP RESTful Application Programming Model 입문 — Business Object 4-Layer 구조 완전 가이드
[RAP] ABAP RESTful Application Programming Model 입문 — Business Object 4-Layer 구조 완전 가이드
1. 개요 및 학습 목표
RAP(ABAP RESTful Application Programming Model)는 SAP S/4HANA 및 BTP ABAP Environment에서 OData 서비스를 선언적으로 구축하는 현대적 프레임워크입니다. 기존 SEGW 기반 OData 개발과 달리, CDS View부터 Behavior Definition, Service Definition까지 코드 중심으로 Business Object를 정의하고, 프레임워크가 CRUD 처리와 저장 시퀀스를 자동 관리합니다. 이 튜토리얼에서는 Travel 시나리오를 통해 RAP의 4-Layer 구조를 단계별로 구현합니다.
학습 목표 체크리스트:
- RAP의 4-Layer 아키텍처(CDS View, Behavior Definition, Service Definition, Service Binding)를 이해한다
- CDS Root View Entity로 데이터 모델을 선언할 수 있다
- Behavior Definition에서 CRUD, Action, Validation, Determination을 정의할 수 있다
- Service Definition과 Service Binding으로 OData V4 서비스를 발행할 수 있다
- Managed 시나리오에서 Action을 구현하고 테스트할 수 있다
2. 선수 지식
- ABAP 기본 문법 (DATA, SELECT, METHOD 등)
- CDS View 기초 (define view entity 문법)
- OData 프로토콜 기본 개념 (Entity Set, CRUD 동작)
- ADT(ABAP Development Tools, Eclipse 기반) 사용 경험
3. 환경 / 버전 / 준비물
| 항목 | 권장 사양 |
|---|---|
| SAP 시스템 | S/4HANA 2023 이상 또는 BTP ABAP Environment |
| 개발 도구 | ADT (Eclipse 2023-06 이상 + ABAP Development Tools 플러그인) |
| OData 버전 | OData V4 (UI 또는 Web API) |
| 데모 데이터 | SAP Flight Reference Scenario (/DMO/ 패키지) |
| 권한 | 개발자 권한 (패키지 생성, 서비스 발행 가능) |
SAP Flight Reference Scenario가 설치되어 있지 않다면, SAP-samples/abap-platform-rap-workshops 리포지토리의 설치 가이드를 참고하시기 바랍니다. BTP ABAP Environment에는 일반적으로 사전 설치되어 있습니다.
4. 핵심 개념 — RAP 4-Layer 아키텍처
RAP의 Business Object는 4개 레이어가 쌓이는 구조로 동작합니다. 건물에 비유하면 다음과 같습니다.
비유: RAP BO = 건물 짓기
1층(CDS View) = 설계도: 어떤 데이터가 있는지 구조를 선언합니다.
2층(Behavior Definition) = 규칙서: 이 건물에서 무엇을 할 수 있는지(생성, 수정, 삭제, 승인 등) 규칙을 정합니다.
3층(Service Definition) = 출입구: 외부에서 접근할 수 있도록 어떤 Entity를 노출할지 결정합니다.
4층(Service Binding) = 도로 연결: 실제 URL을 생성하여 Fiori 앱이나 외부 시스템이 호출할 수 있게 합니다.
4-1. CDS View (데이터 모델 레이어)
CDS Root View Entity는 Business Object의 뼈대입니다. define root view entity 키워드로 루트 노드를 선언하며, Composition과 Association으로 자식 노드(예: Booking)와의 관계를 표현합니다. 필드에 @Semantics 어노테이션을 붙이면 Fiori Elements UI가 자동으로 적절한 컨트롤을 렌더링합니다.
4-2. Behavior Definition (동작 정의 레이어)
Behavior Definition(BDEF)은 BO가 지원하는 오퍼레이션을 선언적으로 기술합니다. 핵심 구성 요소는 다음과 같습니다.
- Standard Operations:
create; update; delete;— CRUD 허용 여부를 한 줄로 선언 - Action: 비즈니스 로직 실행 (예: 여행 승인). OData에서 POST 요청으로 호출
- Validation: 저장(save) 시점에 데이터 일관성을 검사 (예: 날짜 유효성)
- Determination: 생성/수정 시점에 필드를 자동 계산 (예: 초기 상태값 설정)
- field ( readonly | mandatory ): 필드별 제어 속성 선언
4-3. Managed vs Unmanaged 시나리오
Managed 시나리오에서는 RAP 프레임워크가 CRUD 로직과 save sequence(Interaction Phase + Save Phase)를 자동 처리합니다. 개발자는 Validation, Determination, Action 같은 비즈니스 로직만 구현하면 됩니다. 반면 Unmanaged 시나리오는 개발자가 모든 저장 로직을 직접 구현하며, 기존 레거시 Business Object를 RAP으로 래핑할 때 주로 사용합니다. 신규 개발이라면 Managed 시나리오가 일반적으로 권장됩니다.
5. 실전 코드 3단계
1단계: CDS Root View Entity 정의 (기본 예제)
가장 먼저 데이터 모델을 정의합니다. SAP Flight Reference Scenario의 /dmo/travel 테이블을 기반으로 Travel BO의 루트 뷰를 생성합니다.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Travel BO - Interface View'
define root view entity ZI_Travel
as select from /dmo/travel as Travel
{
key Travel.travel_id as TravelId,
Travel.agency_id as AgencyId,
Travel.customer_id as CustomerId,
Travel.begin_date as BeginDate,
Travel.end_date as EndDate,
Travel.booking_fee as BookingFee,
Travel.total_price as TotalPrice,
Travel.currency_code as CurrencyCode,
Travel.description as Description,
Travel.overall_status as OverallStatus,
Travel.created_by as CreatedBy,
Travel.created_at as CreatedAt,
Travel.last_changed_by as LastChangedBy,
Travel.last_changed_at as LastChangedAt
}
주요 포인트:
define root view entity: 이 CDS가 BO의 루트 노드임을 선언합니다. Composition이 있는 경우 자식 노드를 연결할 수 있습니다.@AccessControl.authorizationCheck: #CHECK: CDS Access Control(DCL)을 활성화하여 권한 체크를 수행합니다.- 필드 앨리어스(CamelCase)를 사용하여 OData Entity의 Property 이름을 정의합니다.
2단계: Behavior Definition 작성 (실무 시나리오)
CDS View 위에 동작 규칙을 정의합니다. Managed 시나리오를 선택하고, CRUD뿐 아니라 Action, Validation, Determination까지 포함한 실무 수준의 BDEF를 작성합니다.
managed implementation in class zbp_i_travel unique;
strict ( 2 );
define behavior for ZI_Travel alias Travel
persistent table /dmo/travel
lock master
authorization master ( instance )
etag master LastChangedAt
{
// --- Standard Operations ---
create;
update;
delete;
// --- Field Control ---
field ( readonly ) TravelId;
field ( mandatory ) AgencyId, CustomerId, BeginDate, EndDate;
// --- Actions ---
action acceptTravel result [1] $self;
action rejectTravel result [1] $self;
// --- Validations (save 시점에 실행) ---
validation validateDates on save { create; update; }
validation validateCustomer on save { create; update; }
// --- Determination (modify 시점에 실행) ---
determination setStatusToOpen on modify { create; }
// --- DB 테이블 필드 매핑 ---
mapping for /dmo/travel
{
TravelId = travel_id;
AgencyId = agency_id;
CustomerId = customer_id;
BeginDate = begin_date;
EndDate = end_date;
BookingFee = booking_fee;
TotalPrice = total_price;
OverallStatus = overall_status;
}
}
주요 포인트:
managed implementation in class zbp_i_travel unique: Managed 시나리오 선언.zbp_i_travel은 Behavior Implementation 클래스입니다.strict ( 2 ): RAP strict mode level 2를 활성화하여 최신 규칙을 적용합니다.lock master: 이 BO가 잠금(Lock)의 주체임을 선언합니다.etag master LastChangedAt: 낙관적 잠금(Optimistic Concurrency Control)을 위한 ETag 필드를 지정합니다.%tky는 트랜잭션 키로, BO 인스턴스를 내부적으로 식별하는 데 사용됩니다.mapping블록은 CDS 필드 앨리어스와 실제 DB 테이블 컬럼을 연결합니다.
3단계: Action 구현 + Service 발행 (프로덕션)
Behavior Definition에 선언한 acceptTravel Action을 실제로 구현합니다. Local Handler Class 안에서 EML(Entity Manipulation Language)을 사용합니다.
CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS accept_travel FOR MODIFY
IMPORTING keys FOR ACTION travel~acceptTravel RESULT result.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD accept_travel.
" 1) OverallStatus를 'A'(Accepted)로 업데이트
MODIFY ENTITIES OF zi_travel IN LOCAL MODE
ENTITY travel
UPDATE FIELDS ( OverallStatus )
WITH VALUE #( FOR key IN keys
( %tky = key-%tky
OverallStatus = 'A' ) )
REPORTED DATA(update_reported).
" 2) 업데이트된 결과를 다시 읽어서 반환
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY travel ALL FIELDS WITH
CORRESPONDING #( keys )
RESULT DATA(travels).
" 3) Action 결과 매핑
result = VALUE #( FOR travel IN travels
( %tky = travel-%tky
%param = travel ) ).
ENDMETHOD.
ENDCLASS.
마지막으로 Service Definition과 Service Binding을 생성합니다.
@EndUserText.label: 'Travel Service'
define service ZUI_Travel {
expose ZI_Travel as Travel;
}
Service Binding은 ADT에서 마우스로 생성합니다:
- ADT에서 Service Definition
ZUI_Travel을 우클릭 > New Service Binding - Binding Type으로 OData V4 - UI 선택 (Fiori Elements 연동 시) 또는 OData V4 - Web API (외부 시스템 연동 시)
- Publish 버튼 클릭 > Service URL 생성 확인
- Entity Set 옆의 Preview 버튼으로 Fiori Elements 앱을 즉시 테스트
6. 흔한 실수 / 트러블슈팅
FAQ 1: "Behavior Definition을 활성화했는데 CDS View에서 오류가 발생합니다"
CDS View가 define root view entity로 선언되어 있는지 확인하세요. 일반 define view entity는 BO의 루트가 될 수 없습니다. Composition 관계가 있다면 자식 View도 함께 활성화해야 합니다.
FAQ 2: "mapping 블록에서 필드 매핑 오류가 납니다"
mapping for 뒤에 오는 테이블 이름은 persistent table에 선언한 테이블과 동일해야 합니다. 또한 CDS 앨리어스 이름(왼쪽)과 DB 컬럼 이름(오른쪽)의 대소문자를 정확히 맞춰야 합니다.
FAQ 3: "Action 호출 시 '%tky is initial' 오류가 발생합니다"
MODIFY ENTITIES 구문에서 %tky = key-%tky로 트랜잭션 키를 정확히 전달하고 있는지 확인하세요. %key가 아니라 %tky를 사용해야 합니다. %tky는 키 필드뿐 아니라 %is_draft 등의 시스템 필드를 포함하는 확장 키입니다.
FAQ 4: "Service Binding에서 Publish 버튼이 비활성화됩니다"
Transport Request에 올바르게 할당되었는지, 그리고 현재 사용자에게 서비스 발행 권한이 있는지 확인하세요. BTP ABAP Environment에서는 일반적으로 자동 할당되지만, On-Premise 환경에서는 TR 할당이 필요합니다.
FAQ 5: "Validation이 실행되지 않습니다"
Validation은 save 시점에만 실행됩니다. Fiori Elements 앱에서 Save 버튼을 누르기 전까지는 트리거되지 않습니다. on save { create; update; } 구문에서 트리거 조건(create, update)이 올바른지 확인하세요.
7. 다음 단계 / 관련 주제
- Projection Layer 추가: Interface View(ZI_) 위에 Consumption View(ZC_)를 만들어 UI 어노테이션과 Value Help를 분리하는 패턴을 학습하세요.
- Composition (Parent-Child BO): Travel > Booking > BookingSupplement 같은 다단계 BO 구조를 구성해 보세요.
- Draft Handling:
with draft;키워드를 추가하여 임시 저장 기능을 구현할 수 있습니다. - Custom Entity + RAP Unmanaged: 외부 API 호출 결과를 RAP BO로 래핑하는 고급 패턴도 살펴보세요.
- ABAP Unit + RAP BO Test:
CL_BOTD_TXBUFDBL_BO_TEST_ENV를 활용한 단위 테스트 작성법을 익히세요.