Claude Opus 5 리뷰: Anthropic의 신제품은 구매할 가치가 있을까?

Claude Opus 5 리뷰: Anthropic의 신제품은 구매할 가치가 있을까?

Claude Opus 5 리뷰: Anthropic의 신제품은 구매할 가치가 있을까?

2026년 7월 28일 사실 확인 완료.

간단한 평가: 이 Claude Opus 5 리뷰에서는 코딩 에이전트, 복잡한 비즈니스 워크플로우, 그리고 Fable 5에 항상 비용을 지불하지 않으면서도 최첨단 수준의 성능을 원하는 구매자들에게 매력적인 하이엔드 모델을 소개합니다. Anthropic는 입력 토큰 100만 개당 $5, 출력 토큰 100만 개당 $25를 청구하며, 이 모델은 동기식 Messages API에서 100만 토큰의 컨텍스트 윈도우와 최대 128,000개의 출력 토큰을 지원합니다. 단순한 채팅, 짧은 요약, 또는 대량이지만 가치가 낮은 요청의 경우 이 모델이 자동으로 최선의 선택이 되는 것은 아닙니다.

가장 설득력 있는 근거는 과장된 주장이 아니라 실용적인 측면에 있습니다. Opus 5는 Anthropic의 최상위 등급에 비해 관리하기 쉬운 비용 구조와 함께 충분한 추론 여력을 결합하고 있습니다. 단 한 번의 디버깅 테스트에서 이 모델은 접두사 일치 버그를 정확히 찾아내고, 가장 작은 규모의 패치를 제안하며, 해당 버그에 초점을 맞춘 회귀 테스트를 추가하고, 로컬 환경에서 통과되는 검증 명령어를 제공했습니다. 이는 해당 작업에 대한 유용한 증거일 뿐, 이 모델이 모든 코딩 업무를 성공적으로 수행할 것이라는 증거는 아닙니다.

최적 대상: 코딩 에이전트, 장문 맥락 분석, 기업 자동화, 그리고 막대한 실패 비용이 발생하는 팀들은 프리미엄 모델의 도입을 정당화한다. 다음과 같은 경우에는 건너뛰세요: 속도와 단가는 추론의 질이 마지막 단계에서 얼마나 뛰어난지보다 더 중요합니다.

Claude Opus 5란 무엇인가요?

Claude Opus 5는 복잡한 에이전트 기반 코딩 및 기업 업무에 적합한 Anthropic의 프리미엄 일상용 모델입니다. Anthropic는 2026년 7월 24일에 이를 발표했다., 이를 사려 깊고 선제적이며 다른 모델들보다 더 효율적이라고 평가했습니다. 이 모델은 Claude Opus 4.8을 대체했으며, Claude Max의 기본 모델이 되었고, Claude Pro에서 사용할 수 있는 가장 강력한 모델이 되었습니다.

Anthropic 발표 자료에 Claude Opus 5 타이틀, 2026년 7월 24일 출시일, 그리고 ‘오늘부터 이용 가능’이라는 문구가 표시되어 있음
Anthropic는 2026년 7월 24일 Claude Opus 5를 발표하며, 해당 제품이 당일 출시되었다고 밝혔다.

이 제품의 마케팅 전략은 오푸스(Opus)의 기존 출시 제품들과는 다소 이례적입니다. 이 제품은 단순히 ‘최고 수준의 지능’을 갖춘 모델로만 포지셔닝되지 않습니다. Anthropic는 사용자가 매일 사용할 수 있도록, 노력 수준을 조절할 수 있고 적당한 지연 시간을 갖도록 설계되었습니다. 덕분에 장시간 실행되는 에이전트나 까다로운 프로덕션 작업에 이 모델을 도입하는 것이 더 타당해지며, 비교적 단순한 워크로드는 여전히 더 빠르고 저렴한 모델로 처리할 수 있습니다.

이용 방법은 경로에 따라 다릅니다. 일반 사용자는 해당 Claude 요금제를 통해 Opus 5를 이용할 수 있으며, 개발자는 Claude API 및 지원되는 클라우드 플랫폼을 통해 이를 호출할 수 있습니다. GlobalGPT에도 전용 제품 페이지가 마련되어 있습니다. Anthropic의 구독 등급을 비교하려는 독자분들은 다음을 이용하실 수 있습니다. Claude 무료, Pro, Max 요금제 비교 결제 방식을 선택하기 전에.

Claude Opus 5 가격, API 및 주요 사양

공식 Claude API 가격입력 토큰 100만 개당 $5 그리고 출력 토큰 100만 개당 $25. 이는 기본 API 요금이며, Claude 소비자용 구독 요금이나 타사 플랫폼 요금제가 아닙니다. 프롬프트 캐싱과 일괄 처리에는 별도의 요금이 적용되므로, 표면적인 입력 가격만 곱하는 대신 전체 요청 패턴을 종합적으로 비교해야 합니다.

분야Claude Opus 5그 의미는
Claude API ID클로드-오푸스-5공식 Claude API 요청 시 이 정확한 모델 값을 사용하십시오.
기준 입력 가격$5 / MTok캐싱 또는 일괄 처리 할인 적용 전의 표준 입력 토큰 비율.
기준 출하 가격$25 / MTok출력 집약적인 에이전트는 비용이 급격히 증가할 수 있습니다.
컨텍스트 창100만 토큰요청의 품질 및 검색 전략에 따라 대규모 저장소 및 문서 모음에 적합합니다.
최대 출력128K 토큰동기식 Messages API에 적용됩니다. Message Batches의 경우 최대 30만 건까지 별도의 베타 경로가 제공됩니다.
신뢰할 수 있는 지식의 기준점2026년 5월모델 기준으로는 비교적 최신이지만, 실제 데이터 수집을 대체할 수는 없다.
지연 시간 비교보통Anthropic의 가장 빠른 모델은 아니며, 지연 시간은 작업량, 도구 및 워크로드에 따라 여전히 달라집니다.
Claude 플랫폼 문서 표에 표시된 Claude Opus 5 API ID 및 별칭
Claude 플랫폼은 claude-opus-5를 현재 Opus 5 API ID 및 별칭으로 식별합니다.
Claude 플랫폼 문서 표: Claude Opus 5의 가격, 적용 범위, 최대 출력 및 컷오프 사양
Claude 플랫폼은 Opus 5를 입력/출력 토큰 100만 개당 $5/$25로 표시하며, 100만 토큰의 컨텍스트 윈도우, 최대 128k 토큰의 출력, 2026년 5월을 컷오프 시점으로 설정하고 있습니다.
Claude 플랫폼 문서: Claude Opus 5의 컨텍스트, 출력 및 컷오프 행
Claude 플랫폼은 1M 컨텍스트 윈도우, 최대 128k 출력, 2026년 5월 컷오프를 명시하고 있습니다.

소비자가 이용할 수 있도록, Anthropic 목록: Claude Pro $20은 월별 요금제이며, $200이 연간 청구되는 경우 월 $17이 적용됩니다. Claude Max는 월 $100부터 시작합니다. Anthropic에 따르면 Opus 5는 Pro 요금제에서 가장 강력한 모델이며 Max 요금제의 기본 모델이지만, 요금제 할당량 및 제품 기능은 계량형 API 사용량과는 별도로 적용됩니다.

더 자세한 비용 내역을 확인하시려면, Claude AI 요금제 및 API 가격 안내서 소비자 구독, API 과금 및 사용 한도를 구분합니다. 이러한 구분은 중요합니다. “요금제에 포함됨”이라고 해서 API 호출이 무제한인 것은 아니며, API 요금만으로는 소비자가 이용할 수 있는 채팅 분량을 알 수 없습니다.

Claude Opus 5 벤치마크 결과

중요한 경계: 아래의 수치는 다음과 같습니다. Anthropic가 공개한 벤치마크 결과, 이번 리뷰를 위해 별도로 수행된 독립적인 측정 결과는 아닙니다. 이 결과들은 Anthropic가 목표로 하는 성능 및 비용 위치를 이해하는 데 유용하지만, 사용자의 프롬프트, 도구, 저장소 또는 지연 시간 허용 범위에서 동일한 결과가 보장되는 것은 아닙니다.

평가Anthropic가 발표한 주장읽는 방법
Frontier-Bench v0.1Opus 5는 작업당 비용을 낮추면서도 Opus 4.8의 성능을 두 배 이상 뛰어넘습니다.모든 경우에 걸쳐 성능이 두 배로 향상되는 것이 아니라, 광범위한 에이전트 성능 신호가 나타났습니다.
CursorBench 3.2최대 성능을 발휘할 때, Opus 5는 Fable 5의 최고 점수에 0.5% 차이로 근접하며, 작업당 비용은 절반 수준입니다.Anthropic의 검증된 노력 설정 하에서 나타나는 강력한 코딩 에이전트 경제성.
Zapier AutomationBench작업당 비용은 동일하면서도, 그 다음으로 높은 합격률보다 약 1.5배 높은 합격률을 기록했습니다.종단간 비즈니스 자동화에 대한 전망은 밝지만, 워크플로우 설계는 여전히 중요합니다.
OSWorld 2.0Fable 5의 최고 실적을 비용의 3분의 1 남짓으로 뛰어넘었습니다.이 벤치마크에서 컴퓨터 사용 효율이 매우 뛰어난 것으로 나타납니다.
Anthropic 발표문 및 Claude Opus 5 CursorBench 3.2 성능 및 비용 비교
Anthropic에 따르면, Opus 5는 Fable 5의 CursorBench 3.2 최고 점수에 0.5% 차이로 근접하면서도 작업당 비용은 절반 수준에 불과하다고 합니다.
Zapier AutomationBench와 OSWorld 2.0에서 Claude Opus 5를 비교한 Anthropic 벤치마크 텍스트
Anthropic는 Zapier AutomationBench에서 1.5배 높은 합격률을 기록했으며, OSWorld 2.0에서는 비용 면에서 우위를 점했다고 보고합니다.

노력은 결과의 일부입니다. Anthropic에 따르면, Opus 5는 Claude API 및 Claude 코드에서 기본적으로 높은 노력 수준을 적용하며, 비교 분석 시에도 high, xhigh 또는 max 설정을 사용합니다. 노력 수준을 높이면 어려운 작업의 성공률을 높일 수 있지만, 토큰 수나 지연 시간, 혹은 둘 다 증가할 수 있습니다. 따라서 작업당 벤치마크 비용은 토큰당 가격만 보는 것보다 더 유용한 정보를 제공하지만, 어느 지표도 실제 워크로드에 대한 직접적인 테스트를 대체할 수는 없습니다.

Claude Opus 5 테스트 방법

우리는 3개의 파일로 구성된 CommonJS 피처셋을 대상으로 한 건의 간결한 근본 원인 디버깅 과제를 수행했습니다. 이 과제에서는 모델이 수정 작업에 앞서 근본 원인을 파악하고, 가능한 한 최소한의 패치를 제안하며, 해당 부분에 집중된 회귀 테스트를 추가하고, 관련 없는 변경 사항은 피하며, 정확한 검증 명령어를 제시해야 했습니다.

그런 다음, 답변이 자신 있게 들린다고 해서 그대로 정답으로 받아들이기보다는 패치를 따로 확인해 보았습니다. local 명령어는 다음과 같았습니다. node --test test/account-summary.test.cjs. 수정 전에는 이 테스트 모음에서 통과 1건과 실패 1건이 발생했습니다. 정확한 등가성 패치를 적용한 후에는 통과 2건과 실패 0건이 발생했습니다.

이 방법은 디버깅 워크플로우의 한 측면, 즉 문제 진단, 패치 관리 체계, 회귀 테스트의 품질, 검증 가능성에 대해 유용한 정보를 제공합니다. 다만, 전반적인 코딩 리더십, 장기적인 에이전트 신뢰성, 속도, 또는 다양한 언어에 걸친 성능은 측정하지 않습니다.

Claude Opus 5 실사용 후기

근본 원인 디버깅: 정확하고, 최소한이며, 검증 가능해야 한다

본 테스트에서 Claude Opus 5는 결함 위치를 정확히 특정하여 normalizedQuery.startsWith(account.id.toLowerCase()). 다음 쿼리를 사용하여 ACCT-10, 접두사 검사가 일치했습니다 acct-1 먼저, 그러니까 Array.prototype.find 정확한 ID에 도달하기도 전에 잘못된 계정을 반환했습니다.

제안된 수정 사항은 접두사 일치 방식을 정확한 일치 방식으로 변경했으며, 공백이 추가된 대소문자가 혼합된 ACCT-10 입력. 관련 없는 코드는 수정하지 않았습니다. 실제 저장소에서는 이러한 절제가 중요합니다. 지나치게 광범위한 “정리” 작업은 원래 버그보다 더 많은 검토 작업을 야기할 수 있기 때문입니다.

가장 인상 깊었던 부분은 전체적인 흐름이었습니다. 근본 원인을 파악하고, 기존 테스트에서 이를 놓친 이유를 설명한 뒤, 최소한의 변경을 가하고, 적절한 회귀 테스트를 추가한 다음, 이를 검증하기 위한 명령어를 제시하는 과정이었습니다. 이 결과는 Opus 5의 ’코딩 에이전트’라는 포지셔닝과 일치하지만, 여전히 하나의 고정된 방식에 그칩니다. 보다 포괄적인 워크플로 입문 가이드를 보려면 다음을 참조하십시오. Claude AI를 코딩에 사용하는 방법.

T1–T4 문제문, 정답 및 복사 가능한 코드 전체

T1: 근본 원인 디버깅

