📖 개요와 이 글에서 얻어갈 것
SAP BTP(Business Technology Platform)에서 애플리케이션을 배포하려는 순간 누구나 마주치는 첫 갈림길이 있습니다. Cloud Foundry 런타임이냐, Kyma 런타임이냐. 둘 다 "앱을 올릴 수 있는 곳"이지만 설계 철학과 운영 방식이 완전히 다르기 때문에, 잘못 고르면 몇 달 뒤 마이그레이션 비용을 치르게 됩니다. 이 글은 두 런타임의 구조적 차이를 파악하고, 실무에서 바로 쓸 수 있는 선택 기준을 정리하는 실전 예제입니다.
- Cloud Foundry와 Kyma의 아키텍처 차이를 비유로 이해한다
- 워크로드 특성·팀 스킬셋·운영 복잡도 기준의 선택 프레임을 만든다
- 동일한 API 서비스를 두 런타임에 각각 배포하는 과정을 코드로 비교한다
- 프로덕션 관점의 확장·보안 설정 차이를 확인한다
📚 미리 알아두면 좋은 배경
이 글은 입문자 눈높이로 작성했지만, 다음 개념을 알고 있으면 훨씬 수월합니다. HTTP 기반 REST API의 기본 구조, 터미널(CLI) 명령어 실행 경험, 그리고 "컨테이너"가 무엇인지에 대한 대략적인 감각 정도면 충분합니다. Kubernetes를 몰라도 따라올 수 있도록 Kyma 부분은 개념부터 풀어서 설명합니다.
🔧 테스트 환경
2026년 기준 SAP BTP Free Tier(또는 Trial) 계정에서 두 런타임 모두 무료로 체험할 수 있습니다. 서브어카운트에서 Cloud Foundry 환경과 Kyma 환경을 각각 활성화(Enable)해 두세요.
- SAP BTP: Free Tier 서브어카운트, Cloud Foundry 환경 + Kyma 환경 활성화
- Cloud Foundry CLI v8+:
cf명령어 도구 - kubectl v1.30+: Kubernetes 클러스터 제어 도구
- kubelogin(oidc-login) 플러그인: Kyma의 kubeconfig 인증에 일반적으로 필요
- Docker 또는 호환 빌드 도구: Kyma 배포용 컨테이너 이미지 빌드
Free Tier의 Kyma는 노드 수와 리소스가 제한되므로, 이 글의 예제는 소형 워크로드 기준으로 구성했습니다.
💡 핵심 개념 — 두 런타임은 어떻게 다른가
비유로 시작해 보겠습니다. Cloud Foundry는 풀옵션 관리형 아파트입니다. 짐(소스 코드)만 들고 들어가면 가구(런타임 스택), 수도·전기(라우팅, 로드밸런싱), 경비(플랫폼 보안)가 이미 갖춰져 있습니다. cf push 한 줄이면 빌드팩(buildpack)이 소스를 감지해 실행 환경을 자동 구성합니다. 대신 벽을 허물거나 배관을 바꾸는 것(인프라 커스터마이징)은 불가능합니다.
Kyma는 골조만 갖춘 오피스텔에 가깝습니다. 실체는 SAP가 관리해 주는 Kubernetes 클러스터 위에 Istio 서비스 메시, 서버리스 Function, 이벤트 처리, API 노출(APIRule) 같은 모듈이 얹힌 형태입니다. 컨테이너 이미지를 직접 만들어야 하고 YAML 매니페스트도 직접 작성하지만, 그만큼 사이드카 주입, 세밀한 트래픽 제어, 커스텀 오퍼레이터 활용 같은 클라우드 네이티브 패턴을 자유롭게 쓸 수 있습니다.
실무 선택 기준을 표로 정리하면 다음과 같습니다.
| 판단 축 | Cloud Foundry가 유리 | Kyma가 유리 |
|---|---|---|
| 팀 스킬셋 | Kubernetes 경험이 없는 팀 | K8s/컨테이너 운영 경험 보유 |
| 워크로드 형태 | 전형적인 웹 앱·API (CAP, Java, Node.js) | 이벤트 기반, 마이크로서비스, 서드파티 컨테이너 |
| 배포 단위 | 소스 코드 (빌드팩 자동 빌드) | 컨테이너 이미지 |
| 운영 복잡도 | 낮음 — 플랫폼이 대부분 관리 | 중간 — 매니페스트·네임스페이스 직접 관리 |
| 확장 제어 | 인스턴스 수·메모리 단위의 단순 스케일링 | HPA, 리소스 쿼터 등 세밀한 제어 |
| 생태계 활용 | BTP 서비스 바인딩 중심 | Helm 차트, K8s 오픈소스 생태계 전체 |
한 줄 요약: "소스를 밀어넣고 끝내고 싶다면 Cloud Foundry, 컨테이너와 Kubernetes 생태계가 필요하다면 Kyma"가 일반적인 출발점입니다. 두 런타임은 배타적이지 않아서, 같은 서브어카운트에서 병행 운영하는 사례도 흔합니다.
💻 직접 해보기 — 같은 서비스를 두 런타임에 올려보기
가상의 물류 스타트업이 만든 배송비 계산 API parcel-rate-api를 두 런타임에 배포하며 차이를 체감해 보겠습니다.
1단계: Cloud Foundry — manifest 하나로 배포
프로젝트 루트에 manifest.yml을 만들고 소스만 푸시하면 됩니다. Node.js 프로젝트라면 빌드팩이 package.json을 감지해 알아서 빌드합니다.
applications:
- name: parcel-rate-api
memory: 256M
instances: 1
buildpacks:
- nodejs_buildpack
env:
RATE_TABLE_REGION: KR
services:
- parcel-pg-db # 미리 생성한 PostgreSQL 서비스 인스턴스
routes:
- route: parcel-rate-api.cfapps.ap12.hana.ondemand.com
# 로그인 → 서비스 생성 → 배포까지 세 줄
cf login -a https://api.cf.ap12.hana.ondemand.com --sso
cf create-service postgresql-db development parcel-pg-db
cf push
여기서 핵심은 컨테이너 이미지를 만들지 않았다는 점입니다. 라우팅 URL, TLS, 로드밸런싱이 전부 자동입니다. 이 단순함이 Cloud Foundry의 최대 무기입니다.
2단계: Kyma — 매니페스트 직접 작성과 로그·장애 대비
같은 앱을 Kyma에 올리려면 먼저 이미지를 빌드해 레지스트리에 푸시한 뒤, Deployment와 APIRule을 작성합니다. 이때 헬스 체크(probe)를 넣어 장애 시 자동 재시작되도록 하는 것이 실무 포인트입니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: parcel-rate-api
namespace: logistics-dev
spec:
replicas: 2
selector:
matchLabels: { app: parcel-rate-api }
template:
metadata:
labels: { app: parcel-rate-api }
spec:
containers:
- name: api
image: registry.example.com/logistics/parcel-rate-api:1.2.0
ports: [{ containerPort: 8080 }]
envFrom:
- secretRef: { name: parcel-db-credentials }
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
initialDelaySeconds: 10
readinessProbe:
httpGet: { path: /readyz, port: 8080 }
apiVersion: gateway.kyma-project.io/v2
kind: APIRule
metadata:
name: parcel-rate-api
namespace: logistics-dev
spec:
hosts: [ parcel-rate ]
service: { name: parcel-rate-api, port: 8080 }
gateway: kyma-system/kyma-gateway
rules:
- path: /v1/rates/*
methods: [ GET, POST ]
jwt:
authentications:
- issuer: https://mytenant.authentication.ap12.hana.ondemand.com/oauth/token
jwksUri: https://mytenant.authentication.ap12.hana.ondemand.com/token_keys
로그 확인과 트러블슈팅도 kubectl로 직접 수행합니다.
kubectl -n logistics-dev logs deploy/parcel-rate-api --tail=100
kubectl -n logistics-dev describe pod -l app=parcel-rate-api
Cloud Foundry 대비 작성할 것이 확실히 많지만, JWT 검증을 게이트웨이 레벨에서 선언적으로 걸 수 있는 등 제어 범위가 넓다는 것을 알 수 있습니다.
3단계: 프로덕션 관점 — 확장과 보안 설정 비교
트래픽이 늘어날 때의 대응 방식이 두 런타임의 성격을 가장 잘 보여줍니다. Cloud Foundry는 인스턴스 수를 직접 늘리거나 Application Autoscaler 서비스에 정책을 바인딩합니다.
{
"instance_min_count": 2,
"instance_max_count": 6,
"scaling_rules": [
{ "metric_type": "cpu", "threshold": 70,
"operator": ">", "adjustment": "+1" }
]
}
Kyma에서는 표준 Kubernetes HPA를 그대로 사용하고, 리소스 상한을 함께 선언해 폭주를 방지합니다.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: parcel-rate-api-hpa
namespace: logistics-dev
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: parcel-rate-api
minReplicas: 2
maxReplicas: 6
metrics:
- type: Resource
resource:
name: cpu
target: { type: Utilization, averageUtilization: 70 }
보안 측면에서 Cloud Foundry는 XSUAA 서비스 바인딩과 앱 내부 미들웨어로 인가를 처리하는 패턴이 일반적이고, Kyma는 위 2단계처럼 APIRule + Istio 계층에서 앱 코드 밖에서 차단하는 구조를 선호합니다. 테스트 관점에서는 CF의 cf push --strategy rolling, Kyma의 롤링 업데이트 + readinessProbe 조합이 무중단 배포의 기본기입니다.
⚠️ 자주 만나는 함정
- Q1. Free Tier에서 Kyma를 켰는데 Pod가 Pending 상태로 멈춰요. — 노드 리소스 부족이 대부분입니다.
kubectl describe pod에서Insufficient cpu/memory이벤트를 확인하고, requests 값을 낮추거나 replicas를 1로 줄이세요. Free Tier Kyma는 소형 클러스터라는 점을 항상 염두에 둬야 합니다. - Q2. cf push는 성공했는데 앱이 계속 crashed 상태예요. — 빌드팩 환경에서는 앱이 반드시
PORT환경 변수의 포트로 리슨해야 합니다. 8080 고정 바인딩이 가장 흔한 원인이며,cf logs parcel-rate-api --recent로 시작 로그를 먼저 확인하세요. - Q3. Kyma APIRule을 만들었는데 외부에서 404가 떠요. — Service의 포트·이름 불일치, 또는 host 중복이 주범입니다.
kubectl get apirule -n logistics-dev에서 STATUS가 Ready인지 확인하고, VirtualService가 생성됐는지 점검하세요. - Q4. 둘 중 하나만 골라야 하나요? — 아닙니다. 코어 비즈니스 API는 Cloud Foundry(CAP)로, 이벤트 처리·서드파티 컨테이너는 Kyma로 나누는 하이브리드 구성이 실무에서 자주 권장됩니다. 다만 운영 채널이 둘로 늘어나는 비용은 감안해야 합니다.
🚀 더 파볼 주제
선택 기준이 잡혔다면 다음 주제로 나아가 보세요. Cloud Foundry 트랙이라면 CAP(Cloud Application Programming Model)과 MTA 기반 다중 모듈 배포, XSUAA 인가 모델이 자연스러운 다음 걸음입니다. Kyma 트랙이라면 Kyma Serverless Function, SAP Event Mesh 연동을 통한 이벤트 기반 아키텍처, Helm 차트를 활용한 배포 표준화를 추천합니다. 두 런타임을 병행한다면 Cloud Connector와 Destination 서비스로 온프레미스 연결을 공통화하는 패턴도 살펴볼 가치가 있습니다.
📚 더 읽어볼 자료
댓글 0
아직 댓글이 없습니다.