Skip to content

feat: 오늘의 한마디 삭제 API 연결#232

Merged
ljh130334 merged 2 commits into
developfrom
feat/api-today
Sep 8, 2025
Merged

feat: 오늘의 한마디 삭제 API 연결#232
ljh130334 merged 2 commits into
developfrom
feat/api-today

Conversation

@ljh130334

@ljh130334 ljh130334 commented Sep 2, 2025

Copy link
Copy Markdown
Member

#️⃣ 연관된 이슈

#231

📝작업 내용

1. API 함수 생성: src/api/rooms/deleteDailyGreeting.ts

  • DELETE /rooms/{roomId}/daily-greeting/{attendanceCheckId} 엔드포인트 연동
  • 스웨거 문서와 동일한 응답 타입 정의

2. MessageList 컴포넌트 수정:

  • 삭제 API 연동하여 "개발중" 메시지 제거
  • roomId props 추가

3. TodayWords 페이지 수정:

  • MessageList에 roomIdonMessageDelte props 전달
  • 삭제 후 상태 동기화 처리

Summary by CodeRabbit

  • 신기능
    • 오늘의 한마디를 방 단위로 삭제할 수 있습니다. 삭제 성공/실패 및 방 정보 미입력 시 스낵바로 안내합니다.
  • 버그 수정
    • 삭제 후 목록이 즉시 갱신되고 선택된 메시지가 올바르게 초기화됩니다.
    • 일부 환경에서 피드가 정상적으로 로드되지 않던 현상을 개선했습니다.

@ljh130334 ljh130334 self-assigned this Sep 2, 2025
@ljh130334 ljh130334 added the 📬 API 서버 API 통신 label Sep 2, 2025
@coderabbitai

coderabbitai Bot commented Sep 2, 2025

Copy link
Copy Markdown

Walkthrough

토큰 부재 시 하드코딩된 Authorization 토큰을 주입하도록 요청 인터셉터와 Feed 초기화 로직을 수정. 새로운 방 단위 "오늘의 한마디" 삭제 API를 추가하고, MessageList/TodayWords에 삭제 흐름을 연동하며 roomId와 삭제 콜백을 전달해 상태를 동기화.

Changes

Cohort / File(s) Summary
Auth 토큰 기본값 주입
src/api/index.ts, src/pages/feed/Feed.tsx
로컬 저장소에 토큰이 없을 때 하드코딩된 Bearer 토큰을 Authorization 헤더 및 localStorage에 설정하도록 변경. 기존 토큰이 있을 때의 동작은 동일.
오늘의 한마디 삭제 API 추가
src/api/rooms/deleteDailyGreeting.ts
방의 오늘의 한마디를 삭제하는 DELETE API 모듈 신설. DeleteDailyGreetingResponse 타입과 deleteDailyGreeting(roomId, attendanceCheckId) 함수 추가. 오류 로깅 후 재throw.
Today-words UI 삭제 연동
src/components/today-words/MessageList/MessageList.tsx, src/pages/today-words/TodayWords.tsx
MessageList에 roomId?: number, onMessageDelete? prop 추가. 삭제 시 deleteDailyGreeting 호출, 성공 시 로컬 목록 갱신 및 스낵바 표시. TodayWords는 삭제 핸들러 추가 및 MessageList에 roomId/콜백 전달.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as 사용자
  participant ML as MessageList
  participant API as apiClient
  participant S as 서버
  participant TW as TodayWords(State)

  User->>ML: 메시지 삭제 클릭
  ML->>ML: selectedMessageId 확인, roomId 확인
  alt roomId 있음
    ML->>API: DELETE /rooms/{roomId}/daily-greeting/{attendanceCheckId}
    API->>S: 요청 (Authorization 포함)
    S-->>API: 응답 { isSuccess, data.roomId ... }
    alt 성공
      API-->>ML: 응답 데이터
      ML->>TW: onMessageDelete(messageId)
      TW->>TW: 로컬 messages 상태에서 제거
      ML->>User: 스낵바(삭제 완료)
    else 실패
      API-->>ML: 오류/실패 메시지
      ML->>User: 스낵바(실패 메시지)
    end
  else roomId 없음
    ML->>User: 스낵바(방 정보 없음)
  end
  ML->>ML: 선택 해제
