Skip to content

πŸ”—API & ✨Feat : 챗봇 api μ—°κ²°#124

Merged
KongMezu merged 13 commits intodevelopfrom
api/#117/chatbot-api
Nov 14, 2025
Merged

πŸ”—API & ✨Feat : 챗봇 api μ—°κ²°#124
KongMezu merged 13 commits intodevelopfrom
api/#117/chatbot-api

Conversation

@KongMezu
Copy link
Copy Markdown
Contributor

@KongMezu KongMezu commented Nov 14, 2025

πŸ”₯ μž‘μ—… λ‚΄μš©

  • 챗봇 api μ—°κ²° μ™„λ£Œ
  • ν”„λ‘œν•„ 이미지 μΆ”κ°€

πŸ€” μΆ”ν›„ μž‘μ—… 사항

  • μ„œλ²„ 문제 ν•΄κ²° ν›„ μž‘λ™.. 확인

πŸ”—Β μ΄μŠˆ

PR Point (To Reviewer)

챗봇 api μ—°κ²°

챗봇 api μ—°κ²° ν–ˆμŠ΅λ‹ˆλ‹€.
둜그인 μœ μ € : λ‹€μ‹œ 챗봇 μ ‘μ†μ‹œ 12μ‹œκ°„ λ™μ•ˆ 이전 μ±„νŒ… 기둝 확인 κ°€λŠ₯
λΉ„λ‘œκ·ΈμΈ μœ μ € : μƒˆλ‘œ μ ‘μ†μ‹œ 리셋

그리고 api μ—μ„œ λ°›μ•„μ˜€λŠ” κΈ€μžλ„ 이λͺ¨ν‹°μ½˜, λ§ˆμΉ¨ν‘œ(.) 에 맞게 μ€„λ°”κΏˆμ΄ κ°€λŠ₯ν•˜λ„λ‘ ν•΄λ†¨μŠ΅λ‹ˆλ‹€.

+) instance axios 경둜 μˆ˜μ •

πŸ“ΈΒ ν”Όκ·Έλ§ˆ μŠ€ν¬λ¦°μƒ· or κΈ°λŠ₯ GIF

λΉ„λ‘œκ·ΈμΈ

-.Clipchamp.4.mp4

둜그인

-.Clipchamp.5.mp4

Summary by CodeRabbit

  • μƒˆλ‘œμš΄ κΈ°λŠ₯

    • 챗봇 μ„Έμ…˜ μžλ™ μƒμ„±Β·λ‘œμ»¬ μ €μž₯ 및 만료 μ‹œ μž¬μƒμ„±Β·μž¬μ‹œλ„ μžλ™ν™”
    • μ±„νŒ… 흐름 톡합: λ©”μ‹œμ§€ μ „μ†‘β†’μ„œλ²„ ν˜ΈμΆœβ†’μ‘λ‹΅ 포맷 후화면에 μΆ”κ°€
    • μž…λ ₯ μ»΄ν¬λ„ŒνŠΈμ— λΉ„ν™œμ„±ν™”(disabled) μ œμ–΄ μΆ”κ°€
  • 버그 μˆ˜μ • / κ°œμ„ 

    • μ„Έμ…˜ μƒνƒœ 기반 μž…λ ₯·전솑 λ²„νŠΌ λΉ„ν™œμ„±ν™” 일관 적용
    • API 였λ₯˜ 처리·둜그 κ°•ν™” 및 μ„Έμ…˜ 만료 처리 κ°œμ„ 
    • μ±„νŒ… νžˆμŠ€ν† λ¦¬ λ‘œμ»¬μ— μ €μž₯(μ΅œμ‹  10개, 만료 μ •μ±… 적용)
  • UI

    • 둜고 이미지 ꡐ체, ARIA 라벨 μ •λΉ„
    • λ©”μ‹œμ§€ λ‚΄μš©μ˜ μ€„λ°”κΏˆ 보쑴 κ°œμ„ 

@vercel
Copy link
Copy Markdown

vercel bot commented Nov 14, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
af-fe Ready Ready Preview Comment Nov 14, 2025 10:38am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Nov 14, 2025

Warning

Rate limit exceeded

@KongMezu has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 14 minutes and 24 seconds before requesting another review.

βŒ› How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 8c53017 and 73f2c6b.

πŸ“’ Files selected for processing (1)
  • src/shared/api/instance.ts (1 hunks)

Walkthrough

챗봇 API ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„Έμ…˜ 관리 ν›…(useChatbot)이 μΆ”κ°€λ˜κ³ , 챗봇 νŽ˜μ΄μ§€κ°€ ν›… 기반 μ„Έμ…˜Β·λ©”μ‹œμ§€ νλ¦„μœΌλ‘œ λ¦¬νŒ©ν„°λ§λ˜μ—ˆμŠ΅λ‹ˆλ‹€. ChattingInput에 disabled?: boolean prop이 λ„μž…λ˜μ–΄ μ„Έμ…˜ 없을 λ•Œ μž…λ ₯/전솑이 μ°¨λ‹¨λ©λ‹ˆλ‹€.

Changes

Cohort / File(s) λ³€κ²½ μš”μ•½
ChattingInput λ³€κ²½
src/pages/chatbot/components/ChattingInput.tsx
ChattingInputProps에 disabled?: boolean μΆ”κ°€. μ»΄ν¬λ„ŒνŠΈμ—μ„œ disabledλ₯Ό νŒŒκ΄΄ν•˜κ³ , ν‚€λ‹€μš΄ 및 전솑 클릭을 disabled일 λ•Œ λ¬΄μ‹œν•˜λ„λ‘ μ²˜λ¦¬ν•˜λ©° λ²„νŠΌμ— disabled 속성 적용.
챗봇 νŽ˜μ΄μ§€ λ¦¬νŒ©ν„°λ§
src/pages/chatbot/index.tsx
useChatbot ν›… λ„μž… 및 λ©”μ‹œμ§€ 흐름을 ν›…μ˜ messages둜 톡합. handleSendλ₯Ό async둜 λ³€κ²½ν•΄ μ‚¬μš©μž λ©”μ‹œμ§€ μΆ”κ°€ β†’ API 호좜 β†’ 봇 λ©”μ‹œμ§€ μΆ”κ°€ 순으둜 처리. μ„Έμ…˜ μœ λ¬΄μ— 따라 ChattingInput λΉ„ν™œμ„±ν™” 및 UI/ARIA 정리, Image μ»΄ν¬λ„ŒνŠΈ μ‚¬μš©.
API ν΄λΌμ΄μ–ΈνŠΈ μΆ”κ°€
src/shared/api/chatbot/chatbot.ts
Axios 기반 ν΄λΌμ΄μ–ΈνŠΈ μΆ”κ°€. getBaseUrl(), createChatSession() 및 fetchChatResponse(message, sessionId) κ΅¬ν˜„. λ‹€μ–‘ν•œ 응닡 ν˜•νƒœ 처리, NEXT_PUBLIC_BACKEND_URL 검증, 404(μ„Έμ…˜ 만료) 특수 처리(SESSION_EXPIRED) 및 λΈŒλΌμš°μ € λ‘œμ»¬μŠ€ν† λ¦¬μ§€ 정리, μ—λŸ¬/λ‘œκΉ… 포함.
μ„Έμ…˜ ν›… μΆ”κ°€
src/shared/hooks/chatbot/useChatbot.ts
useChatbot() ν›… μΆ”κ°€. λ‘œμ»¬μŠ€ν† λ¦¬μ§€ 기반 μ„Έμ…˜ λΆ€νŠΈμŠ€νŠΈλž©(chatbot:sessionId), μ‚¬μš©μžλ³„ νžˆμŠ€ν† λ¦¬ λ‘œλ“œ/만료 검사, λ©”μ‹œμ§€ μƒνƒœ 및 addMessage 제곡. useMutation으둜 응닡 페칭, SESSION_EXPIRED μ‹œ μ„Έμ…˜ μž¬μƒμ„± ν›„ μž¬μ‹œλ„ 둜직 포함.
ChattingBubble μŠ€νƒ€μΌ
src/pages/chatbot/components/ChattingBubble.tsx
λ©”μ‹œμ§€ λ‚΄μš© div에 whiteSpace: 'pre-line' μŠ€νƒ€μΌ μΆ”κ°€λ‘œ μ€„λ°”κΏˆ 보쑴.

Sequence Diagram(s)

