코드스페이스 — 통합 개발환경
GenD 코드스페이스는 브라우저에서 바로 쓰는 개인 개발환경입니다. 하나의 코드스페이스가 JupyterLab 과 VS Code 를 동시에 제공하며 — 두 IDE 는 같은 컨테이너, 같은 홈 디렉토리를 공유하므로 노트북에서 만든 파일을 VS Code 에서 즉시 이어서 편집할 수 있습니다.
본 가이드는 Epic #2614 (M1) 의 산출물입니다. IDE 별 활용 시나리오는 IDE 선택 가이드 를 참조하세요.
사용 자격 — codespace-users 그룹
코드스페이스는 사용자마다 전용 컨테이너와 볼륨을 점유하므로, 명시적으로 자격을 부여받은 사용자만 생성할 수 있습니다 (#2659).
-
자격은 Keycloak
codespace-users그룹 멤버십으로 관리됩니다. -
데이터 접근 역할(
analyst등)과는 별개입니다 — 데이터를 조회할 수 있어도 코드스페이스 자격이 없으면 생성되지 않습니다. -
자격이 없는 상태로 [시작]을 누르면 다음 안내가 표시됩니다:
코드스페이스 사용 권한이 없습니다 —
'codespace-users'그룹 소속이 필요합니다.이 경우 플랫폼 관리자에게 그룹 추가를 요청하세요.

자격이 없는 계정(analyst 역할 보유, codespace-users 미소속)으로 [시작]을 눌렀을
때의 실제 prod 화면입니다. 안내가 토스트와 상단 배너로 표시되고, 카드는 "시작 전"
상태로 되돌아가 재시도할 수 있습니다.
자격 통제는 JupyterHub 인증자와 GenD API 양쪽에서 이중 시행됩니다. /jupyter 로
직접 로그인하는 경로와 GenD UI 경로가 각각 검사되므로 한쪽만 우회할 수 없습니다.
그룹 추가는 Keycloak 관리 콘솔 → 그룹 → codespace-users → Members 에서 수행합니다.
시작하기 — 단계별 가이드
아래 스크린샷은 prod 환경 E2E 로 캡처한 실제 화면입니다 (Epic #2614 검증). 아래 절차는
codespace-users자격이 있는 사용자 기준입니다.
1. 코드스페이스 탭 이동
ML 허브 → 개발 → 코드스페이스 탭으로 이동합니다. 내 코드스페이스 카드에 현재 상태(중지됨/실행 중)와 마지막 활동 시각이 표시됩니다. 중지 상태여도 워크스페이스 (파일)는 보존되어 있습니다.

2. 프로필 선택
프로필 셀렉트에서 리소스 크기를 고릅니다 — Basic(1 CPU/2G) · Standard(2/4) · Large(4/8) · JupyterLab 경량(노트북 전용). 실행 중에는 변경할 수 없고, 중지 후 다시 시작할 때 바꿀 수 있습니다.

3. 시작
시작을 누르면 카드가 "시작 중"으로 바뀝니다. 첫 시작(이미지 풀)은 수 분 걸릴 수 있으며, 지연되면 카드에 사유(스케줄링 대기 등)가 표시됩니다.

준비가 끝나면 [JupyterLab 열기]·[VS Code 열기]·[중지] 버튼이 활성화됩니다.

4. IDE 열기 — JupyterLab / VS Code
버튼을 누르면 각 IDE 가 새 탭에서 열립니다. 인증은 GenD SSO 세션을 그대로 사용합니다(별도 로그인 불필요). 두 IDE 는 같은 홈 디렉토리를 공유하므로 동시에 열어 오가며 작업할 수 있습니다.

VS Code 첫 진입 시 워크스페이스 신뢰 확인("Do you trust the authors…")이 뜹니다 — 본인 홈 디렉토리이므로 Yes, I trust the authors 를 선택하면 됩니다.

5. 중지
중지를 누르면 확인 다이얼로그가 뜹니다. 중지해도 파일은 보존되며(커널 메모리는 휘발), 다시 시작하면 그대로 복원됩니다.


프로필
| 프로필 | 리소스 (limit) | IDE | 용도 |
|---|---|---|---|
| 코드스페이스 Basic (기본) | 1 CPU / 2G | JupyterLab + VS Code | 일반 분석·개발 |
| 코드스페이스 Standard | 2 CPU / 4G | JupyterLab + VS Code | 데이터 분석 |
| 코드스페이스 Large | 4 CPU / 8G | JupyterLab + VS Code | ML 실험 |
| JupyterLab (경량) | 1 CPU / 2G | JupyterLab 전용 | 노트북만 필요할 때 |
- limit 은 상한이며, 클러스터가 한가하면 그 이하 자원으로도 즉시 시작됩니다.
- 실행 중에는 프로필을 바꿀 수 없습니다 — 중지 후 다른 프로필로 다시 시작하세요. 홈 디렉토리(PVC)는 프로필과 무관하게 보존됩니다.
자동 종료 (idle culling)
- 1시간 무활동 시 코드스페이스가 자동 중지됩니다 (파일은 보존, 커널 상태는 휘발).
- 최대 수명은 8시간입니다 — 장시간 학습·배치 작업은 코드스페이스가 아니라 파이프라인 또는 서빙으로 옮기세요.
- 중지된 코드스페이스는 카드에서 다시 시작하면 홈 디렉토리 그대로 재개됩니다.
스토리지
- 사용자마다 개인 볼륨(PVC)이 홈 디렉토리(
/home/jovyan)에 마운트됩니다. 신규 사용자는 10Gi 로 생성됩니다. - 코드스페이스 간(프로필 변경·재시작·IDE 전환)에도 볼륨은 항상 동일합니다.
터미널에서 GenD 사용하기 — gend CLI
코드스페이스 이미지에는 gend CLI 가 사전 설치되어 있습니다. 터미널을 열고
한 번만 gend init 을 실행하면 인증과 git 자격증명이 함께 준비됩니다:
gend init
gend init 이 하는 일 (각 단계는 실패해도 나머지를 계속 진행):
- 로그인 — 브라우저가 없는 환경이므로 자동으로 디바이스 플로우(RFC 8628)로
전환합니다. 출력된 URL·코드로 인증하면 토큰이
~/.gend/에 저장됩니다. - Gitea 사용자 동기화 + 60분 PAT 발급 →
~/.gitconfig(author) 와~/.git-credentials(0600) 시드. 이후git push/pull이 자격증명 입력 없이 동작합니다.
로그인 후에는 데이터셋을 CLI 로 바로 다룰 수 있습니다:
gend dataset create my-set --modality text # 데이터셋 생성 (v1.2+)
gend dataset upload <id> data/ # 배치 업로드 — 100MB 초과 parquet 는 청크 자동 전환 (v1.2+)
gend dataset list # 데이터셋 목록
gend dataset show <id> # 상세(버전 수·행 수)
gend dataset rows <id> --version 3 # 특정 버전 행 조회
gend dataset rows <id> --json > data.jsonl # JSONL 로 파이프 (학습 스크립트 입력)
gend dataset versions <id> # 버전 이력
gend dataset export <id> --version 3 --wait # Gold export 생성 + 완료 대기
gend dataset download <id> --version 3 -o data/ # export 내려받기 — S3 자격 불필요 (v1.2+)
gend dataset usage # 워크스페이스 스토리지 사용량 + 쿼터 (v1.2+)
gend dataset request-quota --hard-gb 10 --reason "..." # 쿼터 증설 신청 → 관리자 승인 (v1.2+)
CLI 는 여러분의 신원으로 호출하므로 워크스페이스 접근 권한이 그대로 적용됩니다
(권한 없는 데이터셋은 목록·조회에서 제외). export 산출물은 gend dataset download 로 API 를 경유해 내려받습니다 — S3 자격이 필요 없습니다 (v1.2+).
git 형상관리
gend init 이 시드한 자격증명으로 사내 Gitea 를 바로 쓸 수 있습니다. jupyterlab-git·
nbdime·pre-commit 도 함께 준비되어 있습니다 — 자세한 내용은
Notebook ↔ Git 가이드 참조.
보안 — 터미널 격리 모델
코드스페이스 터미널에서 사용자는 임의 셸 명령을 실행할 수 있습니다. 영향 범위(blast radius)는 본인 컨테이너로 봉쇄되며, 네 겹으로 격리됩니다 (Epic #2649 에서 리포에 명시 pin):
| 계층 | 설정 | 차단하는 것 |
|---|---|---|
| 컨테이너 권한 | uid 1000(비루트) · allowPrivilegeEscalation: false · capabilities drop [ALL] | 루트 탈취·권한상승·커널 capability 남용 |
| ServiceAccount | 네임스페이스 default SA(rolebinding 없음) | 팟의 SA 토큰으로 kubectl/kube-apiserver 호출 → 전부 거부 |
| 클라우드 메타데이터 | cloudMetadata.blockWithIptables: true | 노드 관리 ID(IMDS 169.254.169.254) 탈취 → 클라우드 계정 공격 |
| Egress NetworkPolicy | networkPolicy.enabled: true, egressAllowRules.privateIPs: false | postgres·trino·vault·gend-api 내부 ClusterIP 직결 (사설 IP 전대역 차단) |
- 노트북은 hub/proxy/DNS 와 공용 인터넷(pip install 등) 만 도달합니다. 데이터 쿼리는
내부 Trino 직결이 아니라 공용 ingress 의 gend-api
/query(SqlGuard + DataGrant) 경유로만 가능합니다 — 이는 의도된 설계입니다. - 자원은 프로필별 CPU/메모리 limit + PVC 10Gi 로 상한이 있어, 폭주해도 본인 팟에 국한됩니다.
규제·표준(ISMS-P·전자금융감독규정·ISO 27001 등) 항목별 대응 현황, 실제 사고 사례, 미충족 항목의 정직한 공개, 고객이 직접 실행하는 검증 절차는 코드스페이스 보안 — 고객사 요구사항 대응 가이드 를 참조하세요.
NetworkPolicy 는 클러스터에 네트워크 정책 enforcer 가 있어야 실효합니다. prod AKS 는
Calico(kubernetes.azure.com/network-policy=calico)로 강제되지만, enforcer 가 없는
클러스터(예: kind 의 kindnet)에 배포하면 위 Egress 격리가 inert(무효) 가 됩니다.
GenD 를 단독으로 온프레미스 배포하는 경우, 클러스터 CNI 가 NetworkPolicy 를 강제하는지
반드시 확인하세요. 이 격리 값들의 회귀는 CI(scripts/test_cross_pr_consistency.py)가
머지 차단합니다.
운영 (관리자)
helm 반영 절차 — API 토큰 주의
JupyterHub 의 hub.services.gend-api.apiToken 정본은 K8s Secret jupyterhub-api-token
입니다. values-azure.yaml 은 placeholder 만 담고 있으므로 helm upgrade 시 반드시
--set 으로 라이브 토큰을 주입해야 합니다 (placeholder 그대로 적용되면 gend-api 의
노트북 관리 API 가 401):
HUB_TOKEN=$(kubectl --context aks-genos-prod -n gend get secret jupyterhub-api-token \
-o jsonpath='{.data.token}' | base64 -d)
# 적용 전 라이브 값과 리포 values 의 diff 확인 (드리프트 되밀림 방지)
helm --kube-context aks-genos-prod get values jupyterhub -n gend > /tmp/live-values.yaml
diff /tmp/live-values.yaml infra/jupyterhub/values-azure.yaml # 차이 검토 후
helm --kube-context aks-genos-prod upgrade jupyterhub jupyterhub/jupyterhub -n gend \
--version 4.3.3 -f infra/jupyterhub/values-azure.yaml \
--set hub.services.gend-api.apiToken="$HUB_TOKEN" \
--set singleuser.image.name=genosprodacr.azurecr.io/gend-singleuser \
--timeout 180s
토큰 로테이션: 새 랜덤 값 생성 → Secret patch → 위 절차로 helm upgrade →
kubectl rollout restart deploy/gend-api.
기존 사용자 PVC 확장 (2Gi → 10Gi)
managed-csi-tagged(StandardSSD) 는 allowVolumeExpansion: true 이므로 온라인 확장이
가능합니다. 신규 사용자만 10Gi 로 생성되며, 기존 클레임은 필요 시 개별 확장합니다:
kubectl --context aks-genos-prod -n gend patch pvc claim-<username> \
-p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'
# 파일시스템 확장은 다음 코드스페이스 시작(팟 마운트) 시 자동 반영
사용 자격 부여·회수 (codespace-users)
# 그룹 ID 조회
GID=$(kubectl --context aks-genos-prod -n gend exec deploy/gend-api -c gend-api -- \
python3 -c "print('<Keycloak 관리 콘솔에서 확인>')")
# 부여: Keycloak 관리 콘솔 → Groups → codespace-users → Members → Add member
# 회수: 같은 화면에서 Leave
- 회수해도 기존 볼륨(PVC)은 삭제되지 않습니다 — 실행 중 코드스페이스는 계속 동작하며, 중지 후 재시작 시점부터 차단됩니다. 즉시 차단이 필요하면 회수 후 해당 사용자의 코드스페이스를 관리자가 중지시키세요.
- 자격 그룹명을 바꾸려면
infra/jupyterhub/values*.yaml의gend-codespace-entry-gate와apps/api/.../config.py의codespace_required_group을 함께 갱신해야 합니다(CI 가 정합을 검사).
프로필 변경 시 함께 갱신할 것
profileList 의 slug 는 gend-api settings.jupyterhub_profiles 와 문자열 계약입니다.
values.yaml·values-azure.yaml·apps/api/src/gend_api/config.py 세 곳을 함께 바꾸지
않으면 tests/test_notebook.py 의 values 정합 테스트가 머지를 차단합니다.