`; document.body.appendChild(el); return el; } const bubble = ensureBubble(); const elH = bubble.querySelector("#tt-title"); const elB = bubble.querySelector("#tt-body"); const elClose = bubble.querySelector(".tt-close"); // ---------------- Parse [[term|heading|body]] anywhere ---------------- const TOKEN_RE = /\[\[([^|\]]+)\|([^|\]]+)\|([^\]]+)\]\]/g; const BLOCK_SKIP = new Set(["SCRIPT","STYLE","NOSCRIPT","TEXTAREA","INPUT","SELECT","CODE","PRE","TEMPLATE","IFRAME"]); function shouldSkipTextNode(n){ let el = n.parentElement; while (el){ if (BLOCK_SKIP.has(el.tagName) || el.isContentEditable) return true; el = el.parentElement; } return false; } const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); const textNodes = []; while (walker.nextNode()){ const n = walker.currentNode; if (!n.nodeValue || shouldSkipTextNode(n)) continue; if (TOKEN_RE.test(n.nodeValue)) textNodes.push(n); TOKEN_RE.lastIndex = 0; } textNodes.forEach(node => { const frag = document.createDocumentFragment(); const insideLink = !!node.parentElement.closest("a"); let text = node.nodeValue, last = 0; TOKEN_RE.lastIndex = 0; let m; while ((m = TOKEN_RE.exec(text))){ if (m.index > last) frag.appendChild(document.createTextNode(text.slice(last, m.index))); const term=m[1].trim(), heading=m[2].trim(), body=m[3].trim(); const t = insideLink ? document.createElement("span") : document.createElement("button"); if (insideLink){ t.setAttribute("role","button"); t.setAttribute("tabindex","0"); } else { t.type="button"; } t.className="tt-trigger"; t.textContent=term; t.setAttribute("data-tt-h", heading); t.setAttribute("data-tt-b", body); t.setAttribute("aria-haspopup","dialog"); t.setAttribute("aria-expanded","false"); frag.appendChild(t); last = TOKEN_RE.lastIndex; } if (last = 2) return el; el = el.parentElement; } // Fallback: nearest non-inline container el = trigger.parentElement || document.body; while (el && el !== document.body){ const d = getComputedStyle(el).display; if (d !== "inline" && d !== "contents") return el; el = el.parentElement; } return document.body; } // Utility: child of `ancestor` that contains `target` (direct child) function directChildContaining(ancestor, target){ for (const ch of ancestor.children){ if (ch === target || ch.contains(target)) return ch; } return null; } function getElementTarget(e) { // If target is already an Element, use it if (e.target instanceof Element) return e.target; // Otherwise, walk the composed/path for the first Element const path = (typeof e.composedPath === 'function') ? e.composedPath() : []; for (const n of path) if (n instanceof Element) return n; return null; } // ---------------- Dim everything except the trigger branch (sibling branches only) ---------------- function dimAllOtherBranches(container, trigger){ undim(); // clear previous const dimEls = []; const wrappedTexts = []; const pathEls = []; // Build ELEMENT-only path [container -> ... -> trigger] const path = []; for (let el = trigger; el && el !== container; el = el.parentElement) path.push(el); path.push(container); path.reverse(); // At each ancestor level, find the *direct* child that leads to the trigger for (let i = 0; i { if (node.nodeType !== 3) return; // text only if (!node.nodeValue || !node.nodeValue.trim()) return; // If this text node sits inside branchChild, skip if (branchChild && branchChild.contains && branchChild.contains(node)) return; const span = document.createElement("span"); span.style.transition = `opacity ${DIM_EASE_MS}ms ease`; span.style.opacity = String(DIM_OPACITY); span.textContent = node.nodeValue; node.parentNode.replaceChild(span, node); wrappedTexts.push(span); }); // Keep a reference to the path elements (so we can explicitly restore opacity if needed) if (anc && anc.nodeType === 1) pathEls.push(anc); } // Hard-guard: explicitly set opacity:1 on the entire path to neutralize any inherited fade pathEls.forEach(el => { el.style.opacity = "1"; }); dimCtx = { container, dimEls, wrappedTexts, pathEls }; } function undim(){ if (!dimCtx) return; const { dimEls, wrappedTexts, pathEls } = dimCtx; // Animate back dimEls.forEach(el => { el.style.transition = `opacity ${DIM_EASE_MS}ms ease`; el.style.opacity = "1"; // remove inline style after the animation so we don't override site CSS setTimeout(() => { if (el) el.style.opacity = ""; }, DIM_EASE_MS + 50); }); wrappedTexts.forEach(span => { span.style.transition = `opacity ${DIM_EASE_MS}ms ease`; span.style.opacity = "1"; span.addEventListener("transitionend", () => { if (!span.parentNode) return; span.parentNode.replaceChild(document.createTextNode(span.textContent || ""), span); }, { once:true }); }); // Clear hard-guard on path pathEls.forEach(el => { if (el) el.style.opacity = ""; }); dimCtx = null; } // ---------------- Positioning (centered, edge-aware, flip) ---------------- function clamp(v,min,max){ return Math.max(min,Math.min(max,v)); } function measureBubbleForPlacement(){ const wasOpen = bubble.classList.contains("is-open"); if (!wasOpen){ bubble.style.visibility="hidden"; bubble.classList.add("is-open"); } const rect = bubble.getBoundingClientRect(); if (!wasOpen){ bubble.classList.remove("is-open"); bubble.style.visibility=""; } return { w: rect.width, h: rect.height }; } function placeAnchored(trigger){ const vw=innerWidth, vh=innerHeight; const r = trigger.getBoundingClientRect(); const { w, h } = measureBubbleForPlacement(); let left = r.left + (r.width/2) - (w/2); left = clamp(left, EDGE_PADDING, Math.max(EDGE_PADDING, vw - EDGE_PADDING - w)); const topBelow = r.bottom + OFFSET_Y; const spaceBelow = vh - topBelow - EDGE_PADDING; const placeBelow = spaceBelow >= h; let top = placeBelow ? topBelow : (r.top - h - OFFSET_Y); top = clamp(top, EDGE_PADDING, Math.max(EDGE_PADDING, vh - EDGE_PADDING - h)); bubble.style.left = left + "px"; bubble.style.top = top + "px"; const br = bubble.getBoundingClientRect(); if (br.bottom > vh - EDGE_PADDING){ bubble.style.maxHeight = (vh - 2*EDGE_PADDING) + "px"; bubble.style.overflowY = "auto"; } else { bubble.style.maxHeight = "none"; bubble.style.overflowY = "visible"; } } // ---------------- Open / Close (place → fade/scale) ---------------- function animateIn(){ bubble.style.transition = "none"; bubble.style.opacity = "0"; bubble.style.transform = "scale(0.95)"; void bubble.offsetWidth; bubble.style.transition = "opacity .18s ease, transform .18s ease"; bubble.style.opacity = "1"; bubble.style.transform = "scale(1)"; } function animateOut(done){ bubble.style.transition = "opacity .16s ease, transform .16s ease"; bubble.style.opacity = "0"; bubble.style.transform = "scale(0.95)"; const end = () => { bubble.removeEventListener("transitionend", end); done && done(); }; bubble.addEventListener("transitionend", end); setTimeout(end, 260); } function openFromTrigger(trigger){ if (current && current !== trigger) forceClose(); current = trigger; trigger.setAttribute("aria-expanded","true"); elH.textContent = trigger.getAttribute("data-tt-h") || ""; elB.textContent = trigger.getAttribute("data-tt-b") || ""; bubble.classList.add("is-open"); bubble.setAttribute("aria-hidden","false"); placeAnchored(trigger); animateIn(); const container = findTextContainer(trigger); dimAllOtherBranches(container, trigger); hoverCount = 0; cancelCloseTimer(); } function forceClose(){ if (!current) return; bubble.classList.remove("is-open"); bubble.setAttribute("aria-hidden","true"); current.setAttribute("aria-expanded","false"); current = null; undim(); hoverCount = 0; cancelCloseTimer(); } function closeWithAnim(){ if (!current) return; const t = current; animateOut(() => { bubble.classList.remove("is-open"); bubble.setAttribute("aria-hidden","true"); t.setAttribute("aria-expanded","false"); current = null; undim(); }); } function scheduleClose(){ cancelCloseTimer(); closeTimer = setTimeout(() => { if (hoverCount { if (isCoarse()) return; const target = getElementTarget(e); if (!target) return; const t = target.closest(".tt-trigger"); if (!t) return; onZoneEnter(); if (!current || current !== t) openFromTrigger(t); }; const handleLeave = (e) => { if (isCoarse()) return; const target = getElementTarget(e); if (!target) return; const t = target.closest(".tt-trigger"); if (!t) return; onZoneLeave(); }; document.addEventListener("pointerenter", handleEnter, true); document.addEventListener("mouseenter", handleEnter, true); document.addEventListener("pointerleave", handleLeave, true); document.addEventListener("mouseleave", handleLeave, true); // ---------------- Keyboard ---------------- document.addEventListener("focusin", (e) => { if (!e.target) return; const t = e.target.closest(".tt-trigger"); if (t) openFromTrigger(t); }); document.addEventListener("focusout", (e) => { if (!e.target) return; const t = e.target.closest(".tt-trigger"); if (t && current === t) closeWithAnim(); }); // ---------------- Mobile / coarse ---------------- document.addEventListener("pointerdown", (e) => { if (!isCoarse()) return; const t = e.target.closest(".tt-trigger"); if (!t) return; e.preventDefault(); e.stopPropagation(); if (current === t && bubble.classList.contains("is-open")) { closeWithAnim(); return; } openFromTrigger(t); }, true); document.addEventListener("click", (e) => { if (!isCoarse()) return; if (!bubble.classList.contains("is-open")) return; const inBubble = !!e.target.closest(".tt-bubble"); const onTrigger = !!e.target.closest(".tt-trigger"); if (!inBubble && !onTrigger) closeWithAnim(); }, true); // Close button + ESC elClose.addEventListener("click", closeWithAnim); document.addEventListener("keydown", (e) => { if (e.key === "Escape") closeWithAnim(); }); // Reposition on resize/scroll while open const reposition = () => { if (!current) return; placeAnchored(current); }; addEventListener("resize", reposition, { passive: true }); addEventListener("scroll", reposition, { passive: true }); });

개발자를 위한 최고의 AI

Claude는 세계 최고 수준의 엔지니어링 팀과 소프트웨어 기업들이 앞서 나가기 위해 선택하는 강력한 도구입니다.

빌드 시작하기
도입 문의
Play video

64.3%

SWE-bench Pro에서 선두를 달리는 Opus 4.7

60x

AI 플랫폼 고객의 코드 리뷰 피드백 속도 향상

95%

엔터프라이즈 소프트웨어 고객의 테스트 실행 시간 단축

logologo
logologo
logologo
logologo
logologo
logologo
logologo
logologo

Claude와 함께 코드를 작성하세요

코드베이스를 깊이 있게 파악하고, 고품질 소프트웨어를 더 빠르게 개발할 수 있습니다.

인증 오류를 확인해 보겠습니다. 먼저 관련 파일을 살펴보겠습니다.

인증 관련 파일 검토 중...

* src/services/authService.js

* src/components/Login.jsx

* src/store/authSlice.js

로그인 흐름 실행 중...

오류 감지됨: "401 Unauthorized: Token expired"

주요 원인:

* 토큰 갱신 메커니즘이 만료된 토큰을 올바르게 처리하지 못함

* 요청 헤더에 refresh token 포함되지 않음

* 401 응답에 대한 부적절한 오류 처리

authService.js에 올바른 리프레시 로직 업데이트 중...

401 처리를 위해 요청 인터셉터 업데이트 중...

수정 사항 테스트 중...

* 로그인 성공 ✓

* 토큰 갱신 정상 작동 ✓

* 토큰 만료 시 올바른 리디렉션 동작 ✓

인증 오류가 수정되었습니다! 이제 로그인 흐름에서 토큰 만료를 정상적으로 처리합니다.

업무 부담은 줄이고, 코딩 영향력은 확장하세요

Claude로 복잡한 소프트웨어를 작성, 테스트, 디버깅하고, GitHub 통합을 통해 전문가 수준의 추론으로 코드베이스를 분석하며, 컴퓨터 사용 기능으로 개발 작업을 위임하고, 공유 워크스페이스에서 더 스마트한 엔지니어링 의사 결정을 내릴 수 있습니다.

더 알아보기

Claude Code로 에이전틱 코딩(Agentic Coding)을 경험해 보세요

Claude Code는 Sonnet 4.6을 터미널 환경에 제공해, 코드베이스를 심층적으로 이해하고, 파일 편집과 명령 실행을 사용자 환경에서 직접 수행할 수 있도록 지원합니다.

더 알아보기

개발자들이 사랑하는 Claude

"오늘 한 번도 코드를 작성해 본 적 없는 친구에게 Claude로 간단한 앱을 만들고 Cloudflare에 배포하는 법을 알려주었습니다. 누군가가 이제 자신도 소프트웨어를 만들 수 있다는 사실을 깨닫는 순간을 지켜보는 건 정말 멋진 경험입니다. 모두가 무엇이든 만들 수 있도록 합시다."

Logan Grasby, @LoganGrasby

"어젠밤 누군가에게 Claude Code, Opus를 소개했는데, 우리는 새벽 4시까지 프로젝트를 만들었습니다. 정말 놀라웠어요! 2만 줄의 코드, 감사 로깅, 완전한 Prisma 데이터베이스, 완전한 아키텍처, 그리고 완전한 구현을 위한 4단계 로드맵까지 만들었습니다."

Teneika Askew, @teneikaask_you

"방금 약혼녀에게 Claude를 써서 몇 달간 그녀의 업무를 괴롭게 만들던 단순 작업들을 자동화하는 코드를 작성하는 법을 가르쳐 주었습니다. 풀이 죽고 회의적이던 그녀가 약 15분 만에 방 안을 돌아다니며 춤을 추기 시작했습니다. 엔드 유저 프로그래밍의 시대가 바로 지금입니다."

Kasey, @kaseyklimes

"Claude 4 Opus는 우리가 약속받았던 바로 그 미래입니다. 자리에 앉아 프롬프트를 조금 작성한 다음, 프로그램이 원하는 대로 작동하는지 확인합니다. '8시간'의 작업이 거의 노동이나 입력 없이 완료됩니다. 이제 아이스크림을 사러 가서 토큰이 더 생길 때까지 Twitch를 볼 시간입니다."

@airkatakana

"민망하게 들릴 수도 있겠지만, Claude와 Cursor의 강력함에 손에 땅이 차고 심장이 두근거릴 정도입니다. 방금 코드 한 줄 건드리지 않고 제 커스텀 API 위에 프론트엔드와 백엔드를 모두 갖춘 새 기능을 통째로 만든 다음, SwiftUI로 전환하기까지 했습니다."

Majd Taby, @jtaby

"Claude Code + Opus 4는 세계 최고의 에이전틱 코딩 도구이며, 다른 제품과는 비교가 되지 않습니다."

Mckay Wrigley, @mckaywrigley

"Anthropic은 Sonnet과 Opus 같은 모델, 그리고 Claude Code 같은 개발자 도구로 업계를 선도하고 있습니다."

Jon Meyers, @jonmeyers_io

"새로운 Claude를 쓰니 코딩할 때 제가 사기꾼이 된 기분이 듭니다. 구석에서 '음, 잘하고 있어요 보스, 계속 하세요' 라고 말하는 사람이 된 느낌이에요."

Nick, @nickcammarata
이전
0/5
다음

Claude Developer Platform으로 제품을 빌드하세요

Claude의 강력한 AI 기능을 앱에 통합해 프로덕션급 솔루션을 더 빠르게 제공할 수 있습니다.

너는 고객 지원 티켓을 분류하는 데 특화된 AI 어시스턴트야. 너의 임무는 제공된 티켓 내용을 분석한 뒤, 사전 정의된 목록 중 가장 적절한 카테고리에 티켓을 할당하는 거야. 또한 분류 결정에 대한 근거를 제시해야 해.

먼저, 사용 가능한 카테고리를 확인해:

<category_list>
{{CATEGORY_LIST}}
</category_list>

이제 분류해야 하는 지원 티켓의 내용은 다음과 같아:

<ticket_content>
{{TICKET_CONTENT}}
</ticket_content>

다음 단계를 따라 작업을 수행해야 해:
– 티켓 내용을 주의 깊게 읽고 분석한다.
– 해당 내용이 각 카테고리와 어떻게 연관되는지 고려한다.
– 티켓에 가장 적합한 카테고리를 선택한다.
– 추론 프로세스를 자세히 설명한다.

응답 시 다음 구조를 사용해 줘:
<classification_analysis>
이 섹션에서는 사고 프로세스를 다음과 같이 세분화해야 해:
– 티켓 내용 중 가장 유의미한 부분들을 인용한다.
– 각 카테고리를 나열하고 티켓 내용과의 연관성을 기술한다.
– 각 카테고리에 대해, 티켓을 분류할 수 있는 이유와 그렇지 않은 이유를 제시한다.
– 가장 가능성이 높은 상위 3개 카테고리를 순위별로 제시한다.
</classification_analysis>

<classification>
<category>선택한 카테고리를 여기에 기재</category>
<reasoning>이 카테고리를 선택한 이유를 간결하게 요약</reasoning>
</classification>

분석은 철저히 하고, 설명은 명확하게 작성해. 너의 목표는 충분한 근거를 바탕으로 정확한 분류를 제시하는 거야.

차원이 다른 AI 경험 제공

  • API를 활용해 Claude를 귀사의 솔루션에 최적화된 형태로 통합할 수 있습니다.
  • Workbench에서 프롬프트를 개선하고 평가할 수 있습니다.
  • 최첨단 인텔리전스를 애플리케이션에 구축할 수 있습니다
  • 풍부한 문서와 도구로 누구나 AI 개발자가 될 수 있습니다

기업이 Claude를 선택하는 이유

"CursorBench에서 Claude Opus 4.8은 모든 노력 수준에 걸쳐 이전 Opus 모델을 능가합니다. 도구 호출은 의미 있게 더 효율적이어서 같은 수준의 지능을 더 적은 단계로 구현하며, 엔드 투 엔드 작업을 끝까지 완수합니다."

Michael Truell, 공동 창업자 겸 CEO

"Claude Opus 4.8은 눈에 띄게 더 나은 판단력을 갖추고 있습니다. Claude Code에서 적절한 질문을 던지고, 자신의 실수를 잡아내며, 계획이 타당하지 않을 때 이의를 제기하고, 큰 변경을 가하기 전에 복잡한 다중 서비스 탐색에 대해 확신을 쌓아 갑니다. 함께 빌드하기에 훌륭한 모델입니다."

Tom Pritchard, 소프트웨어 엔지니어

"Claude Opus 4.8은 도구를 깔끔하게 사용하고, 자율 엔지니어링 워크로드가 무인으로 계속 실행되는 데 필요한 일관성으로 지시를 따릅니다. Opus 4.6 대비 개선되었으며, Opus 4.7에서 보였던 코멘트 과다 및 도구 호출 문제도 해결되었습니다. Anthropic의 이번 릴리스는 Devin 위에서 빌드하는 엔지니어들에게 더 빠른 역량 향상으로 직결됩니다."

Scott Wu, CEO

"93개 작업으로 구성된 코딩 벤치마크에서 Claude Opus 4.7은 Opus 4.6 대비 해결률을 13% 끌어올렸으며, 여기에는 Opus 4.6과 Sonnet 4.6 모두 해결하지 못했던 4개 작업이 포함됩니다. 더 빠른 중간 지연 시간과 엄격한 지시 준수 능력이 결합되어, 복잡하고 장시간 실행되는 코딩 워크플로우에 특히 의미가 큽니다. 다단계 작업에서 발생하는 마찰을 줄여 개발자가 흐름을 유지하고 빌드에 집중할 수 있도록 합니다."

Mario Rodriguez, Chief Product Officer

"Replit에 있어 Claude Opus 4.7은 쉬운 결정을 내릴 수 있는 업그레이드였습니다. 사용자들이 매일 수행하는 작업에서 동일한 품질을 더 낮은 비용으로 달성하는 것을 확인했습니다. 로그와 트레이스 분석, 버그 탐색, 수정안 제안과 같은 작업에서 더욱 효율적이고 정밀합니다. 개인적으로는 기술적 논의 중에 더 나은 의사결정을 내릴 수 있도록 반론을 제기하는 방식이 정말 마음에 듭니다. 진정으로 더 나은 동료처럼 느껴집니다."

Michele Catasta, President

"Claude Opus 4.7은 매우 강력하며, Factory Droids의 작업 성공률을 Opus 4.6 대비 10~15% 끌어올렸습니다. 도구 오류는 줄었고, 검증 단계에서의 후속 처리도 더욱 안정적입니다. 중간에 멈추지 않고 작업을 끝까지 수행해내는데, 이는 엔터프라이즈 엔지니어링 팀이 정확히 필요로 하는 부분입니다."

Leo Tchourakov, Member of Technical Staff

"Rakuten-SWE-Bench에서 Claude Opus 4.7은 Opus 4.6 대비 3배 많은 프로덕션 작업을 해결했으며, 코드 품질과 테스트 품질에서 두 자릿수의 향상을 기록했습니다. 이는 의미 있는 도약이며, 저희 팀이 매일 출시하는 엔지니어링 작업에 있어 명확한 업그레이드입니다."

Yusuke Kaji, General Manager, AI for Business

"Ramp에서 Claude Opus 4.7은 에이전트 팀 워크플로우에서 두각을 나타냅니다. 역할 충실도, 지시 사항 준수, 협업, 그리고 복잡한 추론 능력이 더욱 향상되었으며, 특히 여러 도구와 코드베이스, 디버깅 맥락을 아우르는 엔지니어링 작업에서 그 효과가 두드러집니다. Opus 4.6과 비교했을 때 단계별 안내가 훨씬 덜 필요하며, 엔지니어링팀이 운영하는 내부 에이전트 워크플로우의 확장에 큰 도움이 됩니다."

Austin Ray, Software Engineer
이전
0/5
다음
100K+

Google Cloud에 배포된 애플리케이션

75%

매주 8~10시간 이상 절약하는 엔지니어

코딩 리소스

프로그래머들은 왜 다크 모드를 선호할까요?

잘 모르겠어요
Claude에게 질문하기