147 lines
8.4 KiB
JavaScript
147 lines
8.4 KiB
JavaScript
const quizData = [
|
|
{
|
|
q: "AI 협업 기반 코드 교차 검증 전략의 5단계 사이클은 무엇이며, 각 단계는 무엇으로 구성되어 있습니까?",
|
|
a: "계획, 검증, 실행, 검증, 테스트로 구성됩니다. Antigravity가 계획을 수립하고, Claude Code가 검증하며, Antigravity가 코드를 구현하고, Claude Code가 최종 검토한 후, TestSprite MCP가 자동 테스트를 진행합니다."
|
|
},
|
|
{
|
|
q: "첫 번째 단계에서 Antigravity가 수립한 계획을 별도의 문서 파일로 저장하는 이유는 무엇입니까?",
|
|
a: "후속 단계에서 Claude Code가 검토할 수 있는 물리적인 근거를 만들기 위함입니다. 이는 AI 모델 간의 명확한 정보 전달과 이력 관리를 가능하게 합니다."
|
|
},
|
|
{
|
|
q: "Claude Code는 1차 계획 검증 단계에서 어떤 기준을 바탕으로 계획을 검토하며, 그 역할은 무엇입니까?",
|
|
a: "미리 설정된 코드 작성 원칙과 기준(메모리, 에이전트, 훅 등)을 바탕으로 검토합니다. 설계상의 오류를 사전에 파악하고 보안사항을 제시하는 '설계 감리' 역할을 수행합니다."
|
|
},
|
|
{
|
|
q: "이 교차 검증 전략이 Claude Code의 토큰 사용량을 획기적으로 절감할 수 있는 핵심적인 이유 두 가지를 설명하시오.",
|
|
a: "첫째, 비용이 높은 Claude Code를 실제 구현이 아닌 '검증'에만 집중 배치하기 때문입니다. 둘째, 구현(Antigravity) 및 자동 테스트(TestSprite) 단계에서는 Claude Code의 토큰이 소모되지 않습니다."
|
|
},
|
|
{
|
|
q: "전체 사이클의 마지막 단계에서 TestSprite MCP가 수행하는 주요 역할은 무엇입니까?",
|
|
a: "완성된 코드에 대해 자동화된 테스트를 실행합니다. 문제가 발견되면 상세 리포트를 생성하여 Antigravity에게 전달함으로써 피드백 루프를 시작합니다."
|
|
},
|
|
{
|
|
q: "TestSprite MCP의 API 키를 발급받을 때 반드시 지켜야 할 중요한 보안 수칙은 무엇입니까?",
|
|
a: "API 키는 단 한 번만 화면에 노출되므로, 즉시 복사하여 별도의 안전한 장소에 반드시 보관해야 합니다."
|
|
},
|
|
{
|
|
q: "TestSprite MCP가 테스트 계획을 수립하기 위해 반드시 제공받아야 하는 문서는 무엇이며, 이 문서는 어떻게 생성할 수 있습니까?",
|
|
a: "테스트할 기능의 동작을 설명하는 'Product specification Doc'(기능 명세서)가 필요합니다. 이는 Claude Code에게 요청하여 간단히 생성할 수 있습니다."
|
|
},
|
|
{
|
|
q: "TestSprite MCP가 제공하는 테스트 리포트의 가장 강력하고 직관적인 특징은 무엇입니까?",
|
|
a: "각 단계별 실행 화면을 스크린샷으로 제공하여, 어느 화면에서 어떤 문제가 발생했는지 마치 사람이 직접 테스트한 것처럼 파악할 수 있다는 점입니다."
|
|
},
|
|
{
|
|
q: "Claude와 같은 고성능 AI 모델을 사용함에도 불구하고 교차 검증 전략이 필요한 근본적인 이유는 무엇입니까?",
|
|
a: "최신 연구 기준 고성능 AI 모델의 초기 코드 테스트 통과율이 약 42%에 불과하기 때문입니다. 이러한 한계를 극복하고 완성도를 극대화하기 위해 상호 보완이 필요합니다."
|
|
},
|
|
{
|
|
q: "이 교차 검증 전략의 전체 과정을 한 문장의 비유로 요약하여 설명하시오.",
|
|
a: "Antigravity라는 숙련된 시공사가 집을 짓기 전과 후에, Claude Code라는 꼼꼼한 설계사가 도면과 완공 상태를 철철히 감리하는 것과 같습니다."
|
|
}
|
|
];
|
|
|
|
const glossaryData = [
|
|
{ term: "AI 협업 기반의 코드 교차 검증 전략", def: "Antigravity와 Claude Code를 활용하여 계획-검증-실행-검증-테스트의 5단계 사이클을 통해 코드 품질을 극대화하고 비용을 절감하는 방법론." },
|
|
{ term: "Antigravity", def: "구글의 AI 모델로, 초기 계획 수립과 실제 코드 구현(실행)을 담당하는 '숙련된 시공사' 역할." },
|
|
{ term: "Claude Code", def: "앤스로픽의 AI 모델로, 계획과 결과물을 검증(Review)하고 감리하는 '꼼꼼한 설계사' 역할." },
|
|
{ term: "TestSprite MCP", def: "자동화 테스트 실행 도구. 실행 화면 스크린샷을 포함한 상세 리포트를 제공하여 최종 테스트 단계를 수행함." },
|
|
{ term: "교차 검증 (Cross-Validation)", def: "두 개 이상의 AI 모델이 상호 검토하여 논리적 오류를 줄이고 정교한 결과를 얻는 과정." },
|
|
{ term: "토큰 (Token)", def: "AI 모델의 언어 처리 단위. 이 전략을 통해 고비용 모델의 토큰 사용량을 2/3 수준으로 절감할 수 있음." },
|
|
{ term: "피드백 루프 (Feedback Loop)", def: "테스트 문제 발생 시 리포트를 Antigravity에게 전달하여 수정-재검증 사이클을 반복하는 것." },
|
|
{ term: "코드 작성 원칙과 기준", def: "Claude Code에 설정된 프로젝트 고유 규칙(메모리, 에이전트, 훅 등)으로 검증의 기준이 됨." },
|
|
{ term: "Product specification Doc", def: "TestSprite MCP가 테스트 계획 수립을 위해 필요로 하는 기능 명세서." }
|
|
];
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
// Tab Switching Logic
|
|
const navBtns = document.querySelectorAll('.nav-btn');
|
|
const tabContents = document.querySelectorAll('.tab-content');
|
|
|
|
navBtns.forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
const tabId = btn.getAttribute('data-tab');
|
|
|
|
// Update Buttons
|
|
navBtns.forEach(b => b.classList.remove('active'));
|
|
btn.classList.add('active');
|
|
|
|
// Update Content
|
|
tabContents.forEach(content => {
|
|
content.classList.remove('active');
|
|
if (content.id === `tab-${tabId}`) {
|
|
content.classList.add('active');
|
|
}
|
|
});
|
|
|
|
// Scroll to top when switching
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
});
|
|
});
|
|
|
|
// Inject Quiz
|
|
const quizContainer = document.getElementById('quiz-container');
|
|
quizData.forEach((item, index) => {
|
|
const card = document.createElement('div');
|
|
card.className = 'quiz-card';
|
|
card.innerHTML = `
|
|
<div class="quiz-card-inner">
|
|
<div class="quiz-card-front">
|
|
<span class="quiz-number">Q${(index + 1).toString().padStart(2, '0')}</span>
|
|
<p class="question-text">${item.q}</p>
|
|
<p style="font-size: 0.8rem; opacity: 0.5; margin-top: 1rem;">Click to see answer</p>
|
|
</div>
|
|
<div class="quiz-card-back">
|
|
<p class="answer-text">${item.a}</p>
|
|
</div>
|
|
</div>
|
|
`;
|
|
card.addEventListener('click', () => {
|
|
card.classList.toggle('flipped');
|
|
});
|
|
quizContainer.appendChild(card);
|
|
});
|
|
|
|
// Inject Glossary
|
|
const glossaryContainer = document.getElementById('glossary-container');
|
|
glossaryData.forEach(item => {
|
|
const card = document.createElement('div');
|
|
card.className = 'glossary-card';
|
|
card.innerHTML = `
|
|
<h3>${item.term}</h3>
|
|
<p>${item.def}</p>
|
|
`;
|
|
glossaryContainer.appendChild(card);
|
|
});
|
|
|
|
// Background Stars
|
|
const starsContainer = document.querySelector('.stars-container');
|
|
for (let i = 0; i < 100; i++) {
|
|
const star = document.createElement('div');
|
|
star.className = 'star';
|
|
const size = Math.random() * 2;
|
|
star.style.width = `${size}px`;
|
|
star.style.height = `${size}px`;
|
|
star.style.left = `${Math.random() * 100}%`;
|
|
star.style.top = `${Math.random() * 100}%`;
|
|
star.style.opacity = Math.random();
|
|
star.style.position = 'absolute';
|
|
star.style.backgroundColor = 'white';
|
|
star.style.borderRadius = '50%';
|
|
if (Math.random() > 0.8) {
|
|
star.style.animation = `twinkle ${Math.random() * 3 + 2}s infinite alternate`;
|
|
}
|
|
starsContainer.appendChild(star);
|
|
}
|
|
});
|
|
|
|
// Twinkle Animation
|
|
const style = document.createElement('style');
|
|
style.textContent = `
|
|
@keyframes twinkle {
|
|
from { opacity: 0.2; transform: scale(1); }
|
|
to { opacity: 1; transform: scale(1.2); }
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|