RAP BO가 레이어로 나뉘는 이유
RAP(ABAP RESTful Application Programming Model)에서 Business Object(BO)는 단일 파일이 아니라 여러 개의 개발 객체가 하나의 묶음으로 동작하는 구조입니다. 데이터를 어떻게 보여줄지, 어떤 동작을 허용할지, 그 동작이 실제로 어떻게 구현되는지를 한 곳에 몰아넣으면 변경 영향도가 커지고 재사용도 어렵습니다. 그래서 RAP는 데이터 모델(CDS), 동작 선언(BDEF), 로직 구현(Behavior Pool) 세 개의 레이어로 책임을 분리합니다.
비유하자면 식당의 메뉴판(CDS), 주문 규칙(BDEF), 주방장의 조리법(Behavior Implementation)에 해당합니다. 각 레이어는 독립적으로 교체되거나 확장될 수 있어야 합니다.
- CDS View Entity — 어떤 필드, 어떤 연관, 어떤 시맨틱을 가진 데이터인가
- Behavior Definition(BDEF) — 무엇을 할 수 있는가(Create/Update/Delete/Action/Validation)
- Behavior Implementation(ABP) — 그 동작을 실제로 어떻게 수행하는가
레이어 1 — CDS View Entity (데이터 모델)
RAP BO의 가장 아래에는 Root CDS View Entity가 있습니다. 데이터베이스 테이블이나 다른 CDS 뷰를 기반으로 필드를 노출하고, 연관(association)으로 자식 노드와 연결합니다.
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Booking Root View'
define root view entity ZR_Booking
as select from zbooking
{
key booking_uuid as BookingUUID,
booking_id as BookingID,
customer_name as CustomerName,
flight_date as FlightDate,
@Semantics.amount.currencyCode: 'CurrencyCode'
booking_fee as BookingFee,
currency_code as CurrencyCode,
booking_status as BookingStatus,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt
}
이 레이어는 데이터의 형태만 책임집니다. 예약을 만들 수 있는지, 수수료가 0보다 커야 하는지 같은 규칙은 들어가지 않습니다.
레이어 2 — BDEF (동작 선언)
Behavior Definition은 CDS Entity에 대해 어떤 표준 오퍼레이션과 사용자 정의 액션이 허용되는지를 선언합니다. managed 또는 unmanaged 구현 타입을 명시하고, 필드 속성, Determination, Validation, Action을 함께 등록합니다.
managed implementation in class zbp_r_booking unique;
strict ( 2 );
define behavior for ZR_Booking alias Booking
persistent table zbooking
lock master
authorization master ( instance )
etag master LastChangedAt
{
create;
update;
delete;
field ( readonly ) BookingUUID, CreatedBy, CreatedAt;
field ( mandatory ) CustomerName, FlightDate, BookingFee;
determination calculateBookingID on save { create; }
validation validateFee on save { create; field BookingFee; }
action ( features : instance ) cancelBooking result [1] $self;
mapping for zbooking
{
BookingUUID = booking_uuid;
CustomerName = customer_name;
FlightDate = flight_date;
BookingFee = booking_fee;
BookingStatus = booking_status;
}
}
BDEF에는 ABAP 로직이 한 줄도 없습니다. 무엇을 할 수 있다만 선언하고, 어떻게는 다음 레이어에 위임합니다.
레이어 3 — Behavior Implementation (로직 구현)
BDEF에서 지정한 Behavior Pool 클래스가 실제 로직을 담당합니다.
CLASS zbp_r_booking DEFINITION
PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF ZR_Booking.
ENDCLASS.
CLASS lhc_booking DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS validateFee FOR VALIDATE ON SAVE
IMPORTING keys FOR Booking~validateFee.
ENDCLASS.
CLASS lhc_booking IMPLEMENTATION.
METHOD validateFee.
READ ENTITIES OF ZR_Booking IN LOCAL MODE
ENTITY Booking FIELDS ( BookingFee )
WITH CORRESPONDING #( keys )
RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking).
IF booking-BookingFee <= 0.
APPEND VALUE #( %tky = booking-%tky ) TO failed-booking.
APPEND VALUE #(
%tky = booking-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Booking fee must be positive' )
%element-BookingFee = if_abap_behv=>mk-on
) TO reported-booking.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Handler Class vs Saver Class 역할
- Local Handler Class (lhc_) — Create/Update/Delete, Action, Validation, Determination을 처리합니다. cl_abap_behavior_handler를 상속합니다.
- Local Saver Class (lsc_) — SAVE 단계를 책임집니다. unmanaged 구현이나 managed with additional save 시나리오에서 cl_abap_behavior_saver를 상속합니다.
Validation / Determination / Action 위치
- Validation — 저장 전 데이터 유효성 검증. on save 시점.
- Determination — 다른 필드 값으로부터 파생 값 자동 계산. on save 또는 on modify.
- Action — 사용자 트리거 비즈니스 동작. 명시적 호출 시 실행.
Managed vs Unmanaged 레이어 차이
- Managed — RAP 런타임이 트랜잭션 버퍼와 DB 저장을 처리합니다. 개발자는 매핑과 추가 로직만 작성합니다.
- Managed with additional save — managed의 편의를 유지하면서 save 시점에 추가 처리를 Saver 클래스에 구현합니다.
- Unmanaged — Create/Update/Delete를 포함한 모든 동작을 직접 구현합니다. 기존 BAPI 래핑에 적합합니다.
핵심 한 줄
RAP Business Object는 무엇을 보여줄지(CDS) — 무엇을 할 수 있는지(BDEF) — 어떻게 할지(Behavior Impl)라는 세 질문에 각각 다른 파일이 답하도록 설계된 모델입니다. 이 분리만 지켜도 변경 영향도가 줄고 유지보수가 수월해집니다.
댓글 0
아직 댓글이 없습니다.