목표: 승인 워크플로우를 자동화하고, 5일간의 학습을 완성된 엔드-투-엔드 시나리오로 통합한다.
시나리오: SAP Build Process Automation으로 자동 승인 워크플로우 생성 → Java 앱과 REST 통합 → 전체 데모.
런타임: CAP Java (Spring Boot) + SAP Build PA
소요 시간: 이론 1.5시간 + 실습 2.5시간 + 발표 1시간
이론:
자동화의 정의와 BTP에서의 위치를 이해한다
SAP Build Process Automation (RPA + BPM)의 개념을 안다
Workflow vs Integration Automation을 구분한다
BTP 4대 기둥을 모두 경험한다
실습:
SAP Build Process Automation 테넌트 활성화
간단한 승인 워크플로우 생성 (UI 기반)
Java 앱과 API 통합 (RestTemplate 사용) ← Java 특화
5일 동안 만든 앱의 완전한 E2E 데모 시나리오 구성
동료 앞에서 발표 (선택)
최종 Git 커밋 및 다음 단계 가이드
출장비 승인 프로세스 (Traditional):
1. 신청자: 이메일로 신청서 작성
2. 신청자: PDF로 변환 후 매니저에게 이메일
3. 매니저: 이메일 확인, 스프레드시트에 기록
4. 매니저: 회계팀에 이메일 전달
5. 회계팀: 또 다른 시스템에 재입력
6. 회계팀: 지출 처리 및 송금
7. 신청자: "언제 나오나?" 추적 불가
→ 4-5일 소요, 에러 발생 확률 높음
1. [신청자] 앱에서 신청
↓
2. [시스템] 자동으로 매니저에게 알림 (메일)
↓
3. [매니저] 앱에서 승인/반려 (1-2시간 내)
↓
4. [시스템] 자동으로 회계팀에 전달
↓
5. [회계팀] 다른 시스템 수동 입력 (또는 API 자동화로 제거)
↓
6. [신청자] 앱에서 실시간 상태 조회 가능
→ 2-3시간 소요, 에러 0%, 추적 가능
┌─────────────────────────────────────────────────────┐
│ SAP Business Technology Platform │
│ │
│ ┌─────────────┐ ┌────────────┐ ┌─────────────┐ │
│ │ 데이터&분석 │ │ 통합 │ │ 앱 개발 │ │
│ │(Analytics) │ │(Integration) │ (CAP Java) │ │
│ └─────────────┘ └────────────┘ └─────────────┘ │
│ ↓ ↓ ↓ │
│ 분석 시스템간 개발 │
│ 데이터 흐름 (DAY1-4) │
│ │
│ ┌───────────────────────────────────────────────┐ │
│ │ AI & Automation (자동화) ← 오늘 배우는 것 │ │
│ │ │ │
│ │ SAP Build Process Automation (BPA) │ │
│ │ ├─ RPA: 사람의 반복 작업 자동화 │ │
│ │ │ (마우스, 키보드 자동 조작) │ │
│ │ │ │ │
│ │ └─ BPM: 비즈니스 프로세스 자동화 ← 오늘 │ │
│ │ (의사결정, 워크플로우) │ │
│ └───────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
| 구분 | RPA | BPM |
|---|---|---|
| 대상 | 사람의 반복 작업 | 비즈니스 프로세스 |
| 예 | 웹 양식 자동 입력 | 승인 워크플로우 |
| 기술 | 화면 조작 자동화 | 프로세스 흐름 정의 |
| 개발자 | 불필요 | 비즈니스 애널리스트 |
| 이 강좌 | 10분 시연 | 집중 실습 |
출장비 신청 앱 (Java CAP)
↓ (신청 제출)
[Java Handler] triggerApprovalWorkflow()
↓ (HTTP POST + RestTemplate)
SAP Build PA API
↓ (워크플로우 시작)
[의사결정] 금액 확인 → 매니저/CFO 할당
↓ (사용자 승인)
[REST Call] CAP Java API 호출
↓ (PATCH /travel/TravelRequests)
[Java Handler] handleApprovalCallback()
↓ (상태 업데이트)
Database (HANA)
↓
[신청자] 앱에서 상태 조회
BTP Cockpit:
trial Subaccount
→ Service Marketplace
→ "SAP Build Process Automation" 검색
→ Create Instance
Plan: "Standard"
Instance Name: "travel-automation"
→ Create
완료 후:
Service Instances and Subscriptions
→ "SAP Build Process Automation"
→ "Go to Application"
SAP Build Tenant
→ Build Processes
→ Create
Name: "Travel Approval Workflow"
Project: "Travel Expense App"
→ Create
Step 1: 트리거
Trigger: "Travel Request Created"
├─ request_id (UUID)
├─ title (String)
├─ amount (Decimal)
└─ requester_email (String)
Step 2: 의사결정
Decision: "Check Amount"
├─ IF amount >= 1000000 → CFO 승인 필요
└─ ELSE → 매니저 승인
Step 3: 사용자 태스크
Task: "Manager/CFO Approval"
├─ Assigned To: [매니저 또는 CFO]
├─ Title: "{{ title }} 승인 필요"
├─ Actions: Approve / Reject
└─ Due Date: Today + 1 Day
Step 4: REST API 호출 (Java와 동일하게 BPA에서 설정)
REST Call: "Update CAP Backend"
├─ Method: PATCH
├─ URL: {{ environment.backendUrl }}/travel/TravelRequests({{ requestId }})
├─ Body: { "status": "{{ approvalDecision }}" }
├─ Auth: OAuth 2.0
└─ Output: Response
Step 5: 알림
Email: "Send Result"
├─ To: {{ requester_email }}
├─ Subject: "출장비 신청 {{ approvalDecision }}"
└─ Body: 결과 메시지
Step 6: 완료
End: "Process Complete"
Save → Test
├─ 입력값 제공
│ request_id: "xxxxx"
│ title: "도쿄 출장"
│ amount: 850000
│ requester_email: "user@example.com"
└─ Run
이미 Spring Web에 포함되어 있으므로 추가 작업 불필요:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
TravelServiceHandler.java 에 추가:
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.beans.factory.annotation.Value;
@Component
@ServiceName("TravelService")
public class TravelServiceHandler {
@Value("${bpa.endpoint:}")
private String bpaEndpoint;
@Value("${bpa.auth-token:}")
private String bpaAuthToken;
private final RestTemplate restTemplate;
// 생성자 주입
public TravelServiceHandler(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
/**
* 신청 제출 시 BPA 워크플로우 트리거
*/
@On(event = "submit", entity = "TravelRequests")
public void onSubmitTravelRequest(TravelRequests request) {
// 상태 업데이트
request.setStatus("Submitted");
db.update(request).execute();
// BPA 워크플로우 트리거 (로컬에서는 스킵)
if (bpaEndpoint != null && !bpaEndpoint.isEmpty()) {
triggerApprovalWorkflow(request);
}
}
/**
* BPA 워크플로우 트리거
* RestTemplate를 사용한 HTTP POST
*/
private void triggerApprovalWorkflow(TravelRequests request) {
try {
// 페이로드 구성
Map<String, Object> payload = new HashMap<>();
payload.put("request_id", request.getId());
payload.put("title", request.getTitle());
payload.put("amount", request.getTotalAmount());
payload.put("requester_email", request.getRequesterEmail());
// HTTP 헤더 설정
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(bpaAuthToken);
// HTTP 요청 생성
HttpEntity<Map<String, Object>> httpRequest =
new HttpEntity<>(payload, headers);
// BPA API 호출
String bpaUrl = bpaEndpoint + "/workflows/Travel%20Approval%20Workflow";
Map<String, Object> response = restTemplate.postForObject(
bpaUrl,
httpRequest,
Map.class
);
log.info("BPA 워크플로우 트리거: {}", request.getId());
} catch (Exception e) {
// 워크플로우 실패해도 신청은 계속 진행 (로그만 기록)
log.warn("BPA 트리거 실패: {}", e.getMessage());
}
}
/**
* BPA 워크플로우 콜백 (BPA에서 호출)
*/
@PostMapping("/callbacks/approvalResult")
public Map<String, Object> handleApprovalCallback(
@RequestBody Map<String, Object> result
) {
log.info("BPA 콜백 수신: {}", result);
try {
String requestId = (String) result.get("request_id");
String decision = (String) result.get("approvalDecision");
// DB 업데이트
TravelRequests request = db.selectOne(TravelRequests.class)
.byKey(requestId)
.execute();
if (request != null) {
request.setStatus(decision); // "Approved" 또는 "Rejected"
db.update(request).execute();
}
return Map.of("status", "success");
} catch (Exception e) {
return Map.of("status", "error", "message", e.getMessage());
}
}
}
src/main/resources/application.yaml:
# BPA 통합 설정 (클라우드에서 환경 변수로 제공)
bpa:
endpoint: ${BPA_ENDPOINT:}
auth-token: ${BPA_AUTH_TOKEN:}
클라우드 배포 시:
cf set-env travel-api BPA_ENDPOINT "https://your-bpa-tenant..."
cf set-env travel-api BPA_AUTH_TOKEN "your-token"
cf restage travel-api
# 터미널 1: Java 서버
mvn spring-boot:run
# 터미널 2: Fiori UI
cd app/travel-expense-ui
npm start
브라우저에서:
http://localhost:3000
→ [신청서 작성]
→ 제목: "도쿄 출장"
→ 금액: 850,000
→ [Create] 클릭
↓
[목록에 추가됨 (Draft)]
→ 해당 항목 클릭
↓
[Object Page 열기]
→ [Submit] 클릭
↓
상태 → "Submitted"
→ (로컬: BPA 트리거 안 됨 — 정상)
1. 신청자: 앱 접속 → 신청 생성 → 제출
↓
2. Java CAP: triggerApprovalWorkflow() 자동 호출
↓
3. SAP Build PA: 워크플로우 시작
↓
4. 매니저: BPA의 "My Tasks"에서 승인 버튼 클릭
↓
5. SAP Build PA: REST Call 실행
↓
6. Java CAP: /callbacks/approvalResult 수신
↓
7. 신청자: 앱에서 상태 "Approved" 확인
cd /home/user/projects/sap-btp-travel-expense
# 최종 파일 추가
git add .
# 커밋
git commit -m "day5: SAP Build PA 워크플로우 + Java RestTemplate 통합 + E2E 완성"
# 태그 추가 (버전 관리)
git tag -a v1.0.0-complete -m "5일 강좌 완성 (Java CAP)"
# 푸시
git push origin main
git push origin v1.0.0-complete
프로젝트 루트에 README.md:
# 출장비 승인 앱 (Travel Expense App) — Java 버전
SAP BTP에서 구축한 완전한 엔드-투-엔드 애플리케이션입니다.
## 기술 스택
- **Backend:** CAP Java (Spring Boot 3.x)
- **Frontend:** Fiori Elements (SAPUI5)
- **Database:** SQLite (로컬) / HANA Cloud (클라우드)
- **Security:** XSUAA + Spring Security
- **Automation:** SAP Build Process Automation
- **Deployment:** Cloud Foundry (MTA)
## 빠른 시작 (로컬)
```bash
# 1. Java 서버 시작
mvn spring-boot:run
# 2. Fiori UI 시작 (다른 터미널)
cd app/travel-expense-ui
npm start
# 3. 접속
http://localhost:3000
DAY1: BTP 개념 + CAP Java 시작
DAY2: CDS 모델링 + Java Handler
DAY3: Fiori Elements UI
DAY4: 클라우드 보안 & 배포
DAY5: 자동화 + E2E 완성
자세한 내용은 강의 자료 참조.
---
## 5일차 마무리 체크
[ ] SAP Build PA 테넌트 활성화
[ ] 워크플로우 설계 완료
[ ] Java RestTemplate으로 BPA 트리거
[ ] BPA 콜백 핸들러 구현
[ ] 로컬 E2E 테스트 성공
[ ] 클라우드 배포 완료
[ ] 최종 README 작성
[ ] Git 커밋 + 태그
---
## 5일 강좌 최종 성과
SAP BTP의 4대 기둥 이해
CAP Java로 엔터프라이즈 백엔드 구축
Fiori Elements로 엔터프라이즈 UI 자동 생성
XSUAA + Spring Security로 클라우드 보안
MTA로 Cloud Foundry 배포
SAP Build PA로 자동화 통합
완전한 E2E 애플리케이션 완성
이제 혼자 비슷한 앱을 만들 수 있습니다!
---
> **다음:** 심화 학습 경로 (Integration Suite, Analytics Cloud, Kyma)