같은 모델, 두 개의 문 : Bedrock Mantle 엔드포인트와 bedrock-runtime을 도쿄 리전에서 실측 비교

같은 모델, 두 개의 문 : Bedrock Mantle 엔드포인트와 bedrock-runtime을 도쿄 리전에서 실측 비교

Amazon Bedrock에는 추론 요청을 받는 엔드포인트가 두 개 있습니다. 예전부터 쓰던 bedrock-runtime.{region}.amazonaws.com과, OpenAI 호환 API와 Anthropic Messages API를 제공하는 bedrock-mantle.{region}.api.aws입니다. AWS 공식 문서는 두 엔드포인트가 같은 Mantle 추론 엔진 위에서 동작하며 bedrock-mantle이라는 이름은 엔진이 아니라 엔드포인트 표면을 가리킨다고 설명합니다. 그렇다면 “같은 모델을 같은 리전에서 호출할 때 응답 속도도 같은가”라는 질문이 자연스럽게 생깁니다. 이 글은 그 질문을 문서가 아니라 실측으로 확인합니다.

만들 것은 도쿄 리전(ap-northeast-1)에서 같은 모델을 두 엔드포인트로 번갈아 호출해 지연 시간을 비교하는 벤치마크입니다. Bedrock API 키, 두 엔드포인트의 URL과 모델 ID 표기 차이, IAM 액션 네임스페이스 차이, 쿼터 구조 차이를 거치게 됩니다. 어떤 기능을 어디에 사용했는지는 글 마지막에 표로 정리해두었습니다.

만들 것은 도쿄 리전(ap-northeast-1)에서 같은 모델을 두 엔드포인트로 번갈아 호출해 지연 시간을 비교하는 벤치마크입니다. Bedrock API 키, 두 엔드포인트의 URL과 모델 ID 표기 차이, IAM 액션 네임스페이스 차이, 쿼터 구조 차이를 거치게 됩니다. 어떤 기능을 어디에 사용했는지는 글 마지막에 표로 정리해두었습니다.

실습 환경

항목내용
배포 대상AWS ap-northeast-1 (도쿄), IAM 리소스만 생성
런타임 요건Terraform 1.15.8, AWS Provider 6.62.0, openai 3.6.0, anthropic 1.2.0, boto3 1.42
비교 모델gpt-oss-120b (Chat Completions API), Claude Haiku 4.5 (Anthropic Messages API)
측정 시각2026-09-01 (KST 오후)

목표 아키텍처

이 실험의 핵심은 “조건을 최대한 같게 맞추는 것”입니다. 같은 리전, 같은 모델, 같은 프롬프트, 같은 API 키, 같은 클라이언트 PC에서 엔드포인트 호스트 이름만 바꿔 호출해야 두 엔드포인트의 차이만 남습니다. 그래서 별도 서버를 두지 않고 개발자 PC에서 직접 호출하는 구성을 택했습니다.

배포 모델은 단순합니다. AWS 쪽에 만드는 리소스는 IAM 사용자 하나, 그 사용자에게 붙는 인라인 정책 하나, 그리고 그 사용자에게 발급되는 Bedrock 장기 API 키 하나뿐입니다. Bedrock 장기 API 키는 실체가 IAM 서비스 전용 자격 증명(service-specific credential)이므로 Terraform의 aws_iam_service_specific_credential 리소스로 만들 수 있습니다. 벤치마크 스크립트는 이 키 하나로 두 엔드포인트를 모두 호출합니다. 두 엔드포인트 모두 Bedrock API 키 인증을 지원하기 때문입니다.

호출 대상은 도쿄 리전의 두 엔드포인트입니다. bedrock-runtime은 OpenAI 호환 API를 /openai/v1 경로에, Anthropic Messages API를 /anthropic 경로에 제공합니다. bedrock-mantle은 OpenAI 호환 API를 /v1 경로에, Messages API를 /anthropic/v1/messages에 제공합니다. 두 엔드포인트 뒤에는 같은 Mantle 추론 엔진이 있고, 지표는 각각 AWS/BedrockAWS/BedrockMantle 네임스페이스로 CloudWatch에 발행됩니다.

한 가지 비대칭이 있습니다. gpt-oss-120b는 두 엔드포인트 모두 도쿄 in-region으로 제공되지만, Claude Haiku 4.5는 bedrock-runtime에 도쿄 in-region 모델 ID가 없고 Geographic Inference Profile(도쿄와 오사카 사이 라우팅)로만 호출할 수 있습니다. 반면 bedrock-mantle은 크로스리전 추론이 없고 요청한 리전에서 처리가 끝납니다. 따라서 Claude 비교는 “in-region 대 Geographic Inference Profile” 비교라는 점을 감안해서 읽어야 합니다.