통과 — 접두사 일치 결함을 발견하고, 가장 작은 패치를 제안했으며, 해당 결함에 초점을 맞춘 회귀 테스트를 추가했습니다.

Claude Opus 5 실습 기반 근본 원인 디버깅 결과
접두사 일치 문제를 결함으로 파악하고, 기존 테스트에서 이를 놓친 이유를 설명했으며, 정확한 일치 여부와 추가 회귀 테스트를 제안했다.
T1 문제 문항 및 정답 전체 보기
전체 프롬프트
의도적으로 규모를 작게 만든 CommonJS 피처스트를 디버깅하고 있습니다. 아래의 세 개 파일과 명시된 재현 방법만을 바탕으로 작업하십시오.

요구 사항:
1. 수정안을 제안하기 전에 근본 원인을 명시하십시오.
2. 버그를 수정하는 가장 작은 패치를 제안하십시오.
3. 수정 전에는 실패하고 수정 후에는 통과하는, 해당 버그에 집중된 회귀 테스트를 하나 추가하십시오.
4. 피처 루트 디렉터리에서 실행해야 할 정확한 검증 명령어를 제시하십시오.
5. 관련 없는 코드는 재작성하지 마십시오. 파일 이름을 변경하거나, 의존성을 추가하거나, 공개 API를 변경하지 마십시오.
6. 정확히 다음 섹션들을 순서대로 반환하십시오: `ROOT CAUSE`, `PATCH`, `VERIFICATION`, `LIMITATIONS`.
7. `PATCH` 섹션에서는 `diff` 태그로 둘러싼 블록 안에 하나의 통합 diff를 제공하십시오. `VERIFICATION` 섹션에서는 `text` 태그로 둘러싼 블록 안에 하나의 명령어를 제공하십시오.

재현 방법: `summarizeAccount(accounts, ' ACCT-10 ')`는 `{ id: 'acct-10', name: 'Nimbus', seats: 24 }`를 반환해야 하지만, `acct-1` 계정을 반환합니다.

파일: `src/find-account.cjs`
```js
function findAccount(accounts, query) {
  const normalizedQuery = query.trim().toLowerCase();
  return accounts.find((account) =>
    normalizedQuery.startsWith(account.id.toLowerCase()),
  );
}

module.exports = { findAccount };
```

파일: `src/account-summary.cjs`
```js
const { findAccount } = require('./find-account.cjs');

function summarizeAccount(accounts, requestedId) {
  const account = findAccount(accounts, requestedId);
  if (!account) return null;
  return { id: account.id, name: account.name, seats: account.seats };
}

module.exports = { summarizeAccount };
```

파일: `test/account-summary.test.cjs`
```js
const test = require('node:test');
const assert = require('node:assert/strict');
const { summarizeAccount } = require('../src/account-summary.cjs');

const accounts = [
  { id: 'acct-1', name: 'Atlas', seats: 5 },
  { id: 'acct-10', name: 'Nimbus', seats: 24 },
];

test('정확한 계정 ID를 요약합니다', () => {
  assert.deepEqual(summarizeAccount(accounts, 'acct-1'), {
    id: 'acct-1',
    name: 'Atlas',
    seats: 5,
  });
});
```
Claude Opus 5

근본 원인

findAccount는 등가가 아닌 접두사를 기준으로 일치 여부를 확인합니다:

js
normalizedQuery.startsWith(account.id.toLowerCase())
normalizedQuery.startsWith(account.id.toLowerCase())

Array.prototype.find는 조건식을 만족하는 첫 번째 요소를 반환합니다. ‘ACCT-10‘의 경우 정규화된 쿼리는 ‘acct-10’이며, 첫 번째 계정의 ID인 ‘acct-1’은 이 쿼리의 접두사이므로 startsWith가 true가 되고, acct-10이 테스트되기 전에 acct-1에서 검색이 조기 종료됩니다.
trim().toLowerCase()를 통한 정규화는 올바릅니다. 공백이나 대소문자 문제는 아닙니다. summarizeAccount는 단순히 데이터를 전달하는 역할일 뿐이며, 문제가 있는 것은 아닙니다.
기존 테스트로는 이 문제를 포착할 수 없습니다. ‘acct-1’은 자체의 접두사이자 첫 번째 요소이므로, 해당 입력에 대해서는 접두사 일치와 정확한 일치를 구분할 수 없습니다.

패치

diff
--- a/src/find-account.cjs+++ b/src/find-account.cjs@@ -1,8 +1,8 @@ function findAccount(accounts, query) {   const normalizedQuery = query.trim().toLowerCase();-  return accounts.find((account) =>-    normalizedQuery.startsWith(account.id.toLowerCase()),-  );+  return accounts.find(+    (account) => account.id.toLowerCase() === normalizedQuery,+  ); }  module.exports = { findAccount };--- a/test/account-summary.test.cjs+++ b/test/account-summary.test.cjs@@ -14,3 +14,11 @@ test('summarizes an exact account ID', () => {     seats: 5,   }); });++test('matches the full ID rather than a prefix, with padding and mixed case', () => {+  assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {+    id: 'acct-10',+    name: 'Nimbus',+    seats: 24,+  });+});
--- a/src/find-account.cjs
+++ b/src/find-account.cjs
@@ -1,8 +1,8 @@
 function findAccount(accounts, query) {
   const normalizedQuery = query.trim().toLowerCase();
-  return accounts.find((account) =>
-    normalizedQuery.startsWith(account.id.toLowerCase()),
-  );
+  return accounts.find(
+    (account) => account.id.toLowerCase() === normalizedQuery,
+  );
 }

 module.exports = { findAccount };
--- a/test/account-summary.test.cjs
+++ b/test/account-summary.test.cjs
@@ -14,3 +14,11 @@
 test('정확한 계정 ID를 요약합니다', () => {
 seats: 5,
   });
 });
+
+test('접두사가 아닌 전체 ID와 일치하며, 공백이 포함되고 대소문자가 혼합된 경우', () => {
+  assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {
+    id: 'acct-10',
+    name: 'Nimbus',
+    seats: 24,
+  });
+});

수정 전에는 acct-1 / Atlas / 5 객체에서 새로운 테스트가 실패했으나, 수정 후에는 통과합니다.

검증

텍스트
node --test test/account-summary.test.cjs
node --test test/account-summary.test.cjs

제한 사항

• 적용 범위: 연산자 하나가 변경되었습니다. 이름 변경이나 새로운 종속성은 없으며, findAccount 및 summarizeAccount의 시그니처와 반환 형식은 변경되지 않았습니다.
• 기존에 존재하던 동작으로, 별도 조치 없이 그대로 둔 경우 (이 버그의 적용 범위 외):
• 문자열이 아닌 requestedId(null, 숫자)의 경우, .trim()을 호출하면 여전히 예외가 발생합니다.
• 계정 ID 자체는 트리밍되지 않으므로, 저장된 ‘acct-10’은 여전히 일치하지 않습니다. 쿼리만 정규화됩니다.
• 케이싱에는 단순한 toLowerCase() 함수가 사용되며, 유니코드 정규화나 로케일 기반 접기 처리는 적용되지 않습니다.
• 중복 ID의 경우에도 여전히 첫 번째 일치 항목으로 처리되며, 조회 시간은 O(n)을 유지합니다.
• 테스트 커버리지: 이 단일 회귀 테스트는 보고된 재현 사례만을 정확히 대상으로 합니다. 발견되지 않은(null) 경로와 형식이 잘못된 입력에 대해서는 테스트가 수행되지 않습니다.

ROOT CAUSE
findAccount matches by prefix, not by equality:

```js
normalizedQuery.startsWith(account.id.toLowerCase())
```

Array.prototype.find returns the first element satisfying the predicate. For ' ACCT-10 ' the normalized query is 'acct-10', and the first account's ID 'acct-1' is a prefix of it, so startsWith is true and acct-1 short-circuits the search before acct-10 is ever tested.
The trim().toLowerCase() normalization is correct — whitespace and casing are not the problem. summarizeAccount is a pass-through and is not at fault.
The existing test cannot catch this: 'acct-1' is a prefix of itself and is the first element, so prefix matching and exact matching are indistinguishable for that input.
PATCH

```diff
--- a/src/find-account.cjs
+++ b/src/find-account.cjs
@@ -1,8 +1,8 @@
 function findAccount(accounts, query) {
   const normalizedQuery = query.trim().toLowerCase();
-  return accounts.find((account) =>
-    normalizedQuery.startsWith(account.id.toLowerCase()),
-  );
+  return accounts.find(
+    (account) => account.id.toLowerCase() === normalizedQuery,
+  );
 }

 module.exports = { findAccount };
--- a/test/account-summary.test.cjs
+++ b/test/account-summary.test.cjs
@@ -14,3 +14,11 @@
 test('summarizes an exact account ID', () => {
     seats: 5,
   });
 });
+
+test('matches the full ID rather than a prefix, with padding and mixed case', () => {
+  assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {
+    id: 'acct-10',
+    name: 'Nimbus',
+    seats: 24,
+  });
+});
```

Before the fix the new test fails with the acct-1 / Atlas / 5 object; after the fix it passes.
VERIFICATION

```text
node --test test/account-summary.test.cjs
```

LIMITATIONS
• Scope: one operator changed. No renames, no new dependencies, and findAccount / summarizeAccount signatures and return shapes are unchanged.
• Pre-existing behavior left alone (out of scope for this bug):
• A non-string requestedId (null, a number) still throws on .trim().
• Account IDs themselves are not trimmed, so a stored ' acct-10' still will not match — only the query is normalized.
• Casing uses plain toLowerCase(); no Unicode normalization or locale-aware folding.
• Duplicate IDs still resolve to the first match, and lookup remains O(n).
• Test coverage: the single regression test targets exactly the reported reproduction. The not-found (null) path and malformed input remain untested.

T2: 계정 상태 분석

부분적 — 핵심 지표를 산출하고 조치의 우선순위를 정했으나, 작성된 답변에는 요청된 ‘재확인’ 표시가 포함되지 않은 채 끝났습니다.

Claude Opus 5차 실습 계정 건전성 분석 결과
위험에 처한 MRR을 $34,800(94.31%)으로 산출함; E-505를 상급 부서로 이관하고 후속 조치 우선순위를 지정함; 요청된 재확인 마커 없이 답변이 종료됨.
T2 프롬프트 및 답변 전체 보기
전체 프롬프트
제공된 `account-health.csv` 파일을 폐쇄형 데이터셋으로 분석하십시오. 외부 정보를 사용하지 말고, 누락된 값을 임의로 채워 넣지 마십시오.

리스크 규칙 (각 규칙을 독립적으로 평가하십시오):
- `inactivity`: `days_since_login >= 30`
- `payment`: `failed_payments >= 2`
- `low_utilization`: `seats_used / seats_purchased = 80`인 경우.
- `weak_health_without_risk`: 계정이 위험 상태가 아닌데도 `health_score = 9`이고 `open_tickets >= 3`인 경우.

요구 사항:
1. 모든 계정에 대해 발동된 위험 플래그와 모순 플래그를 계산하십시오.
2. 계정, MRR, 위험 상태 계정, 위험 상태 MRR, 에스컬레이션 대상 계정, 모순 행, 구매된 라이선스 수, 사용 중인 라이선스 수에 대한 데이터셋 합계를 보고하십시오.
3. 정확히 5개의 열(`계정 | 위험 트리거 | 모순 | 우선순위 | 권장 조치`)로 구성된 조치 테이블을 생성하십시오.
4. 직접 계산된 값은 `측정된 사실(Measured facts)` 제목 아래에, 판단에 따른 결정은 `추론(Inference)` 제목 아래에 배치하십시오.
5. `재확인` 항목 아래에는 0.50과 동일한 경우를 포함하여 모든 합계와 모든 임계값 경계를 독립적으로 재확인할 수 있을 만큼 충분한 산술 계산을 표시하십시오.
6. 규칙을 묵묵히 수정하거나 재해석하지 마십시오. 신호가 직관적이지 않다고 느껴진다면, 분류를 변경하기보다는 모순으로 기록하십시오.

`account-health.csv`:
```csv
account_id,account_name,plan,mrr_usd,days_since_login,failed_payments,seats_purchased,seats_used,health_score,nps,open_tickets
A-101,Aster,Enterprise,12000,45,0,100,82,92,9,1
B-202,Beacon,Pro,4200,4,2,20,18,70,7,0
C-303,Cinder,Pro,3600,12,0,20,8,65,10,4
D-404,Dahlia,Starter,900,5,0,5,4,42,6,0
E-505,Ember,Enterprise,15000,65,3,200,70,35,3,6
F-606,Fjord,Starter,1200,29,1,4,2,85,9,3
```
Claude Opus 5

검증된 사실

출처: account-health.csv, 6행, 종료된 것으로 처리됨. 결측값 보정은 없음.

계정별 규칙 평가

계정
일수 ≥ 30
실패 2회 이상
util < 0.50
위험 건수
상태
A-101 애스터
✅ 45
❌ 0
❌ 0.82
1
위험군
B-202 비콘
❌ 4
✅ 2
❌ 0.90
1
위험군
C-303 신더
❌ 12
❌ 0
✅ 0.40
1
위험군
D-404 달리아
❌ 5
❌ 0
❌ 0.80
0
위험군에 속하지 않는
E-505 엠버
✅ 65
✅ 3
✅ 0.35
3
위험군 + 상급 부서로 이관
F-606 피오르드
❌ 29
❌ 1
❌ 0.50
0
위험군에 속하지 않는
계정별 모순 표시
계정
위험을 동반한 건강
위험이 없는 건강 악화
티켓을 든 프로모터
A-101 애스터
✅ (92 ≥ 80, 고위험군)