sequenceDiagram
    participant User as μ‚¬μš©μž
    participant Input as ChattingInput
    participant Page as ChatPage
    participant Hook as useChatbot
    participant API as BackendAPI

    User->>Input: ν…μŠ€νŠΈ μž…λ ₯ ν›„ Send
    alt Input.disabled == true
        Input-->>User: μž…λ ₯/전솑 λ¬΄μ‹œ
    else
        Input->>Page: onSend(message)
        Page->>Page: messages += {role: "user", content}
        Page->>Hook: mutate(message)
        Hook->>API: fetchChatResponse(message, sessionId)
        alt SESSION_EXPIRED (404)
            API-->>Hook: 404 / SESSION_EXPIRED
            Hook->>API: createChatSession()
            API-->>Hook: new sessionId
            Hook->>Hook: sessionId κ°±μ‹  & localStorage μ €μž₯
            Hook->>API: fetchChatResponse(message, new sessionId)
        end
        API-->>Hook: answer
        Hook-->>Page: mutation success (answer)
        Page->>Page: messages += {role: "bot", content: answer}
        Page->>Input: render μ—…λ°μ΄νŠΈ 및 μžλ™ 슀크둀
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • 주의 κ²€ν†  지점:
    • src/shared/api/chatbot/chatbot.ts의 응닡 νŒŒμ‹±, 404/SESSION_EXPIRED λΆ„κΈ° 및 localStorage 정리 둜직
    • src/shared/hooks/chatbot/useChatbot.ts의 μ΄ˆκΈ°ν™”(λ‘œμ»¬μŠ€ν† λ¦¬μ§€ 동기화), νžˆμŠ€ν† λ¦¬ 만료/보쑴 둜직, μ„Έμ…˜ μž¬μƒμ„± ν›„ μž¬μ‹œλ„ 흐름
    • src/pages/chatbot/index.tsx의 비동기 λ©”μ‹œμ§€ μ—…λ°μ΄νŠΈ μˆœμ„œμ™€ μ—λŸ¬ 처리
    • ChattingInput.tsx의 disabled μ „νŒŒκ°€ 이벀트(ν‚€λ‹€μš΄/클릭)λ₯Ό μ •ν™•νžˆ μ°¨λ‹¨ν•˜λŠ”μ§€

Possibly related PRs

  • ✨Feat: μ±—λ΄‡νŽ˜μ΄μ§€ μ œμž‘Β #83 β€” 동일 챗봇 μ»΄ν¬λ„ŒνŠΈ(ChattingInput, ChattingBubble, 챗봇 νŽ˜μ΄μ§€) κ΄€λ ¨ 변경을 λ„μž…/μˆ˜μ •ν•œ PR둜 μ½”λ“œ 레벨 μ—°κ΄€μ„± λ†’μŒ.

Suggested labels

feat

Suggested reviewers

  • skyblue1232

Poem

🐰 μ„Έμ…˜ 씨앗 땅에 심고,
λ‘œμ»¬μ— μ‚΄ν¬μ‹œ μˆ¨κ²Όλ„€.
μž…λ ₯ 잠기면 쉬어가고,
만료면 μƒˆ μ„Έμ…˜ λΆˆλŸ¬μ™€ λ‹΅ν•˜λ„€.
πŸ₯•βœ¨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
βœ… Passed checks (2 passed)
Check name Status Explanation
Title check βœ… Passed PR 제λͺ©μ€ 'πŸ”—API & ✨Feat : 챗봇 api μ—°κ²°'둜 λ³€κ²½μ‚¬ν•­μ˜ μ£Όμš” λ‚΄μš©(챗봇 API μ—°κ²°)을 λͺ…ν™•ν•˜κ²Œ μ„€λͺ…ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.
Description check βœ… Passed PR μ„€λͺ…이 μ£Όμ–΄μ§„ ν…œν”Œλ¦Ώμ˜ λŒ€λΆ€λΆ„ μ„Ήμ…˜μ„ ν¬ν•¨ν•˜κ³  있으며, μž‘μ—… λ‚΄μš©, μΆ”ν›„ μž‘μ—… 사항, 이슈 링크, 리뷰어 포인트, μŠ€ν¬λ¦°μƒ·/GIFκ°€ λͺ¨λ‘ μž‘μ„±λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message.
Please verify that they are correct before merging.

@github-actions github-actions bot added the api api μ—°κ²° label Nov 14, 2025
@github-actions
Copy link
Copy Markdown

🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message.
Please verify that they are correct before merging.

@github-actions github-actions bot added the comment ν•„μš”ν•œ 주석 μΆ”κ°€ 및 λ³€κ²½ label Nov 14, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
src/pages/chatbot/components/ChattingInput.tsx (1)

11-21: disabled 처리 λ°©ν–₯은 μ μ ˆν•˜μ§€λ§Œ, input 자체 λΉ„ν™œμ„±ν™”λ„ κ³ λ €ν•΄λ³Ό 만 ν•©λ‹ˆλ‹€.

  • onKeyDown/onClickλ₯Ό disabled둜 κ°€λ“œν•΄μ„œ μ‹€μ œ 전솑이 λ§‰νžˆλŠ” κ΅¬μ‘°λŠ” 잘 μ •λ¦¬λœ 것 κ°™μŠ΅λ‹ˆλ‹€.
  • λ‹€λ§Œ UX/μ ‘κ·Όμ„± κ΄€μ μ—μ„œ β€œμž…λ ₯창이 λΉ„ν™œμ„±ν™”λλ‹€β€λŠ” μ˜λ„λ₯Ό 더 λΆ„λͺ…νžˆ ν•˜λ €λ©΄, μ•„λž˜μ²˜λŸΌ input에도 λΉ„ν™œμ„± μƒνƒœλ₯Ό λ°˜μ˜ν•˜λŠ” 것을 κ³ λ €ν•΄λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.
    • disabled={disabled} λ˜λŠ” readOnly={disabled} + aria-disabled={disabled} μΆ”κ°€
    • λΉ„ν™œμ„± μ‹œ μŠ€νƒ€μΌ(색상/μ»€μ„œ λ“±)도 ν•¨κ»˜ μ‘°μ •ν•˜λ©΄ μ‚¬μš©μžμ—κ²Œ μƒνƒœκ°€ 더 λͺ…ν™•νžˆ μ „λ‹¬λ©λ‹ˆλ‹€.

ν˜„μž¬ κ΅¬ν˜„λ„ κΈ°λŠ₯μ μœΌλ‘œλŠ” 문제 μ—†μ–΄μ„œ μΆ”ν›„ λ¦¬νŒ©ν„°λ§μœΌλ‘œ 천천히 봐도 될 것 κ°™μŠ΅λ‹ˆλ‹€.

Also applies to: 39-52

src/pages/chatbot/index.tsx (1)

1-5: μ„Έμ…˜ 연계 λ©”μ‹œμ§€ 전솑 ν”Œλ‘œμš°λŠ” 잘 κ΅¬μ„±λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. λ‹€λ§Œ μ—λŸ¬/λŒ€κΈ° μƒνƒœ UXλ₯Ό 쑰금 더 보완할 수 μžˆμŠ΅λ‹ˆλ‹€.

  • useChatbot의 mutateAsync와 sessionIdλ₯Ό μ΄μš©ν•œ handleSend 둜직 ꡬ성은 μžμ—°μŠ€λŸ½κ³ , μ„Έμ…˜ 없을 λ•Œ early return ν•˜λŠ” 것도 λ°©μ–΄μ μœΌλ‘œ μ’‹μŠ΅λ‹ˆλ‹€.
  • λ‹€λ§Œ ν˜„μž¬λŠ”:
    • μ„œλ²„ 였λ₯˜(500/E600 λ“±) μ‹œ console.error만 남기고 UIμ—λŠ” 아무 ν”Όλ“œλ°±μ΄ μ—†μ–΄ μ‚¬μš©μžκ°€ β€œμ™œ 닡이 μ•ˆ μ˜€λŠ”μ§€β€ μ•ŒκΈ° μ–΄λ ΅κ³ ,
    • 응닡 λŒ€κΈ° 쀑에도 μΆ”κ°€ λ©”μ‹œμ§€λ₯Ό 계속 보낼 수 μžˆμ–΄, λΉ λ₯΄κ²Œ μ—¬λŸ¬ 번 전솑 μ‹œ 응닡 μˆœμ„œκ°€ λ’€μ„žμΌ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • React Queryκ°€ μ œκ³΅ν•˜λŠ” isPending/isError λ“±μ˜ μƒνƒœλ₯Ό ν™œμš©ν•΄μ„œ:
    • const { mutateAsync: sendChat, sessionId, isPending, isError } = useChatbot();
    • <ChattingInput onSend={handleSend} disabled={!sessionId || isPending} />
    • μ—λŸ¬ μ‹œ μ±—λ΄‡μ˜ μ‹œμŠ€ν…œ λ©”μ‹œμ§€(예: β€œμ§€κΈˆμ€ μ„œλ²„ μƒνƒœκ°€ μ’‹μ§€ μ•Šμ•„μš”. μž μ‹œ ν›„ λ‹€μ‹œ μ‹œλ„ν•΄ μ£Όμ„Έμš”.”)λ₯Ό messages에 μΆ”κ°€
      같은 ν˜•νƒœλ‘œ UXλ₯Ό κ°œμ„ ν•˜λ©΄ μ‚¬μš©μžκ°€ μƒνƒœλ₯Ό 더 λͺ…ν™•νžˆ 인지할 수 μžˆμ„ 것 κ°™μŠ΅λ‹ˆλ‹€.