Loading
sequenceDiagram
  autonumber
  participant FE as Feed 초기화
  participant LS as localStorage
  participant AX as axios interceptor

  FE->>LS: authToken 조회
  alt 없음
    FE->>LS: 하드코딩 토큰 저장
    note right of FE: 이후 요청부터 토큰 사용
  else 있음
    FE-->>FE: 기존 흐름 유지
  end

  AX->>LS: 요청 시 authToken 확인
  alt 없음
    AX-->>AX: Authorization에 하드코딩 토큰 설정
  else 있음
    AX-->>AX: Authorization에 저장된 토큰 설정
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Poem

당근 깃털 펜을 든 토끼 한 마리 🐇
방 번호 손에 쥐고 툭—메시지 지웠지
바람처럼 조용히, 스낵바는 살짝 칭—
토큰은 주머니 속, 길 잃지 않게 반짝
오늘의 한마디도 가벼워진 발걸음 ✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/api-today

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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@vercel

vercel Bot commented Sep 2, 2025

Copy link
Copy Markdown

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

Project Deployment Preview Comments Updated (UTC)
thip Ready Ready Preview Comment Sep 2, 2025 8:46am

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (5)
src/api/index.ts (1)

38-47: 401 전역 리다이렉트는 신중히: 라우터 네비게이션/재발급 흐름 고려.

window.location으로 즉시 루트 이동은 SPA에서 사용자 경험을 해칠 수 있고, 401이 백그라운드 폴링 등에서 발생 시 불필요한 풀 리로드로 이어집니다.

  • 권장: 401 → (1) 토큰 재발급 시도 → 실패 시 (2) 토큰/세션 정리 후 라우터로 로그인 이동.
  • 최소한 DEV/PROD 분기 또는 특정 엔드포인트만 리다이렉트하도록 범위를 축소하세요.
src/pages/feed/Feed.tsx (1)

159-166: 하드코딩 토큰 사용 자제 및 중복 소스 통합.

api/index.ts와 본 파일 모두에서 토큰을 별도로 주입하면 관리 지점이 늘고 불일치가 발생합니다. 토큰 주입/재발급/삭제는 한 곳(api 레이어 인터셉터)에서만 처리하고, 페이지는 그 결과만 소비하도록 역할을 분리해 주세요.

src/pages/today-words/TodayWords.tsx (1)

325-327: parseInt 기수 명시 권장.

기수 미지정 시 일부 런타임에서 예외 동작 여지가 있습니다. 10진수 기수를 명시하세요.

-                roomId={roomId ? parseInt(roomId) : undefined}
+                roomId={roomId ? parseInt(roomId, 10) : undefined}
src/api/rooms/deleteDailyGreeting.ts (1)

24-28: 에러 표면화 방식 개선(선택).

현재 콘솔 로깅 후 원본 throw는 적절합니다. 필요 시 AxiosError를 제네릭으로 타이핑해 서버 메시지/코드 추출을 표준화하거나, 공통 에러 유틸로 위임하는 것을 고려해 주세요.

-  } catch (error) {
-    console.error('오늘의 한마디 삭제 API 오류:', error);
-    throw error;
-  }
+  } catch (error) {
+    console.error('오늘의 한마디 삭제 API 오류:', error);
+    // 예: 공통 에러 핸들러로 위임하여 메시지 정규화
+    // throw normalizeApiError(error);
+    throw error;
+  }
src/components/today-words/MessageList/MessageList.tsx (1)

81-82: 정렬 시 상태 배열을 직접 변형하지 않도록 방어.

messages.sort는 state를 직접 mutate합니다. 불변성 유지와 불필요한 리렌더 방지를 위해 사본 정렬 또는 useMemo를 사용하세요.

-    const sortedMessages = messages.sort((a, b) => parseInt(a.id) - parseInt(b.id));
+    const sortedMessages = [...messages].sort((a, b) => Number(a.id) - Number(b.id));
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bba8dc8 and 1dd76b2.

📒 Files selected for processing (5)
  • src/api/index.ts (1 hunks)
  • src/api/rooms/deleteDailyGreeting.ts (1 hunks)
  • src/components/today-words/MessageList/MessageList.tsx (4 hunks)
  • src/pages/feed/Feed.tsx (1 hunks)
  • src/pages/today-words/TodayWords.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/api/rooms/deleteDailyGreeting.ts (1)
src/api/index.ts (1)
  • apiClient (7-14)
src/components/today-words/MessageList/MessageList.tsx (1)
src/api/rooms/deleteDailyGreeting.ts (1)
  • deleteDailyGreeting (14-28)
🔇 Additional comments (2)
src/pages/today-words/TodayWords.tsx (1)

299-304: 로컬 상태 동기화 콜백 추가 좋습니다.