❌ (NPS 9 ✓, 티켓 1 ✗)
B-202 비콘
❌ (70 < 80)
❌ (70 ≥ 50)
❌ (NPS 7)
C-303 신더
❌ (65 < 80)
❌ (65 ≥ 50)
✅ (NPS 10, 티켓 4)
D-404 달리아

✅ (42 < 50, 위험군에 해당하지 않음)
❌ (NPS 6)
E-505 엠버
❌ (35 < 80)
❌ (35 < 50이지만 고위험군에 해당함)
❌ (NPS 3)
F-606 피오르드
❌ (85 ≥ 80이지만 고위험군은 아님)
❌ (85 ≥ 50)
✅ (NPS 9, 티켓 3)
데이터셋 총계
미터법
가치
계정
6
총 MRR
$36,900
위험에 처한 계정
4 (A-101, B-202, C-303, E-505)
위험에 처한 MRR
$34,800 (전체 중 94.31%)
계정 에스컬레이션
1 (E-505)
모순 행
4 (A-101, C-303, D-404, F-606)
모순 표시기
4 (1 strong_health_with_risk, 1 weak_health_without_risk, 2 promoter_with_ticket_load)
구매한 좌석
349
사용된 좌석 수
184
추론
아래의 우선순위 순서와 권장 조치는 규칙에 따른 결과가 아닌 판단에 따른 것입니다. 제 순위 산정 기준은 우선 상태를 최우선으로 하고, 그 다음으로 위험에 처한 MRR, 마지막으로 모순 신호 순으로 가중치를 부여합니다.
계정
위험 유발 요인
모순
우선순위
권장 조치
E-505 엠버
비활성, 결제, 낮은 이용률
-
P0
세 가지 규칙 모두 가장 규모가 큰 계정($15,000 MRR)에서 발동됩니다. 활성 이탈 사례로 처리하십시오: 결제 수단을 복구한 후, 미사용 좌석 130석에 대해 경영진 검토를 진행하십시오.
A-101 애스터
비활동
위험을 동반한 건강
P1
$: MRR 12,000, 45일간의 비활성 기간이 있음. 점수는 92점이며 82% 활용도는 양호함. 점수에 따라 조치를 취하기 전에, 로그인 간격이 실제 이용 중단인지 아니면 추적상의 오류(SSO, API 전용 사용)인지 확인하십시오.
C-303 신더
저이용률
티켓을 든 프로모터
P1
40% 활용률로 4장의 미사용 티켓을 보유한 프로모터(nps 10). 티켓 부하가 도입을 가로막는 가장 유력한 요인입니다. 대기열을 정리한 후 좌석 활성화를 추진하십시오.
B-202 비콘
결제
-
P2
원인이 명확한 사례: 최근 4일 이내에 로그인 기록이 있으며 90% 이용률이 90%인 상태에서 2건의 결제 실패가 발생했습니다. 청구 관련 후속 조치만 진행하면 되며, 고객 서비스 조치는 필요하지 않습니다.
F-606 피오르드
-
티켓을 든 프로모터
P3
모든 기준을 아슬아슬하게 충족하고 있습니다(29일, 결제 실패 1회, 이용률 정확히 0.50). 규정상 위험 상태는 아니지만, 하루만 더 방치되거나 결제 실패가 한 번만 더 발생해도 상황이 뒤바뀝니다. 상황을 주시하고 3건의 미결제 내역을 처리해 주세요.
D-404 달리아
-
위험이 없는 건강 악화
P3
규칙이 발동되지 않은 상태에서 42점을 기록했으며, $900 MRR에서 80%가 사용되었습니다. 다음 중 하나

측정된 사실
출처: account-health.csv, 6행, 종료된 것으로 처리됨. 값 보충 없음.
계정별 규칙 평가
계정
일수≥30
실패 횟수≥2
이용률 <0.50
위험 횟수
상태
A-101 Aster
✅ 45
❌ 0
❌ 0.82
1
위험군
B-202 Beacon
❌ 4
✅ 2
❌ 0.90
1
위험군
C-303 Cinder
❌ 12
❌ 0
✅ 0.40
1
위험
D-404 Dahlia
❌ 5
❌ 0
❌ 0.80
0
위험 아님
E-505 Ember
✅ 65
✅ 3
✅ 0.35
3
위험 + 에스컬레이션
F-606 피오르드
❌ 29
❌ 1
❌ 0.50
0
위험 없음
계정별 모순 플래그
계정
위험이 있는 건전한 상태
위험이 없는 취약한 상태
티켓 부하가 있는 프로모터
A-101 애스터
✅ (92 ≥ 80, 위험)
❌
❌ (NPS 9 ✓, 티켓 1 ✗)
B-202 비콘
❌ (70 < 80)
❌ (70 ≥ 50)
❌ (NPS 7)
C-303 신더
❌ (65 < 80)
❌ (65 ≥ 50)
✅ (NPS 10, 티켓 4)
D-404 달리아
❌
✅ (42 < 50, 위험군 아님)
❌ (nps 6)
E-505 엠버
❌ (35 < 80)
❌ (35 < 50이지만 위험군임)
❌ (NPS 3)
F-606 피오르드
❌ (85 ≥ 80이지만 위험군 아님)
❌ (85 ≥ 50)
✅ (NPS 9, 티켓 3)
데이터셋 총계
지표
값
계정 수
6
총 MRR
$36,900
위험에 처한 계정
4 (A-101, B-202, C-303, E-505)
위험에 처한 MRR
$34,800 (전체 중 94.31%)
에스컬레이션 대상 계정
1 (E-505)
모순 행
4 (A-101, C-303, D-404, F-606)
모순 플래그
4개 (1개 strong_health_with_risk, 1개 weak_health_without_risk, 2개 promoter_with_ticket_load)
구매된 좌석
349석
사용된 좌석
184석
추론
아래의 우선순위 순서 및 권장 조치는 규칙에 의한 결과가 아닌 판단에 따른 것입니다. 제 순위 가중치는 우선 순위를 가장 먼저 고려하고, 그 다음으로 위험에 처한 MRR, 마지막으로 모순 신호를 고려합니다.
계정
위험 유발 요인
모순 사항
우선순위
권장 조치
E-505 Ember
비활성, 결제, 낮은 이용률
—
P0
세 가지 규칙이 모두 최대 규모 계정($15,000 MRR)에서 발동되었습니다. 활성 이탈로 처리하십시오: 결제 수단을 복원한 후, 미사용 좌석 130석에 대해 경영진 검토를 진행하십시오.
A-101 Aster
비활성
위험이 있는 건전한 상태
P1
$12,000 MRR 계정이 점수 92점, 건강한 82% 활용도를 보임에도 불구하고 45일간 비활성 상태입니다. 점수에 따라 조치를 취하기 전에, 로그인 간격이 실제 이탈인지 아니면 추적 오류(SSO, API 전용 사용)인지 확인하십시오.
C-303 Cinder
저활용
티켓 부담이 있는 프로모터
P1
40% 활용도를 보이며 4건의 미해결 티켓을 보유한 프로모터(NPS 10). 티켓 부담이 도입을 가로막는 타당한 요인일 수 있으므로, 대기열을 정리한 후 좌석 활성화를 유도하십시오.
B-202 Beacon
결제
—
P2
원인이 명확한 사례: 4일 전 로그인 기록과 90% 활용도를 보이며 2건의 결제 실패가 발생했습니다. 청구 후속 조치만 필요하며, 고객 지원 조치는 불필요합니다.
F-606 피오르드
—
티켓 부하가 있는 프로모터
P3
모든 기준(29일, 결제 실패 1건, 이용률 정확히 0.50)을 아슬아슬하게 충족합니다. 규칙상 위험 상태는 아니지만, 하루만 더 비활성 상태이거나 결제 실패가 한 번만 더 발생해도 위험 상태로 전환됩니다. 3개의 티켓을 모니터링하고 처리하십시오.
D-404 Dahlia
—
weak_health_without_risk
P3
점수 42점, 규칙 발동 없음, $900 MRR 기준 80% 이용률. 다음 중 하나

T3: 반응형 UI 생성

부분적 — 페이지를 런타임에 렌더링한 것이 아니라 검사했다는 점을 명시적으로 밝히면서, 독립적으로 작동하는 긴 구현 코드와 자체 검증 기능을 구현했다.

Claude Opus 5차 실습: 반응형 UI 생성 결과
21,907자 분량의 독립적인 답변을 작성했습니다. 데스크톱, 모바일, 오버플로우 및 접근성 관련 내용을 다루었으며, 레이아웃이 검사된 것이지 런타임에 렌더링된 것이 아님을 명확히 밝혔습니다.
T3 프롬프트 및 답변 전체 보기
전체 프롬프트
아래의 제품 데이터만을 사용하여, 실행 가능한 단일 HTML 파일 형태의 완성도 높은 제품 비교 인터페이스를 구축하십시오.

요구 사항:
1. `html` 태그로 둘러싸인 코드 블록을 정확히 하나 반환하고, 그 뒤에 `SELF-CHECK` 섹션을 추가하십시오. HTML, CSS, JavaScript를 별도의 파일로 분리하지 마십시오.
2. 의미론적 HTML, 내장 CSS 및 내장 순수 자바스크립트만 사용하십시오. 외부 프레임워크, 패키지, 폰트, 이미지, 네트워크 요청 또는 빌드 단계는 사용해서는 안 됩니다.
3. 올바른 `tablist`, `tab` 및 `tabpanel` 의미론을 적용하여 키보드로 접근 가능한 세 개의 탭(`Overview`, `Pricing`, `Limits`)을 제공하십시오. ArrowLeft/ArrowRight 키로 탭을 이동하고 활성화해야 하며, Home/End 키로 첫 번째/마지막 탭으로 이동하여 활성화해야 합니다. 포커스는 항상 표시되어야 합니다.
4. 선택된 탭은 `aria-selected`, `tabindex` 및 표시된 패널을 통해 반영되어야 하며, 비활성 패널은 숨겨져야 합니다.
5. 데스크톱 대상: 너비 1440px. 모바일 대상: 너비 390px이며, 페이지의 수평 오버플로우가 없고, 컨트롤이 잘리지 않으며, 탭 대상의 높이가 최소 44px이고, 비교 카드가 한 열로 쌓여 있어야 합니다.
6. 간결한 헤더, 명확한 권장 사항, 세 개의 제품 카드, 그리고 하나의 간결한 비교 표를 포함하십시오. 가독성 있는 명암비를 유지하고 장식적인 움직임은 피하십시오.
7. 정확히 다음의 제품 정보를 사용하며, 추가 주장을 덧붙이지 마십시오:
   - Atlas: `$19/mo`, `20개 프로젝트`, `10 GB`, `이메일 지원`, 1인 작업에 최적.
   - Beacon: `$49/mo`, `무제한 프로젝트`, `100 GB`, `우선 지원`, 성장 중인 팀에 가장 적합.
   - Cove: `$99/mo`, `무제한 프로젝트`, `1 TB`, `전용 지원`, 규제 대상 업무에 가장 적합.
8. 다른 카드들이 비활성화된 것처럼 보이지 않도록 하면서, Beacon에 눈에 띄는 `전반적으로 가장 우수` 라벨을 부여하십시오.
9. `SELF-CHECK` 섹션에서 시맨틱 탭, 키보드 동작, 1440px 레이아웃, 390px 레이아웃, 수평 오버플로우 및 외부 종속성에 대한 검증을 명확히 보고하십시오. 실제로 뷰포트를 렌더링하지 않은 경우 렌더링했다고 주장하지 마십시오. 코드 검사와 런타임 검증을 구분하십시오.