다이어그램의 구성 요소는 다음과 같습니다.

구성 요소역할
AWS IAM사용자 bedrock-mantle-bench와 API 키 보관
bedrock-runtime 엔드포인트bedrock-runtime.ap-northeast-1.amazonaws.com
bedrock-mantle 엔드포인트bedrock-mantle.ap-northeast-1.api.aws
Mantle 추론 엔진두 엔드포인트가 공유하는 추론 엔진, Zero Operator Access 설계
gpt-oss-120b비교 모델 1
Claude Haiku 4.5비교 모델 2
ap-northeast-3 (오사카)jp. 지리적 추론 프로파일의 라우팅 후보 리전
Amazon CloudWatch두 엔드포인트의 호출 지표

표에서 눈여겨볼 점은 AWS 쪽에 생성되는 리소스가 IAM 세 개뿐이라는 것입니다. 엔드포인트, 엔진, 모델은 모두 AWS가 관리하는 서비스이므로 만들거나 지울 것이 없고, 비용은 호출한 토큰만큼만 발생합니다.

한 회차의 실행 시퀀스를 그려보면 다음과 같습니다.

시퀀스에서 중요한 것은 두 엔드포인트가 같은 엔진으로 들어간다는 점과, 회차마다 호출 순서를 바꿔 특정 엔드포인트가 항상 먼저 호출되는 편향을 줄인다는 점입니다.

Step 1. Terraform으로 실측용 IAM 사용자와 Bedrock API 키 만들기

이 단계에서는 두 엔드포인트를 모두 호출할 수 있는 최소 권한의 IAM 사용자와 Bedrock 장기 API 키를 Terraform으로 만듭니다. 실측이 끝나면 통째로 지울 수 있도록 리소스를 한 곳에 모으는 것이 목적입니다.

먼저 API 키가 왜 필요한지부터 짚겠습니다. OpenAI SDK는 AWS SigV4 서명을 모릅니다. 그래서 OpenAI SDK로 Bedrock을 호출하려면 Bearer 토큰 형태의 Bedrock API 키가 필요합니다. API 키는 두 종류입니다. 단기 키는 최대 12시간 유효하고 생성한 IAM 주체의 권한을 상속하며, 장기 키는 IAM 사용자에 붙는 서비스 전용 자격 증명으로 만료일을 정할 수 있습니다. 공식 문서는 장기 키를 탐색 용도로만 권장합니다. 이 실험은 몇 시간 안에 끝나고 끝나는 즉시 지우므로 장기 키를 만료 1일로 만들었습니다.

Bedrock API 키를 만드는 경로는 세 가지입니다.

발급 경로적합한 상황명령 또는 방법
콘솔한 번 써보고 버릴 때Bedrock 콘솔 > API keys > Long-term API keys > Generate
AWS CLI스크립트에서 즉석 발급aws iam create-service-specific-credential --user-name <user> --service-name bedrock.amazonaws.com --credential-age-days <days>
Terraform (이번 사례)사용자, 정책, 키를 한 단위로 만들고 지울 때aws_iam_service_specific_credential 리소스, credential_age_days 인자

Terraform 구성은 다음과 같습니다. 정책에는 bedrock-runtime용 액션과 bedrock-mantle용 액션을 별도 Statement로 나눠 넣었습니다. 두 엔드포인트의 IAM 액션 네임스페이스가 다르기 때문입니다.

terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 6.0"
}
}
}

provider "aws" {
region = var.region # 기본값 ap-northeast-1
}

resource "aws_iam_user" "bench" {
name = "bedrock-mantle-bench"
path = "/bench/"
}

# runtime과 mantle은 IAM 액션 네임스페이스가 다르다
resource "aws_iam_user_policy" "bench" {
name = "bedrock-both-endpoints-inference"
user = aws_iam_user.bench.name
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "RuntimeEndpoint"
Effect = "Allow"
Action = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream",
"bedrock:CallWithBearerToken",
"bedrock:ListFoundationModels",
"bedrock:ListInferenceProfiles",
"bedrock:GetInferenceProfile"
]
Resource = "*"
},
{
Sid = "MantleEndpoint"
Effect = "Allow"
Action = [
"bedrock-mantle:CreateInference",
"bedrock-mantle:ListModels",
"bedrock-mantle:CallWithBearerToken"
]
Resource = "*"
}
]
})
}

# Bedrock 장기 API 키 = IAM 서비스 전용 자격 증명
resource "aws_iam_service_specific_credential" "bedrock_api_key" {
service_name = "bedrock.amazonaws.com"
user_name = aws_iam_user.bench.name
credential_age_days = 1
depends_on = [aws_iam_user_policy.bench]
}

