Bedrock을 처음 사용하면서 SDK 나 CLI 를 이용해 처음 모델을 호출할 때 거의 모두가 한번 씩은 이 통곡의 벽을 경험하게 됩니다. IAM 정책에 bedrock:InvokeModel을 분명히 넣었는데도 AccessDeniedException이 떨어지는 상황... 검색해서 나오는 글들은 하나같이 "Bedrock 콘솔의 모델 액세스 메뉴에서 모델을 신청하세요"라고 안내하는데, 그 메뉴는 이제 존재하지 않습니다.
이 글에서는 바뀐 동작 방식과 실제 해결 방법을 정리합니다.
1. 증상
Cohere Embed v4로 임베딩을 생성하려고 CLI를 호출했더니 다음 에러가 반환됩니다.
An error occurred (AccessDeniedException) when calling the InvokeModel operation:
Model access is denied due to IAM user or service role is not authorized to perform
the required AWS Marketplace actions (aws-marketplace:ViewSubscriptions,
aws-marketplace:Subscribe) to enable access to this model.
경우에 따라 이런 형태로도 나옵니다.
An error occurred (AccessDeniedException) when calling the InvokeModel operation:
Model access is denied due to arn:aws:sts::111122223333:assumed-role/MyRole/session
is not authorized to perform: aws-marketplace:Subscribe on resource: *
because no identity-based policy allows the action.
헷갈리는 지점은 에러 이름이 bedrock:InvokeModel 권한 문제처럼 보인다는 겁니다. 그래서 대부분 Bedrock 정책만 계속 들여다보다가 시간을 날립니다. 실제로 막고 있는 건 aws-marketplace 쪽입니다.
2. 환경
- 리전: ap-northeast-2 (서울)
- 모델: cohere.embed-v4:0
- 호출 주체: IAM Role (AssumeRole 세션)
- 인터페이스: AWS CLI v2 / Python boto3
- 기존 부여 권한: bedrock:InvokeModel, bedrock:InvokeModelWithResponseStream
두 IAM 액션을 함께 부여한 이유와 API별 차이는 InvokeModel vs InvokeModelWithResponseStream — 스트리밍만 403이 나는 이유에서 정리했습니다.
3. 원인
모델 액세스 페이지가 폐지되었습니다
Amazon Bedrock의 모델 액세스(Model access) 페이지는 폐지되었습니다. 서버리스 파운데이션 모델은 계정에서 처음 호출되는 시점에 모든 AWS 상용 리전에서 자동으로 활성화되며, 더 이상 수동으로 모델 액세스를 요청할 필요가 없습니다.
문제는 이 "자동 활성화"가 공짜로 되는 게 아니라는 점입니다.
서드파티 모델은 Marketplace 구독을 경유합니다
서드파티 모델을 계정에서 처음 호출하면 Bedrock이 백그라운드에서 구독 절차를 자동으로 시작합니다. 이때 필요한 사전 조건이 충족되지 않으면 구독 시도가 실패하고, 이후 API 호출은 계속 AccessDeniedException을 반환합니다. 호출하는 IAM 역할에는 aws-marketplace:Subscribe, aws-marketplace:Unsubscribe, aws-marketplace:ViewSubscriptions 권한이 필요합니다.
즉 첫 호출을 시도하는 주체가 곧 구독을 수행하는 주체입니다. 운영 역할에 Marketplace 권한이 없으면 그 역할로는 영원히 첫 관문을 못 넘습니다.
모든 모델이 해당되는 건 아닙니다
여기가 실무에서 혼선이 제일 큰 부분입니다. Amazon, DeepSeek, Mistral AI, Meta, Qwen, OpenAI 모델은 AWS Marketplace를 통해 제공되지 않기 때문에 Marketplace 권한이 필요하지 않습니다. 반면 Cohere를 비롯한 일부 서드파티 모델은 Marketplace를 경유합니다.
그래서 "같은 역할로 Claude는 잘 되는데 Cohere만 안 되는" 현상이 생깁니다. 권한 설정이 깨진 게 아니라 모델별로 경로가 다른 겁니다.
한 번만 넘으면 됩니다
일단 모델이 활성화되면 계정 내의 모든 사용자가 AWS Marketplace 구독 권한 없이 해당 모델을 호출할 수 있습니다. 이 권한은 계정에서 모델을 처음 사용할 때만 필요합니다.
계정당 1회, 모델당 1회의 이벤트라는 뜻입니다. 이 성격을 이해하면 뒤에 나올 운영 설계가 자연스러워집니다.
4. 해결
방법 A — 최소 권한으로 자동 구독 허용
호출 역할에 아래 정책을 붙입니다. Condition으로 범위를 조여서 임의의 모델을 마음대로 구독하지 못하게 막는 게 핵심입니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowModelInvoke",
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": [
"arn:aws:bedrock:*::foundation-model/cohere.embed-v4:0"
]
},
{
"Sid": "AllowModelSubscription",
"Effect": "Allow",
"Action": [
"aws-marketplace:ViewSubscriptions",
"aws-marketplace:Subscribe",
"aws-marketplace:Unsubscribe"
],
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"aws-marketplace:ProductId": [
"your-marketplace-product-id"
]
},
"StringEquals": {
"aws:CalledViaLast": "bedrock.amazonaws.com"
}
}
}
]
}
두 개의 조건을 같이 거는 이유가 있습니다.
- aws-marketplace:ProductId — 허용된 모델만 구독 가능. 이걸 빼면 Resource: "*"라 모든 Marketplace 상품 구독이 열립니다.
- aws:CalledViaLast — Bedrock을 경유한 호출에서만 유효. 콘솔에서 직접 아무 상품이나 구독하는 경로를 차단합니다.
방법 B — 관리자가 1회 선행 활성화 (권장)
운영 계정에서는 이쪽이 더 깔끔합니다. 관리자 역할로 해당 모델을 한 번만 호출해두면, 그 다음부터는 운영 역할에 Marketplace 권한을 전혀 주지 않아도 됩니다.
# 관리자 자격증명으로 1회 호출하여 구독 완료
cat > /tmp/embed-input.json << 'EOF'
{
"texts": ["activation test"],
"input_type": "search_document"
}
EOF
aws bedrock-runtime invoke-model \
--region ap-northeast-2 \
--model-id cohere.embed-v4:0 \
--content-type application/json \
--accept application/json \
--body fileb:///tmp/embed-input.json \
/tmp/embed-output.json
CLI v2에서 --body에 JSON을 인라인으로 넘기면 base64 관련 에러가 나기 쉽습니다. heredoc으로 파일을 만들고 fileb://로 넘기는 방식이 가장 확실합니다. 경로는 슬래시 3개(fileb:///tmp/...)라는 점에 주의하세요.
대기 시간
권한을 부여한 뒤 구독이 완료되기까지 최대 2분이 걸릴 수 있습니다. 이 시간 동안에는 계속 AccessDeniedException이 반환될 수 있습니다.
정책을 고치자마자 다시 호출해서 같은 에러를 보고 "안 됐다"고 판단하는 실수가 흔합니다. 2분은 기다려보세요.
5. 검증
구독이 정상적으로 걸렸는지 확인합니다.
# 출력 파일에 임베딩 벡터가 들어왔는지 확인
cat /tmp/embed-output.json | jq '.embeddings | length'
# 모델이 계정에서 호출 가능한 상태인지 확인
aws bedrock get-foundation-model \
--region ap-northeast-2 \
--model-identifier cohere.embed-v4:0 \
--query 'modelDetails.modelLifecycle'
이후 Marketplace 권한이 없는 운영 역할로 다시 호출해서 성공하는지 확인하면 끝입니다. 여기까지 통과하면 해당 계정에서는 더 이상 이 문제가 재발하지 않습니다.
6. 삽질 기록
bedrock:*로 전체 허용해봤지만 소용없었습니다. 권한 문제라고 판단되면 일단 와일드카드로 열어보고 범위를 좁히는 게 보통인데, 이 케이스는 서비스 네임스페이스 자체가 달라서 bedrock:*를 아무리 넓혀도 통과하지 못합니다. 에러 메시지에 aws-marketplace:가 찍혀 있다는 걸 놓치기 쉽습니다.
리전 문제로 의심하며 us-east-1에서 재시도했습니다. 모델 가용 리전 이슈일 거라 생각했는데, 결과는 동일한 에러였습니다. 모델 액세스가 자동으로 바뀌면서 리전별 활성화 개념이 사라졌기 때문에, 리전을 바꿔도 같은 벽을 만납니다. 오히려 계정에 불필요한 구독 시도 이력만 남습니다.
첫 호출이 한 번 성공해서 해결됐다고 착각했습니다. 구독이 진행되는 설정 기간(최대 15분) 동안에는 API 호출이 일시적으로 성공할 수 있습니다. 이 구간에 테스트하면 "됐다"고 판단하게 되는데, 실제로는 구독이 완료되지 않아서 잠시 뒤부터 다시 실패합니다. 성공을 확인했다면 15분 뒤에 한 번 더 호출해보세요.
콘솔에서 모델 액세스 메뉴를 찾느라 시간을 썼습니다. 국내외 블로그 상당수가 아직 구버전 기준으로 작성되어 있습니다. 메뉴가 안 보이면 권한이 없어서 숨겨진 거라고 생각하기 쉬운데, 그냥 없어진 기능입니다.
7. 운영 환경에서의 추가 고려사항
EULA 검토 절차가 있는 조직이라면 자동 구독을 열어두기 전에 라이선스 조건을 먼저 검토해야 합니다. 모델 액세스를 차단해야 한다면 SCP(서비스 제어 정책)를 사용합니다.
멀티 계정 환경에서는 계정마다 별도로 첫 활성화가 필요합니다. 계정을 새로 찍어낼 때마다 같은 문제를 겪게 되므로, 계정 베이스라인 구성에 모델 활성화 단계를 넣어두는 편이 낫습니다.
비용 관점에서 Unsubscribe 권한은 신중하게 다루세요. 운영 중인 모델의 구독이 해제되면 서비스 전체가 멈춥니다. 자동 구독 목적이라면 Subscribe와 ViewSubscriptions만으로도 동작합니다.
모델 활성화까지 끝냈다면 다음은 어떤 API로 호출할지의 문제입니다. InvokeModel과 스트리밍 API의 차이, 그리고 스트리밍만 403이 나는 케이스는 다음 글에서 이어집니다.
참고
'IT개발 고군분투기 > AWS' 카테고리의 다른 글
| [AWS Bedrock] InvokeModel vs InvokeModelWithResponseStream — 스트리밍만 403이 나는 이유 (0) | 2026.09.17 |
|---|---|
| [EC2] Amazon Linux 2 에서 Hostname, 시간 변경하기 (0) | 2022.10.06 |
댓글