제품 피처(`fixtures/T3-responsive-ui/product-data.json`에도 저장됨):
```json
{
  "products": [
    {"name":"Atlas","price":"$19/mo","projects":"20 projects","storage":"10 GB","support":"이메일 지원","bestFor":"개인 작업"},
    {"name":"Beacon","price":"$49/mo","projects":"무제한 프로젝트","storage":"100 GB","support":"우선 지원","bestFor":"성장 중인 팀","badge":"종합 최우수"},
    {"name":"Cove","price":"$99/mo","projects":"무제한 프로젝트","storage":"1 TB","support":"전담 지원","bestFor":"규제 대상 업무"}
  ]
}
```
Claude Opus 5
html
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Compare plans — Atlas, Beacon, Cove</title><style>  :root {    --bg: #f6f7f9;    --surface: #ffffff;    --ink: #16191f;    --ink-soft: #4a515c;    --line: #d3d8df;    --line-strong: #b6bdc7;    --accent: #10457e;    --accent-soft: #e8f0f9;    --focus: #0b2f56;    --radius: 10px;  }   * {box-sizing: border-box; }   html { -webkit-text-size-adjust: 100%; }   body {    margin: 0;    padding: 0;    background: var(--bg);    color: var(--ink);    font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;    font-size: 16px;    line-height: 1.5;    overflow-x: hidden;  }   .wrap {    width: 100%;    max-width: 1120px;    margin: 0 auto;    padding: 32px 24px 64px;  }   /* ---------- Header ---------- */   .page-header { margin-bottom: 24px; }   .page-header h1 {    margin: 0 0 8px;    font-size: 1.75rem;    line-height: 1.25;    letter-spacing: -0.01em;  }   .page-header p {    margin: 0;    max-width: 60ch;    color: var(--ink-soft);  }   /* ---------- Recommendation ---------- */   .recommendation {    display: flex;    flex-wrap: wrap;    gap: 4px 10px;    align-items: baseline;    margin: 0 0 28px;    padding: 14px 16px;    background: var(--accent-soft);    border: 1px solid #c2d5e8;    border-left: 4px solid var(--accent);    border-radius: var(--radius);  }   .recommendation strong { color: var(--accent); }   .recommendation span { color: #23405e; }   /* ---------- Tabs ---------- */   .tabs {    display: flex;    flex-wrap: wrap;    gap: 8px;    margin: 0 0 20px;    padding: 0;    border-bottom: 1px solid var(--line);  }   [role="tab"] {    appearance: none;    min-height: 44px;    padding: 10px 18px;    font: inherit;    font-weight: 600;    color: var(--ink-soft);    background: transparent;    border: 1px solid transparent;    border-bottom: 3px solid transparent;    border-radius: 8px 8px 0 0;    cursor: pointer;  }   [role="tab"]:hover { color: var(--ink); background: #eceff3; }   [role="tab"][aria-selected="true"] {    color: var(--accent);    background: var(--surface);    border-color: var(--line) var(--line) var(--accent);    border-bottom-width: 3px;  }   :focus-visible {    outline: 3px solid var(--focus);    outline-offset: 2px;  }   [role="tabpanel"] { outline: none; }   [role="tabpanel"]:focus-visible {    outline: 3px solid var(--focus);    outline-offset: 4px;    border-radius: var(--radius);  }   [hidden] { display: none !important; }   .panel-intro {    margin: 0 0 20px;    max-width: 62ch;    color: var(--ink-soft);  }   /* ---------- Cards ---------- */   .card-grid {    display: grid;    grid-template-columns: repeat(3, minmax(0, 1fr));    gap: 20px;    margin: 0;    padding: 0;    list-style: none;    align-items: start;  }   .card {    display: flex;    flex-direction: column;    height: 100%;    padding: 20px;    background: var(--surface);    border: 1px solid var(--line);    border-radius: var(--radius);  }   .card.is-featured {    border-color: var(--accent);    border-width: 2px;    padding: 19px;  }   .card-head {    display: flex;    flex-wrap: wrap;    gap: 8px;    align-items: center;    justify-content: space-between;    margin-bottom: 4px;  }   .card h3 {    margin: 0;    font-size: 1.2rem;  }   .badge {    padding: 3px 10px;    font-size: 0.75rem;    font-weight: 700;    letter-spacing: 0.02em;    text-transform: uppercase;    color: #ffffff;    background: var(--accent);    border-radius: 999px;    white-space: nowrap;  }   .price {    margin: 8px 0 2px;    font-size: 1.6rem;    font-weight: 700;    letter-spacing: -0.02em;  }   .best-for {    margin: 0 0 14px;    font-size: 0.9375rem;    color: var(--ink-soft);  }   .spec-list {    margin: 0;    padding: 14px 0 0;    border-top: 1px solid var(--line);    font-size: 0.9375rem;  }   .spec-list div {    display: flex;    gap: 12px;    justify-content: space-between;    padding: 5px 0;  }   .spec-list dt { color: var(--ink-soft); }   .spec-list dd {    margin: 0;    font-weight: 600;    text-align: right;  }   /* ---------- Table ---------- */   .table-section { margin-top: 36px; }   .table-section h2 {    margin: 0 0 12px;    font-size: 1.125rem;  }   .table-scroll {    max-width: 100%;    overflow-x: auto;    background: var(--surface);    border: 1px solid var(--line);    border-radius: var(--radius);  }   table {    width: 100%;    border-collapse: collapse;    font-size: 0.9375rem;  }   caption {    padding: 12px 14px;    text-align: left;    color: var(--ink-soft);    font-size: 0.875rem;  }   th, td {    padding: 10px 14px;    text-align: left;    border-top: 1px solid var(--line);    white-space: nowrap;  }   thead th {    background: #eef1f5;    border-top: none;    font-weight: 700;  }   tbody th { font-weight: 600; color: var(--ink-soft); }   th[scope="col"].is-featured { color: var(--accent); }   /* ---------- Mobile ---------- */   @media (max-width: 720px) {    .wrap { padding: 20px 16px 48px; }     .page-header h1 { font-size: 1.4rem; }     .tabs {      gap: 4px;      overflow-x: auto;      -webkit-overflow-scrolling: touch;      flex-wrap: nowrap;    }     [role="tab"] {      flex: 1 0 auto;      padding: 10px 12px;      font-size: 0.9375rem;    }     .card-grid { grid-template-columns: minmax(0, 1fr); }     th, td { padding: 10px 12px; }  }   @media (prefers-reduced-motion: reduce) {    * {transition: none !important; animation: none !important; }  }</style></head><body><main class="wrap">   <header class="page-header">    <h1>Compare plans</h1>    <p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>  </header>   <p class="recommendation">    <strong>Recommended: Beacon</strong>    <span>Best overall for growing teams — $49/mo, unlimited projects, 100&nbsp;GB, priority support.</span>  </p>   <div class="tabs" role="tablist" aria-label="Plan comparison views">    <button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>    <button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>    <button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>  </div>   <!-- Overview -->  <section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">    <p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>     <ul class="card-grid">      <li class="card">        <div class="card-head"><h3>Atlas</h3></div>        <p class="price">$19/mo</p>        <p class="best-for">Best for solo work</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>20 projects</dd></div>          <div><dt>Storage</dt><dd>10 GB</dd></div>          <div><dt>Support</dt><dd>Email support</dd></div>        </dl>      </li>       <li class="card is-featured">        <div class="card-head">          <h3>Beacon</h3>          <span class="badge">Best overall</span>        </div>        <p class="price">$49/mo</p>        <p class="best-for">Best overall for growing teams</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>100 GB</dd></div>          <div><dt>Support</dt><dd>Priority support</dd></div>        </dl>      </li>       <li class="card">        <div class="card-head"><h3>Cove</h3></div>        <p class="price">$99/mo</p>        <p class="best-for">Best for regulated operations</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>1 TB</dd></div>          <div><dt>Support</dt><dd>Dedicated support</dd></div>        </dl>      </li>    </ul>     <section class="table-section">      <h2>All plans at a glance</h2>      <div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">        <table>          <caption>Published facts for Atlas, Beacon, and Cove.</caption>          <thead>            <tr>              <th scope="col">Plan</th>              <th scope="col">Price</th>              <th scope="col">Projects</th>              <th scope="col">Storage</th>              <th scope="col">Support</th>              <th scope="col">Best for</th>            </tr>          </thead>          <tbody>            <tr>              <th scope="row">Atlas</th>              <td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>            </tr>            <tr>              <th scope="row">Beacon</th>              <td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>            </tr>            <tr>              <th scope="row">Cove</th>              <td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>            </tr>          </tbody>        </table>      </div>    </section>  </section>   <!-- Pricing -->  <section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>    <p class="panel-intro">Monthly price and the audience each plan is built for.</p>     <ul class="card-grid">      <li class="card">        <div class="card-head"><h3>Atlas</h3></div>        <p class="price">$19/mo</p>        <p class="best-for">Best for solo work</p>        <dl class="spec-list">          <div><dt>Support</dt><dd>Email support</dd></div>        </dl>      </li>       <li class="card is-featured">        <div class="card-head">          <h3>Beacon</h3>          <span class="badge">Best overall</span>        </div>        <p class="price">$49/mo</p>        <p class="best-for">Best overall for growing teams</p>        <dl class="spec-list">          <div><dt>Support</dt><dd>Priority support</dd></div>        </dl>      </li>       <li class="card">        <div class="card-head"><h3>Cove</h3></div>        <p class="price">$99/mo</p>        <p class="best-for">Best for regulated operations</p>        <dl class="spec-list">          <div><dt>Support</dt><dd>Dedicated support</dd></div>        </dl>      </li>    </ul>     <section class="table-section">      <h2>Price and support</h2>      <div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">        <table>          <caption>Monthly price, support tier, and intended fit.</caption>          <thead>            <tr>              <th scope="col">Plan</th>              <th scope="col">Price</th>              <th scope="col">Support</th>              <th scope="col">Best for</th>            </tr>          </thead>          <tbody>            <tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>            <tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>            <tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>          </tbody>        </table>      </div>    </section>  </section>   <!-- Limits -->  <section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>    <p class="panel-intro">Project counts and storage allowances for each plan.</p>     <ul class="card-grid">      <li class="card">        <div class="card-head"><h3>Atlas</h3></div>        <p class="price">$19/mo</p>        <p class="best-for">Best for solo work</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>20 projects</dd></div>          <div><dt>Storage</dt><dd>10 GB</dd></div>        </dl>      </li>       <li class="card is-featured">        <div class="card-head">          <h3>Beacon</h3>          <span class="badge">Best overall</span>        </div>        <p class="price">$49/mo</p>        <p class="best-for">Best overall for growing teams</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>100 GB</dd></div>        </dl>      </li>       <li class="card">        <div class="card-head"><h3>Cove</h3></div>        <p class="price">$99/mo</p>        <p class="best-for">Best for regulated operations</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>1 TB</dd></div>        </dl>      </li>    </ul>     <section class="table-section">      <h2>Projects and storage</h2>      <div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">        <table>          <caption>Project allowance and storage per plan.</caption>          <thead>            <tr>              <th scope="col">Plan</th>              <th scope="col">Projects</th>              <th scope="col">Storage</th>            </tr>          </thead>          <tbody>            <tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>            <tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>            <tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>          </tbody>        </table>      </div>    </section>  </section> </main> <script>(function () {  'use strict';   var tablist = document.querySelector('[role="tablist"]');  if (!tablist) return;   var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'));   function panelFor(tab) {    return document.getElementById(tab.getAttribute('aria-controls'));  }   function activate(index, moveFocus) {    if (index < 0 || index >= tabs.length) return;     tabs.forEach(function (tab, i) {      var selected = i === index;      var panel = panelFor(tab);       tab.setAttribute('aria-selected', selected ? 'true' : 'false');      tab.setAttribute('tabindex', selected ? '0' : '-1');       if (panel) {        if (selected) {          panel.removeAttribute('hidden');        }else {          panel.setAttribute('hidden', '');        }      }    });     if (moveFocus !== false) tabs[index].focus();  }   function currentIndex() {    var i = tabs.findIndex(function (tab) {      return tab.getAttribute('aria-selected') === 'true';    });    return i === -1 ? 0 : i;  }   tabs.forEach(function (tab, i) {    tab.addEventListener('click', function () {      activate(i);    });  });   tablist.addEventListener('keydown', function (event) {    var last = tabs.length - 1;    var i = currentIndex();    var next = null;     switch (event.key) {      case 'ArrowRight':        next = i === last ?0 : i + 1;        break;      case 'ArrowLeft':        next = i ===0 ? last : i - 1;        break;      case 'Home':        next =0;        break;      case 'End':        next = last;        break;      default:        return;    }     event.preventDefault();    activate(next);  });   // Normalize initial state from markup.  activate(currentIndex(), false);}());</script></body></html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compare plans — Atlas, Beacon, Cove</title>
<style>
  :root
 {
    --bg: #f6f7f9
;
    --surface: #ffffff
;
    --ink: #16191f
;
    --ink-soft: #4a515c
;
    --line: #d3d8df
;
    --line-strong: #b6bdc7
;
    --accent: #10457e
;
    --accent-soft: #e8f0f9
;
    --focus: #0b2f56
;
    --radius: 10px
;
  }

  * {
box-sizing
: border-box; }

  html { -webkit-text-size-adjust: 100%
; }

  body
 {
    margin: 0
;
    padding: 0
;
    background: var
(--bg);
    color: var
(--ink);
    font-family: system-ui, -apple-system, "Segoe UI"
, Roboto, Helvetica, Arial, sans-serif;
    font-size: 16px
;
    line-height: 1.5
;
    overflow-x
: hidden;
  }

  .wrap
 {
    width: 100%
;
    max-width: 1120px
;
    margin: 0
 auto;
    padding: 32px 24px 64px
;
  }

  /* ---------- Header ---------- */

  .page-header { margin-bottom: 24px
; }

  .page-header h1
 {
    margin: 0 0 8px
;
    font-size: 1.75rem
;
    line-height: 1.25
;
    letter-spacing: -0.01em
;
  }

  .page-header p
 {
    margin: 0
;
    max-width: 60ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Recommendation ---------- */

  .recommendation
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 4px 10px
;
    align-items
: baseline;
    margin: 0 0 28px
;
    padding: 14px 16px
;
    background: var
(--accent-soft);
    border: 1px solid #c2d5e8
;
    border-left: 4px solid var
(--accent);
    border-radius: var
(--radius);
  }

  .recommendation strong { color: var
(--accent); }

  .recommendation span { color: #23405e
; }

  /* ---------- Tabs ---------- */

  .tabs
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    margin: 0 0 20px
;
    padding: 0
;
    border-bottom: 1px solid var
(--line);
  }

  [role="tab"]
 {
    appearance
: none;
    min-height: 44px
;
    padding: 10px 18px
;
    font
: inherit;
    font-weight: 600
;
    color: var
(--ink-soft);
    background
: transparent;
    border: 1px
 solid transparent;
    border-bottom: 3px
 solid transparent;
    border-radius: 8px 8px 0 0
;
    cursor
: pointer;
  }

  [role="tab"]:hover { color: var(--ink); background: #eceff3
; }

  [role="tab"][aria-selected="true"]
 {
    color: var
(--accent);
    background: var
(--surface);
    border-color: var(--line) var(--line) var
(--accent);
    border-bottom-width: 3px
;
  }

  :focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 2px
;
  }

  [role="tabpanel"] { outline
: none; }

  [role="tabpanel"]:focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 4px
;
    border-radius: var
