Skip to content

Conversation

@Han-wo
Copy link
Collaborator

@Han-wo Han-wo commented Jul 7, 2025

#️⃣ 이슈

📝 작업 내용

기존 토큰 관련 로직에서 클라이언트에서 접근 할수 있는게 있어서 서버액션으로 변경 후 서버에서만 접근 가능하게 변경

📸 스크린샷

✅ 체크 리스트

  • 적절한 Title 작성
  • 적절한 Label 지정
  • Assignee 및 Reviewer 지정
  • 로컬 작동 확인
  • Merge 되는 브랜치 확인

👩‍💻 공유 포인트 및 논의 사항

Summary by CodeRabbit

  • 신규 기능

    • 서버 측 인증 모듈 및 API 요청 헬퍼 도입으로 인증 및 세션 관리가 강화되었습니다.
    • 인증 상태를 효율적으로 관리하는 새로운 React 훅(useApi)이 추가되었습니다.
  • 버그 수정

    • 토큰 기반 인증 방식에서 httpOnly 쿠키 기반 인증 방식으로 전환되어 인증 관련 오류가 감소했습니다.
  • 리팩터링

    • 클라이언트와 서버 전반에서 인증 로직이 통합되고 단순화되었습니다.
    • 인증 상태 저장소(useAuth)가 동기 방식으로 개선되어 코드 복잡도가 줄었습니다.
    • 여러 컴포넌트에서 토큰 전달 및 관리 로직이 제거되어 코드가 간결해졌습니다.
  • 타입 변경

    • 거래 관련 타입에서 토큰 필드가 삭제되어 인터페이스가 단순화되었습니다.

@Han-wo Han-wo self-assigned this Jul 7, 2025
@Han-wo Han-wo added the 우선순위: MEDIUM New feature or request label Jul 7, 2025
@Han-wo Han-wo linked an issue Jul 7, 2025 that may be closed by this pull request
2 tasks
@Han-wo Han-wo added the ♻️REFACTOR Refactor code label Jul 7, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 7, 2025

Walkthrough

이 PR은 인증 및 인가 방식을 서버 사이드 httpOnly 쿠키 기반으로 전면 개편합니다. 클라이언트와 서버 모두에서 토큰 파라미터와 Authorization 헤더 사용을 제거하고, 인증 상태와 사용자 정보는 쿠키와 서버 액션을 통해 관리하도록 변경되었습니다. 관련 API, 훅, 컴포넌트가 모두 이에 맞게 수정되었습니다.

Changes

파일/그룹 변경 요약
src/actions/auth.ts, src/lib/auth-server.ts 서버 인증/세션 관리 모듈 및 서버 인증 유틸 함수 신규 추가
src/api/make-api-request.ts, src/api/portfolio/index.ts, src/api/side-Info/index.ts, src/api/transaction/index.ts 모든 API 함수에서 토큰 파라미터 및 Authorization 헤더 제거, credentials: "include"로 쿠키 기반 인증으로 전환
src/hooks/use-auth.ts useAuth 훅을 단순화: 쿠키/비동기 로직 삭제, userInfo 객체 및 동기 setter로 변경
src/hooks/use-api.ts 인증 자동 처리 및 401시 자동 로그아웃/리다이렉트하는 useApi 훅 신규 추가
src/hooks/use-token-refresh.ts 세션 연장/로그아웃을 서버 액션 기반으로 전환, 클라이언트 쿠키/라우터 로직 제거
src/app/layout.tsx, src/provider/AuthInitializer.tsx 서버에서 인증 상태/유저 정보 받아 초기화하도록 변경, AuthInitializer 컴포넌트 prop 구조 변경
src/app/login/login-form.tsx 로그인 로직을 서버 액션 기반으로 변경, 상태 관리 및 토스트 처리 개편
src/app/main/_components/asset-info.tsx, src/app/main/_components/stock-info.tsx, src/app/portfolio/_components/portfoilo-card.tsx, src/app/search/[id]/_components/order-stock/buy-and-sell/buyable-quantity.tsx, ... useAuth 훅 사용 방식 및 인증 상태 접근, API 호출 시 토큰 제거 등 인증 방식 일괄 수정
src/app/my-account/page.tsx, src/app/portfolio/page.tsx 페이지 단 인증 체크/리다이렉트 로직을 requireAuth()로 통합, 토큰 관련 코드 제거
src/types/transaction/index.ts 거래 관련 타입에서 token 필드 제거

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Server
    participant API

    Client->>Server: loginAction(credentials)
    Server->>API: POST /login (credentials)
    API-->>Server: { token, userInfo }
    Server->>Client: Set httpOnly cookies (token, userInfo)
    Client->>Server: fetchProtectedData()
    Server->>API: fetch with credentials: include
    API-->>Server: data
    Server-->>Client: data

    Client->>Server: logoutAction()
    Server->>Client: Clear cookies, redirect to /login