λ˜ν•œ μƒλ‹¨μ˜ 'use client';λŠ” Pages Router ν™˜κ²½μ—μ„  λ™μž‘μƒ λ¬Έμ œλŠ” μ—†μ§€λ§Œ, 이 레포 μ»¨λ²€μ…˜(νŽ˜μ΄μ§€λŠ” 기본적으둜 ν΄λΌμ΄μ–ΈνŠΈ μ»΄ν¬λ„ŒνŠΈ) κΈ°μ€€μœΌλ‘  λΆˆν•„μš”ν•˜λ―€λ‘œ μ œκ±°ν•΄λ„ μ’‹κ² μŠ΅λ‹ˆλ‹€.
Based on learnings

Also applies to: 23-27, 30-37, 39-59, 107-107

src/shared/hooks/chatbot/useChatbot.ts (1)

1-44: μ„Έμ…˜ 관리 흐름은 μ•ˆμ •μ μž…λ‹ˆλ‹€. μ„Έμ…˜ 생성 μ‹€νŒ¨ μ‹œ μž¬μ‹œλ„/μ—λŸ¬ λ…ΈμΆœ 경둜만 μΆ”κ°€λ˜λ©΄ 더 μ’‹κ² μŠ΅λ‹ˆλ‹€.

  • SESSION_KEY μΊμ‹œ, inited ref둜 StrictMode 2회 싀행을 λ§‰λŠ” νŒ¨ν„΄, createChatSession/fetchChatResponse 연계 λͺ¨λ‘ μžμ—°μŠ€λŸ½μŠ΅λ‹ˆλ‹€.
  • λ‹€λ§Œ createChatSession이 ν•œ 번 μ‹€νŒ¨ν•˜λ©΄:
    • sessionIdλŠ” 계속 null이고,
    • inited.currentκ°€ trueλΌμ„œ 동일 νƒ­μ—μ„œ 더 이상 μž¬λΆ€νŠΈμŠ€νŠΈλž©μ΄ λ°œμƒν•˜μ§€ μ•Šμ•„,
    • μƒμœ„ μ»΄ν¬λ„ŒνŠΈ μž…μž₯에선 μž…λ ₯창이 영ꡬ적으둜 disabled μƒνƒœκ°€ 될 수 μžˆμŠ΅λ‹ˆλ‹€.

μΆ”κ°€λ‘œ κ³ λ €ν•΄λ³Ό λ§Œν•œ μ μž…λ‹ˆλ‹€.

  • 이 hookμ—μ„œ error μƒνƒœ(λΆ€νŠΈμŠ€νŠΈλž© μ€‘μ˜ μ—λŸ¬/μ„Έμ…˜ 미생성)λ₯Ό λ³„λ„λ‘œ κ΄€λ¦¬ν•΄μ„œ λ°˜ν™˜ν•˜κ±°λ‚˜,
  • μƒμœ„μ—μ„œ β€œλ‹€μ‹œ μ‹œλ„β€ λ²„νŠΌμ„ λˆŒλ €μ„ λ•Œ localStorage.removeItem(SESSION_KEY) ν›„ λΆ€νŠΈμŠ€νŠΈλž© ν•¨μˆ˜λ₯Ό μž¬ν˜ΈμΆœν•  수 μžˆλŠ” APIλ₯Ό λ…ΈμΆœν•˜λŠ” 방식도 μžˆμŠ΅λ‹ˆλ‹€.
  • 이미 mutation 객체 전체λ₯Ό λ°˜ν™˜ν•˜κ³  μžˆμœΌλ‹ˆ, μƒμœ„ μ»΄ν¬λ„ŒνŠΈμ—μ„œ isPending, isErrorλ₯Ό ν™œμš©ν•΄ UXλ₯Ό ν’λΆ€ν•˜κ²Œ λ§Œλ“œλŠ” 것도 ꢌμž₯λ©λ‹ˆλ‹€.

큰 κ΅¬μ‘°λŠ” 잘 μž‘ν˜€ 있고, μœ„ λ‚΄μš©μ€ 이후 μ—λŸ¬ 처리λ₯Ό κ°œμ„ ν•  λ•Œ 참고용으둜 λ³΄μ‹œλ©΄ 될 것 κ°™μŠ΅λ‹ˆλ‹€.

src/shared/api/chatbot/chatbot.ts (1)

1-92: API ν΄λΌμ΄μ–ΈνŠΈλŠ” λ°©μ–΄μ μœΌλ‘œ 잘 μž‘μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ—λŸ¬ 정보 ꡬ쑰화와 νƒ€μž„μ•„μ›ƒλ§Œ μΆ”κ°€λ˜λ©΄ λ”μš± ν™œμš©λ„κ°€ 높을 것 κ°™μŠ΅λ‹ˆλ‹€.

쒋은 점:

  • validateStatus: () => true둜 λͺ¨λ“  응닡을 직접 κ²€μ‚¬ν•˜κ³ , 4xx/5xxμ—μ„œ λͺ…μ‹œμ μœΌλ‘œ μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚€λŠ” νŒ¨ν„΄μ€ λͺ…ν™•ν•©λ‹ˆλ‹€.
  • μ„Έμ…˜/μ±— μ‘λ‹΅μ—μ„œ result/data/루트 ν•„λ“œλ₯Ό λͺ¨λ‘ 탐색해 sessionId/answerλ₯Ό μ–»λŠ” 뢀뢄도 μ‹€μ œ λ°±μ—”λ“œ 응닡 변화에 μ–΄λŠ 정도 μœ μ—°ν•˜κ²Œ λŒ€μ‘ν•˜λ„λ‘ μ„€κ³„λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.
  • NEXT_PUBLIC_BACKEND_URLμ—μ„œ trailing slashλ₯Ό μ œκ±°ν•˜λŠ” 것도 URL κ²°ν•© μ‹œ μ‹€μˆ˜λ₯Ό μ€„μ—¬μ€λ‹ˆλ‹€.

κ°œμ„  μ œμ•ˆ:

  • ν˜„μž¬λŠ” new Error(\챗봇 응닡 μ‹€νŒ¨: ${res.status}`)처럼 HTTP status만 포함해 μ—λŸ¬λ₯Ό λ˜μ§€κΈ° λ•Œλ¬Έμ—, λ°±μ—”λ“œμ—μ„œ λ‚΄λ €μ£ΌλŠ” 도메인 μ—λŸ¬ μ½”λ“œ(예: code: 'E600'`)λ₯Ό ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ ꡬ뢄 μ²˜λ¦¬ν•˜κΈ° μ–΄λ ΅μŠ΅λ‹ˆλ‹€.

    • 예λ₯Ό λ“€μ–΄ μ•„λž˜μ²˜λŸΌ μ»€μŠ€ν…€ μ—λŸ¬ 객체λ₯Ό λ§Œλ“€μ–΄ status, code, message λ“± 메타데이터λ₯Ό λ‹΄μ•„ 두면, μƒμœ„ λ ˆλ²¨μ—μ„œ β€œE600이면 이런 μ•ˆλ‚΄ λ©”μ‹œμ§€λ₯Ό λ„μš΄λ‹€β€ 같은 λΆ„κΈ° μ²˜λ¦¬κ°€ μ‰¬μ›Œμ§‘λ‹ˆλ‹€.

      const apiError = new Error(`챗봇 응닡 μ‹€νŒ¨: ${res.status}`);
      (apiError as any).status = res.status;
      (apiError as any).code = (res.data as any)?.code;
      throw apiError;
  • μž₯κΈ°μ μœΌλ‘œλŠ” axios에 timeout μ˜΅μ…˜μ„ μΆ”κ°€ν•΄, μ„œλ²„κ°€ 응닡을 μ•„μ£Ό 였래 끌고 κ°€λŠ” μƒν™©μ—μ„œ UIκ°€ λ¬΄κΈ°ν•œ λŒ€κΈ°ν•˜μ§€ μ•Šλ„λ‘ ν•˜λŠ” 것도 κ³ λ €ν•΄λ³Ό λ§Œν•©λ‹ˆλ‹€.