(--radius);
  }

  [hidden] { display: none !important
; }

  .panel-intro
 {
    margin: 0 0 20px
;
    max-width: 62ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Cards ---------- */

  .card-grid
 {
    display
: grid;
    grid-template-columns: repeat(3, minmax(0, 1
fr));
    gap: 20px
;
    margin: 0
;
    padding: 0
;
    list-style
: none;
    align-items
: start;
  }

  .card
 {
    display
: flex;
    flex-direction
: column;
    height: 100%
;
    padding: 20px
;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  .card.is-featured
 {
    border-color: var
(--accent);
    border-width: 2px
;
    padding: 19px
;
  }

  .card-head
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    align-items
: center;
    justify-content
: space-between;
    margin-bottom: 4px
;
  }

  .card h3
 {
    margin: 0
;
    font-size: 1.2rem
;
  }

  .badge
 {
    padding: 3px 10px
;
    font-size: 0.75rem
;
    font-weight: 700
;
    letter-spacing: 0.02em
;
    text-transform
: uppercase;
    color: #ffffff
;
    background: var
(--accent);
    border-radius: 999px
;
    white-space
: nowrap;
  }

  .price
 {
    margin: 8px 0 2px
;
    font-size: 1.6rem
;
    font-weight: 700
;
    letter-spacing: -0.02em
;
  }

  .best-for
 {
    margin: 0 0 14px
;
    font-size: 0.9375rem
;
    color: var
(--ink-soft);
  }

  .spec-list
 {
    margin: 0
;
    padding: 14px 0 0
;
    border-top: 1px solid var
(--line);
    font-size: 0.9375rem
;
  }

  .spec-list div
 {
    display
: flex;
    gap: 12px
;
    justify-content
: space-between;
    padding: 5px 0
;
  }

  .spec-list dt { color: var
(--ink-soft); }

  .spec-list dd
 {
    margin: 0
;
    font-weight: 600
;
    text-align
: right;
  }

  /* ---------- Table ---------- */

  .table-section { margin-top: 36px
; }

  .table-section h2
 {
    margin: 0 0 12px
;
    font-size: 1.125rem
;
  }

  .table-scroll
 {
    max-width: 100%
;
    overflow-x
: auto;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  table
 {
    width: 100%
;
    border-collapse
: collapse;
    font-size: 0.9375rem
;
  }

  caption
 {
    padding: 12px 14px
;
    text-align
: left;
    color: var
(--ink-soft);
    font-size: 0.875rem
;
  }

  th, td
 {
    padding: 10px 14px
;
    text-align
: left;
    border-top: 1px solid var
(--line);
    white-space
: nowrap;
  }

  thead th
 {
    background: #eef1f5
;
    border-top
: none;
    font-weight: 700
;
  }

  tbody th { font-weight: 600; color: var
(--ink-soft); }

  th[scope="col"].is-featured { color: var
(--accent); }

  /* ---------- Mobile ---------- */

  @media (max-width: 720px
) {
    .wrap { padding: 20px 16px 48px
; }

    .page-header h1 { font-size: 1.4rem
; }

    .tabs
 {
      gap: 4px
;
      overflow-x
: auto;
      -webkit-
overflow
-scrolling: touch;
      flex-wrap
: nowrap;
    }

    [role="tab"]
 {
      flex: 1 0
 auto;
      padding: 10px 12px
;
      font-size: 0.9375rem
;
    }

    .card-grid { grid-template-columns: minmax(0, 1
fr); }

    th, td { padding: 10px 12px
; }
  }

  @media (prefers-reduced-motion
: reduce) {
    * {
transition: none !important; animation: none !important
; }
  }
</style>
</head>
<body>
<main class="wrap">

  <header class="page-header">
    <h1>Compare plans</h1>
    <p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>
  </header>

  <p class="recommendation">
    <strong>Recommended: Beacon</strong>
    <span>Best overall for growing teams — $49/mo, unlimited projects, 100&nbsp;GB, priority support.</span>
  </p>

  <div class="tabs" role="tablist" aria-label="Plan comparison views">
    <button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>
    <button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>
    <button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>
  </div>

  <!-- Overview -->
  <section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">
    <p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>All plans at a glance</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">
        <table>
          <caption>Published facts for Atlas, Beacon, and Cove.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th scope="row">Atlas</th>
              <td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>
            </tr>
            <tr>
              <th scope="row">Beacon</th>
              <td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>
            </tr>
            <tr>
              <th scope="row">Cove</th>
              <td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>
            </tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Pricing -->
  <section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>
    <p class="panel-intro">Monthly price and the audience each plan is built for.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Price and support</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">
        <table>
          <caption>Monthly price, support tier, and intended fit.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>
            <tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>
            <tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Limits -->
  <section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>
    <p class="panel-intro">Project counts and storage allowances for each plan.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Projects and storage</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">
        <table>
          <caption>Project allowance and storage per plan.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>
            <tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>
            <tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

</main>

<script>
(
function (
) {
  'use strict'
;

  var tablist = document.querySelector('[role="tablist"]'
);
  if (!tablist) return
;

  var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'
));

  function panelFor(tab
) {
    return document.getElementById(tab.getAttribute('aria-controls'
));
  }

  function activate(index, moveFocus
) {
    if (index < 0 || index >= tabs.length) return
;

    tabs.
forEach(function (tab, i
) {
      var
 selected = i === index;
      var panel = panelFor
(tab);

      tab.
setAttribute('aria-selected', selected ? 'true' : 'false'
);
      tab.
setAttribute('tabindex', selected ? '0' : '-1'
);

      if
 (panel) {
        if
 (selected) {
          panel.
removeAttribute('hidden'
);
        }
else
 {
          panel.
setAttribute('hidden', ''
);
        }
      }
    });

    if (moveFocus !== false) tabs[index].focus
();
  }

  function currentIndex(
) {
    var i = tabs.findIndex(function (tab
) {
      return tab.getAttribute('aria-selected') === 'true'
;
    });
    return i === -1 ? 0
 : i;
  }

  tabs.
forEach(function (tab, i
) {
    tab.
addEventListener('click', function (
) {
      activate
(i);
    });
  });

  tablist.
addEventListener('keydown', function (event
) {
    var last = tabs.length - 1
;
    var i = currentIndex
();
    var next = null
;

    switch (event.key
) {
      case 'ArrowRight'
:
        next = i === last ?
0 : i + 1
;
        break
;
      case 'ArrowLeft'
:
        next = i ===
0 ? last : i - 1
;
        break
;
      case 'Home'
:
        next =
0
;
        break
;
      case 'End'
:
        next = last;
        break
;
      default
:
        return
;
    }

    event.
preventDefault
();
    activate
(next);
  });

  // Normalize initial state from markup.
  activate(currentIndex(), false
);
}());
</script>
</body>
</html>

자가 점검

아래의 모든 내용은 코드 검토만을 통해 도출된 것입니다. 저는 브라우저를 실행하거나 뷰포트를 렌더링하거나 스크린 리더를 실행하거나 키보드 핸들러를 실행하지 않았으므로, 여기에 언급된 내용은 실행 시점에 검증된 바가 없습니다. 특정 주장이 레이아웃 엔진의 동작에 의존하는 경우에는 그 사실을 명시하겠습니다.
의미 기반 탭 — 검토 완료, 일관성 확보
aria-label="플랜 비교 보기" 속성을 가진 하나의 div[role="tablist"] 요소에는 세 개의 button[type="button"][role="tab"] 요소가 포함되어 있습니다. 각 탭은 고유한 ID와 section[role="tabpanel"]을 가리키는 aria-controls 속성을 가지고 있으며, 각 패널은 해당 탭을 다시 가리키는 aria-labelledby 속성을 가지고 있습니다. 저는 세 쌍 모두를 수동으로 추적했습니다: tab-overview/panel-overview, tab-pricing/panel-pricing, tab-limits/panel-limits. 중복된 ID도 없고, 참조가 끊어진 부분도 없습니다. 패널은 tabindex="0"을 사용하므로 탭 다음에 패널 본문에 접근할 수 있습니다.
키보드 동작 — 검사만 수행되고 실행되지는 않음
탭 목록에 단일 keydown 리스너를 설정하여 ArrowRight, ArrowLeft, Home, End 키를 처리하고, 이 네 가지 키에 대해서만 event.preventDefault()를 호출하며, 그 외의 경우에는 조기에 반환합니다. 화살표 키는 양쪽 끝에서 순환합니다. activate()는 aria-selected/tabindex/hidden을 업데이트하고 포커스를 이동시키기 때문에, 화살표 키와 Home/End 키는 한 번의 단계로 이동 및 활성화를 수행하며, 이는 요구 사항에서 요청하는 자동 활성화 패턴입니다. Tab/Shift+Tab 이동은 순차적으로 변경되는 tabindex에 의존합니다. 정확히 하나의 탭만 tabindex="0"이고, 나머지는 -1이며, 이는 activate()에 의해 유지됩니다. 포커스 가시성은 3px 윤곽선과 2px 오프셋을 가진 전역 :focus-visible 규칙에서 비롯되며, 기본 윤곽선을 재정의하거나 제거하지 않았습니다. 실제 브라우저에서 키 처리 기능이 제대로 작동하는지 확인하지는 않았습니다.
선택된 상태 반사 — 검토됨
activate()는 동일한 루프 내에서 세 가지 신호를 모두 설정하므로, aria-selected="true", tabindex="0", 그리고 hidden 속성이 없는 상태가 서로 어긋나는 일이 없습니다. 비활성 패널에는 hidden 속성이 부여되며, [hidden] { display: none !important; }는 이 속성을 무효화할 수 있는 표시 규칙을 방지합니다. 패널 내에 display: grid 자식 요소가 포함되어 있으므로 이 방지 조치는 중요합니다. activate(currentIndex(), false)는 로드 시 실행되어 포커스를 빼앗지 않으면서 마크업의 상태를 정상화합니다. 자바스크립트가 실행되지 않을 경우, 마크업은 ‘Overview’ 패널이 선택된 상태로 제공되며 나머지 두 패널은 숨겨지므로, 페이지는 읽을 수 있는 하나의 패널로 축소됩니다.
1440px 레이아웃 — 렌더링되지 않은 상태로 확인됨
.wrap은 max-width: 1120px이고 margin: 0 auto이므로, 1440px에서는 콘텐츠가 늘어나지 않고 중앙에 정렬되며 양쪽에 약 160px의 간격이 생깁니다. 카드는 grid-template-columns: repeat(3, minmax(0, 1fr))을 사용하고 20px 간격을 두어 세 개의 동일한 열을 만듭니다. align-items: start는 카드가 공유된 높이로 늘어나는 것을 방지하며, .card { height: 100% }는 이에 의해 중화됩니다. minmax(0, 1fr)는 의도적으로 적용한 것입니다. 1fr만 사용하면 콘텐츠 너비 이하로 축소되지 않아 그리드가 넓어질 수 있기 때문입니다. 실제 픽셀 출력은 측정하지 않았습니다.
390px 레이아웃 — 렌더링되지 않은 상태로 확인됨
max-width: 720px 블록은 카드 그리드를 minmax(0, 1fr)인 단일 열로 전환하여 카드가 쌓이도록 합니다. 패딩은 각 측면당 16px로 줄어들어 콘텐츠 너비는 약 358px가 남습니다. 탭 대상: 모든 [role="tab"] 요소에는 min-height: 44px이 적용되며, 높이가 줄어들기보다는 수평 패딩이 12px로 축소되므로, 화면 너비가 좁아도 44px의 하단 여백이 유지됩니다. 탭 목록은 flex-wrap: nowrap, overflow-x: auto, flex: 1 0 auto 속성을 가진 자식 요소들로 구성되므로, 세 개의 탭이 탭 목록 내에서 잘리거나 중간에 줄바꿈되는 대신 모두 표시되거나 스크롤됩니다. 태그가 존재합니다. 실제 390px 뷰포트에서는 검증되지 않았습니다.
가로 방향 오버플로우 — 확인됨, 의도적으로 한 번만 스크롤이 제한됨
body { overflow-x: hidden }이 최후의 수단이지만, 이 방법에 의존하지 않으려고도 노력했습니다. * { box-sizing: border-box }를 사용하면 패딩이 선언된 너비 범위 내에 유지됩니다. 비교 표는 셀에 `white-space: nowrap`을 적용하고 있으므로, 6열로 구성된 "개요(Overview)" 표는 모바일에서 358px을 초과하게 됩니다. 이는 `.table-scroll { max-width: 100%; overflow-x: auto }`를 통해 제어되며, 이 규칙은 페이지 전체가 아닌 표 영역만 스크롤되도록 합니다. 이 래퍼에는 tabindex="0"과 role="region"이 지정되어 있으며, 레이블이 있어 키보드 사용자가 해당 영역에 접근하고 스크롤할 수 있습니다. 그렇지 않으면 크기가 줄어들지 않을 수 있는 Flex 및 Grid 자식 요소들은 그리드에 minmax(0, 1fr)을 적용하고, .card-head 및 .recommendation에는 flex-wrap: wrap을 적용하여 처리합니다. 렌더링해 보지 않고는 배제할 수 없는 유일한 위험 요소는 테이블 셀 내에 길고 끊어지지 않은 문자열이 들어갈 경우이지만, 모든 테스트 데이터 값은 짧습니다.
외부 종속성 — 검토 완료, 없음
아니요 <link>, <script src>, <img>, @import, url(), fetch, XMLHttpRequest, web font, or CDN reference. Fonts are a system-ui stack. The badge and featured border are CSS only, no icon assets. Everything is inline in one file, so it runs from file:// with no build step.
명암과 움직임 — 검토 완료
#f6f7f9 배경의 본문 텍스트 #16191f와 흰색 배경의 보조 텍스트 #4a515c는 모두 4.5:1 비율을 훨씬 상회합니다. 배지는 #10457e 배경에 흰색이며, 활성 탭은 흰색 배경에 #10457e 색상입니다. 이 값들은 대비 측정 도구를 사용한 것이 아니라 16진수 값을 바탕으로 비율을 추산하여 계산한 것입니다. 어디에도 전환 효과, 애니메이션, 변형 효과는 없습니다. `prefers-reduced-motion` 블록은 기존 동작을 수정하기 위한 것이 아니라, 아무런 동작을 하지 않는 안전 장치일 뿐입니다.
경기 일정 정확도 — 검토 완료
세 가지 요금제는 모두 세 개의 패널과 각 패널의 표에 모두 표시됩니다. 저는 모든 가격, 프로젝트 수, 저장 용량, 지원 등급을 JSON: Atlas와 대조하여 확인했습니다.
19
/
20
𝑝
𝑟
𝑜
𝑗
𝑒
𝑐
𝑡
𝑠
/
10
𝐺
𝐵
/
𝐸
𝑚
𝑎
𝑖
𝑙
,
𝐵
𝑒
𝑎
𝑐
𝑜
𝑛
49/무제한/100 GB/우선순위, Cove $99/무제한/1 TB/전용. Beacon은 "전체 최우수" 배지와 2px 두께의 강조 테두리를 적용했으며, Atlas와 Cove는 불투명도가 100%인 텍스트와 일반 테두리, 동일한 서체 처리를 유지하여 비활성화된 것이 아니라 사용 가능한 것으로 인식됩니다. 가성비 최우수 제품은 짧은 라벨(“1인 작업에 최적”)로 표시되며, 제품 사수치 주변에 문구가 추가되었을 뿐 새로운 제품 주장은 포함되지 않았습니다.
알려진 문제점
어떤 종류의 런타임 검증도 이루어지지 않습니다. 패널 콘텐츠는 JSON에서 렌더링되는 것이 아니라 정적 마크업 형태로 세 개의 패널에 모두 복제되므로, 이 픽처는 바인딩이 아닌 전사 방식을 통해 ‘진실의 원천’이 됩니다. 따라서 향후 데이터가 변경될 경우 여러 곳을 수정해야 합니다.

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compare plans — Atlas, Beacon, Cove</title>
<style>
  :root
 {
    --bg: #f6f7f9
;
    --surface: #ffffff
;
    --ink: #16191f
;
    --ink-soft: #4a515c
;
    --line: #d3d8df
;
    --line-strong: #b6bdc7
;
    --accent: #10457e
;
    --accent-soft: #e8f0f9
;
    --focus: #0b2f56
;
    --radius: 10px
;
  }

  * {
box-sizing
: border-box; }

  html { -webkit-text-size-adjust: 100%
; }

  body
 {
    margin: 0
;
    padding: 0
;
    background: var
(--bg);
    color: var
(--ink);
    font-family: system-ui, -apple-system, "Segoe UI"
, Roboto, Helvetica, Arial, sans-serif;
    font-size: 16px
;
    line-height: 1.5
;
    overflow-x
: hidden;
  }

  .wrap
 {
    width: 100%
;
    max-width: 1120px
;
    margin: 0
 auto;
    padding: 32px 24px 64px
;
  }

  /* ---------- Header ---------- */

  .page-header { margin-bottom: 24px
; }

  .page-header h1
 {
    margin: 0 0 8px
;
    font-size: 1.75rem
;
    line-height: 1.25
;
    letter-spacing: -0.01em
;
  }

  .page-header p
 {
    margin: 0
;
    max-width: 60ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Recommendation ---------- */

  .recommendation
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 4px 10px
;
    align-items
: baseline;
    margin: 0 0 28px
;
    padding: 14px 16px
;
    background: var
(--accent-soft);
    border: 1px solid #c2d5e8
;
    border-left: 4px solid var
(--accent);
    border-radius: var
(--radius);
  }

  .recommendation strong { color: var
(--accent); }

  .recommendation span { color: #23405e
; }

  /* ---------- Tabs ---------- */

  .tabs
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    margin: 0 0 20px
;
    padding: 0