output "bedrock_api_key" {
value = aws_iam_service_specific_credential.bedrock_api_key.service_credential_secret
sensitive = true
}

적용은 평소와 같습니다.

terraform init
terraform apply -auto-approve
# 벤치마크 스크립트에 키 전달 (PowerShell 예시)
$env:BEDROCK_API_KEY = (terraform output -raw bedrock_api_key)

실제 적용 결과 IAM 사용자, 인라인 정책, API 키 세 리소스가 만들어졌고 출력에는 키 ID와 만료 시각(생성 시각 + 1일)이 표시되었습니다. 키 본문은 sensitive 출력이라 화면에 나오지 않고 terraform output -raw로만 읽습니다.

여기서 막히기 쉬운 지점을 정리하면 다음과 같습니다.

증상원인조치
credential_age_days 인자를 모른다는 오류AWS Provider가 오래됨최신 6.x로 올림 (이번 실습은 6.62.0). 이 인자는 Bedrock 키에만 유효
mantle 호출 시 403 bedrock-mantle:ListModels ... not authorizedbedrock:* 액션은 mantle 호출을 인가하지 않음정책에 bedrock-mantle:CreateInference, bedrock-mantle:ListModels 추가
Bearer 키로 호출 시 거부CallWithBearerToken 액션이 Deny 되어 있음bedrock:CallWithBearerTokenbedrock-mantle:CallWithBearerToken 둘 다 확인
키를 잃어버림service_credential_secret은 생성 시점에만 조회 가능terraform state에 남아 있으므로 output -raw로 재조회, 아니면 리소스 재생성

이 단계가 끝나면 키 하나로 도쿄 리전의 두 엔드포인트를 모두 호출할 수 있습니다.

Step 2. 두 엔드포인트 연결 확인 — URL, 모델 ID, 권한이 어떻게 다른가

이 단계에서는 본격적인 측정에 앞서 각 엔드포인트에 한 번씩 호출해 URL, 모델 ID, 응답 형식이 어떻게 다른지 확인합니다. 벤치마크 결과를 해석하려면 이 차이를 먼저 알아야 합니다.

같은 모델이라도 두 엔드포인트에서 부르는 이름이 다릅니다. bedrock-runtime은 Bedrock 고유의 모델 ID(버전 접미사 포함) 또는 크로스리전 추론 프로파일 ID를 쓰고, bedrock-mantle은 접두사 없는 파운데이션 모델 ID를 씁니다. 다음 표는 이번 실험에서 실제로 동작한 조합입니다.

항목bedrock-runtimebedrock-mantle
OpenAI 호환 base URLhttps://bedrock-runtime.ap-northeast-1.amazonaws.com/openai/v1https://bedrock-mantle.ap-northeast-1.api.aws/v1
Anthropic SDK base URLhttps://bedrock-runtime.ap-northeast-1.amazonaws.com/anthropichttps://bedrock-mantle.ap-northeast-1.api.aws/anthropic
gpt-oss-120b 모델 IDopenai.gpt-oss-120b-1:0 (openai.gpt-oss-120b는 400 오류)openai.gpt-oss-120b
Claude Haiku 4.5 모델 IDjp.anthropic.claude-haiku-4-5-20251001-v1:0 (지리 프로파일)anthropic.claude-haiku-4-5
인증Bedrock API 키 또는 SigV4Bedrock API 키 또는 SigV4
인가 액션bedrock:InvokeModel, bedrock:InvokeModelWithResponseStreambedrock-mantle:CreateInference
GET /models 응답 (도쿄)UnknownOperationException정상 (bedrock-mantle:ListModels 필요)
크로스리전 추론지리, 글로벌 프로파일 지원미지원, 요청 리전에서 처리

연결 확인 스크립트의 핵심은 다음과 같습니다. 두 SDK 모두 base URL과 API 키만 바꾸면 그대로 동작합니다.

import os
from openai import OpenAI
from anthropic import Anthropic

REGION = "ap-northeast-1"
KEY = os.environ["BEDROCK_API_KEY"]

# OpenAI 호환 Chat Completions
runtime = OpenAI(base_url=f"<https://bedrock-runtime>.{REGION}.amazonaws.com/openai/v1", api_key=KEY)
mantle = OpenAI(base_url=f"<https://bedrock-mantle>.{REGION}.api.aws/v1", api_key=KEY)

for name, client, model in [("runtime", runtime, "openai.gpt-oss-120b-1:0"),
("mantle", mantle, "openai.gpt-oss-120b")]:
r = client.chat.completions.create(
model=model, max_tokens=64,
messages=[{"role": "user", "content": "Reply with exactly: pong"}],
extra_body={"reasoning_effort": "low"},
)
print(name, repr(r.choices[0].message.content), r.usage)

