Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .claude/commands/purge-cache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
description: 로컬(.next)과 Vercel의 Data/CDN 캐시를 제거해 stale 데이터를 해소
---

로컬과 Vercel의 캐시를 제거한다. Sanity Studio에서 직접 편집한 내용이 사이트에 반영 안 될 때 사용.

**인자**: `$ARGUMENTS` — `local` | `vercel` | 비어있으면 둘 다.

## 절차

### 로컬 (`local` 또는 인자 없음)

1. `rm -rf .next` 실행 — Next.js Data Cache는 `.next/cache/fetch-cache`에 파일로 저장되므로 dev 서버 재시작만으로는 사라지지 않는다.
2. 실행 후 사용자에게 안내: **dev 서버가 돌고 있었다면 재시작 필요** (`pnpm dev`). Claude가 띄운 서버가 아니면 직접 재시작을 요청한다.

### Vercel (`vercel` 또는 인자 없음)

프로젝트는 `.vercel/project.json`으로 이미 연결되어 있다 (`ram-blog-jul5`).

```bash
vercel cache purge --type data --yes
vercel cache purge --type cdn --yes
```

- Data Cache: `client.fetch`의 `force-cache` 결과 (Sanity 응답) — stale의 주범
- CDN: Full Route Cache로 페이지 자체가 남아있을 수 있어 함께 제거

### 마무리

- 두 명령의 성공 출력(`Successfully purged ...`)을 확인하고 결과를 한 줄로 보고
- 실패 시(로그인 만료 등) `vercel whoami`로 인증 상태를 확인하고 사용자에게 `vercel login` 안내

## 배경

