From 7991874890684f9a57b197844763ad6e1c565e3a Mon Sep 17 00:00:00 2001 From: leeleeleeleejun Date: Thu, 20 Nov 2025 22:23:18 +0900 Subject: [PATCH 1/7] =?UTF-8?q?refactor:=20API=20responses=20return=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=20=EC=88=98=EC=A0=95=20-=20axiosInstance.int?= =?UTF-8?q?erceptors.response=20=EC=97=90=EC=84=9C=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=9D=BC=EA=B4=84=20=EC=8B=A4=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/app/_apis/services/category.ts | 3 +-- apps/web/app/_apis/services/event.ts | 15 ++++----------- apps/web/app/_apis/services/like.ts | 8 ++------ apps/web/app/_apis/services/place.ts | 18 ++++++------------ apps/web/app/_apis/services/request.ts | 8 ++------ 5 files changed, 15 insertions(+), 37 deletions(-) diff --git a/apps/web/app/_apis/services/category.ts b/apps/web/app/_apis/services/category.ts index f009182..0e84cce 100644 --- a/apps/web/app/_apis/services/category.ts +++ b/apps/web/app/_apis/services/category.ts @@ -3,7 +3,6 @@ import { API_PATH } from '@/_constants/path' import { CategorySchema, Category } from '../schemas/category' export const getCategories = async (): Promise => { - const { data: response } = await axiosInstance.get(API_PATH.CATEGORY) - const { data } = response + const { data } = await axiosInstance.get(API_PATH.CATEGORY) return CategorySchema.array().parse(data) } diff --git a/apps/web/app/_apis/services/event.ts b/apps/web/app/_apis/services/event.ts index 4d930a7..924fb43 100644 --- a/apps/web/app/_apis/services/event.ts +++ b/apps/web/app/_apis/services/event.ts @@ -10,14 +10,12 @@ import { } from '@/_apis/schemas/event' export const getPublicEventInfo = async (): Promise => { - const { data: response } = await axiosInstance.get(API_PATH.EVENT.INFO) - const { data } = response + const { data } = await axiosInstance.get(API_PATH.EVENT.INFO) return PublicEventSchema.parse(data) } export const getPrivateEventInfo = async (): Promise => { - const { data: response } = await axiosInstance.get(API_PATH.EVENT.INFO) - const { data } = response + const { data } = await axiosInstance.get(API_PATH.EVENT.INFO) return PrivateEventSchema.parse(data) } @@ -25,16 +23,11 @@ export const participationEvent = async (body: { eventId: string ticketsCount: number }) => { - const { data: response } = await axiosInstance.post( - API_PATH.EVENT.PARTICIPATIONS, - body, - ) - const { data } = response + const { data } = await axiosInstance.post(API_PATH.EVENT.PARTICIPATIONS, body) return data } export const getEventResult = async (): Promise => { - const { data: response } = await axiosInstance.get(API_PATH.EVENT.RESULT) - const { data } = response + const { data } = await axiosInstance.get(API_PATH.EVENT.RESULT) return EventResultSchema.parse(data) } diff --git a/apps/web/app/_apis/services/like.ts b/apps/web/app/_apis/services/like.ts index 15cb28b..8ed83cf 100644 --- a/apps/web/app/_apis/services/like.ts +++ b/apps/web/app/_apis/services/like.ts @@ -7,17 +7,13 @@ type Response = { } export const addLike = async (placeId: string): Promise => { - const { data: response } = await axiosInstance.post( - API_PATH.PLACES.LIKE.POST(placeId), - ) - const { data } = response + const { data } = await axiosInstance.post(API_PATH.PLACES.LIKE.POST(placeId)) return data } export const removeLike = async (placeId: string): Promise => { - const { data: response } = await axiosInstance.delete( + const { data } = await axiosInstance.delete( API_PATH.PLACES.LIKE.DELETE(placeId), ) - const { data } = response return data } diff --git a/apps/web/app/_apis/services/place.ts b/apps/web/app/_apis/services/place.ts index 752118e..bde879c 100644 --- a/apps/web/app/_apis/services/place.ts +++ b/apps/web/app/_apis/services/place.ts @@ -25,10 +25,9 @@ export const getPlacesByRanking = async ( sort: RankingPlaceSort, campus: CampusType, ): Promise => { - const { data: response } = await axiosInstance.get( + const { data } = await axiosInstance.get( API_PATH.PLACES.BY_RANKING(sort, campus), ) - const { data } = response return BasePlaceSchema.array().parse(data) } @@ -36,10 +35,9 @@ export const getPlacesByCategory = async ( id: string, campus: CampusType, ): Promise => { - const { data: response } = await axiosInstance.get( + const { data } = await axiosInstance.get( API_PATH.PLACES.BY_CATEGORY(id, campus), ) - const { data } = response return BasePlaceSchema.array().parse(data) } @@ -49,7 +47,7 @@ export const getPlacesByMap = async ({ maxLatitude, maxLongitude, }: MapBounds): Promise => { - const { data: response } = await axiosInstance.get( + const { data } = await axiosInstance.get( API_PATH.PLACES.BY_MAP({ minLatitude, minLongitude, @@ -57,13 +55,11 @@ export const getPlacesByMap = async ({ maxLongitude, }), ) - const { data } = response return PlaceByMapSchema.array().parse(data) } export const getPlaceDetail = async (id: string): Promise => { - const { data: response } = await axiosInstance.get(API_PATH.PLACES.DETAIL(id)) - const { data } = response + const { data } = await axiosInstance.get(API_PATH.PLACES.DETAIL(id)) return PlaceDetailSchema.parse(data) } @@ -89,16 +85,14 @@ export const getSearchPlaceByKakao = async ({ export const getPlaceByPreview = async ( kakaoPlaceId: string, ): Promise => { - const { data: response } = await axiosInstance.get( + const { data } = await axiosInstance.get( API_PATH.PLACES.NEW.PREVIEW(kakaoPlaceId), ) - const { data } = response return PlaceByPreviewSchema.parse(data) } export const getPlacesByLike = async (): Promise => { - const { data: response } = await axiosInstance.get(API_PATH.PLACES.LIKE.GET) - const { data } = response + const { data } = await axiosInstance.get(API_PATH.PLACES.LIKE.GET) return BasePlaceSchema.array().parse(data) } diff --git a/apps/web/app/_apis/services/request.ts b/apps/web/app/_apis/services/request.ts index 4f03213..a2398f3 100644 --- a/apps/web/app/_apis/services/request.ts +++ b/apps/web/app/_apis/services/request.ts @@ -8,15 +8,11 @@ import { } from '@/_apis/schemas/request' export const getRequests = async (): Promise => { - const { data: response } = await axiosInstance.get(API_PATH.REQUEST.LIST) - const { data } = response + const { data } = await axiosInstance.get(API_PATH.REQUEST.LIST) return RequestSchema.array().parse(data) } export const getRequestDetail = async (id: string): Promise => { - const { data: response } = await axiosInstance.get( - API_PATH.REQUEST.DETAIL(id), - ) - const { data } = response + const { data } = await axiosInstance.get(API_PATH.REQUEST.DETAIL(id)) return RequestDetailSchema.parse(data) } From a6e8029de94dd6f83264a676dbc8e655f04c0ea3 Mon Sep 17 00:00:00 2001 From: leeleeleeleejun Date: Thu, 20 Nov 2025 22:24:08 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A1=B0=ED=9A=8C=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=EC=8A=A4=ED=82=A4=EB=A7=88=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/app/_apis/queries/user.ts | 15 +++++++++++++++ apps/web/app/_apis/schemas/user.ts | 9 +++++++++ apps/web/app/_apis/services/user.ts | 8 ++++++++ apps/web/app/_constants/path.ts | 1 + 4 files changed, 33 insertions(+) create mode 100644 apps/web/app/_apis/queries/user.ts create mode 100644 apps/web/app/_apis/schemas/user.ts create mode 100644 apps/web/app/_apis/services/user.ts diff --git a/apps/web/app/_apis/queries/user.ts b/apps/web/app/_apis/queries/user.ts new file mode 100644 index 0000000..29d94d2 --- /dev/null +++ b/apps/web/app/_apis/queries/user.ts @@ -0,0 +1,15 @@ +import { queryOptions } from '@tanstack/react-query' +import { getUserData } from '@/_apis/services/user' + +export const UserQueryKeys = { + all: () => ['user'] as const, + detail: () => [...UserQueryKeys.all(), 'detail'] as const, +} + +export const useUserQueries = { + detail: () => + queryOptions({ + queryKey: UserQueryKeys.detail(), + queryFn: getUserData, + }), +} diff --git a/apps/web/app/_apis/schemas/user.ts b/apps/web/app/_apis/schemas/user.ts new file mode 100644 index 0000000..8da6727 --- /dev/null +++ b/apps/web/app/_apis/schemas/user.ts @@ -0,0 +1,9 @@ +import z from 'zod' + +export const UserSchema = z.object({ + nickname: z.string(), + profileImageUrl: z.url(), + profileBackgroundHexCode: z.string(), +}) + +export type User = z.infer diff --git a/apps/web/app/_apis/services/user.ts b/apps/web/app/_apis/services/user.ts new file mode 100644 index 0000000..0925dd0 --- /dev/null +++ b/apps/web/app/_apis/services/user.ts @@ -0,0 +1,8 @@ +import axiosInstance from '@/_lib/axiosInstance' +import { API_PATH } from '@/_constants/path' +import { User, UserSchema } from '@/_apis/schemas/user' + +export const getUserData = async (): Promise => { + const { data } = await axiosInstance.get(API_PATH.USER) + return UserSchema.parse(data) +} diff --git a/apps/web/app/_constants/path.ts b/apps/web/app/_constants/path.ts index f40e78b..91b8a53 100644 --- a/apps/web/app/_constants/path.ts +++ b/apps/web/app/_constants/path.ts @@ -45,6 +45,7 @@ export const API_PATH = { `/auth/oauth2?code=${code}&redirectUri=${redirectUri}`, TOKEN: '/auth/token', }, + USER: 'users/me', } export const CLIENT_PATH = { From 6e658e0b921bf133d5ed28c5f40779356341a1bd Mon Sep 17 00:00:00 2001 From: leeleeleeleejun Date: Thu, 20 Nov 2025 22:29:13 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20-=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A9=94=EB=89=B4=20=ED=95=AD=EB=AA=A9=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B6=84=EB=A6=AC=20-=20UserProf?= =?UTF-8?q?ile=EC=97=90=EC=84=9C=EB=A7=8C=20api=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=82=AC=EC=9A=A9=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/app/profile/ProfilePage.tsx | 62 ------------------- .../ProfileMenuItem/ProfileMenuItem.tsx | 19 ++++++ .../_components/ProfileMenuItem/index.ts | 1 + .../_components/UserProfile/UserProfile.tsx | 32 ++++++++++ .../profile/_components/UserProfile/index.ts | 1 + apps/web/app/profile/page.tsx | 36 ++++++++++- apps/web/next.config.ts | 5 ++ 7 files changed, 92 insertions(+), 64 deletions(-) delete mode 100644 apps/web/app/profile/ProfilePage.tsx create mode 100644 apps/web/app/profile/_components/ProfileMenuItem/ProfileMenuItem.tsx create mode 100644 apps/web/app/profile/_components/ProfileMenuItem/index.ts create mode 100644 apps/web/app/profile/_components/UserProfile/UserProfile.tsx create mode 100644 apps/web/app/profile/_components/UserProfile/index.ts diff --git a/apps/web/app/profile/ProfilePage.tsx b/apps/web/app/profile/ProfilePage.tsx deleted file mode 100644 index b7ad8fa..0000000 --- a/apps/web/app/profile/ProfilePage.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { Column, Flex, JustifyBetween } from '@repo/ui/components/Layout' -import { Icon, IconType } from '@repo/ui/components/Icon' -import { Text } from '@repo/ui/components/Text' -import Image from 'next/image' -import { CLIENT_PATH } from '@/_constants/path' - -export const ProfilePage = () => { - return ( - - - - - - - - - ) -} - -const Profile = () => ( - - - {'profileImage'} - - - 배고픈 강아지 - - -) - -const Menu = ({ - href, - title, - icon, -}: { - href: string - title: string - icon: IconType -}) => ( - - - - {title} - - - -) diff --git a/apps/web/app/profile/_components/ProfileMenuItem/ProfileMenuItem.tsx b/apps/web/app/profile/_components/ProfileMenuItem/ProfileMenuItem.tsx new file mode 100644 index 0000000..ae2f1c6 --- /dev/null +++ b/apps/web/app/profile/_components/ProfileMenuItem/ProfileMenuItem.tsx @@ -0,0 +1,19 @@ +import { Icon, IconType } from '@repo/ui/components/Icon' +import { Flex, JustifyBetween } from '@repo/ui/components/Layout' +import { Text } from '@repo/ui/components/Text' + +type Props = { + href: string + title: string + icon: IconType +} + +export const ProfileMenuItem = ({ href, title, icon }: Props) => ( + + + + {title} + + + +) diff --git a/apps/web/app/profile/_components/ProfileMenuItem/index.ts b/apps/web/app/profile/_components/ProfileMenuItem/index.ts new file mode 100644 index 0000000..2c9b103 --- /dev/null +++ b/apps/web/app/profile/_components/ProfileMenuItem/index.ts @@ -0,0 +1 @@ +export { ProfileMenuItem } from './ProfileMenuItem' diff --git a/apps/web/app/profile/_components/UserProfile/UserProfile.tsx b/apps/web/app/profile/_components/UserProfile/UserProfile.tsx new file mode 100644 index 0000000..7f61b19 --- /dev/null +++ b/apps/web/app/profile/_components/UserProfile/UserProfile.tsx @@ -0,0 +1,32 @@ +'use client' + +import { useSuspenseQuery } from '@tanstack/react-query' +import { useUserQueries } from '@/_apis/queries/user' +import { Flex } from '@repo/ui/components/Layout' +import Image from 'next/image' +import { Text } from '@repo/ui/components/Text' + +export const UserProfile = () => { + const { data } = useSuspenseQuery(useUserQueries.detail()) + const { nickname, profileImageUrl, profileBackgroundHexCode } = data + + return ( + + + {'profileImage'} + + + {nickname} + + + ) +} diff --git a/apps/web/app/profile/_components/UserProfile/index.ts b/apps/web/app/profile/_components/UserProfile/index.ts new file mode 100644 index 0000000..331ea78 --- /dev/null +++ b/apps/web/app/profile/_components/UserProfile/index.ts @@ -0,0 +1 @@ +export { UserProfile } from './UserProfile' diff --git a/apps/web/app/profile/page.tsx b/apps/web/app/profile/page.tsx index 2158655..b9b0b42 100644 --- a/apps/web/app/profile/page.tsx +++ b/apps/web/app/profile/page.tsx @@ -1,12 +1,44 @@ +import { CLIENT_PATH } from '@/_constants/path' +import { useUserQueries } from '@/_apis/queries/user' +import { HydrationBoundaryPage } from '@/HydrationBoundaryPage' import { BottomNavigation } from '@/_components/BottomNavigation' import { OnlyLeftHeader } from '@repo/ui/components/Header' -import { ProfilePage } from './ProfilePage' +import { Column } from '@repo/ui/components/Layout' +import { UserProfile } from '@/profile/_components/UserProfile' +import { ProfileMenuItem } from '@/profile/_components/ProfileMenuItem' const Page = () => { return ( <> - + + { + await queryClient.prefetchQuery(useUserQueries.detail()) + }} + > + + + + + + + + ) diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts index 0098c37..246b03f 100644 --- a/apps/web/next.config.ts +++ b/apps/web/next.config.ts @@ -35,6 +35,11 @@ const nextConfig: NextConfig = { hostname: 'example.com', pathname: '/**', }, + { + protocol: 'https', + hostname: process.env.NEXT_PUBLIC_API_URL_HOST || '', //테스트용 주소 + pathname: '/**', + }, ], }, async rewrites() { From d0f99aed44803ccdec7085e902951a7bb83b7c64 Mon Sep 17 00:00:00 2001 From: leeleeleeleejun Date: Thu, 20 Nov 2025 23:17:50 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=EC=B0=9C=ED=95=98=EA=B8=B0,=20?= =?UTF-8?q?=EC=B0=9C=20=EC=B7=A8=EC=86=8C=20=EC=9D=91=EB=8B=B5=20=EC=84=B1?= =?UTF-8?q?=EA=B3=B5=20=EC=8B=9C=20=EC=BF=BC=EB=A6=AC=20=EB=AC=B4=ED=9A=A8?= =?UTF-8?q?=ED=99=94=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/app/_apis/mutations/useAddLike.ts | 15 +++++++++++++-- apps/web/app/_apis/mutations/useRemoveLike.ts | 15 +++++++++++++-- apps/web/app/_apis/services/like.ts | 2 +- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/apps/web/app/_apis/mutations/useAddLike.ts b/apps/web/app/_apis/mutations/useAddLike.ts index 6061277..2a9da92 100644 --- a/apps/web/app/_apis/mutations/useAddLike.ts +++ b/apps/web/app/_apis/mutations/useAddLike.ts @@ -7,8 +7,19 @@ export const useAddLike = () => { return useMutation({ mutationFn: async (id: string) => await addLike(id), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: [...PlaceQueryKeys.byLike()] }) + onSuccess: async (response) => { + const { placeId } = response + + if (!placeId) return + + await Promise.all([ + queryClient.invalidateQueries({ + queryKey: [...PlaceQueryKeys.byLike()], + }), + queryClient.invalidateQueries({ + queryKey: [...PlaceQueryKeys.detail(String(placeId))], + }), + ]) }, // 공통 에러 처리 필요 onError: (error) => console.error(error), diff --git a/apps/web/app/_apis/mutations/useRemoveLike.ts b/apps/web/app/_apis/mutations/useRemoveLike.ts index e8cf24e..2f868c8 100644 --- a/apps/web/app/_apis/mutations/useRemoveLike.ts +++ b/apps/web/app/_apis/mutations/useRemoveLike.ts @@ -7,8 +7,19 @@ export const useRemoveLike = () => { return useMutation({ mutationFn: async (id: string) => await removeLike(id), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: [...PlaceQueryKeys.byLike()] }) + onSuccess: async (response) => { + const { placeId } = response + + if (!placeId) return + + await Promise.all([ + queryClient.invalidateQueries({ + queryKey: [...PlaceQueryKeys.byLike()], + }), + queryClient.invalidateQueries({ + queryKey: [...PlaceQueryKeys.detail(String(placeId))], + }), + ]) }, // 공통 에러 처리 필요 onError: (error) => console.error(error), diff --git a/apps/web/app/_apis/services/like.ts b/apps/web/app/_apis/services/like.ts index 8ed83cf..fc04311 100644 --- a/apps/web/app/_apis/services/like.ts +++ b/apps/web/app/_apis/services/like.ts @@ -2,7 +2,7 @@ import axiosInstance from '@/_lib/axiosInstance' import { API_PATH } from '@/_constants/path' type Response = { - placeId: string + placeId: number message: string } From 91df22cb6731ba44c6609877973fadce40905d77 Mon Sep 17 00:00:00 2001 From: leeleeleeleejun Date: Thu, 20 Nov 2025 23:19:31 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=EA=B0=9C=EC=84=A0=EB=90=9C=20?= =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94=20=EB=B2=84=ED=8A=BC=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B0=8F=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=B2=98=EB=A6=AC=20-=20=EB=82=99=EA=B4=80?= =?UTF-8?q?=EC=A0=81=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=8F=84?= =?UTF-8?q?=EC=9E=85=20(UI=20=EB=A8=BC=EC=A0=80=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=ED=9B=84=20api=EC=8B=A4=ED=96=89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_components/LikeButton/LikeButton.tsx | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/apps/web/app/places/[id]/_components/LikeButton/LikeButton.tsx b/apps/web/app/places/[id]/_components/LikeButton/LikeButton.tsx index 4ad0873..2df55c6 100644 --- a/apps/web/app/places/[id]/_components/LikeButton/LikeButton.tsx +++ b/apps/web/app/places/[id]/_components/LikeButton/LikeButton.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { motion } from 'motion/react' import { Icon } from '@repo/ui/components/Icon' import { useAddLike } from '@/_apis/mutations/useAddLike' @@ -14,20 +14,37 @@ type Props = { export const LikeButton = ({ placeId, initIsLiked }: Props) => { const [isLiked, setIsLiked] = useState(initIsLiked) const [isAnimating, setIsAnimating] = useState(false) - const { mutate: addLike } = useAddLike() - const { mutate: removeLike } = useRemoveLike() - const toggleLikeMutate = isLiked ? removeLike : addLike + const { mutate: addLike, isPending: isAdding } = useAddLike() + const { mutate: removeLike, isPending: isRemoving } = useRemoveLike() + + const isPending = isAdding || isRemoving const onClick = () => { + if (isPending) return + + // 현재 상태 저장 (에러 시 롤백용) + const prevIsLiked = isLiked + // 낙관적 업데이트 (UI 먼저 변경) + const nextIsLiked = !prevIsLiked + setIsLiked(nextIsLiked) + + const toggleLikeMutate = nextIsLiked ? addLike : removeLike + + // 애니메이션 트리거 + if (nextIsLiked) { + setIsAnimating(true) + setTimeout(() => setIsAnimating(false), 200) + } + toggleLikeMutate(placeId, { - onSuccess: () => { - setIsLiked((prev) => !prev) - setIsAnimating(true) - setTimeout(() => setIsAnimating(false), 200) // 0.2초 동안 팝 애니메이션 - }, + onError: () => setIsLiked(prevIsLiked), // 실패 시 롤백 }) } + useEffect(() => { + setIsLiked(initIsLiked) + }, [initIsLiked]) + return ( Date: Thu, 20 Nov 2025 23:47:41 +0900 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20users/me=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/app/_constants/path.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/app/_constants/path.ts b/apps/web/app/_constants/path.ts index 91b8a53..fa65cd6 100644 --- a/apps/web/app/_constants/path.ts +++ b/apps/web/app/_constants/path.ts @@ -45,7 +45,7 @@ export const API_PATH = { `/auth/oauth2?code=${code}&redirectUri=${redirectUri}`, TOKEN: '/auth/token', }, - USER: 'users/me', + USER: '/users/me', } export const CLIENT_PATH = { From 3b6309e8ff979b84ed63c6f1e33808391b70bf90 Mon Sep 17 00:00:00 2001 From: leeleeleeleejun Date: Thu, 20 Nov 2025 23:48:33 +0900 Subject: [PATCH 7/7] feat: update zod import syntax to named import --- apps/web/app/_apis/schemas/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/app/_apis/schemas/user.ts b/apps/web/app/_apis/schemas/user.ts index 8da6727..6fa2f87 100644 --- a/apps/web/app/_apis/schemas/user.ts +++ b/apps/web/app/_apis/schemas/user.ts @@ -1,4 +1,4 @@ -import z from 'zod' +import { z } from 'zod' export const UserSchema = z.object({ nickname: z.string(),