# Anthropic Messages API
runtime_a = Anthropic(base_url=f"<https://bedrock-runtime>.{REGION}.amazonaws.com/anthropic", api_key=KEY)
mantle_a = Anthropic(base_url=f"<https://bedrock-mantle>.{REGION}.api.aws/anthropic", api_key=KEY)

for name, client, model in [("runtime", runtime_a, "jp.anthropic.claude-haiku-4-5-20251001-v1:0"),
("mantle", mantle_a, "anthropic.claude-haiku-4-5")]:
r = client.messages.create(model=model, max_tokens=32,
messages=[{"role": "user", "content": "Reply with exactly: pong"}])
print(name, repr(r.content[0].text), r.usage)

실행하면 네 호출이 모두 성공하는데, gpt-oss-120b의 응답 본문이 엔드포인트에 따라 다르게 옵니다. bedrock-runtime<reasoning>We need to output exactly "pong".</reasoning>pong처럼 추론 과정을 content 안에 태그로 포함해 돌려주고, bedrock-mantlepong만 돌려줍니다. 두 응답의 completion_tokens는 19로 같았습니다. 즉 모델이 생성한 토큰은 같고, 그것을 클라이언트에 어떻게 노출하느냐가 엔드포인트마다 다릅니다. 이 차이는 뒤의 지연 시간 해석에도 영향을 줍니다.

Anthropic SDK를 mantle에 붙일 때 한 가지 주의할 점이 있습니다. base URL을 https://bedrock-mantle.{region}.api.aws까지만 주면 SDK가 /v1/messages를 붙여 404가 납니다. mantle의 Messages API 경로는 /anthropic/v1/messages이므로 base URL에 /anthropic까지 포함해야 합니다.

요청이 어느 경로로 인가되고 처리되는지 흐름으로 정리하면 다음과 같습니다.

흐름에서 주목할 점은 인가와 쿼터가 호스트 이름 단계에서 갈라지고, 엔진에서 다시 합쳐진다는 것입니다. 이 단계가 끝나면 두 엔드포인트의 응답 형식과 권한 차이를 알고 벤치마크를 돌릴 수 있습니다.

Step 3. 벤치마크 스크립트 작성 — 무엇을 어떻게 재는가

이 단계에서는 측정 방법을 정합니다. 지연 시간 비교는 측정 방법이 조금만 달라도 결론이 뒤집히므로, 무엇을 재고 무엇을 통제했는지를 먼저 밝힙니다.

측정 지표는 네 가지입니다.

지표정의측정 모드
E2E 지연요청 전송부터 응답 객체 수신 완료까지 (ms)비스트리밍, 스트리밍
TTFT요청 전송부터 첫 텍스트 델타 수신까지 (ms).
추론 토큰이 아니라 사용자에게 보이는 첫 글자 기준
스트리밍
출력 토큰 속도출력 토큰 수 / (E2E – TTFT), 토큰/초스트리밍
토큰 수응답 usage의 입력, 출력 토큰비스트리밍, 스트리밍
(OpenAI는 stream_options.include_usage, Anthropic은 message_delta 이벤트)

통제한 조건은 다음과 같습니다.

조건설정이유
리전ap-northeast-1 고정두 엔드포인트 모두 도쿄 in-region 제공 리전
모델gpt-oss-120b, Claude Haiku 4.5두 엔드포인트에서 모두 제공되고 도쿄에서 호출 가능
프롬프트short(질문 한 문장), medium(로그 180줄), long(로그 1,400줄)프리필 비중이 다른 세 구간.
입력 토큰은 토크나이저에 따라 gpt-oss 98 / 8,045 / 61,715, Claude 37 / 9,112 / 70,398
max_tokens200출력 길이 편차를 제한
gpt-oss reasoning_effortlow추론 토큰이 출력 한도를 다 쓰는 것을 방지
반복프롬프트별, 모드별 5회, 회차마다 호출 순서 교차순서 편향 완화
재시도max_retries=0, 실패 시 스크립트에서 최대 3회SDK 자동 재시도로 지연이 가려지지 않게
워밍업엔드포인트당 1회, 결과 제외DNS와 TLS 핸드셰이크 비용 제거

medium과 long 프롬프트는 결정적으로 생성한 합성 운영 로그입니다. 로그 한 줄에 서비스 이름, 상태, p99 지연, CPU 사용률을 넣고, 그중 한 줄에만 INCIDENT-7731 root-cause=expired-tls-certificate를 심어 “몇 번 항목에 INCIDENT-7731이 있고 원인은 무엇인가”를 묻습니다. 모델이 프롬프트 전체를 실제로 읽어야 답할 수 있게 하기 위해서입니다.

