목차
ACTION
Action은 Business Object의 데이터에 대해 비즈니스 로직을 실행하는 Method 입니다. 일반적인 CRUD 표준작업 외에 특정 상태를 변경하거나 추가적인 연산을 수행할때 사용합니다. Action의 주요 유형으로는 다음과 같습니다.
1. Instance Action : 특정 행을 지정하여 수행하는 Action으로 가장 일반적인 형태의 Action 입니다.
2. Static Action : 특정 행 지정없이 BO 전체 레벨에서 실행되는 Action 입니다.
3. Factory Action : Action의 실행 결과로 신규 행을 생성하는 Action 입니다. 보통 행 복사 기능에 주로 사용합니다.
4. Internal Action : BO 내부에서만 호출하여 사용하는 Action입니다.
간단하게 RAP에서의 Action은 Classic ABAP에서 버튼을 추가하고 PAI User-Command 에 로직을 구현하는것과 비슷하다고 생각하시면 됩니다.
Instance Action
"Booked" 라는 버튼을 하나 만들겠습니다. 데이터를 선택하고 Booked 버튼을 클릭하면 선택된 행데 대해서 Travel Status를 Booked(B) 상태로 Update 하는 Action을 구현해 보겠습니다. Interface Behavior Definition 으로 이동합니다.
Booked 라는 버튼을 클릭했을때 수행되는 Action을 아래와 같이 추가합니다. Action 앞에 아무것도 입력하지 않으면 Instance Action이 됩니다. Action 명 뒤에 나오는 result는 Action 수행 후 결과값을 반환하겠다는 의미입니다. 그뒤에 [1]은 결과값을 1개만 반환하겠다는 뜻이고 $self는 반환하는 결과값에 대한 타입입니다. $self라고 하면 현재 Action이 수행되고 있는 Entity 즉 Travel Entity의 구조로 반환되게 됩니다. 만약 다른 특정 구조로 반환을 원한다면 $self 대신 특정 구조체를 입력하면 됩니다. 그럼 Quick Assist 기능으로 Action에 대한 Method를 생성해 보겠습니다.

Method가 생성되면 Parameter를 한번 확인해 봅니다. 입력받은 keys정보로 Entity를 읽어서 Status를 'B'로 Update하고 result 로 결과를 반환하면 될 것 같습니다. 먼저 화면에 버튼을 만들고 데이터 선택 후 버튼을 눌렀을때 keys로 값이 어떻게 들어오는지 확인해 보겠습니다.

Travel Metadata Extension을 열어서 아래와 같이 Action 버튼을 추가합니다. 위치는 가독성을 위해 가장 첫번째 필드에 추가하는게 보통이지만 해당 Action 과 관계가 있는 필드에 어노테이션을 추가 해도 상관 없습니다.

마지막으로 Projection Behavior Definition에도 Action을 추가해주고 App을 실행시켜 보겠습니다.

버튼이 추가되었습니다. Instance Action 이기 때문에 데이터가 선택되어야만 버튼이 활성화 됩니다. Method에 디버깅을 걸고 Action 버튼을 클릭해 보겠습니다.

선택한 3건이 한번에 들어오지 않고 한건씩 총 3번 호출되는걸 알 수 있습니다. 그럼 로직을 구현해 보겠습니다.

먼저 입력받은 keys의 값으로 Travel Status 를 'B'로 Update를 합니다. 그 후에 새로 Entity를 읽어서 Update된 정보를 Result로 반환하는 간단한 로직입니다. App을 실행시켜 제대로 반영이 되는지 확인해 보겠습니다.

아래와 같이 데이터를 선택합니다. 필드 갯수가 많아 필드가 잘리는 경우 우측 상단의 "Show More per Row" 버튼을 클릭하면 아래와 같이 모든 필드들을 볼수 있습니다. 이제 set Booked 버튼을 클릭해 보겠습니다.

정상적으로 상태가 변경되었습니다.

Static Action
"Discount 10%" 버튼을 하나 만듭니다. 버튼을 클릭하면 모든 행의 Booking Fee를 10% 할인된 금액으로 Update 하려고 합니다. 이때는 모든 행이 대상이 되기 때문에 특정 행을 선택할 필요가 없습니다. 행을 선택하지 않고 모든 행에 적용해야 하는 경우 Static Action을 사용하면 됩니다. Interface Behavior Definition 으로 이동합니다.
Static Action 인 setDiscount를 추가하고 Method를 생성합니다.

