From 2b2d99a6348264ed4a0ef7f08adc4090f353da41 Mon Sep 17 00:00:00 2001 From: aken-you Date: Wed, 9 Jul 2025 08:58:11 +0900 Subject: [PATCH 01/27] =?UTF-8?q?fix:=20Slack=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EC=A0=84=EC=86=A1=20=EC=8B=9C=20JSON=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=ED=8F=AC=EB=A7=B7=ED=8C=85=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/notify-pr-author-on-review.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/notify-pr-author-on-review.yml b/.github/workflows/notify-pr-author-on-review.yml index d0efcbfb..0f389cec 100644 --- a/.github/workflows/notify-pr-author-on-review.yml +++ b/.github/workflows/notify-pr-author-on-review.yml @@ -54,17 +54,23 @@ jobs: AUTHOR_SLACK_ID: ${{ steps.extract_info.outputs.author_slack_id }} TEXT: ${{ steps.extract_info.outputs.text }} run: | + JSON_DATA=$(jq -n \ + --arg channel "$AUTHOR_SLACK_ID" \ + --arg text "$TEXT" \ + '{ + "channel": $channel, + "text": $text + }') + RESPONSE=$(curl -s -X POST https://slack.com/api/chat.postMessage \ -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ -H "Content-Type: application/json" \ - -d '{ - "channel": "'"$AUTHOR_SLACK_ID"'", - "text": "'"$TEXT"'" - }') + -d "$JSON_DATA") echo "Slack DM 전송 응답: $RESPONSE" if ! echo "$RESPONSE" | jq -e '.ok' | grep -q true; then echo "❌ Slack 메시지 전송 실패" + echo "에러 상세: $(echo "$RESPONSE" | jq -r '.error // "unknown error"')" exit 1 fi From 2802f438fb64e9e924ae8cdae2f021828159ac48 Mon Sep 17 00:00:00 2001 From: aken-you Date: Sat, 12 Jul 2025 00:37:47 +0900 Subject: [PATCH 02/27] =?UTF-8?q?refactor:=20im=20=EC=B1=84=EB=84=90=20id?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - slack bot이 사용자에게 DM을 보내기 전에, 사용자와의 DM 채널 id가 필요하여 조회 --- .github/workflows/notify-pr-author-on-review.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/notify-pr-author-on-review.yml b/.github/workflows/notify-pr-author-on-review.yml index 0f389cec..9a0aae16 100644 --- a/.github/workflows/notify-pr-author-on-review.yml +++ b/.github/workflows/notify-pr-author-on-review.yml @@ -54,8 +54,16 @@ jobs: AUTHOR_SLACK_ID: ${{ steps.extract_info.outputs.author_slack_id }} TEXT: ${{ steps.extract_info.outputs.text }} run: | + # slack bot과 PR 작성자와의 채널 조회 (DM을 보내기 위해, 반드시 slack bot과의 채널 id가 필요함) + JSON_IM_CHANNEL=$(curl -s -X POST https://slack.com/api/conversations.open \ + -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"users\":\"$AUTHOR_SLACK_ID\"}") + # slack bot과의 채널 id 저장 + IM_CHANNEL_ID=$(echo "$JSON_IM_CHANNEL" | jq -r '.channel.id') + JSON_DATA=$(jq -n \ - --arg channel "$AUTHOR_SLACK_ID" \ + --arg channel "$IM_CHANNEL_ID" \ --arg text "$TEXT" \ '{ "channel": $channel, From b0ec139ed9b7447d7bc437a3c4cbed21c31e6988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Sat, 12 Jul 2025 22:40:40 +0900 Subject: [PATCH 03/27] =?UTF-8?q?fix=20:=20QNRR-356=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EC=8B=9C=20memberId=EA=B0=80=20null=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 회원가입 직후 응답받은 memberId 를 쿠키에 설정함으로써 해결 --- src/features/auth/ui/sign-up-modal.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/auth/ui/sign-up-modal.tsx b/src/features/auth/ui/sign-up-modal.tsx index e96c79e4..d6a79d01 100644 --- a/src/features/auth/ui/sign-up-modal.tsx +++ b/src/features/auth/ui/sign-up-modal.tsx @@ -6,7 +6,7 @@ import { } from '@/features/auth/model/use-auth-mutation'; import SignupImageSelector from '@/features/auth/ui/sign-up-image-selector'; import SignupNameInput from '@/features/auth/ui/sign-up-name-input'; -import { getCookie } from '@/shared/tanstack-query/cookie'; +import { getCookie, setCookie } from '@/shared/tanstack-query/cookie'; import Button from '@/shared/ui/button'; import { Modal } from '@/shared/ui/modal'; @@ -59,6 +59,7 @@ export default function SignupModal({ // 회원가입 성공 시 프로필 이미지 업로드 onSuccess: (data) => { if (data && data.content.generatedMemberId) { + setCookie('memberId', data.content.generatedMemberId ) const formData = new FormData(); if (fileInputRef.current?.files?.[0]) { From a254b6ed8f21c15112fc4ff640f1ec67ba5c20e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Sat, 12 Jul 2025 23:27:30 +0900 Subject: [PATCH 04/27] =?UTF-8?q?fix=20:=20QNRR-327=20=20=EA=B5=AC?= =?UTF-8?q?=EA=B8=80=EB=A1=9C=EA=B7=B8=EC=9D=B8=EC=8B=9C=20=EC=99=B8?= =?UTF-8?q?=EB=B6=80=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EB=93=B1=EB=A1=9D=20=EB=B0=8F=20GA=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/redirection/page.tsx | 13 ++++++++----- next.config.ts | 5 +++++ src/features/auth/ui/sign-up-modal.tsx | 18 ++++++++++++++++-- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/app/redirection/page.tsx b/app/redirection/page.tsx index 554bf01a..506e907a 100644 --- a/app/redirection/page.tsx +++ b/app/redirection/page.tsx @@ -31,11 +31,14 @@ function RedirectionContent() { if (isGuest === 'true') { router.push('/sign-up'); - sendGTMEvent({ - event: 'custom_member_join', - dl_timestamp: new Date().toISOString(), - dl_member_id: hashValue(memberId), - }); + // isGuest가 true 인 경우 memberId가 없어서 아래 hashValue 에서 에러가 남. + // 따라서 해당 이벤트는 회원가입 직후인 'sign-up-modal.tsx' 로 이동. + + // sendGTMEvent({ + // event: 'custom_member_join', + // dl_timestamp: new Date().toISOString(), + // dl_member_id: hashValue(memberId), + // }); } else { router.push('/'); router.refresh(); diff --git a/next.config.ts b/next.config.ts index 284e3b98..e1dcedae 100644 --- a/next.config.ts +++ b/next.config.ts @@ -15,6 +15,11 @@ const nextConfig: NextConfig = { hostname: 'test-api.zeroone.it.kr', pathname: '/profile-image/**', }, + { + protocol: 'https', + hostname: 'lh3.googleusercontent.com', + pathname: '/**', // 구글 이미지 전체 허용 + }, ], }, diff --git a/src/features/auth/ui/sign-up-modal.tsx b/src/features/auth/ui/sign-up-modal.tsx index d6a79d01..ebf64fae 100644 --- a/src/features/auth/ui/sign-up-modal.tsx +++ b/src/features/auth/ui/sign-up-modal.tsx @@ -9,6 +9,8 @@ import SignupNameInput from '@/features/auth/ui/sign-up-name-input'; import { getCookie, setCookie } from '@/shared/tanstack-query/cookie'; import Button from '@/shared/ui/button'; import { Modal } from '@/shared/ui/modal'; +import { sendGTMEvent } from '@next/third-parties/google'; +import { hashValue } from '@/shared/lib/hash'; export default function SignupModal({ open, @@ -58,8 +60,19 @@ export default function SignupModal({ { // 회원가입 성공 시 프로필 이미지 업로드 onSuccess: (data) => { - if (data && data.content.generatedMemberId) { - setCookie('memberId', data.content.generatedMemberId ) + + const memberId = data.content.generatedMemberId; + + if (data && memberId) { + setCookie('memberId', memberId) + + // 회원가입 GA 이벤트 전송 + sendGTMEvent({ + event: 'custom_member_join', + dl_timestamp: new Date().toISOString(), + dl_member_id: hashValue(memberId), + }); + const formData = new FormData(); if (fileInputRef.current?.files?.[0]) { @@ -72,6 +85,7 @@ export default function SignupModal({ file: formData, }); } + // 성공 후 홈페이지로 이동 window.location.href = '/'; From 520a8d3b9262848c72e4f754a518ae1d2f0b76bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Sat, 12 Jul 2025 23:38:11 +0900 Subject: [PATCH 05/27] =?UTF-8?q?refactor=20:=20=ED=97=A4=EB=8D=94?= =?UTF-8?q?=EC=9D=98=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85/=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EB=B2=84=ED=8A=BC=EC=8B=9C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EB=AA=A8=EB=8B=AC=ED=8C=9D=EC=97=85?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기획상 시작하기뿐 아니라 헤더의 버튼 눌렀을때도 팝업이 되어야함 --- src/widgets/home/header.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/widgets/home/header.tsx b/src/widgets/home/header.tsx index 85a76796..e0e2ea85 100644 --- a/src/widgets/home/header.tsx +++ b/src/widgets/home/header.tsx @@ -12,11 +12,14 @@ import UserAvatar from '@/shared/ui/avatar'; import Button from '@/shared/ui/button'; import { HeaderDropdown } from '@/shared/ui/dropdown'; import NotiIcon from 'public/icons/notifications_none.svg'; +import LoginModal from '@/features/auth/ui/login-modal'; +import { useState } from 'react'; export default function Header() { const queryClient = useQueryClient(); const router = useRouter(); const memberInfo = useMemberInfo(); + const [loginOpen, setLoginOpen] = useState(false); // 로컬 테스트에서 사용시 주석 제거 // console.log('요청 주소', process.env.API_BASE_URL); @@ -99,9 +102,14 @@ export default function Header() { /> {!memberInfo.data?.isLogin && ( - + setLoginOpen(false)} /> )} From 527fb334fecf6ad308374a2aae7d36617218aff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Sun, 13 Jul 2025 00:32:24 +0900 Subject: [PATCH 06/27] =?UTF-8?q?fix=20:=20QNRR-335=20accessToken=20?= =?UTF-8?q?=EB=A7=8C=EB=A3=8C=ED=86=A0=ED=81=B0=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=B0=8F=20Refresh=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/lib/get-login-user.ts | 60 ++++++++++++++++++++++++++++++-- src/shared/lib/server-cookie.ts | 9 +++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/shared/lib/get-login-user.ts b/src/shared/lib/get-login-user.ts index 74b13368..586219c3 100644 --- a/src/shared/lib/get-login-user.ts +++ b/src/shared/lib/get-login-user.ts @@ -1,11 +1,67 @@ -import { getServerCookie } from './server-cookie'; +import { getServerCookie, setServerCookie } from './server-cookie'; +import axios from 'axios'; +import { redirect } from 'next/navigation'; export async function getLoginUserId(): Promise { + // memberId 쿠키 우선 확인 (기존 로직) const memberIdStr = await getServerCookie('memberId'); if (!memberIdStr) return null; const memberId = Number(memberIdStr); if (isNaN(memberId) || memberId <= 0) return null; - return memberId; + /* + 이하 accessToken 최신화를 위한 로직 + */ + + // 1. accessToken 쿠키 확인 + let accessToken = await getServerCookie('accessToken'); + if (!accessToken) return null; + + // 2. accessToken으로 /auth/me 호출 + try { + // (SSR 이므로 useQuery 를 쓰지 않고 직접 API 호출) + const res = await axios.get( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/auth/me`, + { + headers: { Authorization: `Bearer ${accessToken}` }, + withCredentials: true, + } + ); + // 3. memberId 쿠키와 /auth/me의 memberId가 다르면 null 반환 + if (Number(res.data.content) !== memberId) return null; + + return memberId; + } catch (error: any) { + + // 4. 401이면 만료된 토큰이므로 토큰 갱신 시도 + if (error.response?.status === 401) { + try { + const refreshRes = await axios.get( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/auth/access-token/refresh`, + { withCredentials: true } + ); + accessToken = refreshRes.data.accessToken; + // 5. SSR에서 최신화된 AccessToken을 쿠키등록 + setServerCookie('accessToken', accessToken, { path: '/' }); + + // 6. 갱신된 토큰으로 다시 /auth/me 호출 + const res2 = await axios.get( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/auth/me`, + { + headers: { Authorization: `Bearer ${accessToken}` }, + withCredentials: true, + } + ); + if (Number(res2.data.memberId) !== memberId) return null; + return memberId; + } catch (refreshError) { + // 갱신 실패 → 로그인 페이지로 리다이렉트 + redirect('/login'); + } + } else { + // 기타 에러 → 로그인 페이지로 리다이렉트 + redirect('/login'); + } + } } diff --git a/src/shared/lib/server-cookie.ts b/src/shared/lib/server-cookie.ts index c78766bd..1f422428 100644 --- a/src/shared/lib/server-cookie.ts +++ b/src/shared/lib/server-cookie.ts @@ -8,3 +8,12 @@ export const getServerCookie = async ( return value ?? undefined; }; + +export const setServerCookie = async( + name: string, + value: string, + options: { path?: string } = {}, +): Promise => { + const cookieStore = await cookies(); + cookieStore.set(name, value, { path: '/', ...options }); +}; \ No newline at end of file From 3041544ca5f1c536becf64d663ace7426619a856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Sun, 13 Jul 2025 00:36:23 +0900 Subject: [PATCH 07/27] =?UTF-8?q?chore=20:=20build=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=9A=8C=ED=94=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/lib/get-login-user.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/lib/get-login-user.ts b/src/shared/lib/get-login-user.ts index 586219c3..58110f4b 100644 --- a/src/shared/lib/get-login-user.ts +++ b/src/shared/lib/get-login-user.ts @@ -43,7 +43,7 @@ export async function getLoginUserId(): Promise { ); accessToken = refreshRes.data.accessToken; // 5. SSR에서 최신화된 AccessToken을 쿠키등록 - setServerCookie('accessToken', accessToken, { path: '/' }); + await setServerCookie('accessToken', accessToken, { path: '/' }); // 6. 갱신된 토큰으로 다시 /auth/me 호출 const res2 = await axios.get( @@ -54,6 +54,7 @@ export async function getLoginUserId(): Promise { } ); if (Number(res2.data.memberId) !== memberId) return null; + return memberId; } catch (refreshError) { // 갱신 실패 → 로그인 페이지로 리다이렉트 From a43551e319bc796cf18a5cceed799bdd011e45d2 Mon Sep 17 00:00:00 2001 From: aken-you Date: Sun, 13 Jul 2025 17:37:22 +0900 Subject: [PATCH 08/27] =?UTF-8?q?refactor:=20slackapi/slack-github-action?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workflows/notify-pr-author-on-review.yml | 40 ++++--------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/.github/workflows/notify-pr-author-on-review.yml b/.github/workflows/notify-pr-author-on-review.yml index 9a0aae16..9f60a07c 100644 --- a/.github/workflows/notify-pr-author-on-review.yml +++ b/.github/workflows/notify-pr-author-on-review.yml @@ -49,36 +49,10 @@ jobs: - name: Send Slack DM to PR Author if: steps.extract_info.outputs.skip != 'true' - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - AUTHOR_SLACK_ID: ${{ steps.extract_info.outputs.author_slack_id }} - TEXT: ${{ steps.extract_info.outputs.text }} - run: | - # slack bot과 PR 작성자와의 채널 조회 (DM을 보내기 위해, 반드시 slack bot과의 채널 id가 필요함) - JSON_IM_CHANNEL=$(curl -s -X POST https://slack.com/api/conversations.open \ - -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ - -H "Content-Type: application/json" \ - -d "{\"users\":\"$AUTHOR_SLACK_ID\"}") - # slack bot과의 채널 id 저장 - IM_CHANNEL_ID=$(echo "$JSON_IM_CHANNEL" | jq -r '.channel.id') - - JSON_DATA=$(jq -n \ - --arg channel "$IM_CHANNEL_ID" \ - --arg text "$TEXT" \ - '{ - "channel": $channel, - "text": $text - }') - - RESPONSE=$(curl -s -X POST https://slack.com/api/chat.postMessage \ - -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ - -H "Content-Type: application/json" \ - -d "$JSON_DATA") - - echo "Slack DM 전송 응답: $RESPONSE" - - if ! echo "$RESPONSE" | jq -e '.ok' | grep -q true; then - echo "❌ Slack 메시지 전송 실패" - echo "에러 상세: $(echo "$RESPONSE" | jq -r '.error // "unknown error"')" - exit 1 - fi + uses: slackapi/slack-github-action@v2.1.0 + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: | + channel: ${{ steps.extract_info.outputs.author_slack_id }} + text: ${{ steps.extract_info.outputs.text }} From 8fe44ae31edd8cd6d65572719b693bd341d5894c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Sun, 13 Jul 2025 23:44:39 +0900 Subject: [PATCH 09/27] =?UTF-8?q?chore=20:=20=EC=A3=BC=EC=84=9D=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0,=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EC=82=AC=EC=9D=B4=20gap=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/redirection/page.tsx | 8 -------- src/features/auth/ui/login-modal.tsx | 6 +++--- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/app/redirection/page.tsx b/app/redirection/page.tsx index 506e907a..a7caa192 100644 --- a/app/redirection/page.tsx +++ b/app/redirection/page.tsx @@ -31,14 +31,6 @@ function RedirectionContent() { if (isGuest === 'true') { router.push('/sign-up'); - // isGuest가 true 인 경우 memberId가 없어서 아래 hashValue 에서 에러가 남. - // 따라서 해당 이벤트는 회원가입 직후인 'sign-up-modal.tsx' 로 이동. - - // sendGTMEvent({ - // event: 'custom_member_join', - // dl_timestamp: new Date().toISOString(), - // dl_member_id: hashValue(memberId), - // }); } else { router.push('/'); router.refresh(); diff --git a/src/features/auth/ui/login-modal.tsx b/src/features/auth/ui/login-modal.tsx index 34369ae7..7c2bb6be 100644 --- a/src/features/auth/ui/login-modal.tsx +++ b/src/features/auth/ui/login-modal.tsx @@ -65,7 +65,7 @@ export default function LoginModal({
{/* */} + setIsOpenLoginModal(false)} + /> + + ); +} diff --git a/src/widgets/home/header.tsx b/src/widgets/home/header.tsx index e0e2ea85..69f4fe9e 100644 --- a/src/widgets/home/header.tsx +++ b/src/widgets/home/header.tsx @@ -1,60 +1,20 @@ -'use client'; - -import { sendGTMEvent } from '@next/third-parties/google'; -import { useQueryClient } from '@tanstack/react-query'; import Link from 'next/link'; -import { useRouter } from 'next/navigation'; -import { logout } from '@/features/auth/api/auth'; -import { useMemberInfo } from '@/features/auth/model/use-auth'; -import { hashValue } from '@/shared/lib/hash'; -import { deleteCookie, getCookie } from '@/shared/tanstack-query/cookie'; -import UserAvatar from '@/shared/ui/avatar'; -import Button from '@/shared/ui/button'; -import { HeaderDropdown } from '@/shared/ui/dropdown'; -import NotiIcon from 'public/icons/notifications_none.svg'; -import LoginModal from '@/features/auth/ui/login-modal'; -import { useState } from 'react'; - -export default function Header() { - const queryClient = useQueryClient(); - const router = useRouter(); - const memberInfo = useMemberInfo(); - const [loginOpen, setLoginOpen] = useState(false); - - // 로컬 테스트에서 사용시 주석 제거 - // console.log('요청 주소', process.env.API_BASE_URL); - // console.log( - // '프로필 이미지 주소', - // memberInfo.data?.content?.memberProfile?.profileImage?.resizedImages[0] - // ?.resizedImageUrl, - // ); +import { getUserProfile } from '@/entities/user/api/get-user-profile'; - const handleLogout = async () => { - try { - // 1. 서버에 로그아웃 요청 (refresh token 삭제) - await logout(); +import HeaderUserDropdown from '@/features/auth/ui/header-user-dropdown'; +import OpenLoginModalButton from '@/features/auth/ui/open-login-modal-button'; +import { getServerCookie } from '@/shared/lib/server-cookie'; - const memberId = getCookie('memberId'); - sendGTMEvent({ - event: 'custom_member_logout', - dl_timestamp: new Date().toISOString(), - dl_member_id: hashValue(memberId), - }); +// import NotiIcon from 'public/icons/notifications_none.svg'; - // 2. 클라이언트의 access token 삭제 - deleteCookie('accessToken'); - deleteCookie('memberId'); +export default async function Header() { + const memberId = await getServerCookie('memberId'); + const isLogin = /^\d+$/.test(memberId || ''); - // 3. React Query 캐시 초기화 - queryClient.clear(); - - // 4. 홈으로 리다이렉트 - router.push('/'); - router.refresh(); // 전체 페이지 리프레시 - } catch (error) { - console.error('로그아웃 실패:', error); - } - }; + const userInfo = isLogin ? await getUserProfile(Number(memberId)) : null; + const userImg = isLogin + ? userInfo.memberProfile.profileImage?.resizedImages[0].resizedImageUrl + : 'profile-default.svg'; return (
@@ -70,48 +30,13 @@ export default function Header() { */}
-
+ {/* 알림 기능을 구현하지 못해 주석 처리 */} + {/*
-
- - } - options={[ - { - label: '내 정보 수정', - value: '/my-page', - }, - { - label: '로그아웃', - value: 'logout', - }, - ]} - onChange={async (value) => { - if (value === '/my-page') { - await router.push(value); - } else if (value === 'logout') { - await handleLogout(); - } - }} - /> - {!memberInfo.data?.isLogin && ( - - - setLoginOpen(false)} /> - - )} +
*/} + + {isLogin && } + {!isLogin && }
From 1dc40c83d277e1de696c1ffc7437ddf8bd79c51e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?= Date: Fri, 18 Jul 2025 00:50:53 +0900 Subject: [PATCH 18/27] =?UTF-8?q?delete:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=B3=80=EC=88=98=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/widgets/home/sidebar.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/widgets/home/sidebar.tsx b/src/widgets/home/sidebar.tsx index 3d83620f..cd342461 100644 --- a/src/widgets/home/sidebar.tsx +++ b/src/widgets/home/sidebar.tsx @@ -10,8 +10,6 @@ export default async function Sidebar() { const userProfile = await getUserProfile(memberId); - const hasTodo = false; // 나중에 스터디 참여 유무로 변경할 예정 - return (