def make_log(n_entries: int) -> str:
lines = []
for i in range(1, n_entries + 1):
svc = SERVICES[i % len(SERVICES)]
st = STATUSES[(i * 7) % len(STATUSES)]
lat = 40 + (i * 37) % 900
cpu = 5 + (i * 13) % 90
lines.append(f"[entry {i:05d}] 2026-08-{(i % 28) + 1:02d}T{(i % 24):02d}:{(i * 3) % 60:02d}Z "
f"service={svc} status={st} p99_latency_ms={lat} cpu={cpu}% "
f"note=routine check by operator {chr(65 + i % 26)}{chr(65 + (i * 3) % 26)}")
return "\n".join(lines)

# medium: 180줄에 97번 항목에 needle, long: 1400줄에 1123번 항목에 needle

스트리밍 측정부의 핵심은 다음과 같습니다. TTFT는 delta.content가 비어 있지 않은 첫 청크에서 찍습니다.

def stream(self, prompt):
t0 = time.perf_counter(); ttft = None; out_tok = None
s = self.c.chat.completions.create(
model=self.model, max_tokens=self.max_tokens, stream=True,
messages=[{"role": "system", "content": SYSTEM}, {"role": "user", "content": prompt}],
stream_options={"include_usage": True},
extra_body={"reasoning_effort": "low"},
)
for ch in s:
if getattr(ch, "usage", None):
out_tok = ch.usage.completion_tokens
if ch.choices and ch.choices[0].delta and ch.choices[0].delta.content:
if ttft is None:
ttft = time.perf_counter() - t0
dt = time.perf_counter() - t0
return dict(e2e_ms=dt * 1000, ttft_ms=(ttft or dt) * 1000, out_tok=out_tok)

호출 순서 교차는 다음 한 줄로 처리합니다. 짝수 회차는 runtime을 먼저, 홀수 회차는 mantle을 먼저 호출합니다.

order = ("runtime", "mantle") if i % 2 == 0 else ("mantle", "runtime")

실행 명령은 다음과 같습니다. 두 모델은 서로 간섭하지 않도록 순차로 돌렸습니다.

python bench.py --suite gptoss --runs 5 --out results_gptoss.json
python bench.py --suite haiku --runs 5 --out results_haiku.json

이 단계가 끝나면 엔드포인트별, 프롬프트별, 모드별 원시 데이터와 p50, 평균, 최소, 최대 요약이 JSON으로 남습니다.

Step 4. 실측 결과 — 같은 모델의 지연 비교

이 단계에서는 측정값을 읽습니다. 모든 수치는 2026-09-01 오후(KST)에 서울의 PC에서 도쿄 리전으로 호출한 값이며, 절대값보다 두 엔드포인트의 상대 차이에 주목하시기 바랍니다.

먼저 네트워크 바닥값입니다. 측정에 앞서 curl로 두 호스트의 DNS, TCP 연결, TLS 핸드셰이크 시간을 5회씩 쟀습니다.

호스트DNS (s)TCP 연결 (s)TLS 완료 (s)
bedrock-runtime.ap-northeast-1.amazonaws.com0.045 ~ 0.0570.057 ~ 0.0820.32 ~ 0.75
bedrock-mantle.ap-northeast-1.api.aws0.044 ~ 0.1410.084 ~ 0.1630.31 ~ 1.57

첫 연결의 TLS 비용이 수백 ms로 큰데, 이는 두 엔드포인트 모두 같으므로 벤치마크에서는 워밍업 호출로 제거하고 커넥션을 재사용합니다.

gpt-oss-120b (Chat Completions API, 두 엔드포인트 모두 도쿄 in-region)

측정 구간은 2026-09-01T07:53Z ~ 07:55Z, 모델 ID는 runtime openai.gpt-oss-120b-1:0, mantle openai.gpt-oss-120b, max_tokens=200, reasoning_effort=low, 프롬프트별 모드별 5회입니다. 60회 호출 중 오류와 스로틀은 없었고, medium과 long의 needle 질문은 두 엔드포인트 모두 20회 중 20회 정답이었습니다.

비스트리밍 E2E 지연 (ms, 5회)

프롬프트입력 토큰runtime p50runtime 평균runtime 최소~최대mantle p50mantle 평균mantle 최소~최대p50 차이 (mantle – runtime)
short98591591471 ~ 668641644604 ~ 707+49 (+8%)
medium8,0451,0731,259650 ~ 2,471851807674 ~ 961-222 (-21%)
long61,7153,9053,8583,564 ~ 3,9692,5042,7371,678 ~ 3,968-1,400 (-36%)