Metadata Extension에 버튼을 추가합니다. Action 버튼이 2개이기 때문에 Position으로 위치도 지정해 줍니다.

마지막으로 Projection Behavior Definition 에도 Action 을 추가한 후에 App을 실행해 보겠습니다.

Static Action 이기 때문에 행을 선택하지 않아도 버튼이 활성 상태입니다. 이제 Method에 디버깅을 걸고 버튼을 눌러 값이 어떻게 전달되는지 부터 확인해 보겠습니다.

아래와 같이 디버깅을 건 후 keys 로 전달된 값을 확인하면 화면상의 Travel Entity 정보가 들어오지 않는걸 확인할 수 있습니다. 여기서는 Travel 의 전체 데이터가 대상이기 때문에 EML이 아닌 SELECT 문으로 DB를 직접읽어 전체 데이터를 가져온 후 그 정보로 Travel Entity를 READ 하도록 구현하겠습니다.

1. Travel 테이블의 모든 Key값을 가져옵니다.
2. 가져온 Key 정보로 Travel Entity를 읽습니다.
3. Booking Fee에 10% 할인율을 계산합니다.
4. Travel Entity에 할인율이 적용된 Booking Fee를 Update 합니다.
5. Result 로 결과를 반환합니다.

App을 실행해서 "Discount 10%" 버튼을 클릭해 보겠습니다.

버튼 클릭 후 "Go"버튼을 다시 누르면 할인율이 적용된걸 확인할 수 있습니다. Static Action은 화면 각각의 행별로 결과를 반환하는 Action이 아니기 때문에 Entity가 Update 되어도 화면에는 변경된 값을 갱신할 수 없습니다. "Go"버튼을 눌러 Entity를 다시 읽으면 그때 최신 정보로 다시 반영됩니다. 즉 Static Action은 화면과 상관없는 일괄처리 작업시 유용한 기능입니다.

Factory Action
"Copy"라는 버튼을 만듭니다. 행을 선택하고 버튼을 누르면 선택한 행을 Copy해서 새로운 Travel ID를 생성해 보겠습니다. 이런경우에 Factory Action이 필요합니다. Interface Behavior Definition 으로 이동합니다.
lineCopy 라는 Factory Action 을 추가합니다. 여러건을 동시에 Copy 하기 위해 카디널리티를 [1..*]로 지정했습니다.

Metadata Extension에 버튼을 추가합니다.

마지막으로 Projection Behavior Definition에도 Action을 추가합니다.

Method에 디버깅을 걸고 App을 실행시켜 보겠습니다. 행을 선택하고 Copy버튼을 눌러서 Method에 데이터가 어떻게 넘어오는지 확인해 보겠습니다.

아래와같이 Method에 디버깅을 걸고 화면상에서 3건을 선택하고 "Copy" 버튼을 눌러보겠습니다. Method는 세번이 호출되는것을 알 수 있습니다. Keys로 넘어오는 데이터를 보면 %CID와 Key값인 Travel ID 모두 넘어옵니다. Travel ID로는 선택한 Entity의 값을 READ 하는데 사용하고 %CID 로는 신규 Travel ID를 생성하는데 사용하면 될 것 같습니다. 그럼 로직을 구현해 보겠습니다.