ν˜„μž¬ λ™μž‘ μžμ²΄μ—λŠ” 문제 μ—†μ–΄ 보이고, μœ„ λ‚΄μš©μ€ μΆ”ν›„ μ„œλ²„ μ—λŸ¬(E600 λ“±)λ₯Ό ν”„λ‘ νŠΈμ—μ„œ 더 μ„Έλ°€ν•˜κ²Œ μ²˜λ¦¬ν•΄μ•Ό ν•  λ•Œ 도움이 될 κ°œμ„  ν¬μΈνŠΈμž…λ‹ˆλ‹€.

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 81659e0 and 5206f59.

β›” Files ignored due to path filters (1)
  • public/assets/chatbot.svg is excluded by !**/*.svg
πŸ“’ Files selected for processing (4)
  • src/pages/chatbot/components/ChattingInput.tsx (2 hunks)
  • src/pages/chatbot/index.tsx (4 hunks)
  • src/shared/api/chatbot/chatbot.ts (1 hunks)
  • src/shared/hooks/chatbot/useChatbot.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
πŸ“š Learning: 2025-10-31T17:34:04.352Z
Learnt from: jjangminii
Repo: geulDa/FE PR: 64
File: src/pages/map/result/components/ResultMap.tsx:3-3
Timestamp: 2025-10-31T17:34:04.352Z
Learning: The geulDa/FE project uses Next.js Pages Router (not App Router), so components should import useRouter from 'next/router' and should not use the 'use client' directive.

Applied to files:

  • src/pages/chatbot/index.tsx
🧬 Code graph analysis (3)
src/shared/hooks/chatbot/useChatbot.ts (1)
src/shared/api/chatbot/chatbot.ts (2)
  • createChatSession (28-56)
  • fetchChatResponse (59-92)
src/pages/chatbot/components/ChattingInput.tsx (1)
src/shared/hooks/useChattingInput.ts (1)
  • useChattingInput (8-49)
src/pages/chatbot/index.tsx (3)
src/shared/hooks/chatbot/useChatbot.ts (1)
  • useChatbot (9-44)
src/pages/chatbot/components/ChattingBubble.tsx (1)
  • Chatting (32-43)
src/pages/chatbot/components/ChattingInput.tsx (1)
  • ChattingInput (16-60)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy

Comment on lines +69 to 90
<main
role='log'
aria-label='μ±„νŒ… λ‚΄μš©'
aria-live='polite'
className={cn(mainStyle())}
>
{/* 둜고 + 기본 멘트 */}
<div className={cn(introStyle())}>
{/* 둜고 자리 (μž„μ‹œ) */}
<div
className='w-[6rem] h-[6rem] rounded-full bg-gray-200 flex-shrink-0'
aria-hidden="true"
{/* 둜고 자리*/}
<Image
src='/assets/chatbot.svg'
alt='챗봇 ν”„λ‘œν•„ μ•„μ΄μ½˜'
width={60}
height={60}
className='rounded-full flex-shrink-0'
priority
/>
<Chatting
message='μ•ˆλ…•ν•˜μ„Έμš”, κΈ€λ‹€μ—μš”! λΆ€μ²œμ‹œ 여행에 λŒ€ν•œ 정보λ₯Ό μ‰½κ²Œ μ•Œλ €λ“œλ¦΄κ²Œμš”.'
variant='received'
aria-label="κΈ€λ‹€μ˜ λ©”μ‹œμ§€: μ•ˆλ…•ν•˜μ„Έμš”, κΈ€λ‹€μ—μš”! λΆ€μ²œμ‹œ 여행에 λŒ€ν•œ 정보λ₯Ό μ‰½κ²Œ μ•Œλ €λ“œλ¦΄κ²Œμš”."
aria-label='κΈ€λ‹€μ˜ λ©”μ‹œμ§€: μ•ˆλ…•ν•˜μ„Έμš”, κΈ€λ‹€μ—μš”! λΆ€μ²œμ‹œ 여행에 λŒ€ν•œ 정보λ₯Ό μ‰½κ²Œ μ•Œλ €λ“œλ¦΄κ²Œμš”.'
/>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟑 Minor

🧩 Analysis chain

ARIA 섀정은 μ „λ°˜μ μœΌλ‘œ μ’‹μ§€λ§Œ, 첫 Chatting의 aria-label prop은 μ‹€μ œλ‘œ μ‚¬μš©λ˜μ§€ μ•Šμ„ κ°€λŠ₯성이 ν½λ‹ˆλ‹€.

  • <main>에 role='log', aria-live='polite', aria-label='μ±„νŒ… λ‚΄μš©'을 λΆ€μ—¬ν•œ 점, bottomRef에 aria-hidden='true'λ₯Ό μ€€ 점은 SR κ΄€μ μ—μ„œ 잘 μž‘ν˜€ μžˆμŠ΅λ‹ˆλ‹€.

  • λ‹€λ§Œ 첫 번째 Chatting μ»΄ν¬λ„ŒνŠΈμ— λ„˜κΈ΄ aria-label:

    <Chatting
      message='...'
      variant='received'
      aria-label='κΈ€λ‹€μ˜ λ©”μ‹œμ§€: ...'
    />

    은 ν˜„μž¬ Chatting κ΅¬ν˜„(λ©”μ‹œμ§€/variant만 μ‚¬μš©, λ‚˜λ¨Έμ§€ propsλ₯Ό DOM에 μ „λ‹¬ν•˜μ§€ μ•ŠμŒ) 상 μ‹€μ œ DOMκΉŒμ§€ μ „λ‹¬λ˜μ§€ μ•Šμ„ κ°€λŠ₯성이 λ†’μŠ΅λ‹ˆλ‹€. νƒ€μž… μ •μ˜κ°€ message/variant만 ν—ˆμš©ν•œλ‹€λ©΄ TS μ—λŸ¬λ„ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • μ„ νƒμ§€λŠ” 두 κ°€μ§€ 정도가 μžˆμ–΄ λ³΄μž…λ‹ˆλ‹€.

    1. aria-label을 μ—¬κΈ°μ„œ μ œκ±°ν•˜κ³ , ν•„μš”ν•˜λ©΄ Chatting λ‚΄λΆ€ 둜직/문ꡬλ₯Ό μ‘°μ •ν•΄μ„œ 접근성을 톡일성 있게 κ΄€λ¦¬ν•œλ‹€.
    2. Chatting의 propsλ₯Ό ChattingProps & React.HTMLAttributes<HTMLDivElement>처럼 ν™•μž₯ν•˜κ³ , λ‚΄λΆ€μ—μ„œ ...restλ₯Ό bubble에 μŠ€ν”„λ ˆλ“œν•΄ μ™ΈλΆ€μ—μ„œ μ „λ‹¬ν•œ aria-*λ₯Ό κ·ΈλŒ€λ‘œ 내렀보낸닀.

ν˜„μž¬ ꡬ쑰에선 ①이 κ°„λ‹¨ν•˜κ³ , β‘‘λŠ” Chatting을 더 λ²”μš©μ μœΌλ‘œ μ“°κ³  싢을 λ•Œ κ³ λ €ν•  λ§Œν•œ λ°©ν–₯μž…λ‹ˆλ‹€.

Also applies to: 98-104



---

🏁 Script executed:

```shell
#!/bin/bash
# Find the Chatting component definition
fd -t f -e tsx -e ts | head -20 | xargs grep -l "export.*Chatting" 2>/dev/null | head -5

Length of output: 94


🏁 Script executed:

#!/bin/bash
# Search for Chatting component definition with ast-grep
ast-grep --pattern 'export $_ Chatting'

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Also search more broadly for Chatting
rg -n "component.*Chatting|function Chatting|const Chatting" --type=tsx --type=ts -A 5 | head -50

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Check the current file to see both sections mentioned
cat src/pages/chatbot/index.tsx | head -110 | tail -50

Length of output: 1309


🏁 Script executed:

#!/bin/bash
# Look for ChattingProps type definition
rg -n "type ChattingProps|interface ChattingProps" --type=tsx --type=ts -A 10

Length of output: 27



---

🏁 Script executed:

```shell
#!/bin/bash
# Find Chatting component files
fd "Chatting" --type f

Length of output: 131


🏁 Script executed:

#!/bin/bash
# Search for Chatting in components directory
fd "." src/pages/chatbot/components/ --type f

Length of output: 94


🏁 Script executed:

#!/bin/bash
# Search for ChattingProps definition - use grep directly
grep -r "ChattingProps" src/pages/chatbot/ 2>/dev/null

Length of output: 238


🏁 Script executed:

#!/bin/bash
# Search for Chatting component definition - broader search
grep -r "function Chatting\|const Chatting\|export.*Chatting" src/pages/chatbot/ 2>/dev/null | grep -v node_modules | head -20

Length of output: 206


🏁 Script executed:

#!/bin/bash
# Look at ChattingBubble since it was found
cat src/pages/chatbot/components/ChattingBubble.tsx

Length of output: 884


aria-label prop이 Chatting μ»΄ν¬λ„ŒνŠΈμ— μ „λ‹¬λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

검증 κ²°κ³Ό, 리뷰 지적이 μ •ν™•ν•©λ‹ˆλ‹€. src/pages/chatbot/components/ChattingBubble.tsx의 ChattingProps μΈν„°νŽ˜μ΄μŠ€λŠ” message와 variant만 ν—ˆμš©ν•˜λ©°, μ»΄ν¬λ„ŒνŠΈλŠ” μΆ”κ°€ propsλ₯Ό DOM에 μ „λ‹¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

라인 85-88μ—μ„œ μ „λ‹¬ν•œ aria-label='κΈ€λ‹€μ˜ λ©”μ‹œμ§€: ...'은 λ¬΄μ‹œλ˜κ³ , Chatting μ»΄ν¬λ„ŒνŠΈμ˜ κΈ°λ³Έ 제곡 aria-label={variant === 'sent' ? 'λ‚΄ λ©”μ‹œμ§€' : 'μƒλŒ€λ°© λ©”μ‹œμ§€'}만 μ‚¬μš©λ©λ‹ˆλ‹€. 더 ꡬ체적인 μ ‘κ·Όμ„± 정보λ₯Ό λ‹΄μœΌλ €λ˜ μ˜λ„κ°€ μ‹€ν˜„λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

ν•΄κ²°μ•ˆ:

  1. 라인 85-88의 aria-label prop을 μ œκ±°ν•˜κ³  μ»΄ν¬λ„ŒνŠΈ κΈ°λ³Έκ°’ μ‚¬μš©
  2. λ˜λŠ” ChattingPropsλ₯Ό React.HTMLAttributes<HTMLDivElement>와 ν•©μΉ˜κ³  λ‚΄λΆ€μ—μ„œ ...rest μŠ€ν”„λ ˆλ“œ 처리

ν˜„μž¬ ꡬ쑰에선 ①이 κ°„λ‹¨ν•©λ‹ˆλ‹€.

πŸ€– Prompt for AI Agents
In src/pages/chatbot/index.tsx around lines 69 to 90, the aria-label prop passed
to the Chatting component is ignored because ChattingProps only allows message
and variant and the component doesn't forward extra props; remove the explicit
aria-label from lines 85-88 so the Chatting component's built-in aria-label
logic is used, or alternatively update ChattingBubble.tsx to extend
React.HTMLAttributes<HTMLDivElement> and spread ...rest onto the root element to
accept and forward custom aria attributes (option 1 is the simpler fix in this
context).

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/shared/api/chatbot/chatbot.ts (2)

78-83: API ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ localStorageλ₯Ό 직접 μ‘°μž‘ν•˜λŠ” 것은 관심사 뢄리 μΈ‘λ©΄μ—μ„œ κ°œμ„ μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

fetchChatResponse ν•¨μˆ˜ λ‚΄μ—μ„œ localStorageλ₯Ό 직접 μ œκ±°ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” API ν΄λΌμ΄μ–ΈνŠΈμ˜ μ±…μž„ λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜λ©°, ν˜ΈμΆœν•˜λŠ” μͺ½(hook)μ—μ„œ SESSION_EXPIRED μ—λŸ¬λ₯Ό λ°›μ•„ μ²˜λ¦¬ν•˜λ„λ‘ ν•˜λŠ” 것이 더 κΉ”λ”ν•©λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 λ¦¬νŒ©ν† λ§μ„ κ³ λ €ν•΄λ³΄μ„Έμš”:

  if (res.status === 404 && res.data?.code === 'E602') {
-   if (typeof window !== 'undefined') {
-     localStorage.removeItem('chatbot:sessionId');
-   }
    throw new Error('SESSION_EXPIRED');
  }

localStorage μ •λ¦¬λŠ” useChatbot.ts의 μ—λŸ¬ ν•Έλ“€λŸ¬λ‘œ 이동:

// useChatbot.ts의 catch λΈ”λ‘μ—μ„œ
if (err.message === 'SESSION_EXPIRED') {
  if (typeof window !== 'undefined') {
    localStorage.removeItem(SESSION_KEY);
  }
  // ... μƒˆ μ„Έμ…˜ 생성
}

78-78: λ“€μ—¬μ“°κΈ° 이슈.

if λ¬Έ μ•žμ— λΆˆν•„μš”ν•œ 곡백이 μžˆμŠ΅λ‹ˆλ‹€.