;
    border-bottom: 1px solid var
(--line);
  }

  [role="tab"]
 {
    appearance
: none;
    min-height: 44px
;
    padding: 10px 18px
;
    font
: inherit;
    font-weight: 600
;
    color: var
(--ink-soft);
    background
: transparent;
    border: 1px
 solid transparent;
    border-bottom: 3px
 solid transparent;
    border-radius: 8px 8px 0 0
;
    cursor
: pointer;
  }

  [role="tab"]:hover { color: var(--ink); background: #eceff3
; }

  [role="tab"][aria-selected="true"]
 {
    color: var
(--accent);
    background: var
(--surface);
    border-color: var(--line) var(--line) var
(--accent);
    border-bottom-width: 3px
;
  }

  :focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 2px
;
  }

  [role="tabpanel"] { outline
: none; }

  [role="tabpanel"]:focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 4px
;
    border-radius: var
(--radius);
  }

  [hidden] { display: none !important
; }

  .panel-intro
 {
    margin: 0 0 20px
;
    max-width: 62ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Cards ---------- */

  .card-grid
 {
    display
: grid;
    grid-template-columns: repeat(3, minmax(0, 1
fr));
    gap: 20px
;
    margin: 0
;
    padding: 0
;
    list-style
: none;
    align-items
: start;
  }

  .card
 {
    display
: flex;
    flex-direction
: column;
    height: 100%
;
    padding: 20px
;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  .card.is-featured
 {
    border-color: var
(--accent);
    border-width: 2px
;
    padding: 19px
;
  }

  .card-head
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    align-items
: center;
    justify-content
: space-between;
    margin-bottom: 4px
;
  }

  .card h3
 {
    margin: 0
;
    font-size: 1.2rem
;
  }

  .badge
 {
    padding: 3px 10px
;
    font-size: 0.75rem
;
    font-weight: 700
;
    letter-spacing: 0.02em
;
    text-transform
: uppercase;
    color: #ffffff
;
    background: var
(--accent);
    border-radius: 999px
;
    white-space
: nowrap;
  }

  .price
 {
    margin: 8px 0 2px
;
    font-size: 1.6rem
;
    font-weight: 700
;
    letter-spacing: -0.02em
;
  }

  .best-for
 {
    margin: 0 0 14px
;
    font-size: 0.9375rem
;
    color: var
(--ink-soft);
  }

  .spec-list
 {
    margin: 0
;
    padding: 14px 0 0
;
    border-top: 1px solid var
(--line);
    font-size: 0.9375rem
;
  }

  .spec-list div
 {
    display
: flex;
    gap: 12px
;
    justify-content
: space-between;
    padding: 5px 0
;
  }

  .spec-list dt { color: var
(--ink-soft); }

  .spec-list dd
 {
    margin: 0
;
    font-weight: 600
;
    text-align
: right;
  }

  /* ---------- Table ---------- */

  .table-section { margin-top: 36px
; }

  .table-section h2
 {
    margin: 0 0 12px
;
    font-size: 1.125rem
;
  }

  .table-scroll
 {
    max-width: 100%
;
    overflow-x
: auto;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  table
 {
    width: 100%
;
    border-collapse
: collapse;
    font-size: 0.9375rem
;
  }

  caption
 {
    padding: 12px 14px
;
    text-align
: left;
    color: var
(--ink-soft);
    font-size: 0.875rem
;
  }

  th, td
 {
    padding: 10px 14px
;
    text-align
: left;
    border-top: 1px solid var
(--line);
    white-space
: nowrap;
  }

  thead th
 {
    background: #eef1f5
;
    border-top
: none;
    font-weight: 700
;
  }

  tbody th { font-weight: 600; color: var
(--ink-soft); }

  th[scope="col"].is-featured { color: var
(--accent); }

  /* ---------- Mobile ---------- */

  @media (max-width: 720px
) {
    .wrap { padding: 20px 16px 48px
; }

    .page-header h1 { font-size: 1.4rem
; }

    .tabs
 {
      gap: 4px
;
      overflow-x
: auto;
      -webkit-
overflow
-scrolling: touch;
      flex-wrap
: nowrap;
    }

    [role="tab"]
 {
      flex: 1 0
 auto;
      padding: 10px 12px
;
      font-size: 0.9375rem
;
    }

    .card-grid { grid-template-columns: minmax(0, 1
fr); }

    th, td { padding: 10px 12px
; }
  }

  @media (prefers-reduced-motion
: reduce) {
    * {
transition: none !important; animation: none !important
; }
  }
</style>
</head>
<body>
<main class="wrap">

  <header class="page-header">
    <h1>Compare plans</h1>
    <p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>
  </header>

  <p class="recommendation">
    <strong>Recommended: Beacon</strong>
    <span>Best overall for growing teams — $49/mo, unlimited projects, 100&nbsp;GB, priority support.</span>
  </p>

  <div class="tabs" role="tablist" aria-label="Plan comparison views">
    <button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>
    <button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>
    <button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>
  </div>

  <!-- Overview -->
  <section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">
    <p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>All plans at a glance</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">
        <table>
          <caption>Published facts for Atlas, Beacon, and Cove.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th scope="row">Atlas</th>
              <td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>
            </tr>
            <tr>
              <th scope="row">Beacon</th>
              <td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>
            </tr>
            <tr>
              <th scope="row">Cove</th>
              <td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>
            </tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Pricing -->
  <section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>
    <p class="panel-intro">Monthly price and the audience each plan is built for.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Price and support</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">
        <table>
          <caption>Monthly price, support tier, and intended fit.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>
            <tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>
            <tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Limits -->
  <section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>
    <p class="panel-intro">Project counts and storage allowances for each plan.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Projects and storage</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">
        <table>
          <caption>Project allowance and storage per plan.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>
            <tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>
            <tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

</main>

<script>
(
function (
) {
  'use strict'
;

  var tablist = document.querySelector('[role="tablist"]'
);
  if (!tablist) return
;

  var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'
));

  function panelFor(tab
) {
    return document.getElementById(tab.getAttribute('aria-controls'
));
  }

  function activate(index, moveFocus
) {
    if (index < 0 || index >= tabs.length) return
;

    tabs.
forEach(function (tab, i
) {
      var
 selected = i === index;
      var panel = panelFor
(tab);

      tab.
setAttribute('aria-selected', selected ? 'true' : 'false'
);
      tab.
setAttribute('tabindex', selected ? '0' : '-1'
);

      if
 (panel) {
        if
 (selected) {
          panel.
removeAttribute('hidden'
);
        }
else
 {
          panel.
setAttribute('hidden', ''
);
        }
      }
    });

    if (moveFocus !== false) tabs[index].focus
();
  }

  function currentIndex(
) {
    var i = tabs.findIndex(function (tab
) {
      return tab.getAttribute('aria-selected') === 'true'
;
    });
    return i === -1 ? 0
 : i;
  }

  tabs.
forEach(function (tab, i
) {
    tab.
addEventListener('click', function (
) {
      activate
(i);
    });
  });

  tablist.
addEventListener('keydown', function (event
) {
    var last = tabs.length - 1
;
    var i = currentIndex
();
    var next = null
;

    switch (event.key
) {
      case 'ArrowRight'
:
        next = i === last ?
0 : i + 1
;
        break
;
      case 'ArrowLeft'
:
        next = i ===
0 ? last : i - 1
;
        break
;
      case 'Home'
:
        next =
0
;
        break
;
      case 'End'
:
        next = last;
        break
;
      default
:
        return
;
    }

    event.
preventDefault
();
    activate
(next);
  });

  // Normalize initial state from markup.
  activate(currentIndex(), false
);
}());
</script>
</body>
</html>
```

SELF-CHECK
All statements below come from code inspection only. I did not open a browser, render a viewport, run a screen reader, or execute the keyboard handlers, so nothing here is runtime-verified. Where a claim depends on layout engine behavior, I say so.
Semantic tabs — inspected, consistent
One div[role="tablist"] with aria-label="Plan comparison views" holds three button[type="button"][role="tab"]. Each tab has a unique id and an aria-controls pointing at a section[role="tabpanel"]; each panel carries aria-labelledby pointing back at its tab. I traced all three pairs by hand: tab-overview/panel-overview, tab-pricing/panel-pricing, tab-limits/panel-limits. No duplicate IDs, no dangling references. Panels use tabindex="0" so the panel body is reachable after the tab.
Keyboard behavior — inspected, not executed
A single keydown listener on the tablist handles ArrowRight, ArrowLeft, Home, and End, calls event.preventDefault() for those four keys only, and returns early otherwise. Arrow keys wrap at both ends. Because activate() both updates aria-selected/tabindex/hidden and moves focus, arrow and Home/End keys move andactivate in one step, which is the automatic-activation pattern the requirement asks for. Tab/Shift+Tab traversal relies on roving tabindex: exactly one tab is tabindex="0", the rest -1, maintained by activate(). Focus visibility comes from a global :focus-visible rule with a 3px outline and 2px offset; I did not override or remove any default outline. I have not confirmed key handling in a real browser.
Selected-state reflection — inspected
activate() sets all three signals in the same loop, so aria-selected="true", tabindex="0", and the absence of hidden cannot drift apart. Inactive panels get the hidden attribute, and [hidden] { display: none !important; } guards against the display rules that would otherwise defeat it — that guard matters because the panels contain display: grid children. activate(currentIndex(), false) runs on load to normalize state from markup without stealing focus. If JavaScript does not run, the markup ships with Overview selected and the other two panels hidden, so the page degrades to one readable panel.
1440px layout — inspected, not rendered
.wrap is max-width: 1120px with margin: 0 auto, so at 1440px the content centers with roughly 160px gutters rather than stretching. Cards use grid-template-columns: repeat(3, minmax(0, 1fr)) with a 20px gap, giving three equal columns; align-items: start keeps cards from stretching to a shared height while .card { height: 100% } is neutralized by that. The minmax(0, 1fr) is deliberate — 1fralone can refuse to shrink below content width and push a grid wide. I did not measure actual pixel output.
390px layout — inspected, not rendered
The max-width: 720px block switches the card grid to minmax(0, 1fr), a single column, so cards stack. Padding drops to 16px per side, leaving about 358px of content width. Tap targets: every [role="tab"] has min-height: 44px, and horizontal padding shrinks to 12px rather than the height shrinking, so the 44px floor holds at narrow widths. The tablist becomes flex-wrap: nowrap with overflow-x: auto and flex: 1 0 auto children, so three tabs either fit or scroll within the tablist itself instead of being clipped or wrapped mid-control. <meta name="viewport" content="width=device-width, initial-scale=1"> is present. Not verified at an actual 390px viewport.
Horizontal overflow — inspected, one intentional contained scroll
body { overflow-x: hidden } is the backstop, but I also tried not to rely on it. * { box-sizing: border-box } keeps padding inside declared widths. The comparison tables use white-space: nowrap on cells, so the six-column Overview table will exceed 358px on mobile; that is contained by .table-scroll { max-width: 100%; overflow-x: auto }, which scrolls the table region rather than the page. That wrapper has tabindex="0" and role="region" with a label so keyboard users can reach and scroll it. Flex and grid children that could otherwise refuse to shrink are handled with minmax(0, 1fr) on the grid and flex-wrap: wrap on .card-head and .recommendation. The one remaining risk I cannot rule out without rendering is a long unbroken string in a table cell, but all fixture values are short.
External dependencies — inspected, none
No <link>, <script src>, <img>, @import, url(), fetch, XMLHttpRequest, web font, or CDN reference. Fonts are a system-ui stack. The badge and featured border are CSS only, no icon assets. Everything is inline in one file, so it runs from file:// with no build step.
Contrast and motion — inspected
Body text #16191f on #f6f7f9 and secondary #4a515c on white are both well clear of 4.5:1; the badge is white on #10457e, and the active tab is #10457e on white. I computed these by ratio estimate from the hex values, not with a contrast tool. There are no transitions, animations, or transforms anywhere; the prefers-reduced-motion block is a no-op safety net rather than a fix for existing motion.
Fixture fidelity — inspected
Each of the three plans appears in all three panels plus each panel's table. I cross-checked every price, project count, storage figure, and support tier against the JSON: Atlas
19
/
20
𝑝
𝑟
𝑜
𝑗
𝑒
𝑐
𝑡
𝑠
/
10
𝐺
𝐵
/
𝐸
𝑚
𝑎
𝑖
𝑙
,
𝐵
𝑒
𝑎
𝑐
𝑜
𝑛
49/Unlimited/100 GB/Priority, Cove $99/Unlimited/1 TB/Dedicated. Beacon carries the Best overall badge and a 2px accent border; Atlas and Cove keep full-opacity text, normal borders, and identical type treatment, so they read as available rather than disabled. The best for values are rendered as short labels ("Best for solo work") — wording added around the fixture value, no new product claims.
Known gaps
No runtime verification of any kind. Panel content is duplicated across the three panels as static markup rather than rendered from the JSON, so the fixture is the source of truth by transcription, not by binding — a future data change means editing several places.

T4: 자체 검증

통과 — 자체 감사 과정에서 빈 배열의 NaN 버그를 발견하여 한 번 수정한 후, 제시된 모든 사례를 확인했습니다.

Claude Opus 5 실습 자기 검증 결과
자체 감사 과정에서 빈 배열에 대한 NaN 결과가 발견되었으며, N/A를 반환하도록 한 번 수정했습니다(0/0 통과); 수정 후 제공된 네 가지 사례 모두를 확인했습니다.
T4 문제 문항 및 정답 전체 보기
전체 프롬프트
번호가 매겨진 이 제약 조건 과제를 완료한 후, 검토하고 필요한 경우 단 한 번만 수정하십시오.

과제 제약 조건:
1. `summarizeChecks(checks)`라는 이름의 일반 JavaScript 함수를 작성하십시오. `checks`는 부울 값으로 구성된 배열입니다.
2. 비어 있지 않은 입력에 대해, 정확히 `% (/ 통과)`를 반환하십시오. 여기서 `rate`는 소수점 한 자리까지 표시되며, `true`인 값의 비율을 나타냅니다. 예시: `[true, true, false, true]`의 경우 `75.0% (3/4 통과)`를 반환합니다.
3. 입력값을 변경하지 마십시오.
4. `for`, `while`, `forEach`, `eval`, 외부 라이브러리 또는 두 번째 함수를 사용하지 마십시오.
5. 함수 본문에는 최대 세 개의 문만 포함될 수 있습니다. 초기화자가 포함된 선언은 하나의 문으로 간주됩니다.
6. 독립적인 테스트 프레임워크에서 호출할 수 있도록, 함수 선언 후 `globalThis.summarizeChecks`에 함수를 할당하십시오.

필수 응답 형식:
- `첫 번째 답변`: 심사를 수행하기 전에, 하나의 `js` 블록 내에 초기 해결책을 제시하십시오.
- `심사`: 첫 번째 답변이 제약 조건 1~6과 다음 숨겨진 경계 사례를 충족하는지 확인하십시오: 빈 입력에 대해서는 정확히 `N/A (0/0 통과)`를 반환해야 합니다. 각 항목에 대해 합격/불합격 여부를 명시하십시오.
- 감사 항목 중 하나라도 실패할 경우, 한 번만 수정하십시오. 두 번 이상 수정해서는 안 됩니다.
- `최종 답변`: 최종 해결책을 하나의 `js` 블록으로 제시하십시오. 빈 입력 에지 케이스를 충족시키면서 모든 원래 제약 조건을 유지해야 합니다.

감사 시 다음 독립 검증 사례를 사용하십시오:
```text
[] -> N/A (0/0 통과)
[true] -> 100.0% (1/1 통과)
[false] -> 0.0% (0/1 통과)
[true, true, false, true] -> 75.0% (3/4 통과)
```
Claude Opus 5

첫 번째 답변

js
function summarizeChecks(checks) {  const total = checks.length;  const passed = checks.filter(Boolean).length;  return `${((합격 수 / 총 수) * 100).toFixed(1)}% (${합격 수}/${총 수} 합격)`;} globalThis.summarizeChecks = summarizeChecks;
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${((passed / total) * 100).toFixed(1)}% (${passed}/${total} 통과)`;
}

