어제가 "누가 무엇을 할 수 있는가"의 권한이었다면, 오늘은 "트래픽이 어디로 흐르는가"의 네트워크다. 기본 설정에서 SageMaker 학습 작업은 AWS가 관리하는 격리된 네트워크에서 실행되고 필요하면 인터넷에 접근할 수 있다. 편하지만 두 가지 걸림돌이 있다 — ① 데이터가 인터넷 경로로 유출될 수 있다는 우려, ② 금융·의료 규제의 "모든 트래픽은 우리 VPC 안에서만" 요구.
항목
기본 (SageMaker 관리 네트워크)
VPC 모드 (VpcConfig)
네트워크 격리 (EnableNetworkIsolation)
컨테이너가 붙는 곳
AWS가 관리하는 네트워크
내 VPC 서브넷의 ENI
VPC 모드와 병행 가능. 아웃바운드 자체를 차단
인터넷 접근
가능
서브넷 라우팅에 달림(프라이빗이면 불가)
불가
보안 그룹·NACL 적용
불가
가능
해당 없음(호출 자체가 없음)
S3 접근 경로
서비스가 알아서 처리
VPC 엔드포인트가 있어야 함
SageMaker가 데이터를 미리 내려 컨테이너에 제공
설정 키
없음(기본값)
Subnets + SecurityGroupIds
EnableNetworkIsolation: true
대표 용도
실험·PoC
규제 준수, 트래픽 경로 통제
최고 수준 격리, 데이터 반출 차단
대표 부작용
통제 수단이 없음
엔드포인트 누락 시 작업이 멈춤
pip install·외부 API 호출 불가
세 단계는 배타적이지 않고 쌓아 올리는 관계다. VPC 모드로 트래픽을 내 경계 안으로 끌어들이고, 인터넷 게이트웨이를 없애고, 빠진 경로를 VPC 엔드포인트로 메우고, 가장 민감한 워크로드에는 네트워크 격리를 얹는다.
[기본 모드]학습 컨테이너 → AWS 관리 네트워크 → (인터넷 가능)[VPC 모드]학습 컨테이너 → 고객 VPC 서브넷(ENI) → 보안 그룹 → VPC 엔드포인트 → S3 / SageMaker API (인터넷 게이트웨이 없음)[VPC 모드 + 네트워크 격리]학습 컨테이너 ─╳─ 아웃바운드 전면 차단 ▲ └── SageMaker가 미리 내려받아 마운트해 준 데이터만 사용
💡 관련 이론: VPC 모드의 본질은 "트래픽의 경로를 고객이 통제 가능한 경계 안으로 끌어들이는 것"이다. 일단 VPC 안으로 들어오면 보안 그룹·NACL·라우팅 테이블·VPC 엔드포인트 등 익숙한 VPC 통제 수단을 전부 적용할 수 있다. 격리는 "막는 것"이 아니라 "내가 볼 수 있는 곳으로 트래픽을 모으는 것"에서 시작한다.
VPC 모드만으로는 부족할 수 있다. 더 강한 격리는 네트워크 격리(network isolation)다. 이를 켜면 컨테이너가 어떤 아웃바운드 네트워크 호출도 못 한다 — 인터넷은 물론 VPC 내부 호출도 막힌다. 컨테이너는 오직 SageMaker가 제공한 데이터로만 동작한다.
{ "EnableNetworkIsolation": true}
네트워크 격리를 켜면 컨테이너가 외부 패키지를 다운로드하거나 외부 API를 호출할 수 없다. 그래서 의존성을 미리 컨테이너 이미지에 다 넣어둬야 한다. 가장 엄격한 격리가 필요한 민감 워크로드에 쓴다.
EnableNetworkIsolation과 VPC 모드는 헷갈리기 쉽지만 다른 레벨이다. VPC 모드는 "트래픽을 고객 VPC로 보낸다"이고, 네트워크 격리는 "컨테이너의 모든 아웃바운드를 끊는다"이다. 둘을 함께 쓰면 가장 강력하다 — 그런데 격리를 켜면 학습 데이터는 SageMaker가 미리 다운로드해 컨테이너에 마운트한다. "컨테이너가 인터넷에서 모델을 못 받게 하라"는 시나리오의 정답이 네트워크 격리다.
⚠️ 함정: 네트워크 격리를 켜면 학습 스크립트 안의 pip install, 사전학습 가중치 다운로드, 외부 지표 서버 전송이 전부 실패한다. "왜 로컬에선 되는데 SageMaker에서만 안 되지"의 상당수가 이 경우다. 대응은 ① 의존성을 커스텀 이미지에 굽거나 ② 소스 디렉터리에 requirements.txt를 함께 올려 SageMaker가 시작 전에 처리하게 하는 것이다.
VPC 모드로 인터넷 게이트웨이를 없애면 컨테이너가 S3나 SageMaker API에 어떻게 접근할까? 답은 VPC 엔드포인트다. 트래픽이 인터넷을 거치지 않고 AWS 백본 내부로만 흐른다. 두 종류가 있고, 어느 쪽인지 구분하는 것이 시험 범위에 든다.
항목
게이트웨이 엔드포인트
인터페이스 엔드포인트 (PrivateLink)
지원 서비스
S3, DynamoDB 두 개뿐
SageMaker API·Runtime, ECR, CloudWatch Logs, STS 등 대부분
동작 방식
라우팅 테이블에 경로를 추가
서브넷에 ENI를 만들고 프라이빗 IP 부여
보안 그룹 부착
불가(엔드포인트 정책으로 통제)
가능(ENI에 SG를 붙임)
이름 해석
라우팅으로 처리
프라이빗 DNS가 서비스 도메인을 프라이빗 IP로 해석
비용
없음
시간당 + 데이터 처리량 과금
온프레미스에서 사용
불가(해당 VPC 내부에서만)
가능(Direct Connect·VPN 경유)
액세스 제어 수단
엔드포인트 정책
엔드포인트 정책 + 보안 그룹
인터넷 없는 VPC 모드 학습을 돌리려면 다음 엔드포인트들이 필요하다.
필요한 VPC 엔드포인트 (인터넷 없는 VPC 모드 학습 시)- com.amazonaws.<region>.s3 (게이트웨이) → 데이터 · 아티팩트 · ECR 이미지 레이어- com.amazonaws.<region>.sagemaker.api (인터페이스) → 작업 제어- com.amazonaws.<region>.sagemaker.runtime (인터페이스) → 추론 호출- com.amazonaws.<region>.ecr.api (인터페이스) → 이미지 메타데이터 · 인증- com.amazonaws.<region>.ecr.dkr (인터페이스) → Docker pull- com.amazonaws.<region>.logs (인터페이스) → CloudWatch Logs- com.amazonaws.<region>.sts (인터페이스) → 역할 assume
이 엔드포인트들이 빠지면 "VPC 모드로 했더니 작업이 멈춰서 안 끝난다"는 현상이 생긴다 — 컨테이너가 S3나 ECR에 닿지 못해서다. 특히 ECR 이미지 레이어는 S3에 저장되므로, ECR 엔드포인트만 만들고 S3 게이트웨이 엔드포인트를 빠뜨리면 이미지 pull이 실패한다.
무엇이 실제로 만들어져 있는지는 EC2 API로 바로 확인할 수 있다.
import boto3ec2 = boto3.client('ec2')resp = ec2.describe_vpc_endpoints( Filters=[{'Name': 'vpc-id', 'Values': ['vpc-0abc123456789def0']}])for ep in resp['VpcEndpoints']: print(ep['ServiceName'], ep['VpcEndpointType'], ep['State']) # ServiceName에 s3 / sagemaker.api / ecr.dkr / logs / sts 가 다 있는지 대조
PrivateLink(인터페이스 엔드포인트)의 핵심 가치는 "AWS 서비스 트래픽이 퍼블릭 인터넷을 절대 타지 않는다"이다. 엔드포인트가 VPC 안에 프라이빗 IP를 가지므로, 컨테이너 입장에서 S3나 SageMaker가 마치 같은 VPC 안에 있는 것처럼 보인다. 데이터 유출 경로를 인터넷에서 AWS 백본으로 옮기는 것이 격리의 마지막 퍼즐이다.
┌──────────────────────── 고객 VPC ────────────────────────┐│ ││ 프라이빗 서브넷 A 프라이빗 서브넷 B ││ ┌─────────────────┐ ┌─────────────────┐ ││ │ 학습 컨테이너 │◀─────────▶│ 학습 컨테이너 │ ││ │ ENI (sg-app) │ 노드 간 │ ENI (sg-app) │ ││ └────────┬────────┘ 통신 └────────┬────────┘ ││ │ 443/HTTPS │ ││ ▼ ▼ ││ ┌────────────────────────────────────────────┐ ││ │ 인터페이스 엔드포인트 ENI (sg-endpoint) │ ││ └────────────────────────────────────────────┘ ││ │ ││ ├──▶ SageMaker API / Runtime ││ ├──▶ ECR (api · dkr) ││ ├──▶ CloudWatch Logs ││ └──▶ STS ││ ││ 라우팅 테이블 ──▶ [S3 게이트웨이 엔드포인트] ──▶ S3 ││ ││ ✗ 인터넷 게이트웨이 없음 ✗ NAT 게이트웨이 없음 │└──────────────────────────────────────────────────────────┘
인터페이스 엔드포인트로 가는 트래픽은 프라이빗 DNS가 만든다. 컨테이너는 평소처럼 sagemaker.<region>.amazonaws.com을 호출하는데, VPC 내부 DNS가 그 이름을 엔드포인트 ENI의 프라이빗 IP로 해석해 준다. 프라이빗 DNS를 꺼두면 코드가 퍼블릭 IP로 나가려다 실패하므로 사실상 필수 설정이다.
컨테이너 ENI와 VPC 엔드포인트 ENI에 붙는 보안 그룹으로 트래픽을 더 좁힌다. 분산 학습에서는 컨테이너들끼리 통신해야 하므로 자기 참조 규칙이 필요하다.
SageMaker 컨테이너 보안 그룹 (sg-app)- 인바운드: sg-app 자기 자신으로부터 모든 TCP (분산 학습 노드 간 통신)- 아웃바운드: 443 → sg-endpoint (HTTPS로 VPC 엔드포인트 호출)VPC 엔드포인트 보안 그룹 (sg-endpoint)- 인바운드: 443 ← sg-app (컨테이너로부터 HTTPS)
규칙
없으면 생기는 일
sg-app 자기 참조 인바운드
멀티 노드 분산 학습에서 노드 간 통신이 막혀 학습이 시작되지 않는다
sg-app 아웃바운드 443 → sg-endpoint
컨테이너가 어떤 VPC 엔드포인트에도 닿지 못해 작업이 멈춘다
sg-endpoint 인바운드 443 ← sg-app
엔드포인트를 만들었는데도 연결이 거부된다
아웃바운드를 443으로 엔드포인트 보안 그룹에만 허용하면 트래픽이 다른 곳으로 새지 않는다. 보안 그룹을 IP 대역이 아니라 다른 보안 그룹 ID로 참조하는 것이 요령이다. ENI가 매번 새 IP로 생기는 SageMaker 환경에서 IP 기반 규칙은 관리가 불가능하다.