Skip to content

fix: 로그아웃 시, 익스텐션 토큰 제거#246

Merged
jllee000 merged 3 commits intodevelopfrom
fix/#243/2ndSp-QA
Jan 18, 2026
Merged

fix: 로그아웃 시, 익스텐션 토큰 제거#246
jllee000 merged 3 commits intodevelopfrom
fix/#243/2ndSp-QA

Conversation

@jllee000
Copy link
Collaborator

@jllee000 jllee000 commented Jan 18, 2026

📌 Related Issues

관련된 Issue를 태그해주세요. (e.g. - close #25)

📄 Tasks

  1. 윈도우 메시징 기법으로, 로그아웃 신호 전달
  2. 신호에 따라 크롬스토리지 토큰 제거

⭐ PR Point (To Reviewer)

📷 Screenshot

@vercel
Copy link

vercel bot commented Jan 18, 2026

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

Project Deployment Review Updated (UTC)
pinback-client-client Ready Ready Preview, Comment Jan 18, 2026 8:56am
pinback-client-landing Ready Ready Preview, Comment Jan 18, 2026 8:56am

@github-actions github-actions bot added the fix 버그 수정하라 러브버그 label Jan 18, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 18, 2026

Walkthrough

도메인 URL에서 www 서브도메인을 제거하고, 로그아웃 시 익스텐션과 클라이언트 간 메시지 기반 토큰 동기화를 추가하며, MacStep 자산을 WebP에서 SVG로 변경하고, 401/403 에러 시 토큰 제거를 비활성화했습니다.

Changes

Cohort / File(s) 변경 사항
도메인 URL 정규화
apps/client/public/firebase-messaging-sw.js, apps/extension/src/App.tsx, apps/extension/src/background.ts, apps/extension/src/pages/LogOutPop.tsx, apps/extension/src/shared/components/Header.tsx
모든 참조 URL에서 www 서브도메인 제거: https://www.pinback.todayhttps://pinback.today
익스텐션 로그아웃 메시징 흐름
apps/client/src/shared/components/ProfilePopup.tsx, apps/extension/src/background.ts, apps/extension/src/content.ts
클라이언트 로그아웃 시 Extension-Logout postMessage 전송; 익스텐션의 background 및 content 스크립트에서 메시지 수신 후 chrome.storage.local에서 토큰 제거
인증 응답 인터셉터
apps/client/src/shared/apis/setting/axiosInstance.ts
401/403 에러 처리 시 localStorage에서 토큰 제거 로직 주석 처리
온보딩 자산
apps/client/src/pages/onBoarding/components/funnel/step/MacStep.tsx
macNotice 자산 형식 변경: .webp → .svg

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client (ProfilePopup)
    participant Window as window.postMessage
    participant BG as Extension (background.ts)
    participant Content as Extension (content.ts)
    participant Storage as chrome.storage.local

    Client->>Client: Remove token & email from localStorage
    Client->>Window: postMessage({type: 'Extension-Logout'}, origin)
    
    par Parallel Processing
        Window->>BG: Receive Extension-Logout message
        BG->>Storage: Remove 'token'
        Storage-->>BG: ✓ Token removed
        BG->>BG: Log 'Token removed!'
    and
        Window->>Content: Receive Extension-Logout message
        Content->>Storage: Remove 'token'
        Storage-->>Content: ✓ Token removed
        Content->>Content: Log 'Token removed!'
    end
    
    Client->>Client: Navigate to login page
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested labels

fix, 재림, frontend

Suggested reviewers

  • constantly-dev

Poem

🐰 www를 떨쳐내고
익스텐션과 손을 잡아
토큰 메시지 왕복왕복
SVG로 그려진 맥 화면
로그아웃도 동기화도 깔끔하게 ✨

🚥 Pre-merge checks | ❌ 5
❌ Failed checks (3 warnings, 2 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning PR 설명에서 'Tasks' 및 'PR Point (To Reviewer)' 섹션이 비어있어 변경사항에 대한 상세한 작업 내용과 검토자 주의사항이 누락되었습니다. Tasks 섹션에서 변경사항을 요약하고(토큰 제거 로직, 도메인 변경 등), PR Point 섹션에 리뷰어가 주목해야 할 사항을 추가하세요.
Out of Scope Changes check ⚠️ Warning PR에는 주요 목표(토큰 제거 처리)와 관련 없는 변경사항이 포함되어 있습니다: 도메인 URL 변경(www.pinback.today → pinback.today), 이미지 형식 변경(webp → svg), localStorage 토큰 제거 주석 처리. 도메인 변경과 이미지 업데이트는 별도 PR로 분리하고, 토큰 제거 주석 처리의 의도를 명확히 하세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive PR은 이슈 #243(2차 스프린트 QA)의 요구사항을 충족하는 변경사항을 구현했으며, 불필요하게 연결된 이슈 #25(Progress bar)는 관련이 없습니다. 이슈 #243의 구체적인 QA 항목 목록을 확인하여 모든 요구사항이 충족되었는지 검증하고, 이슈 #25 연결을 제거하세요.
Title check ❓ Inconclusive PR 제목 'Fix/#243/2nd sp qa'는 이슈 #243 참조 형식이지만 변경 사항의 핵심 내용을 명확하게 설명하지 않습니다. 제목만으로는 도메인 URL 업데이트, 이미지 파일 형식 변경, 토큰 처리 로직 등 실제 변경 내용을 파악하기 어렵습니다. PR 제목을 더 구체적으로 수정하여 주요 변경 사항을 명확하게 나타내도록 권장합니다. 예: 'Fix: Update domain URLs and token logout handling for QA' 또는 'Fix/#243: Update URLs and implement extension logout flow'.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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

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

@github-actions
Copy link

✅ Storybook chromatic 배포 확인:
🐿️ storybook

@jllee000 jllee000 changed the title Fix/#243/2nd sp qa fix: 로그아웃 시, 익스텐션 토큰 제거 Jan 18, 2026
Copy link
Collaborator

@jjangminii jjangminii left a comment

Choose a reason for hiding this comment

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

빠른 반영 감사합니다-!

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

🤖 Fix all issues with AI agents
In `@apps/client/src/shared/apis/setting/axiosInstance.ts`:
- Around line 49-52: On 401/403 handling in the axios error interceptor (the
block that currently calls window.location.href =
'/onboarding?step=SOCIAL_LOGIN' and returns Promise.reject(error)), restore the
token removal logic by removing the stored auth token (undo the commented out
localStorage.removeItem('token')) before redirecting; if the removal was
intentionally disabled, add a clear comment above this block explaining why the
token must persist and what other mechanism will clear it, referencing the axios
error interceptor where window.location.href and Promise.reject(error) are used
so reviewers can find the change.

In `@apps/extension/src/background.ts`:
- Around line 24-30: The background.ts chrome.runtime.onMessage listener for
'Extension-Logout' is never called because ProfilePopup.tsx uses
window.postMessage and content.ts handles it via
window.addEventListener('message'); either remove the unused
chrome.runtime.onMessage handler from background.ts, or change messaging to
centralize logout in background.ts by updating ProfilePopup.tsx (or content.ts)
to call chrome.runtime.sendMessage({ type: 'Extension-Logout' }) and ensure
content.ts forwards the window message to the background with
chrome.runtime.sendMessage; then keep the existing chrome.runtime.onMessage
handler in background.ts to remove the token from chrome.storage.local.

In `@apps/extension/src/content.ts`:
- Around line 14-21: The logout handler in the window message listener only
removes the token from chrome.storage.local and never notifies the background
script, leaving the background 'Extension-Logout' listener unused; update the
handler in content.ts (the window.addEventListener callback that checks
event.data.type === 'Extension-Logout') to also call
chrome.runtime.sendMessage({ type: 'Extension-Logout' }) (or include any
required payload) after removing the token so the background.ts listener
receives the logout event and can perform its cleanup.
🧹 Nitpick comments (3)
apps/extension/src/background.ts (1)

16-30: 두 개의 onMessage 리스너를 하나로 통합하는 것을 고려해주세요.

현재 chrome.runtime.onMessage.addListener가 두 번 등록되어 있습니다. 하나의 리스너 내에서 메시지 타입을 분기 처리하면 코드가 더 깔끔해집니다.

♻️ 통합 리스너 제안
-chrome.runtime.onMessage.addListener((message) => {
-  if (message.type === 'SET_TOKEN') {
-    chrome.storage.local.set({ token: message.token }, () => {
-      console.log('Token saved!');
-    });
-  }
-});
-
-chrome.runtime.onMessage.addListener((message) => {
-  if (message.type === 'Extension-Logout') {
-    chrome.storage.local.remove('token', () => {
-      console.log('Token removed!');
-    });
-  }
-});
+chrome.runtime.onMessage.addListener((message) => {
+  if (message.type === 'SET_TOKEN') {
+    chrome.storage.local.set({ token: message.token }, () => {
+      console.log('Token saved!');
+    });
+  } else if (message.type === 'Extension-Logout') {
+    chrome.storage.local.remove('token', () => {
+      console.log('Token removed!');
+    });
+  }
+});
apps/client/src/shared/components/profilePopup/ProfilePopup.tsx (1)

45-53: 내부 함수 정의를 인라인으로 간소화할 수 있습니다.

sendExtensionLogout 함수가 정의 직후 한 번만 호출됩니다. 함수 래핑 없이 직접 postMessage를 호출하면 더 간결해집니다.

♻️ 간소화 제안
   const handleLogout = () => {
     localStorage.removeItem('token');
     localStorage.removeItem('email');
-    const sendExtensionLogout = () => {
-      window.postMessage(
-        {
-          type: 'Extension-Logout',
-        },
-        window.location.origin
-      );
-    };
-    sendExtensionLogout();
+    window.postMessage({ type: 'Extension-Logout' }, window.location.origin);
     navigate('/login');
   };
apps/extension/src/content.ts (1)

1-21: 두 개의 메시지 리스너를 하나로 통합하는 것을 고려해주세요.

SET_TOKENExtension-Logout을 같은 리스너에서 분기 처리하면 코드 중복이 줄어들고 유지보수가 용이해집니다.

♻️ 통합 리스너 제안
 window.addEventListener('message', (event) => {
   if (event.source !== window) return;
+
   if (event.data.type === 'SET_TOKEN') {
     chrome.runtime.sendMessage({
       type: 'SET_TOKEN',
       token: event.data.token,
     });
     chrome.storage.local.set({ token: event.data.token }, () => {
       console.log('Token saved!', event.data.token);
     });
+  } else if (event.data.type === 'Extension-Logout') {
+    chrome.storage.local.remove('token', () => {
+      console.log('Token removed!');
+    });
   }
 });
-
-window.addEventListener('message', (event) => {
-  if (event.source !== window) return;
-  if (event.data.type === 'Extension-Logout') {
-    chrome.storage.local.remove('token', () => {
-      console.log('Token removed!');
-    });
-  }
-});

Comment on lines +49 to 52
// localStorage.removeItem('token');
window.location.href = '/onboarding?step=SOCIAL_LOGIN';

return Promise.reject(error);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

401/403 에러 시 토큰 제거 로직 비활성화에 대한 검토가 필요합니다.

인증 에러(401/403) 발생 시 토큰을 제거하지 않고 온보딩 페이지로 리다이렉트만 하는 것은 다음과 같은 문제를 야기할 수 있습니다:

  1. 무효한 토큰 잔존: 만료되거나 유효하지 않은 토큰이 localStorage에 남아 후속 요청에서 반복적으로 401/403 에러를 발생시킬 수 있습니다.
  2. 인증 루프 가능성: 리다이렉트 후에도 토큰이 남아있어 의도치 않은 동작을 유발할 수 있습니다.
  3. 상태 불일치: 서버에서는 토큰이 유효하지 않다고 판단했지만, 클라이언트에는 토큰이 남아있는 불일치 상태가 됩니다.

이 변경의 의도가 있다면 주석으로 사유를 명시하거나, 토큰 제거 로직을 유지하는 것을 권장합니다.

🔒 토큰 제거 로직 복원 제안
-      // localStorage.removeItem('token');
+      localStorage.removeItem('token');
       window.location.href = '/onboarding?step=SOCIAL_LOGIN';
🤖 Prompt for AI Agents
In `@apps/client/src/shared/apis/setting/axiosInstance.ts` around lines 49 - 52,
On 401/403 handling in the axios error interceptor (the block that currently
calls window.location.href = '/onboarding?step=SOCIAL_LOGIN' and returns
Promise.reject(error)), restore the token removal logic by removing the stored
auth token (undo the commented out localStorage.removeItem('token')) before
redirecting; if the removal was intentionally disabled, add a clear comment
above this block explaining why the token must persist and what other mechanism
will clear it, referencing the axios error interceptor where
window.location.href and Promise.reject(error) are used so reviewers can find
the change.

Comment on lines +24 to +30
chrome.runtime.onMessage.addListener((message) => {
if (message.type === 'Extension-Logout') {
chrome.storage.local.remove('token', () => {
console.log('Token removed!');
});
}
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n "Extension-Logout" --type ts -C 5

Repository: Pinback-Team/pinback-client

Length of output: 2307


background.ts의 Extension-Logout 리스너는 실제로 호출되지 않습니다.

ProfilePopup.tsx에서 window.postMessage로 'Extension-Logout' 메시지를 전송하고, content.tswindow.addEventListener('message') 리스너가 이를 받아 직접 처리합니다. 따라서 chrome.runtime.onMessage를 사용하는 background.ts의 리스너(lines 24-30)는 절대 호출되지 않습니다.

이 리스너는 제거하거나, content.ts의 처리 로직을 background.ts로 이동하면서 chrome.runtime.sendMessage를 사용하도록 메시지 패싱 방식을 통일해야 합니다.

🧰 Tools
🪛 GitHub Check: lint

[warning] 27-27:
Unexpected console statement

🤖 Prompt for AI Agents
In `@apps/extension/src/background.ts` around lines 24 - 30, The background.ts
chrome.runtime.onMessage listener for 'Extension-Logout' is never called because
ProfilePopup.tsx uses window.postMessage and content.ts handles it via
window.addEventListener('message'); either remove the unused
chrome.runtime.onMessage handler from background.ts, or change messaging to
centralize logout in background.ts by updating ProfilePopup.tsx (or content.ts)
to call chrome.runtime.sendMessage({ type: 'Extension-Logout' }) and ensure
content.ts forwards the window message to the background with
chrome.runtime.sendMessage; then keep the existing chrome.runtime.onMessage
handler in background.ts to remove the token from chrome.storage.local.

Comment on lines +14 to +21
window.addEventListener('message', (event) => {
if (event.source !== window) return;
if (event.data.type === 'Extension-Logout') {
chrome.storage.local.remove('token', () => {
console.log('Token removed!');
});
}
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

SET_TOKEN 흐름과 일관성이 없습니다.

SET_TOKENchrome.runtime.sendMessage로 background에 전달하고 로컬에도 저장하지만, Extension-Logout은 로컬에서만 토큰을 제거합니다. background.tsExtension-Logout 리스너가 추가되었지만 이 메시지가 전달되지 않아 해당 리스너는 dead code가 됩니다.

일관성을 위해 background에도 메시지를 전달하거나, background.ts의 해당 리스너를 제거하는 것이 좋습니다.

🔧 background로 메시지 전달 추가
 window.addEventListener('message', (event) => {
   if (event.source !== window) return;
   if (event.data.type === 'Extension-Logout') {
+    chrome.runtime.sendMessage({ type: 'Extension-Logout' });
     chrome.storage.local.remove('token', () => {
       console.log('Token removed!');
     });
   }
 });
📝 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
window.addEventListener('message', (event) => {
if (event.source !== window) return;
if (event.data.type === 'Extension-Logout') {
chrome.storage.local.remove('token', () => {
console.log('Token removed!');
});
}
});
window.addEventListener('message', (event) => {
if (event.source !== window) return;
if (event.data.type === 'Extension-Logout') {
chrome.runtime.sendMessage({ type: 'Extension-Logout' });
chrome.storage.local.remove('token', () => {
console.log('Token removed!');
});
}
});
🧰 Tools
🪛 GitHub Check: lint

[warning] 18-18:
Unexpected console statement

🤖 Prompt for AI Agents
In `@apps/extension/src/content.ts` around lines 14 - 21, The logout handler in
the window message listener only removes the token from chrome.storage.local and
never notifies the background script, leaving the background 'Extension-Logout'
listener unused; update the handler in content.ts (the window.addEventListener
callback that checks event.data.type === 'Extension-Logout') to also call
chrome.runtime.sendMessage({ type: 'Extension-Logout' }) (or include any
required payload) after removing the token so the background.ts listener
receives the logout event and can perform its cleanup.

@jllee000 jllee000 merged commit fc5e3c3 into develop Jan 18, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix 버그 수정하라 러브버그

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Fix] 2nd Sprint - QA

2 participants