스트리밍 TTFT와 E2E (ms, 5회)

프롬프트runtime TTFT p50runtime E2E p50runtime E2E 최소~최대mantle TTFT p50mantle E2E p50mantle E2E 최소~최대TTFT p50 차이 (mantle – runtime)
short9921,049765 ~ 4,309566654539 ~ 880-426 (-43%)
medium905938836 ~ 1,020782783568 ~ 869-122 (-14%)
long2,8052,8661,116 ~ 4,5473,5383,5392,646 ~ 4,103+733 (+26%)

출력 토큰 수와 스트리밍 청크 수 (p50)

프롬프트runtime 출력 토큰mantle 출력 토큰runtime 청크 수mantle 청크 수
short464322
medium424031
long725341

세 표에서 읽을 수 있는 것은 다음과 같습니다.

  • 비스트리밍 p50은 short에서 mantle이 49ms 느리고, medium과 long에서는 mantle이 각각 222ms, 1,400ms 빠릅니다. 그런데 스트리밍에서는 long의 방향이 뒤집혀 runtime이 733ms 빠릅니다. 같은 프롬프트에서 모드에 따라 승자가 바뀐다는 것은, 두 엔드포인트의 차이가 회차 간 편차보다 작다는 뜻입니다. runtime long 스트리밍의 최소값 1,116ms와 최대값 4,547ms, mantle long 비스트리밍의 1,678ms와 3,968ms가 그 편차의 크기입니다.
  • 가장 반복적으로 관측된 차이는 short 프롬프트의 TTFT입니다. mantle 566ms, runtime 992ms로 mantle이 400ms 남짓 빨랐습니다. 다만 runtime short 스트리밍에는 4,309ms짜리 이상치가 하나 있어 평균이 크게 흔들렸습니다.
  • 청크 수가 1~4개입니다. gpt-oss-120b는 reasoning_effort=low에서도 추론을 먼저 끝낸 뒤 40~70 토큰짜리 답을 한두 청크로 한 번에 보내므로, TTFT가 E2E와 거의 같습니다. mantle은 추론 텍스트를 걷어내고 최종 답만 보내기 때문에 청크가 1개인 경우가 대부분입니다. 이 모델에서는 스트리밍을 켜도 사용자가 글자가 흘러나오는 것을 볼 수 없다는 뜻이고, 이는 두 엔드포인트가 같습니다.
  • long에서 같은 프롬프트를 반복하는 동안 양쪽 모두 간헐적으로 1.1~1.7초대의 빠른 응답이 섞여 나왔습니다. 응답 usage에 캐시 관련 필드가 없어 원인을 단정할 수 없으므로, 긴 프롬프트의 절대값은 참고로만 보시기 바랍니다.

Claude Haiku 4.5 (Anthropic Messages API, runtime은 jp. 지리적 추론 프로파일)

측정 구간은 2026-09-01T07:58Z ~ 08:00Z, 모델 ID는 runtime jp.anthropic.claude-haiku-4-5-20251001-v1:0(도쿄와 오사카 사이 지리적 추론 프로파일), mantle anthropic.claude-haiku-4-5(도쿄 in-region), max_tokens=200, 프롬프트별 모드별 5회입니다. Claude 토크나이저 기준 입력 토큰은 short 37, medium 9,112, long 70,398입니다. 60회 호출 중 오류와 스로틀은 없었고, needle 질문은 두 엔드포인트 모두 20회 중 20회 정답이었습니다.

비스트리밍 E2E 지연 (ms, 5회)

프롬프트입력 토큰runtime p50runtime 평균runtime 최소~최대mantle p50mantle 평균mantle 최소~최대p50 차이 (mantle – runtime)
short37908926778 ~ 1,119772812763 ~ 914-135 (-15%)
medium9,1121,0681,081943 ~ 1,2121,023989782 ~ 1,098-46 (-4%)
long70,3982,2262,2562,109 ~ 2,5092,2892,5382,008 ~ 3,439+63 (+3%)

스트리밍 TTFT와 E2E (ms, 5회)

프롬프트runtime TTFT p50runtime E2E p50runtime E2E 최소~최대mantle TTFT p50mantle E2E p50mantle E2E 최소~최대TTFT p50 차이 (mantle – runtime)
short881938922 ~ 1,546565817648 ~ 828-315 (-36%)
medium8291,159932 ~ 1,4168241,140960 ~ 1,176-6 (-1%)
long1,9582,0581,915 ~ 2,8111,8462,1152,052 ~ 2,349-113 (-6%)

출력 토큰 수, 스트리밍 청크 수, 출력 토큰 속도 (p50)