자식/부모 간 삭제 동기화를 명확히 해 UI 일관성이 확보됩니다. 현재 구현은 충분합니다.

src/api/rooms/deleteDailyGreeting.ts (1)

14-23: DELETE API 래퍼 구현 깔끔합니다.

타이핑, 경로 구성, data 반환까지 일관적입니다.

Comment thread src/api/index.ts Outdated
Comment on lines +27 to +28
config.headers.Authorization =
'Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjksImlhdCI6MTc1Njc4MjEyNywiZXhwIjoxNzU5Mzc0MTI3fQ.iRU7rN90Vs9Wykxvw-gkyAkbyB-HQENm_WifYHb2UR8eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjksImlhdCI6MTc1Njc4NTY5NSwiZXhwIjoxNzU5Mzc3Njk1fQ.jnYVdrvtHivfyteXPHAZmAM1mkwW2U66EPn7BylzHu0';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

하드코딩된 Bearer 토큰 제거 필요 (보안·운영 리스크 + 토큰 문자열 손상 가능성).

  • 레포지토리에 토큰을 하드코딩하면 유출 위험이 큽니다(XSS/리포 노출/로그 수집 등).
  • 현재 값은 JWT가 2개 연속으로 붙은 형태로 보이며(중복 서명부 존재), 실제 인증 실패를 유발할 수 있습니다.
  • 토큰이 없을 때는 헤더를 비우고(혹은 DEV 환경에서만 .env의 임시 토큰 사용) 401 흐름에서만 로그인/재발급로 이어지도록 해주세요.

아래처럼 DEV 한정 .env 토큰만 주입(선택)하고, 없으면 Authorization을 제거하는 쪽으로 정리하는 것을 권장합니다.

-    } else {
-      console.log('❌ localStorage에 토큰이 없습니다.');
-      config.headers.Authorization =
-        'Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjksImlhdCI6MTc1Njc4MjEyNywiZXhwIjoxNzU5Mzc0MTI3fQ.iRU7rN90Vs9Wykxvw-gkyAkbyB-HQENm_WifYHb2UR8eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjksImlhdCI6MTc1Njc4NTY5NSwiZXhwIjoxNzU5Mzc3Njk1fQ.jnYVdrvtHivfyteXPHAZmAM1mkwW2U66EPn7BylzHu0';
-    }
+    } else {
+      console.warn('❌ localStorage에 토큰이 없습니다.');
+      // DEV 환경에서만 .env 토큰 사용 (선택)
+      if (import.meta.env.DEV && import.meta.env.VITE_DEV_AUTH_TOKEN) {
+        config.headers.Authorization = `Bearer ${import.meta.env.VITE_DEV_AUTH_TOKEN}`;
+      } else {
+        delete config.headers.Authorization;
+      }
+    }
📝 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
config.headers.Authorization =
'Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjksImlhdCI6MTc1Njc4MjEyNywiZXhwIjoxNzU5Mzc0MTI3fQ.iRU7rN90Vs9Wykxvw-gkyAkbyB-HQENm_WifYHb2UR8eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjksImlhdCI6MTc1Njc4NTY5NSwiZXhwIjoxNzU5Mzc3Njk1fQ.jnYVdrvtHivfyteXPHAZmAM1mkwW2U66EPn7BylzHu0';
if (token) {
config.headers.Authorization = `Bearer ${token}`;
} else {
console.warn('❌ localStorage에 토큰이 없습니다.');
// DEV 환경에서만 .env 토큰 사용 (선택)
if (import.meta.env.DEV && import.meta.env.VITE_DEV_AUTH_TOKEN) {
config.headers.Authorization = `Bearer ${import.meta.env.VITE_DEV_AUTH_TOKEN}`;
} else {
delete config.headers.Authorization;
}
}
🤖 Prompt for AI Agents
In src/api/index.ts around lines 27-28, remove the hardcoded Bearer token (it
currently contains two concatenated JWTs) and instead read an optional token
from environment only in DEV (e.g., process.env.DEV_BEARER_TOKEN); if no token
is available delete/omit config.headers.Authorization so requests proceed
without an Authorization header and let the 401 handling trigger login/refresh;
ensure no token string remains in repo, and add a clear comment that production
tokens must never be hardcoded and should come from secure storage.