- if (res.status === 404 && res.data?.code === 'E602') {
+  if (res.status === 404 && res.data?.code === 'E602') {
πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 5206f59 and 08fb368.

πŸ“’ Files selected for processing (2)
  • src/shared/api/chatbot/chatbot.ts (1 hunks)
  • src/shared/hooks/chatbot/useChatbot.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/shared/hooks/chatbot/useChatbot.ts (1)
src/shared/api/chatbot/chatbot.ts (2)
  • createChatSession (28-56)
  • fetchChatResponse (59-99)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy
πŸ”‡ Additional comments (5)
src/shared/api/chatbot/chatbot.ts (3)

3-19: API 응닡 μŠ€ν‚€λ§ˆκ°€ λΆˆν™•μ‹€ν•©λ‹ˆλ‹€.

SessionSuccess와 ChatSuccess νƒ€μž…μ—μ„œ μ—¬λŸ¬ 선택적 ν•„λ“œ(result?, data?, sessionId?, answer?)λ₯Ό μ •μ˜ν•˜μ—¬ λ‹€μ–‘ν•œ 응닡 ν˜•μ‹μ„ μ²˜λ¦¬ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” λ°±μ—”λ“œ API 계약이 λͺ…ν™•ν•˜μ§€ μ•Šκ±°λ‚˜ 일관성이 μ—†μŒμ„ μ‹œμ‚¬ν•©λ‹ˆλ‹€.

λ°±μ—”λ“œ API λ¬Έμ„œλ₯Ό ν™•μΈν•˜μ—¬ μ •ν™•ν•œ 응닡 μŠ€ν‚€λ§ˆλ₯Ό νŒŒμ•…ν•˜κ³ , κ°€λŠ₯ν•˜λ‹€λ©΄ 단일 응닡 ν˜•μ‹μœΌλ‘œ ν‘œμ€€ν™”ν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ μ½”λ“œκ°€ 더 λͺ…ν™•ν•΄μ§€κ³  μ˜ˆμƒμΉ˜ λͺ»ν•œ 응닡 ν˜•μ‹ 처리 λ‘œμ§μ„ 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€.


21-25: ν™˜κ²½ λ³€μˆ˜ 검증이 μ μ ˆν•©λ‹ˆλ‹€.

getBaseUrl ν•¨μˆ˜κ°€ ν™˜κ²½ λ³€μˆ˜λ₯Ό ν™•μΈν•˜κ³  trailing slashλ₯Ό μ œκ±°ν•˜μ—¬ μΌκ΄€λœ URL을 보μž₯ν•©λ‹ˆλ‹€.


27-56: μ„Έμ…˜ 생성 둜직이 κ²¬κ³ ν•©λ‹ˆλ‹€.

λ‹€μ–‘ν•œ 응닡 ν˜•μ‹μ„ μ²˜λ¦¬ν•˜κ³  μ μ ˆν•œ μ—λŸ¬ λ‘œκΉ…μ„ μ œκ³΅ν•©λ‹ˆλ‹€. validateStatus: () => trueλ₯Ό μ‚¬μš©ν•˜μ—¬ μˆ˜λ™μœΌλ‘œ μƒνƒœ μ½”λ“œλ₯Ό ν™•μΈν•˜λŠ” 방식도 μ μ ˆν•©λ‹ˆλ‹€.

src/shared/hooks/chatbot/useChatbot.ts (2)

9-11: inited.current νŒ¨ν„΄μ€ μ μ ˆν•˜μ§€λ§Œ μ œν•œμ‚¬ν•­μ΄ μžˆμŠ΅λ‹ˆλ‹€.

React 18 Strict Mode의 이쀑 λ Œλ”λ§μ„ λ°©μ§€ν•˜κΈ° μœ„ν•œ 일반적인 νŒ¨ν„΄μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ»΄ν¬λ„ŒνŠΈκ°€ μ–Έλ§ˆμš΄νŠΈ ν›„ 재마운트되면 inited.currentκ°€ μ—¬μ „νžˆ trueμ΄λ―€λ‘œ bootstrap이 μ‹€ν–‰λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

이것이 μ˜λ„λœ λ™μž‘μΈμ§€ ν™•μΈν•˜μ„Έμš”. λ§Œμ•½ 재마운트 μ‹œ μƒˆ μ„Έμ…˜μ„ 생성해야 ν•œλ‹€λ©΄, cleanupμ—μ„œ inited.current = false둜 μž¬μ„€μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€.


1-7: 'use client' μ§€μ‹œμ–΄μ™€ μƒμˆ˜ μ •μ˜κ°€ μ μ ˆν•©λ‹ˆλ‹€.

Next.js ν΄λΌμ΄μ–ΈνŠΈ μ»΄ν¬λ„ŒνŠΈμž„μ„ λͺ…μ‹œν•˜κ³  localStorage ν‚€λ₯Ό μƒμˆ˜λ‘œ μ •μ˜ν•˜μ—¬ μž¬μ‚¬μš©μ„±κ³Ό μœ μ§€λ³΄μˆ˜μ„±μ„ λ†’μ˜€μŠ΅λ‹ˆλ‹€.

Comment on lines +13 to +34
useEffect(() => {
if (inited.current) return;
inited.current = true;

const bootstrap = async () => {
try {
const cached = typeof window !== 'undefined' ? localStorage.getItem(SESSION_KEY) : null;
if (cached) {
setSessionId(cached);
return;
}
const id = await createChatSession();
setSessionId(id);
if (typeof window !== 'undefined') localStorage.setItem(SESSION_KEY, id);
} catch (e) {
console.error('μ„Έμ…˜ 생성 μ‹€νŒ¨:', e);
setSessionId(null);
}
};

bootstrap();
}, []);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟑 Minor

잠재적 λ©”λͺ¨λ¦¬ λˆ„μˆ˜: μ»΄ν¬λ„ŒνŠΈ μ–Έλ§ˆμš΄νŠΈ ν›„ μƒνƒœ μ—…λ°μ΄νŠΈ κ°€λŠ₯μ„±.

bootstrap ν•¨μˆ˜κ°€ λΉ„λ™κΈ°λ‘œ μ‹€ν–‰λ˜λŠ” λ™μ•ˆ μ»΄ν¬λ„ŒνŠΈκ°€ μ–Έλ§ˆμš΄νŠΈλ˜λ©΄, setSessionIdκ°€ μ–Έλ§ˆμš΄νŠΈλœ μ»΄ν¬λ„ŒνŠΈμ—μ„œ ν˜ΈμΆœλ˜μ–΄ κ²½κ³ κ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

cleanup ν•¨μˆ˜λ₯Ό μΆ”κ°€ν•˜μ—¬ 이λ₯Ό λ°©μ§€ν•˜μ„Έμš”:

  useEffect(() => {
    if (inited.current) return;
    inited.current = true;
+   let mounted = true;

    const bootstrap = async () => {
      try {
        const cached = typeof window !== 'undefined' ? localStorage.getItem(SESSION_KEY) : null;
        if (cached) {
+         if (mounted) {
            setSessionId(cached);
+         }
          return;
        }
        const id = await createChatSession();
+       if (mounted) {
          setSessionId(id);
          if (typeof window !== 'undefined') localStorage.setItem(SESSION_KEY, id);
+       }
      } catch (e) {
        console.error('μ„Έμ…˜ 생성 μ‹€νŒ¨:', e);
+       if (mounted) {
          setSessionId(null);
+       }
      }
    };

    bootstrap();
+   return () => {
+     mounted = false;
+   };
  }, []);
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (inited.current) return;
inited.current = true;
const bootstrap = async () => {
try {
const cached = typeof window !== 'undefined' ? localStorage.getItem(SESSION_KEY) : null;
if (cached) {
setSessionId(cached);
return;
}
const id = await createChatSession();
setSessionId(id);
if (typeof window !== 'undefined') localStorage.setItem(SESSION_KEY, id);
} catch (e) {
console.error('μ„Έμ…˜ 생성 μ‹€νŒ¨:', e);
setSessionId(null);
}
};
bootstrap();
}, []);
useEffect(() => {
if (inited.current) return;
inited.current = true;
let mounted = true;
const bootstrap = async () => {
try {
const cached = typeof window !== 'undefined' ? localStorage.getItem(SESSION_KEY) : null;
if (cached) {
if (mounted) {
setSessionId(cached);
}
return;
}
const id = await createChatSession();
if (mounted) {
setSessionId(id);
if (typeof window !== 'undefined') localStorage.setItem(SESSION_KEY, id);
}
} catch (e) {
console.error('μ„Έμ…˜ 생성 μ‹€νŒ¨:', e);
if (mounted) {
setSessionId(null);
}
}
};
bootstrap();
return () => {
mounted = false;
};
}, []);
πŸ€– Prompt for AI Agents
In src/shared/hooks/chatbot/useChatbot.ts around lines 13 to 34, the async
bootstrap may call setSessionId after the component unmounts causing a
memory-leak/warning; add a mounted flag (or use a ref) that is true while
mounted and set to false in the effect cleanup, then check that flag before any
setSessionId or localStorage writes (and before console.error handling) so state
updates are only performed when mounted; ensure the flag is closed over by
bootstrap and the effect returns the cleanup that flips it to false.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/pages/chatbot/index.tsx (1)

93-101: ν”„λ‘œν•„ 이미지 μΆ”κ°€λŠ” μ μ ˆν•˜λ‚˜, Chatting에 λ„˜κΈ΄ aria-label은 μ—¬μ „νžˆ λ¬΄μ‹œλ©λ‹ˆλ‹€

  • next/image둜 챗봇 ν”„λ‘œν•„ SVGλ₯Ό λ Œλ”λ§ν•˜κ³ , μ μ ˆν•œ alt ν…μŠ€νŠΈλ₯Ό λΆ€μ—¬ν•œ 뢀뢄은 μ’‹μŠ΅λ‹ˆλ‹€.

  • λ‹€λ§Œ 첫 번째 Chatting μ»΄ν¬λ„ŒνŠΈμ— λ„˜κΈ΄ aria-label:

    <Chatting
      message='μ•ˆλ…•ν•˜μ„Έμš”, κΈ€λ‹€μ—μš”! λΆ€μ²œμ‹œ 여행에 λŒ€ν•œ 정보λ₯Ό μ‰½κ²Œ μ•Œλ €λ“œλ¦΄κ²Œμš”.'
      variant='received'
      aria-label='κΈ€λ‹€μ˜ λ©”μ‹œμ§€: μ•ˆλ…•ν•˜μ„Έμš”, κΈ€λ‹€μ—μš”! λΆ€μ²œμ‹œ 여행에 λŒ€ν•œ 정보λ₯Ό μ‰½κ²Œ μ•Œλ €λ“œλ¦΄κ²Œμš”.'
    />

    은 ν˜„μž¬ Chatting κ΅¬ν˜„(ChattingBubble.tsx의 ChattingPropsκ°€ message/variant만 ν—ˆμš©, λ‚˜λ¨Έμ§€ propsλŠ” DOM으둜 μ „λ‹¬ν•˜μ§€ μ•ŠμŒ) 상 μ‹€μ œ DOMκΉŒμ§€ μ „λ‹¬λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이전 PRμ—μ„œ μ§€μ λœ 것과 λ™μΌν•œ μ΄μŠˆμž…λ‹ˆλ‹€.

  • 이 PRμ—μ„œλŠ” κ°„λ‹¨ν•˜κ²Œ 이 aria-label prop을 μ œκ±°ν•˜κ³ , Chatting μ»΄ν¬λ„ŒνŠΈ λ‚΄λΆ€μ˜ κΈ°λ³Έ aria-label λ‘œμ§μ— λ§‘κΈ°λŠ” μͺ½μ΄ λ¬΄λ‚œν•΄ λ³΄μž…λ‹ˆλ‹€.

μ˜ˆμ‹œ diff:

-          <Chatting
-            message='μ•ˆλ…•ν•˜μ„Έμš”, κΈ€λ‹€μ—μš”! λΆ€μ²œμ‹œ 여행에 λŒ€ν•œ 정보λ₯Ό μ‰½κ²Œ μ•Œλ €λ“œλ¦΄κ²Œμš”.'
-            variant='received'
-            aria-label='κΈ€λ‹€μ˜ λ©”μ‹œμ§€: μ•ˆλ…•ν•˜μ„Έμš”, κΈ€λ‹€μ—μš”! λΆ€μ²œμ‹œ 여행에 λŒ€ν•œ 정보λ₯Ό μ‰½κ²Œ μ•Œλ €λ“œλ¦΄κ²Œμš”.'
-          />
+          <Chatting
+            message='μ•ˆλ…•ν•˜μ„Έμš”, κΈ€λ‹€μ—μš”! λΆ€μ²œμ‹œ 여행에 λŒ€ν•œ 정보λ₯Ό μ‰½κ²Œ μ•Œλ €λ“œλ¦΄κ²Œμš”.'
+            variant='received'
+          />