프롬프트runtime 출력 토큰mantle 출력 토큰runtime 청크 수mantle 청크 수runtime 토큰/초mantle 토큰/초
short30301011151128
medium26261112110119
long25261112113115

결과에서 읽을 수 있는 것은 다음과 같습니다.

  • medium 이상에서는 두 엔드포인트가 사실상 같은 곡선입니다. 비스트리밍 p50 차이가 -46ms와 +63ms, 스트리밍 TTFT 차이가 -6ms와 -113ms로, 모두 회차 간 편차(수백 ms) 안에 있습니다.
  • short에서는 gpt-oss와 같은 경향이 다시 나타났습니다. 스트리밍 TTFT가 mantle 565ms, runtime 881ms로 mantle이 300ms 남짓 빨랐고, 비스트리밍도 135ms 빨랐습니다. 두 모델에서 같은 방향으로 반복된 유일한 차이입니다. 다만 표본이 5회이므로 “짧은 요청은 mantle이 빠르다”고 단정하기보다 “짧은 요청에서 mantle이 느리지는 않다” 정도로 읽는 것이 안전합니다.
  • gpt-oss와 달리 청크가 9~16개로 나뉘어 왔고 출력 토큰 속도는 양쪽 모두 110~150 토큰/초로 같은 수준입니다. Claude에서는 스트리밍이 실제로 점진적으로 표시됩니다.
  • runtime 쪽은 jp. 지리적 추론 프로파일이라 요청이 오사카로 갈 수도 있는 조건이었는데도, 도쿄 in-region인 mantle과의 차이가 100ms 안팎이었습니다. 지리 프로파일의 라우팅 비용이 이 실험에서는 눈에 띄지 않았습니다.

응답 형식 차이

지연 수치와 별개로 응답 형식이 달랐던 점을 정리합니다.

항목bedrock-runtimebedrock-mantle
gpt-oss 추론 과정 노출content 안에 <reasoning>...</reasoning> 태그로 포함content에 최종 답만 포함
gpt-oss 출력 토큰 수 (completion_tokens)추론 토큰 포함추론 토큰 포함 (같은 값)
gpt-oss 정답률 (needle 찾기)medium, long 모두 정답medium, long 모두 정답
요청 IDx-request-id 헤더x-request-id 헤더

runtime의 <reasoning> 태그는 애플리케이션에서 파싱해 걷어내야 하므로, 사용자에게 보이는 첫 글자 기준 TTFT를 재려면 태그 이후의 텍스트를 기준으로 삼아야 합니다. 이번 측정의 TTFT는 태그를 포함한 첫 청크 기준이므로 runtime 쪽이 조금 유리하게 측정되었을 수 있습니다.

이 단계가 끝나면 “같은 엔진이라는 문서 설명이 실측에서도 성립하는가”에 대한 답을 갖게 됩니다.

Step 5. 긴 프롬프트 테스트 — 6만 토큰에서 무엇이 달라지나

이 단계에서는 long 프롬프트(gpt-oss 기준 61,715 토큰, Claude 기준 70,398 토큰) 결과를 따로 봅니다. 긴 프롬프트는 프리필(입력 토큰 처리) 시간이 지배적이라 엔진 차이가 있다면 가장 크게 드러나는 구간이고, 동시에 쿼터 구조의 차이가 실제로 작동하는 구간입니다.

두 모델의 long 결과만 모아 보면 다음과 같습니다. 입력 토큰은 같은 텍스트를 각 모델의 토크나이저로 센 값입니다.

모델입력 토큰모드runtime p50 (ms)mantle p50 (ms)차이 (mantle – runtime)needle 정답
gpt-oss-120b61,715비스트리밍 E2E3,9052,504-1,400 (-36%)10/10, 10/10
gpt-oss-120b61,715스트리밍 TTFT2,8053,538+733 (+26%)10/10, 10/10
Claude Haiku 4.570,398비스트리밍 E2E2,2262,289+63 (+3%)10/10, 10/10
Claude Haiku 4.570,398스트리밍 TTFT1,9581,846-113 (-6%)10/10, 10/10

표에서 주목할 점은 세 가지입니다. 첫째, 6만~7만 토큰을 넣어도 두 엔드포인트 모두 2~4초 안에 첫 글자가 나왔고 정답률은 40회 모두 100%였습니다. 둘째, gpt-oss에서 두 모드의 차이 방향이 서로 반대인데, 이는 엔드포인트 간 차이가 아니라 회차 편차로 읽어야 합니다. 셋째, Claude에서는 in-region(mantle)과 지리적 추론 프로파일(runtime)의 차이가 100ms 안에 들어왔습니다. 긴 프롬프트에서 “어느 엔드포인트가 구조적으로 빠르다”는 신호는 이번 실측에서 나오지 않았습니다.