Loading

Assessment against linked issues

Objective Addressed Explanation
서버에서만 쿠키를 접근하게 인증인가 방식 수정 (#103)
인증/인가 관련 기존 토큰 기반 방식 제거 및 서버 액션, 쿠키 기반 인증 적용 (#103)

Assessment against linked issues: Out-of-scope changes

(해당 PR의 모든 변경은 인증/인가 방식 개편과 직접적으로 연관되어 있습니다. 범위를 벗어난 기능적 변경은 발견되지 않았습니다.)

Possibly related PRs

Poem

🐇
쿠키 속에 비밀을 담아
토큰은 안녕, 서버가 맡아
로그인, 로그아웃 모두 깔끔하게
인증의 길을 새로 열었네
토끼도 이제 안심하고
서버의 품에서 꿈을 꾸네!
🍪✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link

github-actions bot commented Jul 7, 2025

Copy link

@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: 3

🧹 Nitpick comments (2)
src/hooks/use-api.ts (1)

1-1: any 타입 사용에 대한 타입 안전성 검토가 필요합니다.

범용 API 훅에서 any 타입 사용은 불가피할 수 있지만, 가능한 경우 제네릭 타입을 사용하여 타입 안전성을 향상시킬 수 있는지 검토해보세요.

다음과 같은 제네릭 타입 사용을 고려해보세요:

-const post = useCallback(
-  (url: string, data?: any) =>
+const post = useCallback(
+  <T = any>(url: string, data?: T) =>
     apiCall(url, {
       method: "POST",
       body: data ? JSON.stringify(data) : undefined,
     }),
   [apiCall],
 );
src/actions/auth.ts (1)

103-103: 프로덕션 환경에서 콘솔 로그 제거 고려

민감한 정보가 로그에 노출될 수 있으므로, 프로덕션 환경에서는 콘솔 로그를 제거하거나 조건부로 출력하는 것을 권장합니다.

Also applies to: 133-133, 191-191, 230-230, 234-234, 264-264

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36db61e and e8a207b.

📒 Files selected for processing (24)
  • src/actions/auth.ts (1 hunks)
  • src/api/make-api-request.ts (1 hunks)
  • src/api/portfolio/index.ts (1 hunks)
  • src/api/side-Info/index.ts (2 hunks)
  • src/api/transaction/index.ts (1 hunks)
  • src/app/layout.tsx (2 hunks)
  • src/app/login/login-form.tsx (4 hunks)
  • src/app/main/_components/asset-info.tsx (6 hunks)
  • src/app/main/_components/stock-info.tsx (2 hunks)
  • src/app/my-account/page.tsx (3 hunks)
  • src/app/portfolio/_components/portfoilo-card.tsx (3 hunks)
  • src/app/portfolio/page.tsx (1 hunks)
  • src/app/search/[id]/_components/order-stock/buy-and-sell/buyable-quantity.tsx (3 hunks)
  • src/app/search/[id]/_components/order-stock/buy-and-sell/index.tsx (0 hunks)
  • src/app/search/[id]/_components/order-stock/edit-cancel/index.tsx (2 hunks)
  • src/app/search/[id]/_components/order-stock/index.tsx (1 hunks)
  • src/app/search/[id]/_components/order-stock/order-history/index.tsx (2 hunks)
  • src/app/search/[id]/hooks/use-limit-order-data.ts (1 hunks)
  • src/hooks/use-api.ts (1 hunks)
  • src/hooks/use-auth.ts (1 hunks)
  • src/hooks/use-token-refresh.ts (4 hunks)
  • src/lib/auth-server.ts (1 hunks)
  • src/provider/AuthInitializer.tsx (1 hunks)
  • src/types/transaction/index.ts (0 hunks)
💤 Files with no reviewable changes (2)
  • src/types/transaction/index.ts
  • src/app/search/[id]/_components/order-stock/buy-and-sell/index.tsx
🧰 Additional context used
🧠 Learnings (1)
src/app/login/login-form.tsx (1)
Learnt from: cindycho0423
PR: Online-Investment-Platform/Front_End#48
File: src/app/search/[id]/_components/transaction-form/transaction-table.tsx:34-34
Timestamp: 2024-12-10T11:31:41.241Z
Learning: 이 프로젝트에서는 폼 제출 로직이 상위 컴포넌트에서 관리되며, 하위 컴포넌트에서는 `<form>` 태그를 사용하지만 `onSubmit` 핸들러가 없을 수 있습니다.
🧬 Code Graph Analysis (12)
src/app/search/[id]/_components/order-stock/order-history/index.tsx (1)
src/api/transaction/index.ts (1)
  • getTradeHistory (77-81)
src/app/portfolio/page.tsx (1)
src/lib/auth-server.ts (1)
  • requireAuth (29-35)
src/app/main/_components/stock-info.tsx (1)
src/api/side-Info/index.ts (2)
  • fetchMyStocks (13-29)
  • fetchStockCount (31-47)
src/api/portfolio/index.ts (1)
src/app/portfolio/types/index.ts (1)
  • PortfolioData (3-10)
src/app/search/[id]/hooks/use-limit-order-data.ts (2)
src/context/stock-info-context.tsx (1)
  • useStockInfoContext (54-62)
src/api/transaction/index.ts (1)
  • getTrade (52-56)
src/app/main/_components/asset-info.tsx (2)
src/store/use-toast-store.ts (1)
  • useToast (19-35)
src/actions/auth.ts (1)
  • logoutAction (115-138)
src/hooks/use-token-refresh.ts (1)
src/actions/auth.ts (2)
  • logoutAction (115-138)
  • extendSessionAction (145-197)
src/app/search/[id]/_components/order-stock/buy-and-sell/buyable-quantity.tsx (3)
src/context/stock-info-context.tsx (1)
  • useStockInfoContext (54-62)
src/api/side-Info/index.ts (1)
  • fetchMyStocks (13-29)
src/utils/price.ts (2)
  • getKoreanPrice (1-5)
  • calculateBuyableQuantity (17-25)
src/app/my-account/page.tsx (1)
src/lib/auth-server.ts (2)
  • makeAuthenticatedRequest (38-57)
  • requireAuth (29-35)
src/app/login/login-form.tsx (2)
src/store/use-toast-store.ts (1)
  • useToast (19-35)
src/actions/auth.ts (1)
  • loginAction (51-109)
src/actions/auth.ts (1)
src/validation/schema/auth/index.tsx (1)
  • LoginResponse (31-38)
src/api/transaction/index.ts (2)
src/api/make-api-request.ts (1)
  • makeApiRequest (1-34)
src/types/transaction/index.ts (9)
  • TradeAtMarketPriceFormDataType (55-60)
  • SellMarketPriceResponse (48-53)
  • TradeAtLimitPriceFormDataType (62-68)
  • TradeLimitPriceResponse (40-46)
  • MarketPriceHistoryResponse (23-30)
  • LimitPriceOrderHistory (5-12)
  • ModifyTradeFormData (70-72)
  • CancelData (1-3)
  • TradeHistory (14-21)
⏰ 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: storybook-preview
🔇 Additional comments (48)
src/app/search/[id]/_components/order-stock/index.tsx (1)

10-10: useAuth 훅의 default import 변경사항 승인

useAuth 훅이 default export로 리팩토링된 것에 맞춰 import 방식이 올바르게 변경되었습니다. 컴포넌트 내부 로직은 변경되지 않아 기존 기능이 유지됩니다.

src/app/search/[id]/_components/order-stock/edit-cancel/index.tsx (2)

1-1: "use client" 지시어 정정 승인

주석 처리되어 있던 "use client" 지시어가 올바르게 활성화되었습니다.


47-47: 토큰 파라미터 제거로 인한 보안 개선

cancelTradeMutation.mutate에서 토큰 파라미터가 제거되어 서버 사이드 쿠키 기반 인증으로 전환되었습니다. 이는 클라이언트 사이드에서 토큰 접근을 방지하는 보안 개선사항입니다.

src/app/layout.tsx (2)

10-10: 서버 사이드 인증 유틸리티 import 승인

서버 사이드 인증 상태 확인을 위한 getServerAuth import가 추가되었습니다.


49-59: 서버 사이드 인증 상태 초기화로 인한 성능 및 보안 개선

서버에서 인증 상태를 미리 확인하여 AuthInitializer에 전달하는 방식으로 변경되었습니다. 이는 다음과 같은 장점을 제공합니다:

  • 클라이언트 사이드 하이드레이션 불일치 방지
  • 초기 로딩 시 인증 상태 깜빡임 현상 제거
  • 서버 사이드 인증 보안 강화
src/api/make-api-request.ts (2)

9-9: 토큰 파라미터 제거로 인한 API 인터페이스 간소화

options에서 토큰 파라미터가 제거되어 API 호출 인터페이스가 간소화되었습니다.


16-16: httpOnly 쿠키 기반 인증으로의 보안 개선

credentials: "include" 설정으로 httpOnly 쿠키가 자동으로 포함되도록 변경되었습니다. 이는 클라이언트 사이드에서 토큰에 직접 접근할 수 없게 하여 XSS 공격으로부터 보호하는 중요한 보안 개선사항입니다.

src/api/portfolio/index.ts (2)

3-3: 함수 시그니처 간소화로 인한 API 사용성 개선

fetchPortfolios 함수에서 토큰 파라미터가 제거되어 함수 호출이 간소화되었습니다.


9-9: 쿠키 기반 인증 적용으로 보안 및 일관성 개선

credentials: "include" 설정으로 httpOnly 쿠키 기반 인증이 적용되었습니다. 이는 다른 API 모듈들과 일관성을 유지하며, 전체 애플리케이션의 보안을 강화합니다.

src/app/search/[id]/_components/order-stock/buy-and-sell/buyable-quantity.tsx (3)

5-5: 인증 훅 import 방식 변경 확인됨

useAuth를 default import로 변경한 것이 새로운 인증 구조와 일치합니다.


20-26: 토큰 기반 인증에서 쿠키 기반 인증으로 전환 확인됨

  • token 파라미터 제거와 userInfo 사용으로 변경
  • API 호출에서 토큰 전달 제거
  • 쿼리 활성화 조건 단순화

변경사항이 보안 향상 목표와 일치합니다.


37-39: 사용자 정보 접근 방식 변경 확인됨

userInfo.deposit 사용으로 변경된 것이 새로운 인증 구조와 일치합니다.

src/app/search/[id]/_components/order-stock/order-history/index.tsx (2)

6-6: 일관된 인증 훅 import 방식 변경

다른 컴포넌트들과 동일하게 default import로 변경되었습니다.


12-23: 토큰 제거 및 쿠키 기반 인증 적용

  • token 파라미터 제거
  • getTradeHistory 호출 시 토큰 전달 제거
  • 쿼리 활성화 조건을 isAuthenticated만으로 단순화

변경사항이 전체 인증 리팩토링과 일치합니다.

src/app/main/_components/stock-info.tsx (3)

11-11: 인증 훅 import 방식 통일

전체 애플리케이션에서 일관된 default import 방식으로 변경되었습니다.


67-76: API 호출에서 토큰 제거

  • fetchMyStocks 호출 시 토큰 파라미터 제거
  • 쿼리 활성화 조건 단순화
  • 쿠키 기반 인증으로 전환

변경사항이 보안 강화 목표와 일치합니다.


81-91: useEffect 의존성 및 조건 업데이트

  • fetchStockCount 호출에서 토큰 제거
  • 의존성 배열에서 token 제거
  • 조건문에서 isAuthenticated만 확인

변경사항이 새로운 인증 구조와 일치합니다.

src/app/portfolio/_components/portfoilo-card.tsx (3)

5-5: 인증 훅 import 방식 일관성 유지

다른 컴포넌트들과 동일하게 default import로 변경되었습니다.


17-17: 사용자 정보 접근 방식 변경

annualIncome 대신 userInfo 객체를 사용하도록 변경되었습니다.


64-69: 연봉 데이터 처리 로직 개선

userInfo.annualIncome으로 변경되었으며, parseInt와 fallback 값 0을 사용하여 안전한 파싱 처리가 구현되었습니다.

src/app/search/[id]/hooks/use-limit-order-data.ts (2)

5-5: 인증 훅 import 방식 일관성

전체 애플리케이션의 인증 리팩토링과 일치하는 default import로 변경되었습니다.


9-15: 토큰 기반 인증 제거 및 쿠키 기반 인증 적용

  • token 파라미터 제거
  • getTrade 호출 시 토큰 전달 제거
  • 쿼리 활성화 조건을 isAuthenticated만으로 단순화

커스텀 훅이 새로운 인증 구조와 올바르게 통합되었습니다.

src/provider/AuthInitializer.tsx (2)

7-16: 인터페이스 정의가 명확하고 타입 안전성을 보장합니다.

사용자 정보 구조가 명확하게 정의되어 있고, 모든 필드가 nullable string으로 적절하게 타입이 지정되어 있습니다.


18-26: 서버 측 인증 상태를 클라이언트로 전달하는 브릿지 역할을 잘 수행합니다.

props를 받아 initializeAuth에 전달하고, useEffect의 의존성 배열이 올바르게 설정되어 있습니다. 이는 서버 사이드 인증 상태를 클라이언트 스토어에 초기화하는 새로운 인증 플로우와 잘 일치합니다.

src/app/portfolio/page.tsx (2)

7-7: 서버 측 인증 확인으로 코드가 간결해졌습니다.

requireAuth() 함수를 사용하여 인증 확인 로직이 단순화되었으며, 인증되지 않은 사용자는 자동으로 로그인 페이지로 리다이렉트됩니다.


10-10: 쿠키 기반 인증으로의 전환이 올바르게 적용되었습니다.

fetchPortfolios에서 토큰 매개변수를 제거하여 httpOnly 쿠키 기반 인증을 사용하도록 변경되었습니다. 이는 보안성을 향상시키는 좋은 변경사항입니다.

src/api/side-Info/index.ts (2)

13-29: 쿠키 기반 인증으로 성공적으로 전환되었습니다.

fetchMyStocks 함수에서 토큰 매개변수와 Authorization 헤더를 제거하고 credentials: "include"를 사용하여 httpOnly 쿠키 기반 인증을 구현했습니다. 이는 보안성을 크게 향상시키는 변경사항입니다.


31-47: 일관된 인증 방식이 적용되었습니다.

fetchStockCount 함수도 동일한 패턴으로 쿠키 기반 인증을 사용하도록 변경되었습니다. 코드베이스 전체에서 일관된 인증 방식을 사용하는 것은 유지보수성과 보안성 측면에서 중요합니다.

src/app/login/login-form.tsx (3)

6-6: useTransition을 사용한 비동기 상태 관리가 적절합니다.

useTransition 훅을 사용하여 로그인 처리 중 UI 블로킹을 방지하고 사용자 경험을 개선했습니다.

Also applies to: 34-34


46-66: 서버 액션을 통한 로그인 처리가 보안성을 향상시킵니다.

loginAction을 사용하여 서버 측에서 인증을 처리하고 httpOnly 쿠키를 설정하는 방식으로 변경되었습니다. 클라이언트 스토어에는 사용자 정보만 저장하고 토큰은 서버에서 관리하는 것이 보안상 우수한 접근법입니다.


74-74: 로딩 상태를 반영한 UX 개선이 잘 구현되었습니다.

버튼의 비활성화 상태와 로딩 텍스트를 통해 사용자에게 현재 상태를 명확하게 전달하고 있습니다.

Also applies to: 77-77

src/hooks/use-api.ts (2)

14-45: 쿠키 기반 인증을 위한 표준화된 API 호출 로직이 잘 구현되었습니다.

apiCall 함수가 credentials: "include"를 사용하여 자동으로 쿠키를 포함하고, 401 응답 시 자동으로 인증 상태를 초기화하고 로그인 페이지로 리다이렉트하는 로직이 우수합니다. 이는 전체 애플리케이션에서 일관된 인증 처리를 보장합니다.


47-76: HTTP 메서드 헬퍼 함수들이 잘 구조화되어 있습니다.

GET, POST, PUT, DELETE 메서드에 대한 헬퍼 함수들이 useCallback으로 적절하게 메모이제이션되어 있고, 데이터 직렬화도 올바르게 처리되고 있습니다. delete 메서드를 del로 네이밍한 것도 JavaScript 예약어 충돌을 피하는 좋은 선택입니다.

src/hooks/use-token-refresh.ts (3)

3-6: 서버 액션 통합이 적절합니다!

클라이언트 측 쿠키 조작을 서버 액션으로 대체한 것은 보안 강화를 위한 올바른 접근입니다. useTransition을 사용하여 비동기 작업 중 UI 상태를 관리하는 것도 좋은 선택입니다.


29-38: 로그아웃 처리 순서가 적절합니다

클라이언트 상태를 먼저 정리하고 서버 액션을 호출하는 순서는 즉각적인 UI 피드백을 제공하면서도 서버 측 정리를 보장합니다.


71-89: 세션 연장 로직이 안전하게 구현되었습니다

API 라우트 대신 서버 액션을 직접 사용하여 보안이 강화되었습니다. 에러 처리도 적절히 구현되어 있습니다.

src/app/main/_components/asset-info.tsx (3)

48-56: 쿠키 기반 인증으로의 전환이 적절합니다

Authorization 헤더를 제거하고 credentials: "include"를 사용하여 httpOnly 쿠키를 자동으로 포함시키는 방식은 보안 강화에 효과적입니다.


100-106: 로그아웃 UX가 개선되었습니다

useTransition을 사용하여 로그아웃 진행 상태를 표시하고, 클라이언트 상태를 먼저 정리하는 패턴이 좋습니다.


156-160: 비활성화 상태 처리가 적절합니다

로그아웃 진행 중 버튼을 비활성화하고 상태를 표시하는 것은 중복 요청을 방지하는 좋은 패턴입니다.

src/app/my-account/page.tsx (3)

1-1: 서버 측 인증 유틸리티 사용이 적절합니다

requireAuthmakeAuthenticatedRequest를 사용하여 중앙화된 인증 로직을 활용하는 것은 좋은 패턴입니다.

Also applies to: 31-32


6-16: 토큰 파라미터 제거가 적절합니다

함수 시그니처에서 토큰 파라미터를 제거하고 makeAuthenticatedRequest를 사용하는 것은 보안 강화에 효과적입니다.

Also applies to: 18-28


49-72: 에러 처리가 잘 구현되었습니다

API 호출 실패 시 기본값을 제공하여 안정적인 UI를 보장하는 것은 좋은 패턴입니다.

src/lib/auth-server.ts (1)

37-57: 인증된 요청 헬퍼 구현이 적절합니다

Bearer 토큰을 Authorization 헤더에 포함시키고, 토큰이 없을 때 적절한 에러를 발생시키는 구현이 좋습니다.

src/actions/auth.ts (1)

37-44: 쿠키 옵션 설정이 적절합니다

httpOnly, secure, sameSite 설정으로 쿠키 보안을 강화한 것이 좋습니다. 30분 만료 시간도 적절합니다.

src/api/transaction/index.ts (1)

17-81: 토큰 파라미터 제거가 올바르게 구현되었습니다.

모든 트랜잭션 API 함수에서 토큰 파라미터가 일관되게 제거되었습니다. makeApiRequest가 이제 credentials: "include"를 사용하여 httpOnly 쿠키를 자동으로 포함하므로 보안이 향상되었습니다.

src/hooks/use-auth.ts (3)

5-11: UserInfo 인터페이스가 잘 구조화되었습니다.

사용자 정보를 단일 객체로 그룹화하여 상태 관리가 더 명확해졌습니다. 모든 속성이 nullable로 정의되어 인증되지 않은 상태를 적절히 표현합니다.


24-60: 인증 스토어가 보안 중심으로 잘 리팩토링되었습니다.

클라이언트 사이드 쿠키 및 토큰 처리가 제거되고 서버에서 관리하는 인증 상태만 저장하도록 변경되어 보안이 크게 향상되었습니다. initializeAuth 메서드를 통해 서버 사이드 렌더링과의 통합도 원활하게 지원합니다.


62-63: getAuthState 헬퍼 함수 추가가 적절합니다.

React 컴포넌트 외부에서 인증 상태에 접근할 수 있도록 하는 유용한 헬퍼입니다. 단, 이 함수는 클라이언트 사이드에서만 사용되어야 하며, 서버 사이드에서는 서버 전용 인증 유틸리티를 사용해야 합니다.

Comment on lines +5 to +27
export async function getServerAuth() {
const cookieStore = cookies();

const token = cookieStore.get("token")?.value;
const memberId = cookieStore.get("memberId")?.value;
const memberName = cookieStore.get("memberName")?.value;
const memberNickName = cookieStore.get("memberNickName")?.value;
const annualIncome = cookieStore.get("annualIncome")?.value;
const deposit = cookieStore.get("deposit")?.value;

const isAuthenticated = Boolean(token);

return {
isAuthenticated,
userInfo: {
memberId: memberId || null,
memberName: memberName || null,
memberNickName: memberNickName || null,
annualIncome: annualIncome || null,
deposit: deposit || null,
},
};
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

인증 확인 로직 개선 필요

isAuthenticated가 토큰 존재 여부만으로 결정되는데, memberId와 같은 필수 사용자 정보의 유효성도 함께 검증해야 합니다. 불완전한 인증 상태를 방지하기 위해 다음과 같이 수정을 제안합니다:

-  const isAuthenticated = Boolean(token);
+  const isAuthenticated = Boolean(token && memberId);
📝 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
export async function getServerAuth() {
const cookieStore = cookies();
const token = cookieStore.get("token")?.value;
const memberId = cookieStore.get("memberId")?.value;
const memberName = cookieStore.get("memberName")?.value;
const memberNickName = cookieStore.get("memberNickName")?.value;
const annualIncome = cookieStore.get("annualIncome")?.value;
const deposit = cookieStore.get("deposit")?.value;
const isAuthenticated = Boolean(token);
return {
isAuthenticated,
userInfo: {
memberId: memberId || null,
memberName: memberName || null,
memberNickName: memberNickName || null,
annualIncome: annualIncome || null,
deposit: deposit || null,
},
};
}
export async function getServerAuth() {
const cookieStore = cookies();
const token = cookieStore.get("token")?.value;
const memberId = cookieStore.get("memberId")?.value;
const memberName = cookieStore.get("memberName")?.value;
const memberNickName = cookieStore.get("memberNickName")?.value;
const annualIncome = cookieStore.get("annualIncome")?.value;
const deposit = cookieStore.get("deposit")?.value;
const isAuthenticated = Boolean(token && memberId);
return {
isAuthenticated,
userInfo: {
memberId: memberId || null,
memberName: memberName || null,
memberNickName: memberNickName || null,
annualIncome: annualIncome || null,
deposit: deposit || null,
},
};
}
🤖 Prompt for AI Agents
In src/lib/auth-server.ts lines 5 to 27, the isAuthenticated flag is currently
set based only on the presence of a token, which can lead to incomplete
authentication states. Update the logic to also verify that essential user
information like memberId is present and valid before setting isAuthenticated to
true. This ensures that authentication status accurately reflects both token
presence and required user data validity.

Comment on lines +258 to +260
// 실제 구현에서는 JWT 토큰 검증 로직 추가
// const isValid = jwt.verify(token, process.env.JWT_SECRET);

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

JWT 토큰 검증 구현 필요

토큰 존재 여부만 확인하고 실제 JWT 검증이 구현되지 않은 것은 심각한 보안 취약점입니다. 유효하지 않거나 만료된 토큰도 통과할 수 있습니다.

JWT 검증 로직을 구현하는 코드를 생성하거나 이를 추적할 새 이슈를 생성할까요?

🤖 Prompt for AI Agents
In src/actions/auth.ts around lines 258 to 260, the current code only checks for
the presence of a token but does not verify its validity using JWT verification,
which is a critical security flaw. Implement the JWT verification logic by using
a library like jsonwebtoken to verify the token against the secret key stored in
process.env.JWT_SECRET, and handle invalid or expired tokens appropriately by
rejecting them or throwing an error.

Comment on lines +129 to +131
cookiesToDelete.forEach((cookieName) => {
cookieStore.delete(cookieName);
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

쿠키 삭제 시 옵션 지정 필요

쿠키를 삭제할 때 설정 시와 동일한 옵션(특히 path)을 지정해야 올바르게 삭제됩니다:

    cookiesToDelete.forEach((cookieName) => {
-      cookieStore.delete(cookieName);
+      cookieStore.delete({
+        name: cookieName,
+        path: "/",
+      });
    });

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/actions/auth.ts around lines 129 to 131, when deleting cookies using
cookieStore.delete, you need to specify the same options (especially path) as
when the cookies were set to ensure proper deletion. Update the
cookieStore.delete calls to include the correct path option matching the cookie
creation settings.

@Han-wo Han-wo merged commit b5cf6c5 into develop Jul 7, 2025
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

우선순위: MEDIUM New feature or request ♻️REFACTOR Refactor code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: 인증인가 방식 수정

2 participants