소스가 좀 길긴하지만 어려운건 없습니다. 하나씩 보겠습니다.
1) 선택한 행에 대한 정보가 Keys로 들어옵니다. Keys의 값으로 Travel 과 Booking Entity를 읽습니다. (여러건을 선택한 경우 해당 Method가 선택한 수 만큼 호출됩니다. )
2) Travel과 Booking 생성시 사용할 내부테이블을 선언합니다.
3) 선택한 정보를 Copy 하는 목적이기 때문에 Travel ID를 제외하고는 모든 정보가 동일해야 합니다. 1번에서 가져온 Entity 정보를 2번에서 선언된 내부테이블로 복사합니다. 단 Travel ID는 제외시킵니다. 그 이유는 CREATE EML을 실행하면 Earlynumbering Method가 호출되고 거기서 Travel ID를 신규 채번하기 위함입니다. 여기서 주의할 점은 실제 Key값인 Travel ID가 빈값이기 때문에 임시 Key인 %CID에 값을 넣어줘야 합니다. Factory Action은 신규 데이터를 생성하기 위한 Action 이기 때문에 시스템이 Keys의 %CID에 값을 넣어줍니다. 그 값을 그대로 사용하면 됩니다. 그리고 Booking은 Travel의 Child 정보이기 때문에 Booking의 %CID_REF 에도 Keys의 %CID를 사용하면 됩니다.(Travel의 %CID와 Booking의 %CID_REF는 서로를 연결해주는 Key값이기 때문에 동일해야 합니다.) 그런 다음 Booking의 CID에는 Booking 고유의 임시키를 지정해야 하기 때문에 유니크한 값을 임의로 지정해 주면 됩니다. 여기서는 Keys로 입력받은 %CID + BookingID 조합으로 Booking의 %CID를 지정했습니다. 부모 Entity에는 필드값을 %data에 넣어주면 되고 Child Entity는 %target 에 넣어줍니다.
4) EML을 사용하여 Travel 및 Booking 정보를 동시에 Create 합니다. 주의할점은 대상 Field에 Travel ID는 제외시켜야 합니다. 그 이유는 Travel ID를 필드로 지정하게 되면 현재 Travel ID가 '00000000' 이기 때문에 시스템은 Travel ID를 '00000000'으로 인식합니다. '00000000'도 하나의 값이기 때문입니다. 하지만 그후에 Earlynumbering을 호출하게 되는데 Travel ID가 '00000000'이기 때문에 신규 채번을 해서 시스템에 반환합니다. 시스템은 중간에 Travel ID 정보가 바뀌었다고 판단하고 Dump 에러를 발생시킵니다.
5) 정상적으로 Create가 되었다면 리턴받은 Mapped 정보를 그대로 반환합니다. 그리고 간단한 메세지 처리도 합니다.

App을 실행시켜 보겠습니다. Copy가 되면서 화면에 반영이 잘 되는지 보기위해 Customer ID가 "93"인것만 조회해서 대상을 줄였습니다. 행을 선택하고 Copy 버튼을 클릭합니다.

정상적으로 메세지 처리가 되었습니다.

"OK"를 클릭하면 오브젝트 페이지로 이동되고 결과를 확인할 수 있습니다.

뒤로가기를 누르면 Main 목록에도 자동 갱신되어 신규 Travel ID가 나타납니다.

만약 오브젝트 페이지로 이동시키지 않고 Main 리스트에 바로 추가되게 하려면 Action 선언시 카디널리티를 [1..*]로 주면 됩니다. 저렇게 주게되면 시스템은 반환값이 N개일수도 있다고 판단하고 오브젝트 페이지로 이동시키지 않습니다.
그리고 현재 Factory Action을 일반 Action으로 바꾸고 테스트를 해보면 일반 Action인 경우에도 신규 Travel ID가 생성되지만 화면은 자동 갱신되지 않습니다. Factory Action인 경우 시스템은 이미 신규 정보가 생성된다고 판단하기 때문에 Action이 성공한 후에 Entity 정보를 다시 읽어와 화면에 보여준다고 생각하시면 됩니다.
마지막으로 Internal Action이 있는데 Internal Action은 Determination 실습과 병행해서 사용하려고 합니다. 그때 Internal Action에 대해서 함께 설명하겠습니다.
※Create / Change 이력
현재 데이터를 생성하거나 수정을 해도 Table의 생성/수정 이력필드에 값이 저장이 안되고 있습니다. 이부분을 자동 저장되게끔 어노테이션을 아래와 같이 추가해 보겠습니다. 어노테이션을 추가하고 데이터를 생성하거나 수정한 후에 DB를 확인해 보면 값이 자동으로 Update 되는걸 확인할 수 있습니다.

※Draft 상태표시
하는김에 Main List에서 해당 Travel ID 정보가 Draft 상태인지 표시해주는 어노테이션을 추가해 보겠습니다. Draft 기능을 사용한다면 필수로 추가해 주면 됩니다. Projection View로 이동해서 헤더레벨에 아래 어노테이션을 추가해 줍니다.

그리고 App을 실행시켜 데이터를 수정한 후 저장하지 말고 빠져나오면 아래와 같이 Draft 상태라고 화면에 표시됩니다.

'RAP' 카테고리의 다른 글
| RAP 16 - MANAGED REPORT : DETERMINATION (0) | 2026.08.31 |
|---|---|
| RAP 15 - MANAGED REPORT : FEATURE CONTROL (0) | 2026.08.24 |
| RAP 13 - MANAGED REPORT : VALIDATION (0) | 2026.08.03 |
| RAP 12 - MANAGED REPORT : EML (0) | 2026.07.26 |
| RAP 11 - MANAGED REPORT : Early numbering(2) (0) | 2026.07.21 |