-
Notifications
You must be signed in to change notification settings - Fork 1
Fix(extension): 익스텐션 로그인 상태 분기 및 토큰 저장 로직 수정 #242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough토큰 저장소 메커니즘을 Chrome 로컬 스토리지에서 window.postMessage 기반 통신으로 전환하고, 인증 오류 시 온보딩 리다이렉트 로직을 제거하며, 디버그 로그 문구를 정리한 변경 사항입니다. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
💤 Files with no reviewable changes (1)
⏰ 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)
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. Comment |
|
✅ Storybook chromatic 배포 확인: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/extension/src/content.ts (1)
2-4:event.origin검증 추가 필수 - 심각한 보안 취약점Content script가 모든 웹사이트에서 실행되기 때문에(
"matches": ["<all_urls>"]), 현재event.source !== window검증만으로는 불충분합니다. 악의적인 웹사이트의 JavaScript가 동일한 window 컨텍스트에서window.postMessage()로 임의의 토큰을 설정할 수 있습니다.
event.origin검증을 추가하여 신뢰할 수 있는 도메인(https://www.pinback.today)에서만 메시지를 수락하도록 수정하세요:제안된 수정
window.addEventListener('message', (event) => { + if (event.origin !== 'https://www.pinback.today') return; if (event.source !== window) return; if (event.data.type === 'SET_TOKEN') {개발 환경을 포함해야 한다면:
const ALLOWED_ORIGINS = [ 'https://www.pinback.today', 'http://localhost:3000', ]; window.addEventListener('message', (event) => { if (!ALLOWED_ORIGINS.includes(event.origin)) return; if (event.source !== window) return; // ... });
🤖 Fix all issues with AI agents
In @apps/client/src/shared/apis/queries.ts:
- Line 74: Replace the direct client-side persistence of the JWT by removing the
localStorage.setItem('token', newToken) call and instead either send the
newToken to the backend to set an HttpOnly, Secure cookie (preferred) or store
it in ephemeral in-memory state (e.g., an auth store) combined with a
short-lived access token + refresh token flow; update the code path handling
newToken (reference: localStorage.setItem and variable newToken) to call the
backend endpoint that issues HttpOnly cookies or to populate your in-memory auth
store and implement refresh-token handling so tokens are not stored in
localStorage.
In @apps/extension/src/App.tsx:
- Line 18: Remove the debug console.log in App.tsx: delete the line
console.log(!!result.token, result); (or wrap it behind a development-only guard
like if (process.env.NODE_ENV === 'development') { ... } or use a proper
logger), ensuring no debug console output remains in the production build.
In @apps/extension/src/background.ts:
- Around line 5-7: Remove the debug console.log that prints sensitive info: find
the chrome.storage.local.set call that uses info.email (and the similar
console.log usage around lines 19-21) and delete the console.log(info.email)
statements (or replace with environment-guarded logging, e.g., only log when a
NODE_ENV or build flag indicates development); ensure no direct logging of
info.email or tokens remains in background.ts and keep only non-sensitive or
conditional logs.
In @apps/extension/src/content.ts:
- Line 10: Remove the debug console.log that prints the token
(console.log('Token saved!', event.data.token)); do not output event.data.token
or other sensitive values to the console—either delete the statement entirely or
replace it with a non-sensitive confirmation message (e.g., "Token saved"
without the token) or a secure/log- redacted call that omits event.data.token.
- Around line 9-11: Remove the duplicate local storage write in content.ts:
delete the chrome.storage.local.set(...) call that writes event.data.token and
keep only the chrome.runtime.sendMessage(...) that sends the token; ensure the
background message handler for "SET_TOKEN" (the handler that currently calls
chrome.storage.local.set in background.ts) remains responsible for persisting
event.data.token so the token is stored only once in the SET_TOKEN handling
code.
🧹 Nitpick comments (4)
apps/extension/src/App.tsx (1)
14-14: 로딩 상태 처리 개선 권장
isToken상태를boolean | null에서boolean로 변경하면서 초기값을false로 설정했습니다. 이 경우 토큰 확인이 완료되기 전에LogOutPop이 먼저 렌더링되어 사용자에게 깜빡임이 보일 수 있습니다.로딩 상태를 구분하기 위해 세 가지 상태를 고려해보세요:
null: 아직 확인 중true: 인증됨false: 미인증♻️ 로딩 상태를 포함한 개선안
- const [isToken, setIsToken] = useState(false); + const [isToken, setIsToken] = useState<boolean | null>(null);그리고 렌더링 로직에서:
return ( <> {isToken === null ? ( <div>로딩 중...</div> // 또는 로딩 스피너 ) : isToken ? ( isDuplicatePop ? ( <DuplicatePop onLeftClick={handleDuplicateLeftClick} onRightClick={handleDuplicateRightClick} /> ) : ( <MainPop type={mainPopType} /> ) ) : ( <LogOutPop /> )} </> );apps/client/src/shared/apis/queries.ts (1)
75-84: 함수 추출 권장
sendTokenToExtension함수가onSuccess콜백 내부에 정의되어 있습니다. 이 함수는 재사용 가능한 유틸리티이므로, 모듈 최상위 레벨로 추출하여 테스트 가능성과 재사용성을 높이는 것을 권장합니다.♻️ 함수 추출 제안
파일 상단에 유틸리티 함수로 추출:
// 파일 상단 또는 별도 utils 파일 const sendTokenToExtension = (token: string) => { window.postMessage( { type: 'SET_TOKEN', token, }, window.location.origin ); };그리고 onSuccess에서 직접 호출:
onSuccess: (data) => { const newToken = data?.data?.token || data?.token; if (newToken) { localStorage.setItem('token', newToken); - const sendTokenToExtension = (token: string) => { - window.postMessage( - { - type: 'SET_TOKEN', - token, - }, - window.location.origin - ); - }; sendTokenToExtension(newToken); } // ... },apps/client/src/pages/onBoarding/GoogleCallback.tsx (2)
10-20:useEffect의존성 배열에 필요한 값이 누락되어 있습니다.
navigate와searchParams가 effect 내부에서 사용되지만 의존성 배열이 비어 있습니다. 이로 인해 ESLintreact-hooks/exhaustive-deps경고가 발생할 수 있으며, 향후 리팩토링 시 stale closure 문제가 발생할 수 있습니다.♻️ 의존성 배열 수정 제안
useEffect(() => { const code = searchParams.get('code'); if (!code) { alert('로그인 실패. 다시 시도해주세요.'); navigate('/onboarding?step=SOCIAL_LOGIN'); return; } loginWithCode(code); - }, []); + }, [searchParams, navigate]);참고:
loginWithCode도 의존성에 포함하거나,useCallback으로 감싸는 것이 이상적이지만, 현재 구조에서는 무한 루프를 피하기 위해 위 수정만으로도 충분합니다.
30-39:sendTokenToExtension함수를 조건문 밖으로 추출하는 것을 권장합니다.현재 함수가
if (accessToken)블록 내부에 정의되어 있어 코드 가독성이 떨어지고, 재사용이 어렵습니다. 컴포넌트 외부 또는 최소한handleUserLogin함수 상단으로 이동하면 코드 구조가 더 명확해집니다.♻️ 함수 추출 제안
+const sendTokenToExtension = (token: string) => { + window.postMessage( + { + type: 'SET_TOKEN', + token, + }, + window.location.origin + ); +}; + const GoogleCallback = () => { const navigate = useNavigate(); const [searchParams] = useSearchParams(); // ... 생략 ... const handleUserLogin = ( isUser: boolean, accessToken: string | undefined ) => { if (isUser) { if (accessToken) { localStorage.setItem('token', accessToken); - - const sendTokenToExtension = (token: string) => { - window.postMessage( - { - type: 'SET_TOKEN', - token, - }, - window.location.origin - ); - }; sendTokenToExtension(accessToken); } navigate('/'); } else { navigate('/onboarding?step=ALARM'); } };
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
apps/extension/public/logout_chippi.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/logout_chippi.2512.svgis excluded by!**/*.svg
📒 Files selected for processing (7)
apps/client/src/pages/onBoarding/GoogleCallback.tsxapps/client/src/shared/apis/queries.tsapps/extension/src/App.tsxapps/extension/src/apis/axiosInstance.tsapps/extension/src/background.tsapps/extension/src/content.tsapps/extension/src/pages/LogOutPop.tsx
💤 Files with no reviewable changes (1)
- apps/extension/src/apis/axiosInstance.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-08T11:47:10.642Z
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 30
File: apps/extension/src/App.tsx:10-21
Timestamp: 2025-07-08T11:47:10.642Z
Learning: In apps/extension/src/App.tsx, the InfoBox component currently uses a hardcoded external URL for the icon prop as a temporary static placeholder. The plan is to replace this with dynamic favicon extraction from bookmarked websites in future iterations.
Applied to files:
apps/extension/src/pages/LogOutPop.tsx
📚 Learning: 2025-09-11T11:48:10.615Z
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 75
File: apps/extension/src/apis/axiosInstance.ts:30-34
Timestamp: 2025-09-11T11:48:10.615Z
Learning: Pinback 프로젝트에서는 사용자 이메일 저장 시 'email' 키를 사용하도록 통일했습니다 (localStorage 및 chrome.storage.local 모두).
Applied to files:
apps/extension/src/background.ts
🪛 ast-grep (0.40.4)
apps/client/src/shared/apis/queries.ts
[warning] 73-73: Detected potential storage of sensitive information in browser localStorage. Sensitive data like email addresses, personal information, or authentication tokens should not be stored in localStorage as it's accessible to any script.
Context: localStorage.setItem('token', newToken)
Note: [CWE-312] Cleartext Storage of Sensitive Information [REFERENCES]
- https://owasp.org/www-community/vulnerabilities/HTML5_Security_Cheat_Sheet
- https://cwe.mitre.org/data/definitions/312.html
(browser-storage-sensitive-data)
🪛 GitHub Check: lint
apps/extension/src/App.tsx
[warning] 18-18:
Unexpected console statement
apps/extension/src/background.ts
[warning] 6-6:
Unexpected console statement
[warning] 20-20:
Unexpected console statement
⏰ 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
🔇 Additional comments (2)
apps/extension/src/pages/LogOutPop.tsx (1)
2-2: 아이콘 렌더링 개선 확인Icon 컴포넌트를 SVG 이미지 파일로 교체한 변경사항이 적절합니다. 접근성을 위한 alt 텍스트도 포함되어 있고, 스타일링도 올바르게 적용되었습니다.
Also applies to: 10-14
apps/client/src/pages/onBoarding/GoogleCallback.tsx (1)
22-45: 토큰 전달 로직이 PR 목표에 맞게 잘 구현되었습니다.
window.postMessage를 사용하여 익스텐션으로 토큰을 전달하는 방식으로 변경된 것을 확인했습니다.targetOrigin으로window.location.origin을 사용하여 보안 측면에서도 적절합니다.익스텐션의 content script에서
SET_TOKEN메시지를 올바르게 수신하고 있으며, Chrome storage에 토큰이 정상적으로 저장되고 있습니다. 추가로 background script에서도 메시지를 수신하여 별도로 token을 저장하므로 안정성이 더욱 높습니다.
| }; | ||
|
|
||
| if (newToken) { | ||
| localStorage.setItem('token', newToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
보안: localStorage에 토큰 저장 검토 필요
정적 분석 도구가 올바르게 지적한 것처럼, localStorage에 인증 토큰을 평문으로 저장하는 것은 XSS 공격에 취약합니다(CWE-312). 모든 스크립트가 접근 가능하므로, 악성 스크립트가 토큰을 탈취할 수 있습니다.
다음 대안을 고려해주세요:
- HttpOnly 쿠키 사용 (서버측 설정 필요)
- 짧은 만료 시간의 토큰 + 리프레시 토큰 전략
- 메모리 내 저장 (새로고침 시 재로그인 필요)
localStorage vs cookies for JWT token storage security best practices 2026
🤖 Prompt for AI Agents
In @apps/client/src/shared/apis/queries.ts at line 74, Replace the direct
client-side persistence of the JWT by removing the localStorage.setItem('token',
newToken) call and instead either send the newToken to the backend to set an
HttpOnly, Secure cookie (preferred) or store it in ephemeral in-memory state
(e.g., an auth store) combined with a short-lived access token + refresh token
flow; update the code path handling newToken (reference: localStorage.setItem
and variable newToken) to call the backend endpoint that issues HttpOnly cookies
or to populate your in-memory auth store and implement refresh-token handling so
tokens are not stored in localStorage.
| chrome.storage.local.set({ token: event.data.token }, () => { | ||
| console.log('Token saved!', event.data.token); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find . -name "background.ts" -o -name "content.ts" | head -20Repository: Pinback-Team/pinback-client
Length of output: 137
🏁 Script executed:
cat -n apps/extension/src/content.tsRepository: Pinback-Team/pinback-client
Length of output: 550
🏁 Script executed:
cat -n apps/extension/src/background.tsRepository: Pinback-Team/pinback-client
Length of output: 903
중복 저장 로직 제거 필요
content.ts에서 chrome.storage.local.set으로 토큰을 저장한 후, 동일한 토큰을 chrome.runtime.sendMessage로 background 스크립트에 전달하고 있습니다. background.ts에서는 SET_TOKEN 메시지를 수신하여 동일한 저장소에 다시 저장합니다(9-11줄과 background.ts 19-21줄).
이는 불필요한 중복입니다. 토큰 저장은 background에서만 담당하도록 통일하세요:
content.ts에서 9-11줄의chrome.storage.local.set호출 제거- message 전달만 유지하여 background에서 저장 처리
적용 예시
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);
- });
}
});🤖 Prompt for AI Agents
In @apps/extension/src/content.ts around lines 9 - 11, Remove the duplicate
local storage write in content.ts: delete the chrome.storage.local.set(...) call
that writes event.data.token and keep only the chrome.runtime.sendMessage(...)
that sends the token; ensure the background message handler for "SET_TOKEN" (the
handler that currently calls chrome.storage.local.set in background.ts) remains
responsible for persisting event.data.token so the token is stored only once in
the SET_TOKEN handling code.
| token: event.data.token, | ||
| }); | ||
| chrome.storage.local.set({ token: event.data.token }, () => { | ||
| console.log('Token saved!', event.data.token); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
디버그용 console.log 제거 필요
토큰과 같은 민감한 정보를 콘솔에 출력하지 않도록 해주세요.
🧹 제거 제안
- chrome.storage.local.set({ token: event.data.token }, () => {
- console.log('Token saved!', event.data.token);
- });
+ chrome.storage.local.set({ token: event.data.token });Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In @apps/extension/src/content.ts at line 10, Remove the debug console.log that
prints the token (console.log('Token saved!', event.data.token)); do not output
event.data.token or other sensitive values to the console—either delete the
statement entirely or replace it with a non-sensitive confirmation message
(e.g., "Token saved" without the token) or a secure/log- redacted call that
omits event.data.token.
There was a problem hiding this 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 (1)
apps/extension/src/background.ts (1)
18-20: 토큰 로깅 제거 - 보안 개선!민감한 토큰 정보를 콘솔 로그에서 제거한 것은 보안 측면에서 매우 좋은 개선입니다.
다만, 선택적으로 아래 사항들을 고려해보시면 더 좋을 것 같습니다:
message.token의 유효성 검증 (undefined, null, 빈 문자열 체크)- 스토리지 저장 실패 시 에러 핸들링
♻️ 선택적 개선 제안
chrome.runtime.onMessage.addListener((message) => { if (message.type === 'SET_TOKEN') { + if (!message.token) { + console.error('Invalid token received'); + return; + } chrome.storage.local.set({ token: message.token }, () => { + if (chrome.runtime.lastError) { + console.error('Failed to save token:', chrome.runtime.lastError); + return; + } console.log('Token saved!'); }); } });
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/client/public/firebase-messaging-sw.jsapps/client/src/shared/apis/queries.tsapps/extension/src/App.tsxapps/extension/src/background.tsapps/extension/src/content.tsapps/extension/src/hooks/useSaveBookmarks.tspackages/design-system/src/components/gtag/utils/gtag.ts
💤 Files with no reviewable changes (2)
- apps/client/public/firebase-messaging-sw.js
- apps/extension/src/hooks/useSaveBookmarks.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/extension/src/content.ts
- apps/extension/src/App.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-11T11:48:10.615Z
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 75
File: apps/extension/src/apis/axiosInstance.ts:30-34
Timestamp: 2025-09-11T11:48:10.615Z
Learning: Pinback 프로젝트에서는 사용자 이메일 저장 시 'email' 키를 사용하도록 통일했습니다 (localStorage 및 chrome.storage.local 모두).
Applied to files:
apps/extension/src/background.ts
🪛 ast-grep (0.40.4)
apps/client/src/shared/apis/queries.ts
[warning] 73-73: Detected potential storage of sensitive information in browser localStorage. Sensitive data like email addresses, personal information, or authentication tokens should not be stored in localStorage as it's accessible to any script.
Context: localStorage.setItem('token', newToken)
Note: [CWE-312] Cleartext Storage of Sensitive Information [REFERENCES]
- https://owasp.org/www-community/vulnerabilities/HTML5_Security_Cheat_Sheet
- https://cwe.mitre.org/data/definitions/312.html
(browser-storage-sensitive-data)
🔇 Additional comments (3)
apps/extension/src/background.ts (1)
4-6: 개인정보 로깅 제거 - 좋은 개선사항입니다!사용자 이메일을 콘솔 로그에서 제거한 것은 개인정보보호 측면에서 올바른 개선입니다. PII(Personally Identifiable Information) 데이터를 로그에 남기지 않는 것이 GDPR, CCPA 등 개인정보 보호 규정 준수에 도움이 됩니다.
packages/design-system/src/components/gtag/utils/gtag.ts (1)
43-43: 프로덕션 로그 정리 작업 승인GA 이벤트 전송 디버깅 로그를 제거한 변경사항이 적절합니다. 콘솔 출력을 깔끔하게 유지하면서 핵심 추적 기능은 그대로 유지됩니다.
apps/client/src/shared/apis/queries.ts (1)
75-84: window.postMessage 패턴 올바르게 구현됨window.postMessage를 통한 토큰 전달 방식과 origin 검증(
window.location.origin)이 올바르게 적용되었으며, 익스텐션 콘텐츠 스크립트에서도 메시지를 올바르게 수신하고 검증하고 있습니다:
- ✅ 메시지 출처 검증:
event.source !== window로 동일 윈도우 출처 확인- ✅ 타입 검증:
event.data.type === 'SET_TOKEN'명시적 확인- ✅ 토큰 저장:
chrome.storage.local.set()으로 안전하게 저장- ✅ 배경 스크립트 연동:
chrome.runtime.sendMessage()로 배경 스크립트에 전달, 추가 검증 및 저장보안 측면에서 메시지 검증이 콘텐츠 스크립트와 배경 스크립트 두 단계에서 이루어지고 있어 적절합니다.
| if (newToken) { | ||
| localStorage.setItem('token', newToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n apps/client/src/shared/apis/queries.ts | sed -n '65,90p'Repository: Pinback-Team/pinback-client
Length of output: 899
🏁 Script executed:
# Search for httpOnly cookie usage or alternative token storage patterns
rg -i "httponly|http-only|cookie.*secure|document\.cookie" --type ts --type jsRepository: Pinback-Team/pinback-client
Length of output: 53
🏁 Script executed:
# Check for XSS protection mechanisms like CSP, sanitization, or security headers
rg -i "content-security-policy|csp|sanitize|xss" --type ts --type js --type jsonRepository: Pinback-Team/pinback-client
Length of output: 50385
🏁 Script executed:
# Search for token storage patterns across the codebase
rg "localStorage.*token|sessionStorage.*token|setItem.*token" --type ts --type js -A 2 -B 2Repository: Pinback-Team/pinback-client
Length of output: 2568
🏁 Script executed:
# Check if there's any security configuration file or documentation
fd -e "json" -e "ts" -e "js" | xargs grep -l "security\|csrf\|xss" 2>/dev/null | head -20Repository: Pinback-Team/pinback-client
Length of output: 113
localStorage 토큰 저장 방식의 보안 위험성 확인
localStorage에 인증 토큰을 저장하는 방식이 정적 분석 결과와 일치합니다. 이는 XSS 공격에 취약한 구조입니다 (CWE-312). JavaScript에 접근 가능한 저장소에 민감한 인증 정보가 저장되므로, 악의적인 스크립트가 토큰을 탈취할 수 있습니다.
현재 아키텍처에서는:
- axiosInstance의 요청 인터셉터가 localStorage에서 토큰을 읽음
- httpOnly 쿠키 사용 없음
- XSS 방어 메커니즘(CSP 등) 미적용 상태
토큰 저장 방식을 보안 기준에 맞게 개선하거나, XSS 방어 메커니즘을 적용하여 이 위험을 완화해야 합니다.
🧰 Tools
🪛 ast-grep (0.40.4)
[warning] 73-73: Detected potential storage of sensitive information in browser localStorage. Sensitive data like email addresses, personal information, or authentication tokens should not be stored in localStorage as it's accessible to any script.
Context: localStorage.setItem('token', newToken)
Note: [CWE-312] Cleartext Storage of Sensitive Information [REFERENCES]
- https://owasp.org/www-community/vulnerabilities/HTML5_Security_Cheat_Sheet
- https://cwe.mitre.org/data/definitions/312.html
(browser-storage-sensitive-data)
jjangminii
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
확인했습니다-!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이미지 사라졌을까요?? 😢
📌 Related Issues
📄 Tasks
⭐ PR Point (To Reviewer)
📷 Screenshot
Summary by CodeRabbit
릴리스 노트
Refactor
Chores
UI 개선
✏️ Tip: You can customize this high-level summary in your review settings.