쿼터 관점에서는, 엔드포인트당 long 프롬프트 10회(gpt-oss 기준 약 62만 입력 토큰, Claude 기준 약 70만 입력 토큰)를 1분 남짓에 보냈는데 429나 503이 한 번도 없었습니다.

긴 프롬프트에서 쿼터가 어떻게 차감되는지는 엔드포인트마다 다릅니다. bedrock-mantle은 요청 시작 시 입력 토큰에 max_tokens를 더한 값을 입력 TPM 쿼터에서 예약하고, 응답이 끝나면 미사용분을 돌려줍니다. bedrock-runtime은 입력과 출력을 합산한 모델별 TPM 쿼터를 씁니다.

이번 사례에서 활용한 Bedrock Mantle 기능 정리

벤치마크 하나를 만들면서 실제로 사용한 기능을 단계별로 정리하면 다음과 같습니다.

#기능이번 사례에서의 활용
1Bedrock 장기 API 키한 키로 두 엔드포인트를 모두 호출
2mantle 전용 IAM 액션mantle 호출 인가와 모델 목록 조회
3OpenAI 호환 Chat Completions APIgpt-oss-120b를 두 엔드포인트에서 같은 코드로 호출
4Anthropic Messages APIClaude Haiku 4.5를 두 엔드포인트에서 같은 코드로 호출
5Models APImantle에서 사용 가능한 모델 ID 확인
6스트리밍 응답TTFT와 출력 토큰 속도 측정
7mantle in-region 처리크로스리전 없이 도쿄에서 처리 완결되는 조건으로 비교
8엔드포인트별 분리 쿼터긴 프롬프트 60회 호출 중 스로틀 없음 확인

결론

이번 실측으로 확인한 것은 “같은 엔진”이라는 문서 설명이 도쿄 리전에서 실제 숫자로도 성립하는지였습니다. 두 모델, 세 프롬프트 크기, 두 호출 모드로 총 120회를 호출한 결과, 두 엔드포인트의 p50 차이는 대부분 회차 간 편차 안에 있었고 방향도 일관되지 않았습니다. 6만~7만 토큰의 긴 프롬프트에서도 두 엔드포인트는 같은 속도 구간에 있었고 정답률은 모두 100%였습니다. 가장 반복적으로 보인 차이는 짧은 프롬프트의 TTFT에서 mantle이 300~400ms 빨랐던 것인데, 5회 표본이라 경향 이상으로 단정하기는 어렵습니다. 지금 bedrock-runtime으로 잘 돌아가는 서비스라면 속도 때문에 mantle로 옮길 이유는 이 실측에서 나오지 않았습니다.

따라서 엔드포인트 선택은 속도가 아니라 필요한 기능으로 정하면 됩니다. Guardrails, 지능형 프롬프트 라우팅, 크로스리전 추론, Bedrock 네이티브 API가 필요하면 bedrock-runtime이고, 서버 측 도구, 백그라운드 추론, Projects나 Workspaces 단위의 비용 추적, 또는 mantle에만 올라온 모델이 필요하면 bedrock-mantle입니다. 도입 전에는 두 엔드포인트의 IAM 액션과 쿼터가 완전히 분리되어 있다는 점, 그리고 mantle에는 아직 CloudWatch 지연 지표가 없다는 점을 확인하시기 바랍니다.

글 | 메가존클라우드 Commercial Managed Unit 최영훈 매니저

게시물 주소가 복사되었습니다.

이런 콘텐츠도 있어요!

    테크

    2026년 기업이 재설계해야 할 3가지 AI 보안 패러다임

    공격 주체가 사람이 아닌 AI 에이전트로 진화하면서 기존 보안 체계가 무력화되고 있습니다. 2026년 기업이 반드시 대비해야 할 3가지 AI 보안 핵심 전략(기계 주체 권한 관리, 동적 가드레일 및 AI 레드팀, 데이터 무결성 보장 백업)과 실전 대응 로드맵을 정리했습니다.

    비즈니스

    MegazoneCloud와 Snowflake로 금융 데이터 전략을 고도화하세요.

    금융 산업의 AI 활용이 확대되면서 데이터 통합·보안·규정 준수를 함께 지원하는 데이터 플랫폼의 중요성이 커지고 있습니다.

    Snowflake 금융 서비스 AI 데이터 클라우드는 금융 데이터를 안전하게 통합하고 AI를 적용할 수 있는 환경을 제공합니다. Snowflake Elite 파트너 MegazoneCloud는 검증·설계부터 데이터 이관, AI 구현, 비용 최적화 및 운영까지 End-to-End로 지원합니다.