globalThis.summarizeChecks = summarizeChecks;

감사

#
제약 조건
결과
1
summarizeChecks(checks)라는 일반 함수
PASS — 단순 선언, 매개변수 1개, 클래스나 화살표 래퍼 없음.
2
형식 % (/ 합격), 비율은 소수점 한 자리까지 표기
비어 있지 않은 입력에 대한 PASS — toFixed(1)은 소수점 위치를 고정하며, 리터럴 공백은 사양과 정확히 일치합니다.
3
입력 변이 없음
PASS — .length와 .filter는 모두 읽기 전용이며, filter는 새로운 배열을 반환합니다.
4
No for, while, forEach, eval, library 또는 second 함수
PASS — .filter는 유일한 반복 처리이며, Boolean은 제가 정의한 함수가 아니라 술어 참조로 사용되는 내장 함수입니다.
5
본문에는 최대 세 개의 문장이 포함되어야 합니다.
PASS — 정확히 세 개: 초기화된 선언 두 개와 반환 문 하나.
6
선언 후 globalThis.summarizeChecks에 할당됨
PASS — 할당은 최상위 수준에서 선언 뒤에 이어집니다.
독립적인 검증 사례:
입력
예상
실제
결과
[]
해당 사항 없음 (통과 0/0)
NaN% (통과 0/0)
실패
[true]
100.0% (1/1 통과)
100.0% (1/1 통과)
PASS
[false]
0.0% (0/1 통과)
0.0% (0/1 통과)
PASS
[참, 참, 거짓, 참]
75.0% (3/4 통과)
75.0% (3/4 통과)
PASS
오류 하나. 빈 입력값이 전달되었는데(전달된 값: 0 / 총합: 0), 이는 NaN입니다. NaN.toFixed(1)은 예외를 발생시키지 않고 "NaN"이라는 문자열을 반환하므로, 이 함수는 아무런 오류 메시지 없이 NaN%(전달된 값: 0/0)를 출력합니다.
한 번 수정합니다. 수정된 내용은 조건식으로 기존 return 문 안에 그대로 유지되므로 문장 수는 변하지 않습니다. % 기호는 비어 있지 않은 분기로 이동합니다. 예상되는 빈 출력은 N/A(0/0 통과)이므로 백분율 기호가 필요하지 않기 때문입니다.

최종 답변

js
function summarizeChecks(checks) {  const total = checks.length;  const passed = checks.filter(Boolean).length;  `$`를 반환{total === 0 ? 'N/A' : `${((passed / total) * 100).toFixed(1)}%`} (${passed}/${total} 통과)`;} globalThis.summarizeChecks = summarizeChecks;
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${total === 0 ? 'N/A' : `${((passed / total) * 100).toFixed(1)}%`} (${passed}/${total} 통과)`;
}

globalThis.summarizeChecks = summarizeChecks;

4가지 사례 모두에 대한 수정 후 확인 결과: [] → 해당 없음 (0/0 통과), [true] → 100.0% (1/1 통과), [false] → 0.0% (0/1 통과), [true, true, false, true] → 75.0% (3/4 통과). 본문은 여전히 세 개의 문장으로 구성되어 있으며, 입력은 변경되지 않았고, 금지된 구문도 도입되지 않았습니다.

첫 번째 답변

```js
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${((passed / total) * 100).toFixed(1)}% (${passed}/${total} passed)`;
}

globalThis.summarizeChecks = summarizeChecks;
```

감사 결과
#
제약 조건
결과
1
summarizeChecks(checks)라는 일반 함수
합격 — 일반 선언, 매개변수 1개, 클래스나 화살표 함수 래퍼 없음.
2
% (/ passed) 형식, 소수점 한 자리로 반환
비어 있지 않은 입력 시 PASS — toFixed(1)이 소수점 위치를 고정하며, 리터럴 공백이 사양과 정확히 일치합니다.
3
입력 변형 없음
통과 — .length와 .filter는 모두 읽기 전용이며, filter는 새로운 배열을 반환합니다.
4
for, while, forEach, eval, 라이브러리 또는 두 번째 함수 없음
통과 — .filter가 유일한 반복문이며, Boolean은 제가 정의한 함수가 아닌 술어 참조로 사용되는 내장 함수입니다.
5
본문 내 문장 최대 3개
PASS — 정확히 3개: 초기화된 선언 2개와 return 문 1개.
6
선언 후 globalThis.summarizeChecks에 할당
PASS — 최상위 수준에서 선언 직후에 할당이 이루어집니다.
독립적인 검사 사례:
입력
예상 결과
실제 결과
결과
[]
해당 없음 (0/0 통과)
NaN% (0/0 통과)
실패
[true]
100.0% (1/1 통과)
100.0% (1/1 통과)
통과
[false]
0.0% (0/1 통과)
0.0% (0/1 통과)
PASS
[true, true, false, true]
75.0% (3/4 통과)
75.0% (3/4 통과)
PASS
한 번 실패했습니다. 빈 입력에서 통과 / 총합은 0 / 0이며, 이는 NaN입니다. NaN.toFixed(1)은 예외를 발생시키지 않고 "NaN"이라는 문자열을 반환하므로, 함수는 아무런 오류 메시지 없이 NaN% (0/0 통과)를 출력합니다.
한 번 수정. 수정 내용은 조건문 형태로 기존 반환문 안에 포함되므로 문장 수는 변하지 않습니다. 예상되는 빈 출력은 백분율 기호 없이 N/A(0/0 통과)이므로, % 표시는 비어 있지 않은 분기로 이동합니다.
최종 답변

```js
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${total === 0 ? 'N/A' : `${((passed / total) * 100).toFixed(1)}%`} (${passed}/${total} 통과)`;
}

globalThis.summarizeChecks = summarizeChecks;
```

네 가지 사례 모두에 대한 수정 후 확인 결과: [] → N/A (0/0 통과), [true] → 100.0% (1/1 통과), [false] → 0.0% (0/1 통과), [true, true, false, true] → 75.0% (3/4 통과). 본문은 여전히 세 개의 문장으로 구성되어 있으며, 입력은 변경되지 않았고, 금지된 구문도 도입되지 않았습니다.

여러 공급업체 중에서 선택하는 팀은 여전히 자체 리포지토리, 도구 스택 및 검토 부담을 테스트해야 합니다. 더 광범위한 코딩 비교를 위한 Claude 대 ChatGPT 이 단일 결과 그 너머에서 그러한 상충 관계를 파악하는 데 도움이 됩니다.

Claude Opus 5 대 Opus 4.8 대 Fable 5

Opus 5를 이해하는 가장 명확한 방법은 이를 새로운 프리미엄 주력 모델로 보는 것입니다. Opus 4.8는 전작이며, Fable 5는 여전히 최첨단 기준 모델로 남아 있습니다. Anthropic의 출시 자료에 따르면, Opus 5는 Opus 4.8와 동일한 기본 비용을 유지하면서도, 특정 평가 항목에서는 Fable 5에 근접하는 성능을 보여주며 작업당 비용은 현저히 낮습니다.