Also applies to: 102-106

🧹 Nitpick comments (4)
src/pages/chatbot/components/ChattingBubble.tsx (1)

35-41: 멀티라인 λ©”μ‹œμ§€ ν‘œμ‹œμš© whiteSpace: 'pre-line' μΆ”κ°€ μ’‹μŠ΅λ‹ˆλ‹€

API 응닡에 ν¬ν•¨λœ μ€„λ°”κΏˆμ„ κ·ΈλŒ€λ‘œ 살릴 수 μžˆμ–΄μ„œ μ‹€μ œ λŒ€ν™”μ²˜λŸΌ 보여쀄 수 μžˆλŠ” 변경이라 μ’‹μ•„ λ³΄μž…λ‹ˆλ‹€. μŠ€νƒ€μΌ 일관성을 μœ„ν•΄ λ‚˜μ€‘μ— μ—¬μœ κ°€ 있으면 Tailwind μœ ν‹Έ(whitespace-pre-line)μ΄λ‚˜ chatBubbleStyle에 클래슀둜 λ…Ήμ—¬ λ‘λŠ” 것도 κ³ λ €ν•΄ λ³Ό λ§Œν•©λ‹ˆλ‹€.

src/pages/chatbot/index.tsx (3)

3-12: λΌμš°ν„°/ν›…/μ»΄ν¬λ„ŒνŠΈ import ꡬ성 μ μ ˆν•©λ‹ˆλ‹€

next/router둜 useRouterλ₯Ό κ°€μ Έμ˜€κ³ , useChatbot ν›…κ³Ό ChattingΒ·ChattingInput μ»΄ν¬λ„ŒνŠΈλ₯Ό 이 νŽ˜μ΄μ§€μ—μ„œλ§Œ μ‚¬μš©ν•˜λ„λ‘ 묢은 ꡬ쑰가 Pages Router μ»¨λ²€μ…˜κ³Ό 잘 λ§žμŠ΅λ‹ˆλ‹€.
μΆ”κ°€λ‘œ, 이 νŒŒμΌμ€ Pages Router의 page μ»΄ν¬λ„ŒνŠΈλΌ 'use client' μ§€μ‹œλ¬Έμ€ 사싀상 μ˜λ―Έκ°€ μ—†μœΌλ―€λ‘œ μŠ€νƒ€μΌ μΈ‘λ©΄μ—μ„œ μ œκ±°ν•΄λ„ λ©λ‹ˆλ‹€.


34-45: formatAnswer ν›„μ²˜λ¦¬ λ‘œμ§μ€ μœ μš©ν•˜μ§€λ§Œ, λΈŒλΌμš°μ € ν˜Έν™˜μ„±κ³Ό μœ μ§€λ³΄μˆ˜μ— μœ μ˜ν•˜λ©΄ μ’‹κ² μŠ΅λ‹ˆλ‹€

  • 뢈릿(Β·, β€’)κ³Ό λ¬Έμž₯λΆ€ν˜Έ 뒀에 μ€„λ°”κΏˆμ„ λ„£κ³ , 이λͺ¨μ§€ μ£Όλ³€ 곡백/μ€„λ°”κΏˆμ„ μ •λ¦¬ν•˜λŠ” κ·œμΉ™μ€ 챗봇 닡변을 읽기 μ’‹κ²Œ λ§Œλ“œλŠ” 데 도움이 될 것 κ°™μŠ΅λ‹ˆλ‹€.
  • λ‹€λ§Œ \p{Emoji_Presentation}, \p{Emoji} 같은 μœ λ‹ˆμ½”λ“œ ν”„λ‘œνΌν‹° μ •κ·œμ‹μ€ 일뢀 κ΅¬ν˜• λΈŒλΌμš°μ €μ—μ„œλŠ” 지원이 μ œν•œλ  수 μžˆμœΌλ‹ˆ, νƒ€κ²Ÿ λΈŒλΌμš°μ € λ²”μœ„λ₯Ό κ³ λ €ν•΄λ‘λŠ” 편이 μ’‹μŠ΅λ‹ˆλ‹€.
  • κ·œμΉ™μ΄ κ½€ λ§Žμ•„μ‘ŒμœΌλ‹ˆ, λ‚˜μ€‘μ— 포맷이 더 λ³΅μž‘ν•΄μ§ˆ 경우 μ£Όμ„μœΌλ‘œ μ˜λ„λ₯Ό κ°„λ‹¨νžˆ λ‚¨κΈ°κ±°λ‚˜ 별 μœ ν‹Έ ν•¨μˆ˜ 파일둜 λΆ„λ¦¬ν•˜λŠ” 것도 κ³ λ €ν•΄λ³Ό λ§Œν•©λ‹ˆλ‹€.

51-75: handleSend 흐름은 λ§žμ§€λ§Œ, 전솑 쀑 μƒνƒœ 및 μ—λŸ¬ UXλ₯Ό 쑰금 더 보완할 μ—¬μ§€κ°€ μžˆμŠ΅λ‹ˆλ‹€

  • 곡백 λ¬Έμžμ—΄ 차단, sessionId 미쑴재 μ‹œ early return, μ‚¬μš©μž λ©”μ‹œμ§€ β†’ 챗봇 응닡 순으둜 messagesλ₯Ό μ—…λ°μ΄νŠΈν•˜λŠ” 흐름은 μžμ—°μŠ€λŸ½μŠ΅λ‹ˆλ‹€.
  • ν˜„μž¬ μ‹€νŒ¨ μ‹œμ—λŠ” μ½˜μ†” 둜그만 남고 μ‚¬μš©μžμ—κ²ŒλŠ” 아무 ν”Όλ“œλ°±μ΄ μ—†μ–΄, μ‹€μ œ μ„œλΉ„μŠ€ μ‹œμ—λŠ” β€œλ‹΅λ³€μ„ κ°€μ Έμ˜€μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€β€ 같은 λ©”μ‹œμ§€λ₯Ό 봇 λ©”μ‹œμ§€λ‘œ μΆ”κ°€ν•΄ μ£ΌλŠ” 것도 μ’‹κ² μŠ΅λ‹ˆλ‹€.
  • useChatbotμ—μ„œ React Query useMutation을 μ“°κ³  μžˆμœΌλ―€λ‘œ, isPending 등을 이 μ»΄ν¬λ„ŒνŠΈλ‘œ λŒμ–΄μ™€ ChattingInput의 disabled에 ν•¨κ»˜ λ°˜μ˜ν•˜λ©΄ 연속 클릭/쀑볡 전솑을 λ°©μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예: disabled={!sessionId || isPending}.

Also applies to: 123-123

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 409fd03 and 558fc5b.

