Amazon EC2에서 Bedrock Claude 호출 테스트
안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번 블로그에서는 Amazon EC2에서 Bedrock Claude 호출 테스트를 해봤습니다.
준비 과정
먼저 EC2 인스턴스에서 Bedrock으로 접근할 수 있는 권한이 있는지 확인해야 합니다. 먼저 EC2 인스턴스에 할당된 IAM Role의 정보를 불러옵시다.
$ aws ec2 describe-instances \
--instance-ids i-xxxxxxxxxxx \
--query 'Reservations[*].Instances[*].IamInstanceProfile.Arn' \
--output text
arn:aws:iam::xxxxxxxxxxx:instance-profile/test-iam
이어서 해당 IAM Role에 연결된 정책을 확인합니다.
연결된 정책에 AmazonBedrockFullAccess 혹은 Bedrock에 접근할 수 있는 정책이 연결되어 있다면 OK입니다.
$ aws iam list-attached-role-policies \
--role-name test-iam \
--output table
---------------------------------------------------------------------------------------------------------------------------
| ListAttachedRolePolicies |
+-------------------------------------------------------------------------------------------------------------------------+
|| AttachedPolicies ||
|+-----------------------------------------------------------------------------+-----------------------------------------+|
|| PolicyArn | PolicyName ||
|+-----------------------------------------------------------------------------+-----------------------------------------+|
|| arn:aws:iam::aws:policy/AmazonBedrockFullAccess | AmazonBedrockFullAccess ||
|+-----------------------------------------------------------------------------+-----------------------------------------+|
이어서 Bedrock에 접근이 가능한지 직접 명령어로 확인해 봅시다.
$ aws bedrock list-foundation-models \
--region ap-northeast-1 \
--output table | head -20
-----------------------------------------------------------------------------------------------------------------------------------
| ListFoundationModels |
+---------------------------------------------------------------------------------------------------------------------------------+
|| modelSummaries ||
|+------------------------------------+------------------------------------------------------------------------------------------+|
|| modelArn | arn:aws:bedrock:ap-northeast-1::foundation-model/google.gemma-3-4b-it ||
|| modelId | google.gemma-3-4b-it ||
|| modelName | Gemma 3 4B IT ||
|| providerName | Google ||
|| responseStreamingSupported | True ||
|+------------------------------------+------------------------------------------------------------------------------------------+|
||| inferenceTypesSupported |||
||+-----------------------------------------------------------------------------------------------------------------------------+||
||| ON_DEMAND |||
||+-----------------------------------------------------------------------------------------------------------------------------+||
||| inputModalities |||
||+-----------------------------------------------------------------------------------------------------------------------------+||
||| TEXT |||
||| IMAGE |||
||+-----------------------------------------------------------------------------------------------------------------------------+||
다음은 Python 설치 여부를 확인합니다.
$ python3 --version
Python 3.12.3
pip 설치도 확인합시다.
$ pip3 --version
pip 26.0.1 from /usr/local/lib/python3.12/dist-packages/pip (python 3.12)
마지막으로 boto3 설치 여부를 확인합니다.
$ python3 -c "import boto3; print('boto3 버전:', boto3.__version__)"
boto3 버전: 1.42.63
Bedrock 호출 테스트
테스트 Python 파일을 하나 생성하고 Bedrock 호출을 테스트해 봅시다.
$ vi bedrock_test.py
Bedrock 호출 중...
=== 응답 결과 ===
안녕하세요! 저는 Claude입니다. 열심히 도와드리도록 하겠습니다.
================
여기서 출력 결과를 보면 두 가지로 구분됩니다.
| 구분 | 내용 |
|---|---|
| Input (우리가 보낸 질문) | 안녕하세요! 당신은 누구인가요? |
| Output (Claude의 응답) | 안녕하세요! 저는 Claude입니다. 열심히 도와드리도록 하겠습니다. |
Claude의 응답은 매번 동일하지 않습니다. 같은 질문을 보내도 실행할 때마다 조금씩 다른 문장으로 응답할 수 있습니다.
전체 코드는 다음 내용을 참고해 주세요.
import boto3
import json
client = boto3.client(
service_name='bedrock-runtime',
region_name='ap-northeast-1'
)
# apac. prefix 사용
model_id = "apac.anthropic.claude-3-5-sonnet-20241022-v2:0"
body = json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "안녕하세요! 당신은 누구인가요?"
}
]
})
print("Bedrock 호출 중...")
response = client.invoke_model(
modelId=model_id,
body=body
)
response_body = json.loads(response['body'].read())
result_text = response_body['content'][0]['text']
print("\n=== 응답 결과 ===")
print(result_text)
print("================")
print("\nBedrock 호출 성공!")
에러 발생 시 대처
먼저 ap-northeast-1 혹은 대상 리전에서 사용 가능한 모델 직접 확인할 필요가 있습니다.
아래 코드를 터미널에 그대로 복사 붙여넣기로 실행합니다.
$ python3 -c "
import boto3
client = boto3.client('bedrock', region_name='ap-northeast-1')
response = client.list_foundation_models()
for model in response['modelSummaries']:
print(model['modelId'])
"
실행하면 아래와 같이 리전에서 사용 가능한 모델 목록이 출력됩니다.
google.gemma-3-4b-it
nvidia.nemotron-nano-12b-v2
anthropic.claude-sonnet-4-20250514-v1:0
anthropic.claude-haiku-4-5-20251001-v1:0
qwen.qwen3-235b-a22b-2507-v1:0
openai.gpt-oss-safeguard-120b
google.gemma-3-27b-it
moonshotai.kimi-k2.5
openai.gpt-oss-120b-1:0
anthropic.claude-sonnet-4-5-20250929-v1:0
qwen.qwen3-vl-235b-a22b
qwen.qwen3-next-80b-a3b
deepseek.v3.2
zai.glm-4.7
nvidia.nemotron-nano-3-30b
anthropic.claude-sonnet-4-6
minimax.minimax-m2
zai.glm-4.7-flash
mistral.voxtral-mini-3b-2507
qwen.qwen3-coder-480b-a35b-v1:0
amazon.nova-2-lite-v1:0
google.gemma-3-12b-it
mistral.magistral-small-2509
moonshot.kimi-k2-thinking
mistral.mistral-large-3-675b-instruct
twelvelabs.pegasus-1-2-v1:0
amazon.nova-2-sonic-v1:0
mistral.devstral-2-123b
minimax.minimax-m2.1
cohere.embed-v4:0
deepseek.v3-v1:0
mistral.ministral-3-3b-instruct
anthropic.claude-opus-4-5-20251101-v1:0
qwen.qwen3-coder-30b-a3b-v1:0
qwen.qwen3-32b-v1:0
mistral.ministral-3-14b-instruct
anthropic.claude-opus-4-6-v1
nvidia.nemotron-nano-9b-v2
mistral.ministral-3-8b-instruct
mistral.voxtral-small-24b-2507
openai.gpt-oss-safeguard-20b
openai.gpt-oss-20b-1:0
amazon.titan-embed-text-v1:2:8k
amazon.titan-embed-text-v1
amazon.titan-embed-text-v2:0
amazon.rerank-v1:0
amazon.nova-pro-v1:0
amazon.nova-lite-v1:0
amazon.nova-micro-v1:0
amazon.nova-canvas-v1:0
amazon.nova-reel-v1:0
amazon.nova-sonic-v1:0
anthropic.claude-3-haiku-20240307-v1:0
anthropic.claude-3-5-sonnet-20240620-v1:0
anthropic.claude-3-sonnet-20240229-v1:0:28k
anthropic.claude-3-sonnet-20240229-v1:0:200k
anthropic.claude-3-sonnet-20240229-v1:0
anthropic.claude-3-5-sonnet-20241022-v2:0
anthropic.claude-3-7-sonnet-20250219-v1:0
cohere.embed-english-v3
cohere.embed-multilingual-v3
cohere.rerank-v3-5:0
위에서 확인한 모델 ID를 그대로 사용하면 아래와 같은 에러가 발생할 수 있습니다. 원인으로는 list_foundation_models() 로 조회한 모델 ID는 단순히 리전에서 제공하는 모델 목록일 뿐, 직접 호출이 불가능한 경우가 있습니다.
이 경우 Inference Profile ID 를 사용해야 합니다.
Inference Profile 이란 AWS에서 관리하는 모델 호출 프로파일로, 실제 invoke_model() 호출 시 사용해야 하는 ID입니다.
Bedrock 호출 중...
Traceback (most recent call last):
File "/var/snap/amazon-ssm-agent/12322/bedrock_test.py", line 24, in
response = client.invoke_model(
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/botocore/client.py", line 602, in _api_call
return self.make_api_call(operation_name, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/botocore/context.py", line 123, in wrapper
return func(args, kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/botocore/client.py", line 1078, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.errorfactory.ValidationException: An error occurred (ValidationException) when calling the InvokeModel operation: Invocation of model ID anthropic.claude-3-5-sonnet-20241022-v2:0 with on-demand throughput isn’t supported. Retry your request with the ID or ARN of an inference profile that contains this model.
아래 코드로 실제 호출 가능한 Inference Profile ID를 조회합니다.
$ python3 -c "
import boto3
client = boto3.client('bedrock', region_name='ap-northeast-1')
response = client.list_inference_profiles()
for profile in response['inferenceProfileSummaries']:
print(profile['inferenceProfileId'], '|', profile['inferenceProfileName'])
"
실행하면 아래와 같이 출력됩니다.
apac.anthropic.claude-3-sonnet-20240229-v1:0 | APAC Anthropic Claude 3 Sonnet
apac.anthropic.claude-3-5-sonnet-20240620-v1:0 | APAC Anthropic Claude 3.5 Sonnet
apac.anthropic.claude-3-haiku-20240307-v1:0 | APAC Anthropic Claude 3 Haiku
apac.anthropic.claude-3-5-sonnet-20241022-v2:0 | APAC Anthropic Claude 3.5 Sonnet v2
apac.anthropic.claude-3-7-sonnet-20250219-v1:0 | APAC Anthropic Claude 3.7 Sonnet
apac.amazon.nova-micro-v1:0 | APAC Nova Micro
apac.amazon.nova-lite-v1:0 | APAC Nova Lite
apac.amazon.nova-pro-v1:0 | APAC Nova Pro
global.anthropic.claude-sonnet-4-20250514-v1:0 | Global Claude Sonnet 4
jp.anthropic.claude-sonnet-4-5-20250929-v1:0 | JP Anthropic Claude Sonnet 4.5
global.cohere.embed-v4:0 | Global Cohere Embed v4
apac.anthropic.claude-sonnet-4-20250514-v1:0 | APAC Claude Sonnet 4
jp.anthropic.claude-haiku-4-5-20251001-v1:0 | JP Anthropic Claude Haiku 4.5
global.twelvelabs.pegasus-1-2-v1:0 | GLOBAL TwelveLabs Pegasus v1.2
global.anthropic.claude-haiku-4-5-20251001-v1:0 | Global Anthropic Claude Haiku 4.5
global.amazon.nova-2-lite-v1:0 | GLOBAL Amazon Nova 2 Lite
jp.amazon.nova-2-lite-v1:0 | JP Amazon Nova 2 Lite
global.anthropic.claude-opus-4-5-20251101-v1:0 | GLOBAL Anthropic Claude Opus 4.5
jp.anthropic.claude-sonnet-4-6 | JP Anthropic Claude Sonnet 4.6
global.anthropic.claude-sonnet-4-6 | Global Anthropic Claude Sonnet 4.6
global.anthropic.claude-sonnet-4-5-20250929-v1:0 | Global Claude Sonnet 4.5
global.anthropic.claude-opus-4-6-v1 | Global Anthropic Claude Opus 4.6
리전별 Prefix는 다음과 같습니다.
ap-northeast-1 (도쿄) 리전은 ap. 가 아닌 apac. 을 사용합니다.
처음에 ap. 로 시도하면 동일하게 에러가 발생하니 주의하세요.
| 리전 | Prefix |
|---|---|
| 미국 (us-east-1, us-west-2) | us. |
| 유럽 (eu-west-1 등) | eu. |
| 아시아 (ap-northeast-1 등) | apac. |
조회한 Inference Profile ID로 model_id를 수정합니다.
import boto3
import json
client = boto3.client(
service_name='bedrock-runtime',
region_name='ap-northeast-1'
)
# list_foundation_models() 에서 확인한 ID (직접 호출 불가)
# model_id = "anthropic.claude-3-5-sonnet-20241022-v2:0"
# list_inference_profiles() 에서 확인한 ID (호출 가능)
model_id = "apac.anthropic.claude-3-5-sonnet-20241022-v2:0"
body = json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "안녕하세요! 당신은 누구인가요?"
}
]
})
print("Bedrock 호출 중...")
response = client.invoke_model(
modelId=model_id,
body=body
)
response_body = json.loads(response['body'].read())
print(response_body['content'][0]['text'])
정상적으로 실행되면 아래와 같이 응답이 출력됩니다.
$ vi bedrock_test.py
Bedrock 호출 중...
=== 응답 결과 ===
안녕하세요! 저는 Claude입니다. 열심히 도와드리도록 하겠습니다.
================
마무리
이번 글에서는 EC2에서 Amazon Bedrock 모델을 호출하는 방법과 흔히 겪는 에러 대처법을 정리했습니다.
처음에는 단순히 모델 ID만 넣으면 될 것 같지만, 실제로는 아래 두 단계를 거쳐야 합니다.
| 함수 | 용도 |
|---|---|
| list_foundation_models() | 리전에서 제공하는 모델 존재 여부 확인 |
| list_inference_profiles() | 실제 invoke_model() 호출 시 사용할 ID 확인 |
특히 ap-northeast-1 (도쿄) 리전의 경우 ap. 가 아닌 apac. prefix를 사용한다는 점이 헷갈릴 수 있으니 주의하세요.
Bedrock을 처음 사용할 때 이 부분에서 많이 막히는데, 에러 메시지에 나와있는 대로 Inference Profile ID 를 사용하면 간단히 해결됩니다.







