앞선 글들에서 이런 흐름을 이야기했습니다.
CDS 뷰 작성 → @UI 어노테이션 → RAP 서비스 노출 → Fiori Elements로 화면 확인
각 단계를 따로 설명했지만, 정작 하나로 이어 붙여본 적은 없었습니다. 개념은 알겠는데 손이 안 움직이는 상태였죠. 이 간극을 메우는 데 가장 좋은 교재가 SAP 공식 핸즈온 실습인 RAP100입니다.
이 글은 RAP100을 실제로 완주하면서 정리한 기록입니다. 단계별로 무엇을 배우는지, 어디서 막히는지, 그리고 이 실습이 실무의 어떤 지점과 연결되는지를 담았습니다.
목차
목차
1. RAP100이 무엇인가
RAP100은 SAP이 제공하는 공식 개발자 튜토리얼 미션입니다. RAP을 이용해 SAP Fiori Elements 기반 앱의 UI 서비스를 개발하는 과정으로, ADT 위저드를 활용해 데이터베이스 테이블로부터 필요한 ABAP 아티팩트 전체를 빠르게 생성하는 방식을 씁니다.
앞선 RAP 글과의 차이가 여기에 있습니다. 이전 글에서는 CDS 뷰, 비헤이비어 정의(BDL), 핸들러 클래스, 프로젝션, 서비스 정의를 하나씩 손으로 만들었습니다. 반면 RAP100은 RAP Generator 위저드로 뼈대를 한 번에 생성하고, 그다음부터는 오로지 동작(Behavior) 구현에만 집중합니다.
둘 다 필요합니다. 손으로 한 번 만들어봐야 각 오브젝트가 왜 존재하는지 알 수 있고, 위저드를 써봐야 실무 속도가 납니다.
RAP 워크숍 시리즈에서의 위치
RAP100은 ADT의 RAP Generator를 써서 데이터베이스 테이블로부터 managed RAP BO 기반 UI 서비스를 만드는 초급 과정입니다. RAP110은 late numbering, virtual elements, side effects, 다양한 액션 타입, 비즈니스 이벤트 같은 기능을 다루는 중급 과정이고, RAP120은 SAP Joule for Developers를 활용한 ABAP AI 기능을 다룹니다. 여기에 RAP BO에 대한 ABAP Unit 테스트 작성을 다루는 RAP400도 있습니다.
정리하면 이런 순서입니다.
RAP100 (초급) → 기본기: 결정, 검증, 액션, Draft
RAP110 (중급) → 심화: late numbering, side effects, 비즈니스 이벤트
RAP400 → 테스트: ABAP Unit
RAP120 → AI 활용: Joule for Developers
실습 시나리오
여행(Travel) 처리 앱을 만듭니다. 여러 여행사의 전 세계 여행 건을 관리하는 부서가, Draft 기능을 갖춘 신규 Fiori 앱으로 여행 데이터를 생성·수정·삭제할 수 있게 해달라고 요청한 상황입니다. 구현 복잡도를 낮추기 위해 BO 노드는 Travel 하나만 쓰는 단순화된 데이터 모델을 사용합니다.
BO 노드가 하나뿐이라는 점이 중요합니다. Composition 계층 구조를 다루지 않습니다. 부모-자식 구조는 RAP110에서 다룹니다. 처음 배울 때는 오히려 이 편이 낫습니다. 한 번에 하나씩 가는 것이죠.
2. 환경 준비 — 여기서 가장 많이 포기합니다
솔직히 말하면 RAP100에서 가장 어려운 구간은 코딩이 아니라 환경 세팅입니다. 이 단계를 넘기면 나머지는 순조롭습니다.
필요한 것
최신 버전의 Eclipse용 ABAP Development Tools(ADT)와, 적합한 ABAP 시스템 접근 권한이 필요합니다. SAP BTP ABAP Environment, SAP S/4HANA Cloud Public Edition, 또는 최소 2022 릴리즈 이상의 SAP S/4HANA Cloud Private Edition 및 SAP S/4HANA가 대상입니다.
그리고 ABAP Flight Reference Scenario가 해당 시스템에 임포트되어 있어야 합니다.
준비 순서
공식 요구사항은 네 단계입니다. 최신 Eclipse 플랫폼과 ADT 플러그인 설치, SAP BTP ABAP Environment Trial 사용자 생성, ABAP Cloud Project 생성, 그리고 ADT의 웹 브라우저 설정 조정입니다.
네 번째 항목을 흘려보지 마세요. ADT 내장 브라우저는 Fiori Elements 프리뷰를 제대로 렌더링하지 못하는 경우가 많습니다. Eclipse의 Window → Preferences → General → Web Browser에서 외부 브라우저(Chrome/Edge)를 기본값으로 지정해두면 프리뷰 단계에서 겪는 문제의 절반이 사라집니다.
BTP Trial의 함정
무료 Trial을 쓴다면 알아둘 것이 있습니다.
- 유효기간이 있습니다. 기간이 지나면 인스턴스가 사라집니다. 실습을 여러 날에 나눠 한다면 남은 기간을 확인하세요.
- 일정 기간 미사용 시 자동 중지됩니다. 재시작은 BTP Cockpit에서 가능하지만 시간이 걸립니다.
- 리전 선택이 중요합니다. 물리적으로 가까운 리전을 골라야 ADT 응답이 답답하지 않습니다.
Trial이 부담스럽다면 사내 S/4HANA 개발 시스템에서 진행하는 것도 방법입니다. 다만 2022 이상 릴리즈여야 하고, ABAP Cloud 개발 언어 버전이 활성화되어 있어야 합니다.
Flight Reference Scenario 임포트
RAP100은 /DMO/ 데모 데이터를 참조합니다. 이게 없으면 매입처·고객 밸류 헬프가 전부 비어 있게 됩니다.
abapGit 플러그인으로 아래 저장소를 임포트합니다.
https://github.com/SAP-samples/abap-platform-refscen-flight
임포트 후 활성화(Ctrl+Shift+F3) 를 잊지 마세요. 임포트만 하고 활성화를 안 해서 “왜 데이터가 안 보이지” 하며 헤매는 경우가 흔합니다.
접미사 규칙
RAP100은 여러 명이 같은 시스템에서 동시에 실습하는 워크숍용이라, 모든 오브젝트 이름에 ### 자리에 본인 번호를 넣습니다.
ZRAP100_ATRAV### → ZRAP100_ATRAV000
ZCL_RAP100_GEN_DATA_### → ZCL_RAP100_GEN_DATA_000
혼자 한다면 아무 숫자나 정해서 처음부터 끝까지 일관되게 쓰면 됩니다. 중간에 바꾸면 참조가 깨져서 고생합니다.
3. 실습 흐름 한눈에 보기
초급 과정은 Getting Started와 Exercise 1~5, 중급 과정은 Exercise 6~9로 구성됩니다.
| 단계 | 주제 | 핵심 학습 내용 |
|---|---|---|
| Ex 0 | Getting Started | 패키지 생성, 환경 확인 |
| Ex 1 | DB 테이블 생성 + UI 서비스 생성 | RAP Generator 위저드 |
| Ex 2 | 데이터 모델 확장 + OData Stream | 필드 추가, 첨부 파일 처리 |
| Ex 3 | Early Numbering | 시맨틱 키 채번 |
| Ex 4 | Determination | 값 자동 설정 |
| Ex 5 | Validation | 저장 전 검증 |
| Ex 6 | Action | 버튼 동작 구현 |
| Ex 7 | Dynamic Feature Control | 상태별 버튼 활성/비활성 |
| Ex 8 | ABAP Unit Test | BO 테스트 작성 |
| Ex 9 | EML | 외부에서 BO 접근 |
추가 과정으로 SAP Business Application Studio를 이용해 Fiori Elements 앱을 BTP ABAP Environment에 배포하는 Exercise 10, Fiori Launchpad 통합(Exercise 11), Launchpad Space·Page 템플릿 생성(Exercise 12)이 있습니다. 다만 11번과 12번은 별도 라이선스가 필요합니다.
4. 단계별 실습 정리
Ex 1 — 이 실습의 하이라이트
먼저 데이터 생성기 클래스 ZCL_RAP100_GEN_DATA_###를 선택하고 F9(Run As → ABAP Application Console)로 실행합니다. ABAP 콘솔에 메시지가 표시되면, 데이터베이스 테이블 ZRAP100_ATRAV###를 열고 F8을 눌러 채워진 여행 데이터를 확인합니다.
그다음이 핵심입니다. 데이터베이스 테이블에서 우클릭 후 컨텍스트 메뉴의 Generate ABAP Repository Objects를 선택합니다. 그러면 CDS 뷰 엔티티, 동작 정의와 구현 등 필요한 모든 ABAP 아티팩트가 OData V4 기반 UI 서비스, RAP 비즈니스 오브젝트와 함께 생성됩니다. 생성된 비즈니스 서비스는 트랜잭션 처리가 가능하고, Draft가 활성화되어 있으며, Fiori Elements 앱 생성을 위한 UI 시맨틱이 이미 적용된 상태입니다.
앞선 글에서 손으로 하나씩 만들던 것들이 클릭 몇 번으로 나옵니다. 처음 이걸 보면 허탈하기까지 합니다. 하지만 위저드가 만든 결과물을 열어보면, 이전 글에서 다룬 구조가 그대로 들어 있다는 걸 알 수 있습니다. 그래서 순서가 중요합니다. 구조를 모르는 상태에서 위저드부터 쓰면 생성된 코드를 읽지 못합니다.
주의할 점이 하나 있습니다. 생성기 UI는 클라우드 시스템(ABAP Environment)과 온프레미스 시스템에서 화면이 다르게 보입니다. 튜토리얼 스크린샷과 다르다고 당황할 필요 없습니다.
여기까지만 해도 동작하는 앱이 나옵니다. Service Binding을 열고 Preview를 누르면 List Report 화면이 뜹니다. 데이터 조회, 생성, 수정, 삭제, Draft까지 전부 됩니다. 코드는 한 줄도 안 썼는데도 말이죠.
Ex 2 — 데이터 모델 확장
생성된 CDS 뷰에 필드를 추가하고, 프로젝션과 메타데이터 확장에도 반영하는 과정입니다. 레이어를 하나 건드리면 나머지도 같이 손봐야 한다는 감각을 익히는 단계입니다.
OData Stream은 첨부 파일이나 이미지를 다루기 위한 기능입니다. 실무에서 증빙 파일을 붙여야 하는 요건이 자주 나오니 알아두면 쓸모가 있습니다.
Ex 3 — Early Numbering
RAP100은 시맨틱 키와 내부 unmanaged early numbering을 사용하는 managed BO 런타임 구현을 다룹니다.
UUID를 쓰면 프레임워크가 알아서 채번하지만, 여행번호처럼 사람이 읽는 키는 직접 채번해야 합니다. earlynumbering_create 메서드에서 처리합니다.
abap
METHOD earlynumbering_create.
DATA: entity TYPE STRUCTURE FOR CREATE zrap100_r_traveltp_000,
travel_id_max TYPE /dmo/travel_id.
" 이미 ID가 부여된 인스턴스는 그대로 둔다
LOOP AT entities INTO entity WHERE TravelID IS NOT INITIAL.
APPEND CORRESPONDING #( entity ) TO mapped-travel.
ENDLOOP.
DATA(entities_wo_id) = entities.
DELETE entities_wo_id WHERE TravelID IS NOT INITIAL.
CHECK entities_wo_id IS NOT INITIAL.
" 현재 최대값 조회
SELECT SINGLE FROM zrap100_atrav000
FIELDS MAX( travel_id )
INTO @travel_id_max.
" 순차 부여
LOOP AT entities_wo_id INTO entity.
travel_id_max += 1.
APPEND VALUE #( %cid = entity-%cid
%key = entity-%key
TravelID = travel_id_max ) TO mapped-travel.
ENDLOOP.
ENDMETHOD.
%cid(content ID)를 반드시 매핑해야 합니다. 아직 키가 없는 인스턴스를 프레임워크가 추적하는 임시 식별자인데, 이걸 빠뜨리면 생성은 되지만 화면에 반영이 안 되는 현상이 나타납니다.
MAX+1 방식은 실습용입니다. 실무에서는 동시성 문제가 있으니 번호 범위 객체(Number Range) 를 쓰는 것이 맞습니다.
Ex 4 — Determination
값을 자동으로 채우는 로직입니다. RAP100에서는 생성 시 상태를 ‘Open’으로 설정하고, 예약료가 바뀌면 총액을 재계산합니다.
abap
METHOD setStatusToOpen.
READ ENTITIES OF zrap100_r_traveltp_000 IN LOCAL MODE
ENTITY Travel
FIELDS ( OverallStatus )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
DELETE travels WHERE OverallStatus IS NOT INITIAL.
CHECK travels IS NOT INITIAL.
MODIFY ENTITIES OF zrap100_r_traveltp_000 IN LOCAL MODE
ENTITY Travel
UPDATE FIELDS ( OverallStatus )
WITH VALUE #( FOR travel IN travels
( %tky = travel-%tky
OverallStatus = 'O' ) )
REPORTED DATA(update_reported).
reported = CORRESPONDING #( DEEP update_reported ).
ENDMETHOD.
READ → 가공 → MODIFY 패턴이 계속 반복됩니다. RAP 코드의 기본 문형이라고 보시면 됩니다.
Ex 5 — Validation
저장 전에 값을 검사합니다. 고객번호가 유효한지, 시작일이 종료일보다 앞서는지를 확인합니다.
abap
METHOD validateDates.
READ ENTITIES OF zrap100_r_traveltp_000 IN LOCAL MODE
ENTITY Travel
FIELDS ( BeginDate EndDate TravelID )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels INTO DATA(travel).
" 이전 검증 메시지 초기화
APPEND VALUE #( %tky = travel-%tky
%state_area = 'VALIDATE_DATES' ) TO reported-travel.
IF travel-EndDate < travel-BeginDate.
APPEND VALUE #( %tky = travel-%tky ) TO failed-travel.
APPEND VALUE #( %tky = travel-%tky
%state_area = 'VALIDATE_DATES'
%msg = NEW /dmo/cm_flight_messages(
severity = if_abap_behv_message=>severity-error
textid = /dmo/cm_flight_messages=>end_date_before_begin_date )
%element-BeginDate = if_abap_behv=>mk-on
%element-EndDate = if_abap_behv=>mk-on ) TO reported-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
%state_area가 이 실습에서 얻어가는 개념 중 하나입니다. 같은 이름의 상태 영역으로 이전 메시지를 덮어씁니다. 이게 없으면 사용자가 값을 고쳐도 예전 오류 메시지가 화면에 계속 남습니다.
Ex 6 — Action
Fiori 화면의 버튼이 됩니다. RAP100에서는 여행 승인·반려, 그리고 할인율을 입력받아 적용하는 액션을 만듭니다.
파라미터를 받는 액션은 별도 추상 엔티티를 정의합니다.
abap
// 비헤이비어 정의(BDL)
action deductDiscount parameter zrap100_a_discount_000 result [1] $self;
abap
// 추상 엔티티
define abstract entity zrap100_a_discount_000
{
@EndUserText.label: '할인율 (%)'
discount_percent : abap.int1;
}
이렇게 하면 Fiori 화면에서 버튼을 눌렀을 때 입력 팝업이 자동으로 뜹니다. 별도 UI 개발 없이 파라미터 입력 화면이 생기는 지점이 RAP의 매력입니다.
Ex 7 — Dynamic Feature Control
이미 승인된 건에 “승인” 버튼이 살아 있으면 안 되겠죠. 인스턴스 상태에 따라 버튼을 제어합니다.
abap
METHOD get_instance_features.
READ ENTITIES OF zrap100_r_traveltp_000 IN LOCAL MODE
ENTITY Travel
FIELDS ( TravelID OverallStatus )
WITH CORRESPONDING #( keys )
RESULT DATA(travels)
FAILED failed.
result = VALUE #( FOR travel IN travels
( %tky = travel-%tky
%field-BookingFee = COND #(
WHEN travel-OverallStatus = 'A'
THEN if_abap_behv=>fc-f-read_only
ELSE if_abap_behv=>fc-f-unrestricted )
%action-acceptTravel = COND #(
WHEN travel-OverallStatus = 'A'
THEN if_abap_behv=>fc-o-disabled
ELSE if_abap_behv=>fc-o-enabled ) ) ).
ENDMETHOD.
필드 제어는 %field-, 액션 제어는 %action-입니다. 상수 접두어도 각각 fc-f-와 fc-o-로 다릅니다. 헷갈리기 쉬운 부분입니다.
Ex 8 — ABAP Unit Test
BO에 대한 단위 테스트를 작성합니다. 실무 개발자들이 가장 많이 건너뛰는 부분이지만, RAP은 오히려 테스트하기 좋은 구조입니다. cl_abap_behv_test_environment로 DB를 격리하고 EML로 동작을 검증합니다.
abap
CLASS ltc_travel DEFINITION FINAL FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA environment TYPE REF TO if_cds_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS setup.
METHODS validate_dates FOR TESTING.
ENDCLASS.
여기까지 오면 RAP400으로 넘어갈 준비가 된 셈입니다.
Ex 9 — EML로 외부 접근
EML(Entity Manipulation Language)은 ABAP 언어의 확장으로, RAP 비즈니스 오브젝트에 타입 안전한 API 기반 접근을 제공합니다. SQL과 유사한 문법을 가지며, RAP BO의 트랜잭션 동작을 구현할 때는 물론 RAP 컨텍스트 외부에서 기존 RAP BO에 접근할 때도 사용됩니다. 지정된 엔티티의 오퍼레이션을 트리거하는 방식으로 비즈니스 오브젝트와 상호작용합니다.
이 부분이 실무에서 가장 직접적으로 쓰입니다. 배치 프로그램이나 인터페이스 처리 로직에서 RAP BO를 호출해야 할 때가 있는데, 그때 EML을 씁니다.
abap
MODIFY ENTITIES OF zrap100_r_traveltp_000
ENTITY Travel
CREATE FIELDS ( AgencyID CustomerID BeginDate EndDate BookingFee CurrencyCode )
WITH VALUE #( ( %cid = 'TRAVEL_001'
AgencyID = '070001'
CustomerID = '000101'
BeginDate = '20260901'
EndDate = '20260910'
BookingFee = '50'
CurrencyCode = 'EUR' ) )
MAPPED DATA(mapped)
FAILED DATA(failed)
REPORTED DATA(reported).
IF failed IS INITIAL.
COMMIT ENTITIES RESPONSE OF zrap100_r_traveltp_000
FAILED DATA(commit_failed)
REPORTED DATA(commit_reported).
ENDIF.
COMMIT ENTITIES를 빠뜨리면 저장되지 않습니다. BAPI에서 BAPI_TRANSACTION_COMMIT을 부르는 것과 같은 이치입니다.
5. 자주 막히는 지점
활성화 순서 문제 — CDS 뷰를 고치고 활성화했는데 오류가 사라지지 않는다면, 의존 관계 순서대로 다시 활성화해보세요. 루트 뷰 → BDL → 구현 클래스 → 프로젝션 → 프로젝션 BDL → 서비스 정의 → 서비스 바인딩 순입니다. Ctrl+Shift+F3로 패키지 전체를 한 번에 활성화하는 방법도 있습니다.
서비스 바인딩 재활성화 — 프로젝션이나 서비스 정의를 바꿨는데 프리뷰에 반영이 안 된다면, Service Binding을 열고 Publish(또는 Activate)를 다시 눌러야 합니다. 메타데이터가 캐시되어 있기 때문입니다.
Draft 테이블 불일치 — 필드를 추가한 뒤 Draft 테이블을 갱신하지 않으면 런타임 오류가 납니다. BDL의 draft table 선언부에서 Quick Fix를 다시 실행해 동기화하세요.
프리뷰가 빈 화면 — 대개 UI 어노테이션 문제입니다. @UI.lineItem이 하나도 없으면 컬럼이 보이지 않습니다. 그리고 앞서 언급한 외부 브라우저 설정을 확인하세요.
%tky 관련 오류 — Draft가 활성화된 BO에서 %key를 쓰면 Draft 인스턴스를 찾지 못합니다. %tky로 통일하세요.
메시지 클래스 오류 — /dmo/cm_flight_messages는 Flight Reference Scenario에 포함된 예외 클래스입니다. 이게 없다고 나오면 참조 시나리오 임포트나 활성화가 안 된 것입니다.
6. 완주 후 남는 것
RAP100을 끝내면 이런 것들이 손에 익습니다.
- RAP Generator로 5분 만에 동작하는 서비스 만들기 — 프로토타이핑 속도가 완전히 달라집니다
READ ENTITIES/MODIFY ENTITIES패턴 — RAP 코드의 기본 문형입니다- 결정 · 검증 · 액션의 구분 — 요건을 들었을 때 어디에 넣을지 바로 판단이 섭니다
failed/reported/mapped사용법 — 오류 처리의 표준 구조입니다- EML로 BO 외부 호출 — 배치·인터페이스 개발에 바로 쓰입니다
그리고 무엇보다, CDS → 어노테이션 → 서비스 → 화면이 하나의 흐름이라는 감각이 생깁니다. 개별 기술을 따로 알던 상태와는 확실히 다릅니다.
자격증 준비와의 연결
ABAP Cloud 관련 자격증(C_ABAPD 계열)을 준비한다면 RAP100의 범위가 시험 출제 영역과 상당 부분 겹칩니다. 특히 결정과 검증의 차이, 피처 컨트롤 상수, EML 문법, Draft 동작은 자주 다뤄지는 주제입니다. 문제집을 먼저 푸는 것보다 실습을 한 번 완주하는 편이 오래 남습니다.
7. 다음 단계
RAP100을 마쳤다면 갈 길은 명확합니다.
RAP110 (중급) — late numbering, virtual elements, side effects, 다양한 액션 타입, 비즈니스 이벤트를 다룹니다. 특히 Composition 계층 구조를 여기서 제대로 배웁니다. 실무 BO는 대부분 부모-자식 구조라 이걸 모르면 반쪽입니다.
RAP400 — ABAP Unit 테스트 심화 과정입니다. 팀 개발이라면 필수입니다.
Unmanaged 시나리오 — 기존 레거시 로직을 RAP으로 감싸야 하는 상황입니다. 마이그레이션 프로젝트에서 반드시 마주치게 됩니다.
Fiori Elements 심화 — RAP은 백엔드입니다. 화면을 더 다듬으려면 어노테이션과 Flexible Programming Model을 알아야 합니다.
마치며
RAP100의 진짜 가치는 “동작하는 것을 처음부터 끝까지 만들어봤다” 는 경험 자체에 있다고 생각합니다. 개념 설명만 열 번 읽는 것보다, 화면에 내가 만든 데이터가 뜨고 버튼이 눌리는 걸 한 번 보는 게 낫습니다.
넉넉히 잡아도 하루면 초급 과정(Ex 1~5)은 끝납니다. 중급까지 포함해도 주말 이틀이면 충분합니다. 환경 세팅에서 포기하지만 않는다면 말이죠.
앞선 글들에서 CDS 뷰를 만들고, 어노테이션을 붙이고, RAP 구조를 뜯어봤습니다. 이제 그 조각들을 하나로 이어 붙일 차례입니다. 실습하다 막히는 부분이 있으면 댓글로 남겨주세요.
참고 링크
- RAP100 저장소:
github.com/SAP-samples/abap-platform-rap100 - Flight Reference Scenario:
github.com/SAP-samples/abap-platform-refscen-flight - 워크숍 landing page:
github.com/SAP-samples/abap-platform-rap-workshops - 솔루션 패키지: abapGit으로
ZRAP100_SOL패키지를 임포트하면 완성된 구현을 확인할 수 있습니다. 단, Flight Reference Scenario가 먼저 설치되어 있어야 합니다. - SAP TechEd 2022 워크숍 녹화본에도 RAP 소개와 Exercise 1~7 시연이 담겨 있습니다.
이 글은 작성 시점(2026년 8월) 기준이며, SAP 튜토리얼 구성과 BTP Trial 정책은 변경될 수 있습니다.