모델직책가성비 지표가장 적합
Claude Opus 5프리미엄 일상용 모델; Opus 4.8의 후속 모델입력/출력 MTok당 $5/$25; Anthropic가 발표한 강력한 작업당 비용 결과복잡한 코딩, 자동화, 그리고 신뢰성이 중요한 기업 업무
클로드 오퍼스 4.8이전 Opus 세대Anthropic의 출시 비교 자료에 따르면, Opus 5와 기본 가격이 동일합니다.아직 마이그레이션 유효성 검사가 필요한 기존 고정된 워크플로
클로드 페이블 5프론티어-인텔리전스 등급최고 기준점; Anthropic에 따르면, Opus 5는 CursorBench에서 태스크당 비용이 절반 수준임에도 불구하고 비슷한 성능을 보여준다.경제성보다 최대 성능이 더 중요할 때 가장 어려운 과제들

마이그레이션에 대한 회귀 테스트가 가능하고, 기본 API 요금을 인상하지 않으면서 최신 모델을 도입하고자 한다면 Opus 4.8 대신 Opus 5를 선택하십시오. 자체 평가 결과, Fable 5의 추가 기능이 결과에 충분한 변화를 주어 추가 비용을 지불할 만한 가치가 있다고 판단될 경우 Fable 5를 선택하십시오. Sonnet 5도 포함된 최신 제품군별 세부 정보를 확인하려면 다음을 참조하십시오. Claude Opus 5 vs Fable 5 vs Sonnet 5 비교.

개발자 및 업계의 반응

소셜 미디어 게시물은 초기 사용 현황에 대한 유용한 단서를 제공하지만, 중립적인 기준이 되지는 않습니다. Claude의 공식 계정은 Opus 5를 ‘사려 깊고 선제적인’ 제품으로 묘사하며, Fable 5의 최첨단 성능에 근접하면서도 가격은 절반 수준이라고 설명했습니다. 이는 Anthropic 측이 직접 제시한 출시 포지셔닝일 뿐, 독립적인 확인을 거친 내용은 아닙니다.

2026년 7월 24일, Claude가 Claude Opus 5를 발표했던 원본 X 게시물
Claude는 X 플랫폼용 ‘Opus 5’를 Fable 5 수준의 성능을 갖추면서도 가격은 절반에 불과한, 세심하고 선제적인 모델로 발표했습니다.

JetBrains는 자체 평가 결과 다음과 같은 것으로 나타났다고 보고했다. 45%의 파이썬 합격률이 Opus 4.8보다 높음, 그리고 코드베이스에 대한 더 깊은 이해도 함께 얻을 수 있습니다. 이는 개발자 도구 전문 기업에서 내놓은 구체적이고 타당한 관찰 결과이지만, 이 결과는 JetBrains의 평가에 따른 것이므로 모든 파이썬 벤치마크나 저장소에 일반화해서는 안 됩니다.

Claude Opus 5를 사용했을 때 파이썬 합격률이 높아지고 코드베이스에 대한 이해도가 깊어졌다고 밝힌 JetBrains X 게시물 5
JetBrains는 자체 평가 결과, Opus 4.8 대비 Python 통과율이 45% 더 높았으며 코드베이스에 대한 이해도도 더 깊어진 것으로 나타났다고 밝혔습니다.

Harvey는 기업 지배구조 및 중재를 포함한 법률 업무 전반에 걸쳐 Opus 4.8 대비 품질과 토큰 효율성이 크게 개선되었다고 보고했다. 이는 법률 기술 구매자들에게 의미 있는 소식이지만, 이는 보편적인 법률적 정확성을 입증하는 것보다는 Harvey가 자사의 실무 분야 업무 흐름에 대해 내린 평가에 불과하다.

Harvey X 게시물: 법률 업무의 품질과 토큰 효율성 측면에서 Claude Opus 5의 향상을 보고
하비는 기업 지배구조 및 중재를 포함한 법률 업무의 품질과 토큰 효율성 측면에서 오푸스 5의 개선 사항을 보고했다.

종합해 보면, 이러한 게시물들은 얼리 어답터들이 코드베이스 이해도와 도메인별 지식 업무 측면에서 개선 효과를 체감하고 있음을 시사합니다. 다음 단계로 책임감 있게 진행해야 할 일은 여전히 자체 수용 테스트, 토큰 예산, 그리고 수동 검토 절차를 갖춘 대표적인 시범 운영을 실시하는 것입니다.

Claude Opus 5 API: 모델 ID, 예시 및 마이그레이션 참고 사항

Claude의 공식 API 모델 ID와 별칭은 모두 클로드-오푸스-5. 다음은 최소한의 인슐릭 API 요청 예시입니다. 이 예시는 공식 Messages 엔드포인트만을 보여줄 뿐이며, GlobalGPT의 백엔드 구현에 대해서는 설명하거나 보장하지 않습니다.

curl https://api.anthropic.com/v1/messages \
  --header "x-api-key: $ANTHROPIC_API_KEY" \
  --header "anthropic-version: 2023-06-01" \
  --header "content-type: application/json" \
  --data '{
    "model": "claude-opus-5",
    "max_tokens": 1024,
    "messages": [
 {
 "role": "user",
 "content": "근본 원인을 찾아내고, 가장 작은 수정안을 제안하며, 검증 명령어를 제시해 주세요."
      }
    ]
  }'

이주 체크리스트

  • 모델 값을 다음과 같이 변경하십시오. 클로드-오푸스-5, 그런 다음 직접 회귀 분석과 안전성 평가를 다시 수행하십시오.
  • MTok당 $5 입력 및 $25 출력을 기준으로 예산을 책정하고, 출력 부하가 큰 에이전트 루프와 도구 재시도 횟수를 모니터링하십시오.
  • 구식 관행을 이어가지 마십시오 thinking.type: "enabled" 구성. Anthropic 사고 가이드 오푸스 5에 대한 구상이 이미 진행 중이며, 적응형 설정에 대한 내용을 기록하고 있다고 밝혔다.
  • 128K를 동기식 메시지 API의 최대 출력값으로 간주하십시오. 별도의 메시지 배치(Message Batches) 베타 버전은 Anthropic의 문서화된 베타 헤더를 사용하여 최대 300K까지 지원할 수 있습니다.
  • 공급업체별 모델명을 확인하고 Anthropic 문서를 참조하십시오. anthropic.claude-opus-5 Amazon Bedrock 및 클로드-오푸스-5 Google Cloud용.

Claude Code와 함께 명령줄 워크플로를 활용하고자 하는 개발자를 위한 실용적인 설정 가이드는 다음과 같습니다. Claude 코드에서 GlobalGPT CLI 사용 방법. 자격 증명, 청구 및 제공자 동작이 명확하게 구분되도록, 해당 워크플로를 위의 공식 Anthropic API 예제와 별도로 관리하십시오.

Claude Opus 5는 구매할 만한 가치가 있을까요?

네—실패에 따른 대가가 크고 업무량이 정말로 힘들 때 말이죠. Opus 5는 더 정확한 진단, 도구 활용, 또는 긴 문맥을 고려한 판단을 통해 엔지니어나 분석가의 시간을 절약할 수 있는 상황에서 가장 큰 효과를 발휘합니다. 1M 토큰 규모의 문맥 창, 128K의 동기식 출력 상한, 그리고 작업당 비용 측면에서 긍정적인 평가를 받는 점이 결합되어, 이 모델은 신뢰할 수 있는 프리미엄급 주력 모델로서의 입지를 확고히 하고 있습니다.

Claude Opus 5는 어떤 사람이 사용해야 할까요?

  • 대규모 리포지토리에서 코딩 에이전트를 실행하는 엔지니어링 팀들.
  • 측정 가능한 승인 기준을 바탕으로 다단계 비즈니스 업무를 자동화하는 운영 팀.
  • 모델을 해당 분야의 검토 및 실시간 정보원과 연계할 수 있는 법무, 재무 또는 연구 팀.
  • 캐싱, 일괄 처리, 라우팅 및 회귀 테스트를 통해 비용을 효율적으로 관리할 수 있는 개발자.

누가 다른 것을 선택해야 할까요?

  • 간단한 추출, 분류 또는 요약 재작성이 주를 이루는 대량 처리 애플리케이션.
  • 적당한 성능의 모델조차 너무 느린, 지연 시간에 민감한 제품.
  • 평가 데이터 세트, 비용 모니터링, 또는 주요 산출물에 대한 인력 검토 계획이 없는 팀.
  • 가끔 일반적인 채팅만 필요하고, 추가적인 컨텍스트 기능이나 에이전트 기능을 사용하지 않을 구매자.

Opus 5가 너무 비싸거나 전문적인 느낌이 든다면, 다음 제품을 비교해 보세요. 2026년을 위한 Claude AI 대체 제품. 보다 폭넓은 시장 전망을 파악하려면, 다음 가이드에서 실제 사용 사례에 가장 적합한 AI 모델 워크로드를 모델 클래스에 맞게 할당하는 데 도움이 됩니다.

코딩 담당자들은 팀의 업무 흐름을 표준화하기 전에 현재 이용 가능한 옵션들을 비교해 볼 필요가 있으며, 2026년 코딩에 가장 적합한 AI 모델 성능과 가격을 더 넓은 맥락에서 살펴봅니다.

최종 평결: Claude Opus 5는 하드 코딩, 자동화, 지식 작업과 같은 작업에서 테스트해 볼 가치가 있습니다. 이러한 작업에서는 더 나은 결과가 높은 토큰 비용을 상쇄할 수 있기 때문입니다. 공식 사양은 탄탄하며, Anthropic의 벤치마크 결과는 비용 효율성이 유난히 뛰어나고, 저희가 검증한 디버깅 결과는 정확하고 체계적이었습니다. 모든 작업에 Opus급 모델이 필요한 것이 아니라, 측정 가능한 결과가 나오는 까다로운 작업을 위해 이 모델을 구매하십시오.

Claude Opus 5 자주 묻는 질문

Claude Opus 5는 얼마인가요?

Claude API의 공식 기본 요금은 입력 토큰 100만 개당 $5, 출력 토큰 100만 개당 $25입니다. 소비자용 Claude 요금제는 별도로 제공됩니다. Pro 요금제는 월 $20이며, 연간 결제 시 월 $17입니다. Max 요금제는 월 $100부터 시작합니다.

Claude Opus 5에 어떻게 접속할 수 있나요?

Anthropic에 따르면, Opus 5는 Claude Max의 기본 모델이며 Claude Pro에서 가장 강력한 모델입니다. 개발자는 Claude API를 사용할 수 있으며, 지원되는 클라우드 경로로는 Amazon Bedrock과 Google Cloud가 있으며, 각 제공업체별 액세스 요구 사항이 적용됩니다.

Claude Opus 5 API 모델 ID는 무엇인가요?

Claude API의 공식 모델 ID와 별칭은 모두 claude-opus-5입니다. Anthropic Messages API 요청 시 ‘model’ 필드에 이 값을 정확히 입력한 후,本番 환경으로 마이그레이션하기 전에 자체 회귀 테스트 및 안전성 평가를 다시 수행하십시오.

Claude Opus 5의 적용 범위와 출력 제한은 무엇인가요?

Claude Opus 5는 100만 토큰의 컨텍스트 윈도우를 가지며, 동기식 Messages API에서 최대 128,000 토큰을 출력할 수 있습니다. Anthropic는 베타 헤더가 포함된 메시지 배치(Message Batches)의 경우 최대 300,000 토큰의 출력 토큰 수를 별도로 명시하고 있습니다.

Claude Opus 5의 벤치마크 결과는 독립적으로 검증되었나요?

여기에 인용된 벤치마크 수치는 Anthropic에서 발표한 것으로, 본 리뷰를 위해 별도로 재현한 것이 아닙니다. 이 수치는 Anthropic가 테스트한 성능 및 비용 현황을 보여주는 것이지만, 구매자는 자신의 워크로드를 기준으로 품질, 지연 시간, 도구 사용 현황 및 총 비용을 직접 검증해야 합니다.

Claude Opus 5가 Opus 4.8나 Fable 5보다 더 나은가요?

Opus 5는 Opus 4.8의 최신 후속 모델로, 기본 비용이 동일하므로 회귀 테스트 후 자연스럽게 전환할 수 있는 후보입니다. Fable 5는 여전히 최첨단 기준 모델로 남아 있으며, 평가 결과 추가 기능이 더 높은 비용을 정당화한다고 판단될 때에만 선택하십시오.

Claude Opus 5는 GlobalGPT에서 사용할 수 있나요?

네. GlobalGPT에는 Claude Opus 전용 5페이지가 있습니다. 이용 가능 여부는 계정 상태 및 플랫폼 상황에 따라 달라질 수 있으므로, 시한이 있는 워크플로우를 진행하기 전에 접근 권한을 확인하시고, 플랫폼 접근 권한을 공식 Anthropic API 청구와 별도로 관리하시기 바랍니다.

Claude Opus 5의 비용은 누가 부담해야 할까요?

Opus 5는 까다로운 코딩, 자동화 또는 긴 맥락이 필요한 지식 업무와 같은 작업을 수행하는 팀에 가장 적합하며, 이러한 작업에서는 더 나은 답변을 통해 인력의 소중한 시간을 절약할 수 있습니다. 비교적 단순하거나 처리량이 많거나 지연 시간에 민감한 작업의 경우, 일반적으로 더 저렴하고 빠른 모델을 사용하는 것이 좋습니다.

게시물을 공유하세요:

관련 게시물