Skip to content

Commit 8547233

Browse files
committed
update post
1 parent 603837b commit 8547233

File tree

4 files changed

+97
-5
lines changed

4 files changed

+97
-5
lines changed

content/posts/프로젝트/당근마켓 클론코딩/당근마켓 클론코딩으로 Validator 사용해보기.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ tags:
55
- validator
66
- zod
77
createdAt: 2025-07-03 13:12:42
8-
modifiedAt: 2025-07-03 19:54:53
8+
modifiedAt: 2025-07-03 21:22:03
99
publish: 프로젝트/당근마켓 클론코딩
1010
related:
1111
- 당근마켓 클론코딩
@@ -44,7 +44,7 @@ isMobilePhone(phone);
4444

4545
### Zod와 함께 사용하기
4646

47-
[[당근마켓 클론코딩으로 Zod 배우기#refine 메소드]]를 활용하면 매우 간편하게 추가적인 유효성 검증을 실행할 수 있다.
47+
[[당근마켓 클론코딩으로 Zod 배우기#refine 메소드|zod의 refine 메소드]]를 활용하면 매우 간편하게 추가적인 유효성 검증을 실행할 수 있다.
4848

4949
```typescript
5050
import { z } from "zod";

public/meta-data.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"tags": ["project", "carrot-market", "validator", "zod"],
1919
"series": "",
2020
"createdAt": "2025-07-03 13:12:42",
21-
"modifiedAt": "2025-07-03 19:54:53",
21+
"modifiedAt": "2025-07-03 21:22:03",
2222
"publish": "프로젝트/당근마켓 클론코딩"
2323
},
2424
{
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"content": "\n# 당근마켓 클론코딩으로 Validator 사용해보기\n\n![validator-landing](_assets/attachments/당근마켓%20클론코딩/validator-landing.png)\n\n## Validator과 함께 사용해보기\n\nValidator라이브러리는 간편하게 유효성 검사를 할 수 있는 프리셋 개념의 함수들을 많이 가지고 있다.\n\n### 설치\n\n`Validator`는 javascript모듈이기 때문에 설치시 추가로 타입 설치를 해주어야 `typescript`에서 불편함 없이 사용할 수 있다\n\n```bash\nbun add Validator\nbun i -D @types/Validator\n```\n\n### 기본 사용법\n\n사용 방식도 매우 간단하다. Validator 모듈 안의 `isMobilePhone`, `isJWT` 등등 값을 넣으면 boolean 값으로 바로 알려준다.\n\n```typescript\nimport { isMobilePhone } from \"Validator\";\n\nconst phone = \"010-1234-1234\";\n\nisMobilePhone(phone);\n```\n\n### Zod와 함께 사용하기\n\n[[당근마켓 클론코딩으로 Zod 배우기#refine 메소드]]를 활용하면 매우 간편하게 추가적인 유효성 검증을 실행할 수 있다.\n\n```typescript\nimport { z } from \"zod\";\nimport validator from \"validator\";\n\nconst phoneSchema = z.string().trim().refine(validator.isMobilePhone);\n```\n",
3-
"plainContent": "Validator라이브러리는 간편하게 유효성 검사를 할 수 있는 프리셋 개념의 함수들을 많이 가지고 있다.\nValidator는 javascript모듈이기 때문에 설치시 추가로 타입 설치를 해주어야 typescript에서 불편함 없이 사용할 수 있다\n사용 방식도 매우 간단하다. Validator 모듈 안의 isMobilePhone, isJWT 등등 값을 넣으면 boolean 값으로 바로 알려준다.\n당근마켓 클론코딩으로 Zod 배우기#refine 메소드를 활용하면 매우 간편하게 추가적인 유효성 검증을 실행할 수 있다."
2+
"content": "\n# 당근마켓 클론코딩으로 Validator 사용해보기\n\n![validator-landing](_assets/attachments/당근마켓%20클론코딩/validator-landing.png)\n\n## Validator과 함께 사용해보기\n\nValidator라이브러리는 간편하게 유효성 검사를 할 수 있는 프리셋 개념의 함수들을 많이 가지고 있다.\n\n### 설치\n\n`Validator`는 javascript모듈이기 때문에 설치시 추가로 타입 설치를 해주어야 `typescript`에서 불편함 없이 사용할 수 있다\n\n```bash\nbun add Validator\nbun i -D @types/Validator\n```\n\n### 기본 사용법\n\n사용 방식도 매우 간단하다. Validator 모듈 안의 `isMobilePhone`, `isJWT` 등등 값을 넣으면 boolean 값으로 바로 알려준다.\n\n```typescript\nimport { isMobilePhone } from \"Validator\";\n\nconst phone = \"010-1234-1234\";\n\nisMobilePhone(phone);\n```\n\n### Zod와 함께 사용하기\n\n[[당근마켓 클론코딩으로 Zod 배우기#refine 메소드|zod의 refine 메소드]]를 활용하면 매우 간편하게 추가적인 유효성 검증을 실행할 수 있다.\n\n```typescript\nimport { z } from \"zod\";\nimport validator from \"validator\";\n\nconst phoneSchema = z.string().trim().refine(validator.isMobilePhone);\n```\n",
3+
"plainContent": "Validator라이브러리는 간편하게 유효성 검사를 할 수 있는 프리셋 개념의 함수들을 많이 가지고 있다.\nValidator는 javascript모듈이기 때문에 설치시 추가로 타입 설치를 해주어야 typescript에서 불편함 없이 사용할 수 있다\n사용 방식도 매우 간단하다. Validator 모듈 안의 isMobilePhone, isJWT 등등 값을 넣으면 boolean 값으로 바로 알려준다.\nzod의 refine 메소드를 활용하면 매우 간편하게 추가적인 유효성 검증을 실행할 수 있다."
44
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# 위키링크 앵커 처리 문제 해결 방안
2+
3+
## 문제 상황
4+
- 현재 위키링크에서 앵커를 처리할 때 h3로 하드코딩되어 있음
5+
- 실제 마크다운 파일에서 "refine 메소드"는 h4 레벨(`####`)로 작성되어 있어 링크가 작동하지 않음
6+
7+
## 조사 결과
8+
9+
### 1. 실제 헤딩 레벨 확인
10+
```markdown
11+
#### refine 메소드 // h4 레벨로 작성됨
12+
```
13+
14+
### 2. 다른 시스템의 접근 방식
15+
- **GitHub**: 헤딩 레벨 prefix 없이 텍스트만으로 ID 생성 (예: `refine-메소드`)
16+
- **Obsidian**: 위키링크에서 헤딩 텍스트만 지정하면 레벨과 무관하게 자동으로 찾음
17+
- **GitLab**: 헤딩 레벨과 무관하게 텍스트 기반 ID 생성
18+
19+
## 구현한 해결 방안: 헤딩 레벨 없이 앵커 사용
20+
21+
### 1. generateHeadingId 함수 수정
22+
```typescript
23+
// 이전 (헤딩 레벨 포함)
24+
export function generateHeadingId(text: string, level: number): string {
25+
const prefix = `h${level}-`;
26+
const slug = text
27+
.toLowerCase()
28+
.replace(/\s+/g, '-')
29+
.replace(/[^\w\-가-힣]/g, '');
30+
return `${prefix}${slug}`;
31+
}
32+
33+
// 수정 후 (헤딩 레벨 옵셔널)
34+
export function generateHeadingId(text: string, level?: number): string {
35+
const slug = text
36+
.toLowerCase()
37+
.replace(/\s+/g, '-')
38+
.replace(/[^\w\-가-힣]/g, '');
39+
40+
return level ? `h${level}-${slug}` : slug;
41+
}
42+
```
43+
44+
### 2. 위키링크 처리 부분 수정
45+
```typescript
46+
// 헤딩 ID 형식으로 변환 (헤딩 레벨 없이 생성)
47+
const headingId = generateHeadingId(anchorText);
48+
fullPath = `${encodedPath}#${headingId}`;
49+
```
50+
51+
### 3. 헤딩 컴포넌트 수정
52+
각 헤딩 컴포넌트(h2, h3, h4)에서 레벨 없이 ID 생성:
53+
```typescript
54+
const id = generateHeadingId(headingText);
55+
```
56+
57+
## 장점
58+
1. **유연성**: 헤딩 레벨이 변경되어도 링크가 깨지지 않음
59+
2. **GitHub 호환성**: GitHub 스타일의 앵커 링크와 유사한 방식
60+
3. **단순성**: 작성자가 헤딩 레벨을 신경 쓸 필요 없음
61+
62+
## 대안 방안들
63+
64+
### 방안 2: 모든 헤딩 레벨에 대해 시도하는 방법
65+
```typescript
66+
// 클라이언트 사이드에서 여러 레벨 시도
67+
const tryLevels = [2, 3, 4, 5, 6];
68+
for (const level of tryLevels) {
69+
const headingId = `h${level}-${slug}`;
70+
const element = document.getElementById(headingId);
71+
if (element) {
72+
element.scrollIntoView();
73+
break;
74+
}
75+
}
76+
```
77+
78+
### 방안 3: 빌드 시점에 헤딩 정보 수집
79+
```typescript
80+
// 빌드 시 모든 헤딩 정보를 수집하여 맵 생성
81+
interface HeadingMap {
82+
[fileName: string]: {
83+
[headingText: string]: {
84+
level: number;
85+
id: string;
86+
}
87+
}
88+
}
89+
```
90+
91+
## 결론
92+
헤딩 레벨 없이 앵커를 사용하는 방안 1을 채택하여 구현했습니다. 이는 가장 단순하면서도 유연한 해결책으로, GitHub와 유사한 방식이며 사용자 경험도 개선됩니다.

0 commit comments

Comments
 (0)