읽기 서비스가 전부 태그 기반 `force-cache`인데, `revalidateTag`는 앱 API mutation에서만 호출된다. Sanity Studio 직접 편집은 어떤 revalidate도 트리거하지 않아 환경별 캐시가 stale해진다 (근본 해결은 Sanity 웹훅 → `/api/revalidate`, 백로그).
5 changes: 0 additions & 5 deletions sanity-studio/schemas/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@ export default {
name: 'image',
type: 'string',
},
{
title: 'Blog Name',
name: 'blogName',
type: 'string',
},
{
title: 'Profile Title',
name: 'title',
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default function Header() {
{params.user ? (
<Link href={`/${params.user}`}>
<h1 className='hidden tablet:block text-xl font-semibold hover:text-indigo-600'>
{userProfile?.blogName}
{userProfile?.title}
</h1>
</Link>
) : (
Expand Down
1 change: 1 addition & 0 deletions src/components/setting/ProfileForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export default function ProfileForm({ userData }: Props) {
.then(() => {
router.refresh();
mutate(`/api/${userData.slug}/me`);
mutate(`/api/${userData.slug}`);
router.push(`/${userData.slug}`);
})
.catch((err) => setError(err.toString()))
Expand Down
6 changes: 1 addition & 5 deletions src/model/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ export type AuthUser = {
image?: string;
};

export type UserData = AuthUser & {
blogName: string;
};
export type UserData = AuthUser;

export type SimpleUser = {
id: string;
Expand All @@ -32,15 +30,13 @@ export type SimpleUser = {
export type ProfileUser = AuthUser & {
following: number;
followers: number;
blogName: string;
title: string;
introduce: string;
links: Links;
posts: number;
};

export type HomeUser = AuthUser & {
blogName: string;
title: string;
introduce: string;
links: Links;
Expand Down
11 changes: 2 additions & 9 deletions src/sanity/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,6 @@ export type User = {
email?: string;
password?: string;
image?: string;
blogName?: string;
title?: string;
introduce?: string;
links?: {
Expand Down Expand Up @@ -884,7 +883,6 @@ export type CheckUsernameValidQueryResult = {
email?: string;
password?: string;
image?: string;
blogName?: string;
title?: string;
introduce?: string;
links?: {
Expand Down Expand Up @@ -931,7 +929,6 @@ export type CheckSlugValidQueryResult = {
email?: string;
password?: string;
image?: string;
blogName?: string;
title?: string;
introduce?: string;
links?: {
Expand Down Expand Up @@ -978,7 +975,6 @@ export type CheckEmailValidQueryResult = {
email?: string;
password?: string;
image?: string;
blogName?: string;
title?: string;
introduce?: string;
links?: {
Expand Down Expand Up @@ -1026,14 +1022,13 @@ export type LoginWithEmailQueryResult = {
// Query: *[_type=='user' && _id == $id][0].slug
export type UserSlugByIdQueryResult = string | null;
// Variable: userDataQuery
// Query: *[_type=='user' && _id == $userId][0] {"id":_id,name,username,email,image,blogName}
// Query: *[_type=='user' && _id == $userId][0] {"id":_id,name,username,email,image}
export type UserDataQueryResult = {
id: string;
name: string | null;
username: string | null;
email: string | null;
image: string | null;
blogName: string | null;
} | null;
// Variable: userBySlugQuery
// Query: *[_type == "user" && slug == $slug][0]{ ..., "id":_id, following[]->{"id":_id,username,slug,name,image,title}, followers[]->{"id":_id,username,slug,name,image,title}, "bookmarks":bookmarks[]->_id }
Expand All @@ -1049,7 +1044,6 @@ export type UserBySlugQueryResult = {
email?: string;
password?: string;
image?: string;
blogName?: string;
title?: string;
introduce?: string;
links?: {
Expand Down Expand Up @@ -1093,7 +1087,6 @@ export type UserForProfileQueryResult = {
email?: string;
password?: string;
image?: string;
blogName?: string;
title?: string;
introduce?: string;
links?: {
Expand Down Expand Up @@ -1143,7 +1136,7 @@ declare module '@sanity/client' {
"\n *[_type=='user' && email == $email][0]\n": CheckEmailValidQueryResult;
'\n *[_type==\'user\' && email == $email][0]{\n "id":_id,\n email,\n name,\n username,\n slug,\n password,\n image,\n }\n': LoginWithEmailQueryResult;
"\n *[_type=='user' && _id == $id][0].slug\n": UserSlugByIdQueryResult;
'\n *[_type==\'user\' && _id == $userId][0]\n {"id":_id,name,username,email,image,blogName}\n': UserDataQueryResult;
'\n *[_type==\'user\' && _id == $userId][0]\n {"id":_id,name,username,email,image}\n': UserDataQueryResult;
'\n *[_type == "user" && slug == $slug][0]{\n ...,\n "id":_id,\n following[]->{"id":_id,username,slug,name,image,title},\n followers[]->{"id":_id,username,slug,name,image,title},\n "bookmarks":bookmarks[]->_id\n }\n': UserBySlugQueryResult;
'\n *[_type==\'user\' && slug == $slug][0]{\n ...,\n "id":_id,\n "following":count(following),\n "followers":count(followers),\n "posts":count(*[_type=="post" && author->slug == $slug])\n }\n': UserForProfileQueryResult;
}
Expand Down
8 changes: 2 additions & 6 deletions src/service/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const userSlugByIdQuery = defineQuery(`

const userDataQuery = defineQuery(`
*[_type=='user' && _id == $userId][0]
{"id":_id,name,username,email,image,blogName}
{"id":_id,name,username,email,image}
`);

const userBySlugQuery = defineQuery(`
Expand Down Expand Up @@ -72,7 +72,6 @@ export async function addUser({
email,
name,
image,
blogName: name,
title: `${name}`,
introduce: `안녕하세요 ${name}의 멋진 블로그입니다 :)`,
following: [],
Expand Down Expand Up @@ -101,7 +100,6 @@ export async function addEmailUser({
password,
name,
image: '',
blogName: name,
title: `${name}`,
introduce: `안녕하세요 ${name}의 멋진 블로그입니다 :)`,
following: [],
Expand Down Expand Up @@ -200,7 +198,7 @@ export async function getUserBySlug(slug: string): Promise<HomeUser | null> {
{ slug },
{
cache: 'force-cache',
next: { tags: ['following', 'bookmark'] },
next: { tags: ['following', 'bookmark', `profile/${slug}`] },
}
);

Expand All @@ -213,7 +211,6 @@ export async function getUserBySlug(slug: string): Promise<HomeUser | null> {
slug: user.slug ?? '',
email: user.email ?? '',
image: user.image,
blogName: user.blogName ?? '',
title: user.title ?? '',
introduce: user.introduce ?? '',
links: user.links ?? defaultLinks,
Expand Down Expand Up @@ -246,7 +243,6 @@ export async function getUserForProfile(
image: user.image,
following: user.following ?? 0,
followers: user.followers ?? 0,
blogName: user.blogName ?? '',
title: user.title ?? '',
introduce: user.introduce ?? '',
links: user.links ?? defaultLinks,
Expand Down
Loading