πŸ“’ Files selected for processing (2)
  • src/pages/chatbot/components/ChattingBubble.tsx (1 hunks)
  • src/pages/chatbot/index.tsx (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
πŸ“š Learning: 2025-10-31T17:34:04.352Z
Learnt from: jjangminii
Repo: geulDa/FE PR: 64
File: src/pages/map/result/components/ResultMap.tsx:3-3
Timestamp: 2025-10-31T17:34:04.352Z
Learning: The geulDa/FE project uses Next.js Pages Router (not App Router), so components should import useRouter from 'next/router' and should not use the 'use client' directive.

Applied to files:

  • src/pages/chatbot/index.tsx
🧬 Code graph analysis (2)
src/pages/chatbot/index.tsx (4)
src/shared/hooks/chatbot/useChatbot.ts (1)
  • useChatbot (9-63)
src/shared/lib/utils.ts (1)
  • cn (71-73)
src/pages/chatbot/components/ChattingBubble.tsx (1)
  • Chatting (32-44)
src/pages/chatbot/components/ChattingInput.tsx (1)
  • ChattingInput (16-60)
src/pages/chatbot/components/ChattingBubble.tsx (1)
src/shared/lib/utils.ts (1)
  • cn (71-73)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy
πŸ”‡ Additional comments (2)
src/pages/chatbot/index.tsx (2)

23-33: Message νƒ€μž… μ •μ˜μ™€ λ©”μ‹œμ§€ λ Œλ”λ§ 흐름이 κΉ”λ”ν•©λ‹ˆλ‹€

Messageλ₯Ό text와 variant('received' | 'sent')둜 λͺ…ν™•νžˆ νƒ€μž…ν™”ν•΄μ„œ messages: Message[] μƒνƒœμ™€ messages.map(...) λ Œλ”λ§μ— μž¬μ‚¬μš©ν•œ 점이 μœ μ§€λ³΄μˆ˜ μΈ‘λ©΄μ—μ„œ μ’‹μŠ΅λ‹ˆλ‹€. λ©”μ‹œμ§€ 필터링 없이 동일 배열을 κ·ΈλŒ€λ‘œ 화면에 λ§΅ν•‘ν•˜λŠ” ꡬ쑰라, 이후 μ‹œμŠ€ν…œ λ©”μ‹œμ§€λ‚˜ μƒνƒœ λ©”μ‹œμ§€λ₯Ό μΆ”κ°€ν•  λ•Œλ„ ν™•μž₯ν•˜κΈ° μˆ˜μ›”ν•΄ λ³΄μž…λ‹ˆλ‹€.

Also applies to: 114-116


85-90: role='log' + aria-live + 슀크둀 센티넬 쑰합이 μ ‘κ·Όμ„± μΈ‘λ©΄μ—μ„œ 잘 μž‘ν˜€ μžˆμŠ΅λ‹ˆλ‹€

<main role='log' aria-live='polite' aria-label='μ±„νŒ… λ‚΄μš©'>κ³Ό bottomRefλ₯Ό μ΄μš©ν•œ μžλ™ 슀크둀 νŒ¨ν„΄μ€ μŠ€ν¬λ¦°λ¦¬λ” μ‚¬μš©μžμ—κ²Œλ„ μƒˆλ‘œμš΄ λ©”μ‹œμ§€κ°€ μžμ—°μŠ€λŸ½κ²Œ μ½νžˆλ„λ‘ ν•˜λŠ” ꡬ쑰라 μ’‹μ•„ λ³΄μž…λ‹ˆλ‹€. aria-hidden='true'둜 센티넬λ₯Ό 숨긴 것도 μ μ ˆν•©λ‹ˆλ‹€.

Also applies to: 119-119

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
src/shared/hooks/chatbot/useChatbot.ts (2)

64-93: 이전 λ¦¬λ·°μ—μ„œ μ§€μ λœ λ©”λͺ¨λ¦¬ λˆ„μˆ˜ λ¬Έμ œκ°€ μ—¬μ „νžˆ μ‘΄μž¬ν•©λ‹ˆλ‹€.

비동기 bootstrap μ‹€ν–‰ 쀑 μ»΄ν¬λ„ŒνŠΈκ°€ μ–Έλ§ˆμš΄νŠΈλ˜λ©΄ setSessionId와 setMessages 호좜이 μ–Έλ§ˆμš΄νŠΈλœ μ»΄ν¬λ„ŒνŠΈμ—μ„œ λ°œμƒν•˜μ—¬ λ©”λͺ¨λ¦¬ λˆ„μˆ˜ κ²½κ³ κ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이전 λ¦¬λ·°μ—μ„œ μ œμ•ˆλœ mounted ν”Œλž˜κ·Έλ₯Ό μ‚¬μš©ν•œ cleanup ν•¨μˆ˜ μΆ”κ°€κ°€ ν•„μš”ν•©λ‹ˆλ‹€.

λ˜ν•œ, Lines 76, 85μ—μ„œ localStorage μ ‘κ·Ό μ‹œ typeof window !== 'undefined' 체크가 λˆ„λ½λ˜μ–΄ SSR ν™˜κ²½μ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•˜μ„Έμš”:

  useEffect(() => {
    if (inited.current) return;
    inited.current = true;
+   let mounted = true;

    // νžˆμŠ€ν† λ¦¬ λ‘œλ“œ (둜그인 μœ μ €λ§Œ)
    if (isLoggedIn) {
      const prev = loadHistory();
+     if (mounted) {
        setMessages(prev);
+     }
    }

    const bootstrap = async () => {
      try {
-       const cached = localStorage.getItem(SESSION_KEY);
+       const cached = typeof window !== 'undefined' ? localStorage.getItem(SESSION_KEY) : null;

        if (cached) {
+         if (mounted) {
            setSessionId(cached);
+         }
          return;
        }

        const id = await createChatSession();
+       if (mounted) {
          setSessionId(id);
-         localStorage.setItem(SESSION_KEY, id);
+         if (typeof window !== 'undefined') {
+           localStorage.setItem(SESSION_KEY, id);
+         }
+       }
      } catch (e) {
        console.error('μ„Έμ…˜ 생성 μ‹€νŒ¨:', e);
+       if (mounted) {
          setSessionId(null);
+       }
      }
    };

    bootstrap();
+   return () => {
+     mounted = false;
+   };
  }, []);

96-113: 이전 λ¦¬λ·°μ—μ„œ μ§€μ λœ μž¬μ‹œλ„ 였λ₯˜ μ²˜λ¦¬κ°€ μ—¬μ „νžˆ λˆ„λ½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

Line 104: createChatSession()이 μ‹€νŒ¨ν•˜λ©΄ μ—λŸ¬κ°€ κ·ΈλŒ€λ‘œ μ „νŒŒλ˜μ–΄ μ‚¬μš©μžμ—κ²Œ λͺ…ν™•ν•œ ν”Όλ“œλ°±μ΄ μ œκ³΅λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ˜ν•œ, Line 106μ—μ„œ localStorage.setItem 호좜 μ‹œ typeof window !== 'undefined' 체크가 μ—†μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•˜μ„Έμš”:

      } catch (err: any) {
        if (err.message === 'SESSION_EXPIRED') {
-         const newId = await createChatSession();
-         setSessionId(newId);
-         localStorage.setItem(SESSION_KEY, newId);
-
-         return await fetchChatResponse(body.message, newId);
+         try {
+           const newId = await createChatSession();
+           setSessionId(newId);
+           if (typeof window !== 'undefined') {
+             localStorage.setItem(SESSION_KEY, newId);
+           }
+
+           return await fetchChatResponse(body.message, newId);
+         } catch (retryErr) {
+           console.error('μž¬μ‹œλ„ 쀑 였λ₯˜:', retryErr);
+           throw new Error('μ„Έμ…˜ μž¬μƒμ„± μ‹€νŒ¨. λ‚˜μ€‘μ— λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.');
+         }
        }

        throw err;
      }
🧹 Nitpick comments (1)
src/shared/hooks/chatbot/useChatbot.ts (1)

22-25: μ„±λŠ₯ μ΅œμ ν™” κ³ λ €: memberId 계산을 λ©”λͺ¨μ΄μ œμ΄μ…˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

getMemberIdFromToken()이 λ§€ λ Œλ”λ§ˆλ‹€ ν˜ΈμΆœλ˜μ–΄ localStorage μ ‘κ·Ό 및 JWT 디코딩이 λ°˜λ³΅λ©λ‹ˆλ‹€. μ»΄ν¬λ„ŒνŠΈκ°€ 자주 λ¦¬λ Œλ”λ§λ˜λŠ” 경우 useMemo둜 μ΅œμ ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

+  const memberId = useMemo(() => getMemberIdFromToken(), []);
-  const memberId = getMemberIdFromToken();
   const isLoggedIn = !!memberId;
πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 558fc5b and 3967986.

πŸ“’ Files selected for processing (2)
  • src/pages/chatbot/index.tsx (4 hunks)
  • src/shared/hooks/chatbot/useChatbot.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/chatbot/index.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/shared/hooks/chatbot/useChatbot.ts (2)
src/shared/utils/token.ts (1)
  • getMemberIdFromToken (25-39)
src/shared/api/chatbot/chatbot.ts (2)
  • createChatSession (29-57)
  • fetchChatResponse (60-99)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy

Copy link
Copy Markdown
Contributor

@skyblue1232 skyblue1232 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

챗봇 κ΅¬ν˜„μ΄ UX 적으둜 쒋은 것 κ°™κ³ , μ „μ²΄μ μœΌλ‘œ 잘 μž‘λ™ν•˜λŠ” 것 κ°™λ„€μš”! μˆ˜κ³ ν•˜μ…¨μŠ΅λ‹ˆλ‹€!

@KongMezu KongMezu merged commit a068e70 into develop Nov 14, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api api μ—°κ²° comment ν•„μš”ν•œ 주석 μΆ”κ°€ 및 λ³€κ²½

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[api&feat] 챗봇 νŽ˜μ΄μ§€ ν”„λ‘œν•„ μΆ”κ°€ api μ—°κ²°

2 participants