Comment on lines +107 to +149
const handleDelete = async () => {
if (selectedMessageId && roomId) {
try {
// API에서는 attendanceCheckId가 필요하므로 selectedMessageId를 사용
const attendanceCheckId = parseInt(selectedMessageId);

const result = await deleteDailyGreeting(roomId, attendanceCheckId);

if (result.isSuccess) {
// 로컬 상태에서 메시지 제거
setMessages(prevMessages =>
prevMessages.filter(msg => msg.id !== selectedMessageId)
);

// 부모 컴포넌트에 삭제 알림
if (onMessageDelete) {
onMessageDelete(selectedMessageId);
}

openSnackbar({
message: '오늘의 한마디가 삭제되었습니다.',
variant: 'top',
isError: false,
onClose: () => {},
});
} else {
openSnackbar({
message: result.message || '삭제에 실패했습니다.',
variant: 'top',
isError: true,
onClose: () => {},
});
}
} catch (error) {
console.error('삭제 오류:', error);
openSnackbar({
message: '삭제 중 오류가 발생했습니다.',
variant: 'top',
isError: true,
onClose: () => {},
});
}
} else if (!roomId) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

삭제 처리에 NaN 가드 및 중복 클릭 방지 추가 권장.

  • selectedMessageId 파싱 실패 시(비정상 id) API 경로가 /NaN이 됩니다.
  • 중복 클릭으로 다중 요청이 발생할 수 있습니다(낙관적 업데이트와 경합).

간단 가드와 진행 상태 플래그를 추가해 주세요.

+    const [deleting, setDeleting] = useState(false);
@@
-    const handleDelete = async () => {
-      if (selectedMessageId && roomId) {
+    const handleDelete = async () => {
+      if (deleting) return;
+      if (selectedMessageId && roomId) {
         try {
-          const attendanceCheckId = parseInt(selectedMessageId);
+          const attendanceCheckId = Number(selectedMessageId);
+          if (Number.isNaN(attendanceCheckId)) {
+            openSnackbar({ message: '잘못된 메시지 ID 입니다.', variant: 'top', isError: true, onClose: () => {} });
+            return;
+          }
-          const result = await deleteDailyGreeting(roomId, attendanceCheckId);
+          setDeleting(true);
+          const result = await deleteDailyGreeting(roomId, attendanceCheckId);
@@
-        } catch (error) {
+        } catch (error) {
           console.error('삭제 오류:', error);
           openSnackbar({
             message: '삭제 중 오류가 발생했습니다.',
             variant: 'top',
             isError: true,
             onClose: () => {},
           });
-        }
+        } finally {
+          setDeleting(false);
+        }
       } else if (!roomId) {
📝 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
const handleDelete = async () => {
if (selectedMessageId && roomId) {
try {
// API에서는 attendanceCheckId가 필요하므로 selectedMessageId를 사용
const attendanceCheckId = parseInt(selectedMessageId);
const result = await deleteDailyGreeting(roomId, attendanceCheckId);
if (result.isSuccess) {
// 로컬 상태에서 메시지 제거
setMessages(prevMessages =>
prevMessages.filter(msg => msg.id !== selectedMessageId)
);
// 부모 컴포넌트에 삭제 알림
if (onMessageDelete) {
onMessageDelete(selectedMessageId);
}
openSnackbar({
message: '오늘의 한마디가 삭제되었습니다.',
variant: 'top',
isError: false,
onClose: () => {},
});
} else {
openSnackbar({
message: result.message || '삭제에 실패했습니다.',
variant: 'top',
isError: true,
onClose: () => {},
});
}
} catch (error) {
console.error('삭제 오류:', error);
openSnackbar({
message: '삭제 중 오류가 발생했습니다.',
variant: 'top',
isError: true,
onClose: () => {},
});
}
} else if (!roomId) {
// --- somewhere near the top of your component function ---
const [deleting, setDeleting] = useState(false);
const handleDelete = async () => {
if (deleting) return;
if (selectedMessageId && roomId) {
try {
// API에서는 attendanceCheckId가 필요하므로 selectedMessageId를 사용
const attendanceCheckId = Number(selectedMessageId);
if (Number.isNaN(attendanceCheckId)) {
openSnackbar({
message: '잘못된 메시지 ID 입니다.',
variant: 'top',
isError: true,
onClose: () => {},
});
return;
}
setDeleting(true);
const result = await deleteDailyGreeting(roomId, attendanceCheckId);
if (result.isSuccess) {
// 로컬 상태에서 메시지 제거
setMessages(prevMessages =>
prevMessages.filter(msg => msg.id !== selectedMessageId)
);
// 부모 컴포넌트에 삭제 알림
if (onMessageDelete) {
onMessageDelete(selectedMessageId);
}
openSnackbar({
message: '오늘의 한마디가 삭제되었습니다.',
variant: 'top',
isError: false,
onClose: () => {},
});
} else {
openSnackbar({
message: result.message || '삭제에 실패했습니다.',
variant: 'top',
isError: true,
onClose: () => {},
});
}
} catch (error) {
console.error('삭제 오류:', error);
openSnackbar({
message: '삭제 중 오류가 발생했습니다.',
variant: 'top',
isError: true,
onClose: () => {},
});
} finally {
setDeleting(false);
}
} else if (!roomId) {
// ... existing else-if body ...
🤖 Prompt for AI Agents
In src/components/today-words/MessageList/MessageList.tsx around lines 107 to
149, add a guard and a debounce flag to prevent NaN and duplicate deletes:
validate that selectedMessageId parses to a finite integer (const
attendanceCheckId = Number.parseInt(selectedMessageId); if
Number.isNaN(attendanceCheckId) return with an error snackbar), introduce an
isDeleting state flag checked at the top to ignore re-entrant calls, set
isDeleting = true before the API call and clear it in a finally block, and when
updating local state and calling onMessageDelete compare using the same numeric
id type (e.g., msg.id !== attendanceCheckId) to avoid mismatches; also ensure
any UI delete button/trigger is disabled while isDeleting is true.

Comment thread src/pages/feed/Feed.tsx Outdated
Comment on lines 163 to 169
localStorage.setItem(
'authToken',
'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjksImlhdCI6MTc1Njc4MjEyNywiZXhwIjoxNzU5Mzc0MTI3fQ.iRU7rN90Vs9Wykxvw-gkyAkbyB-HQENm_WifYHb2UR8',
);
console.log('🔑 하드코딩된 토큰으로 설정했습니다.');
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

토큰 설정 후 즉시 return으로 데이터 로드가 영구히 스킵됨(초기 로딩 스피너 고착).

현재 분기에서는 토큰을 저장만 하고 바로 return하여 setTabLoading/데이터 로드가 실행되지 않습니다. 의도치 않게 초기 로딩 상태가 풀리지 않을 수 있습니다. DEV 임시 토큰을 쓰더라도 로딩은 이어가 주세요.

-      if (!authToken) {
-        localStorage.setItem(
-          'authToken',
-          'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjksImlhdCI6MTc1Njc4MjEyNywiZXhwIjoxNzU5Mzc0MTI3fQ.iRU7rN90Vs9Wykxvw-gkyAkbyB-HQENm_WifYHb2UR8',
-        );
-        console.log('🔑 하드코딩된 토큰으로 설정했습니다.');
-        return;
-      }
+      if (!authToken) {
+        if (import.meta.env.DEV && import.meta.env.VITE_DEV_AUTH_TOKEN) {
+          localStorage.setItem('authToken', import.meta.env.VITE_DEV_AUTH_TOKEN);
+          console.log('🔑 DEV 토큰을 설정했습니다.');
+        } else {
+          // 운영에서는 로그인 페이지로 보내거나 토큰 발급 플로우로 유도
+          navigate('/');
+          return;
+        }
+      }
📝 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
localStorage.setItem(
'authToken',
'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjksImlhdCI6MTc1Njc4MjEyNywiZXhwIjoxNzU5Mzc0MTI3fQ.iRU7rN90Vs9Wykxvw-gkyAkbyB-HQENm_WifYHb2UR8',
);
console.log('🔑 하드코딩된 토큰으로 설정했습니다.');
return;
}
if (!authToken) {
if (import.meta.env.DEV && import.meta.env.VITE_DEV_AUTH_TOKEN) {
localStorage.setItem('authToken', import.meta.env.VITE_DEV_AUTH_TOKEN);
console.log('🔑 DEV 토큰을 설정했습니다.');
} else {
// 운영에서는 로그인 페이지로 보내거나 토큰 발급 플로우로 유도
navigate('/');
return;
}
}
🤖 Prompt for AI Agents
In src/pages/feed/Feed.tsx around lines 163 to 169, the branch that writes a
hardcoded dev token to localStorage immediately returns, which prevents the
subsequent data-loading and setTabLoading flow and causes the initial loading
spinner to hang; remove the early return so execution continues after setting
the token (or explicitly call the same data-load and setTabLoading logic used in
the normal path), ensuring the component proceeds to fetch data and clear the
loading state even when using the DEV token.

@ljh130334 ljh130334 merged commit b151dd6 into develop Sep 8, 2025
3 checks passed
@ljh130334 ljh130334 deleted the feat/api-today branch September 9, 2025 00:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📬 API 서버 API 통신

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant