@su-record/vibe 0.4.5 โ†’ 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.claude/agents/simplifier.md +1 -1
  2. package/.claude/commands/vibe.analyze.md +1 -1
  3. package/.claude/commands/vibe.run.md +1 -1
  4. package/.claude/commands/vibe.spec.md +2 -2
  5. package/.claude/commands/vibe.verify.md +1 -1
  6. package/.claude/settings.local.json +3 -1
  7. package/README.md +4 -4
  8. package/bin/vibe +41 -13
  9. package/package.json +1 -1
  10. package/templates/hooks-template.json +1 -1
  11. package/.agent/rules/core/communication-guide.md +0 -104
  12. package/.agent/rules/core/development-philosophy.md +0 -53
  13. package/.agent/rules/core/quick-start.md +0 -121
  14. package/.agent/rules/languages/dart-flutter.md +0 -509
  15. package/.agent/rules/languages/go.md +0 -396
  16. package/.agent/rules/languages/java-spring.md +0 -586
  17. package/.agent/rules/languages/kotlin-android.md +0 -491
  18. package/.agent/rules/languages/python-django.md +0 -371
  19. package/.agent/rules/languages/python-fastapi.md +0 -386
  20. package/.agent/rules/languages/rust.md +0 -425
  21. package/.agent/rules/languages/swift-ios.md +0 -516
  22. package/.agent/rules/languages/typescript-nextjs.md +0 -441
  23. package/.agent/rules/languages/typescript-node.md +0 -375
  24. package/.agent/rules/languages/typescript-react-native.md +0 -446
  25. package/.agent/rules/languages/typescript-react.md +0 -525
  26. package/.agent/rules/languages/typescript-vue.md +0 -353
  27. package/.agent/rules/quality/bdd-contract-testing.md +0 -388
  28. package/.agent/rules/quality/checklist.md +0 -276
  29. package/.agent/rules/quality/testing-strategy.md +0 -437
  30. package/.agent/rules/standards/anti-patterns.md +0 -369
  31. package/.agent/rules/standards/code-structure.md +0 -291
  32. package/.agent/rules/standards/complexity-metrics.md +0 -312
  33. package/.agent/rules/standards/naming-conventions.md +0 -198
  34. package/.agent/rules/tools/mcp-hi-ai-guide.md +0 -665
  35. package/.agent/rules/tools/mcp-workflow.md +0 -51
@@ -1,312 +0,0 @@
1
- # ๐Ÿ”ฌ ์†Œํ”„ํŠธ์›จ์–ด ์—”์ง€๋‹ˆ์–ด๋ง ๋ณต์žก๋„ ์ธก์ •
2
-
3
- ## 4.1 ๋ณต์žก๋„ ๋ฉ”ํŠธ๋ฆญ
4
-
5
- ### Cyclomatic Complexity (์ˆœํ™˜ ๋ณต์žก๋„)
6
-
7
- **์ •์˜**: ์ฝ”๋“œ์˜ ๋…๋ฆฝ์ ์ธ ์‹คํ–‰ ๊ฒฝ๋กœ ์ˆ˜
8
-
9
- **๋ชฉํ‘œ**: โ‰ค 10
10
-
11
- ```typescript
12
- // โŒ ๋†’์€ ์ˆœํ™˜ ๋ณต์žก๋„ (6)
13
- function processUser(user) {
14
- if (user.isActive) { // +1
15
- if (user.hasPermission) { // +1
16
- if (user.email) { // +1
17
- if (user.verified) { // +1
18
- return processData();
19
- }
20
- }
21
- }
22
- }
23
- return null;
24
- }
25
-
26
- // โœ… ๋‚ฎ์€ ์ˆœํ™˜ ๋ณต์žก๋„ (4) - Early returns ์‚ฌ์šฉ
27
- function processUser(user) {
28
- if (!user.isActive) return null; // +1
29
- if (!user.hasPermission) return null; // +1
30
- if (!user.email) return null; // +1
31
- if (!user.verified) return null; // +1
32
-
33
- return processData();
34
- }
35
- ```
36
-
37
- ### Cognitive Complexity (์ธ์ง€ ๋ณต์žก๋„)
38
-
39
- **์ •์˜**: ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ •์‹ ์  ๋…ธ๋ ฅ
40
-
41
- **๋ชฉํ‘œ**: โ‰ค 15
42
-
43
- ```typescript
44
- // โŒ ๋†’์€ ์ธ์ง€ ๋ณต์žก๋„
45
- function calculateDiscount(user, items) {
46
- let discount = 0;
47
- if (user.isPremium) { // +1
48
- for (let item of items) { // +1 (nesting)
49
- if (item.category === 'electronics') { // +2 (nested if)
50
- discount += item.price * 0.1;
51
- } else if (item.category === 'books') { // +1
52
- discount += item.price * 0.05;
53
- }
54
- }
55
- }
56
- return discount;
57
- }
58
-
59
- // โœ… ๋‚ฎ์€ ์ธ์ง€ ๋ณต์žก๋„ - ํ•จ์ˆ˜ ๋ถ„๋ฆฌ
60
- function calculateDiscount(user, items) {
61
- if (!user.isPremium) return 0; // +1
62
- return items.reduce((total, item) => total + getItemDiscount(item), 0);
63
- }
64
-
65
- function getItemDiscount(item) {
66
- const discountRates = {
67
- electronics: 0.1,
68
- books: 0.05,
69
- };
70
- return item.price * (discountRates[item.category] || 0);
71
- }
72
- ```
73
-
74
- ### Halstead Metrics (ํ• ์Šคํ…Œ๋“œ ๋ฉ”ํŠธ๋ฆญ)
75
-
76
- **์ธก์ • ํ•ญ๋ชฉ**:
77
- - **Operators**: ์—ฐ์‚ฐ์ž (=, +, -, *, if, for ๋“ฑ)
78
- - **Operands**: ํ”ผ์—ฐ์‚ฐ์ž (๋ณ€์ˆ˜, ์ƒ์ˆ˜, ํ•จ์ˆ˜๋ช…)
79
- - **Vocabulary**: ๊ณ ์œ  ์—ฐ์‚ฐ์ž + ๊ณ ์œ  ํ”ผ์—ฐ์‚ฐ์ž
80
- - **Length**: ์ „์ฒด ํ† ํฐ ์ˆ˜
81
- - **Difficulty**: ์ฝ”๋“œ ์ดํ•ด ๋‚œ์ด๋„
82
- - **Effort**: ์ฝ”๋“œ ์ž‘์„ฑ์— ํ•„์š”ํ•œ ์ •์‹ ์  ๋…ธ๋ ฅ
83
-
84
- ```typescript
85
- // Halstead ๋ฉ”ํŠธ๋ฆญ ์ธก์ • ์˜ˆ์‹œ
86
- function calculateArea(radius: number): number {
87
- const pi = 3.14159;
88
- return pi * radius * radius;
89
- }
90
-
91
- /*
92
- Operators: =, *, const, function, :, return (6๊ฐœ)
93
- Operands: calculateArea, radius, number, pi, 3.14159 (5๊ฐœ)
94
- Vocabulary: 6 + 5 = 11
95
- Length: ์ „์ฒด ํ† ํฐ ์ˆ˜
96
- Difficulty: Vocabulary์™€ operand ๋ฐ˜๋ณต์œผ๋กœ ๊ณ„์‚ฐ
97
- Effort: Difficulty ร— Volume
98
- */
99
- ```
100
-
101
- ## 4.2 ๊ฒฐํ•ฉ๋„ & ์‘์ง‘๋„
102
-
103
- ### ๋А์Šจํ•œ ๊ฒฐํ•ฉ (Loose Coupling)
104
-
105
- **๋ชฉํ‘œ**: ๋ชจ๋“ˆ ๊ฐ„ ์˜์กด์„ฑ ์ตœ์†Œํ™”
106
-
107
- ```typescript
108
- // โŒ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ - ์ง์ ‘ ์˜์กด์„ฑ
109
- class UserService {
110
- constructor() {
111
- this.database = new PostgreSQLDatabase(); // ์ง์ ‘ ์˜์กด
112
- this.emailService = new SendGridEmail(); // ์ง์ ‘ ์˜์กด
113
- }
114
- }
115
-
116
- // โœ… ๋А์Šจํ•œ ๊ฒฐํ•ฉ - ์˜์กด์„ฑ ์ฃผ์ž…
117
- interface IDatabase {
118
- save(data: unknown): Promise<void>;
119
- load(id: string): Promise<unknown>;
120
- }
121
-
122
- interface IEmailService {
123
- send(to: string, message: string): Promise<void>;
124
- }
125
-
126
- class UserService {
127
- constructor(
128
- private database: IDatabase,
129
- private emailService: IEmailService
130
- ) {}
131
- }
132
-
133
- // ์‚ฌ์šฉ
134
- const userService = new UserService(
135
- new PostgreSQLDatabase(),
136
- new SendGridEmail()
137
- );
138
- ```
139
-
140
- ### ๋†’์€ ์‘์ง‘๋„ (High Cohesion)
141
-
142
- **๋ชฉํ‘œ**: ๊ด€๋ จ๋œ ๊ธฐ๋Šฅ๋งŒ ๋ชจ์Œ
143
-
144
- ```typescript
145
- // โŒ ๋‚ฎ์€ ์‘์ง‘๋„ - ๊ด€๋ จ ์—†๋Š” ๊ธฐ๋Šฅ๋“ค
146
- class Utils {
147
- validateEmail(email: string) { /* */ }
148
- formatCurrency(amount: number) { /* */ }
149
- sendNotification(message: string) { /* */ }
150
- calculateTax(income: number) { /* */ }
151
- }
152
-
153
- // โœ… ๋†’์€ ์‘์ง‘๋„ - ๊ด€๋ จ ๊ธฐ๋Šฅ๋งŒ
154
- class EmailValidator {
155
- validateFormat(email: string) { /* */ }
156
- validateDomain(email: string) { /* */ }
157
- validateMX(email: string) { /* */ }
158
- }
159
-
160
- class CurrencyFormatter {
161
- formatKRW(amount: number) { /* */ }
162
- formatUSD(amount: number) { /* */ }
163
- parseAmount(formatted: string) { /* */ }
164
- }
165
-
166
- class TaxCalculator {
167
- calculateIncomeTax(income: number) { /* */ }
168
- calculateVAT(amount: number) { /* */ }
169
- calculateTotal(income: number) { /* */ }
170
- }
171
- ```
172
-
173
- ## ๋ณต์žก๋„ ๊ฐ์†Œ ์ „๋žต
174
-
175
- ### 1. Early Return ํŒจํ„ด
176
-
177
- ```typescript
178
- // โŒ ์ค‘์ฒฉ๋œ if๋ฌธ
179
- function processOrder(order: Order) {
180
- if (order) {
181
- if (order.isValid) {
182
- if (order.items.length > 0) {
183
- if (order.user.isActive) {
184
- return processItems(order.items);
185
- }
186
- }
187
- }
188
- }
189
- return null;
190
- }
191
-
192
- // โœ… Early return
193
- function processOrder(order: Order) {
194
- if (!order) return null;
195
- if (!order.isValid) return null;
196
- if (order.items.length === 0) return null;
197
- if (!order.user.isActive) return null;
198
-
199
- return processItems(order.items);
200
- }
201
- ```
202
-
203
- ### 2. ์ „๋žต ํŒจํ„ด (Strategy Pattern)
204
-
205
- ```typescript
206
- // โŒ ๋ณต์žกํ•œ if-else ์ฒด์ธ
207
- function calculateShipping(type: string, weight: number) {
208
- if (type === 'express') {
209
- return weight * 5 + 10;
210
- } else if (type === 'standard') {
211
- return weight * 3 + 5;
212
- } else if (type === 'economy') {
213
- return weight * 2;
214
- }
215
- return 0;
216
- }
217
-
218
- // โœ… ์ „๋žต ํŒจํ„ด
219
- interface ShippingStrategy {
220
- calculate(weight: number): number;
221
- }
222
-
223
- class ExpressShipping implements ShippingStrategy {
224
- calculate(weight: number) {
225
- return weight * 5 + 10;
226
- }
227
- }
228
-
229
- class StandardShipping implements ShippingStrategy {
230
- calculate(weight: number) {
231
- return weight * 3 + 5;
232
- }
233
- }
234
-
235
- const strategies: Record<string, ShippingStrategy> = {
236
- express: new ExpressShipping(),
237
- standard: new StandardShipping(),
238
- };
239
-
240
- function calculateShipping(type: string, weight: number) {
241
- const strategy = strategies[type];
242
- return strategy ? strategy.calculate(weight) : 0;
243
- }
244
- ```
245
-
246
- ### 3. ํ•จ์ˆ˜ ์ถ”์ถœ (Extract Function)
247
-
248
- ```typescript
249
- // โŒ ๊ธด ํ•จ์ˆ˜
250
- function processUserRegistration(userData: UserData) {
251
- // 20์ค„: ์ด๋ฉ”์ผ ๊ฒ€์ฆ
252
- // 15์ค„: ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•ด์‹ฑ
253
- // 10์ค„: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ €์žฅ
254
- // 5์ค„: ํ™˜์˜ ์ด๋ฉ”์ผ ๋ฐœ์†ก
255
- }
256
-
257
- // โœ… ํ•จ์ˆ˜ ์ถ”์ถœ
258
- function processUserRegistration(userData: UserData) {
259
- validateEmail(userData.email);
260
- const hashedPassword = hashPassword(userData.password);
261
- const user = saveToDatabase({ ...userData, password: hashedPassword });
262
- sendWelcomeEmail(user.email);
263
- return user;
264
- }
265
-
266
- function validateEmail(email: string) { /* ... */ }
267
- function hashPassword(password: string) { /* ... */ }
268
- function saveToDatabase(data: UserData) { /* ... */ }
269
- function sendWelcomeEmail(email: string) { /* ... */ }
270
- ```
271
-
272
- ## ์ธก์ • ๋„๊ตฌ
273
-
274
- ### TypeScript/JavaScript
275
-
276
- ```bash
277
- # ESLint (๋ณต์žก๋„ ์ธก์ • ํ”Œ๋Ÿฌ๊ทธ์ธ)
278
- npm install eslint-plugin-complexity
279
-
280
- # .eslintrc.js
281
- {
282
- "rules": {
283
- "complexity": ["error", 10],
284
- "max-depth": ["error", 3],
285
- "max-lines-per-function": ["error", 20]
286
- }
287
- }
288
- ```
289
-
290
- ### Python
291
-
292
- ```bash
293
- # Radon (๋ณต์žก๋„ ์ธก์ • ๋„๊ตฌ)
294
- pip install radon
295
-
296
- # Cyclomatic Complexity
297
- radon cc app/ -a -nc
298
-
299
- # Maintainability Index
300
- radon mi app/
301
- ```
302
-
303
- ## ๋ชฉํ‘œ ๋ฉ”ํŠธ๋ฆญ ์š”์•ฝ
304
-
305
- | ๋ฉ”ํŠธ๋ฆญ | ๋ชฉํ‘œ | ์„ค๋ช… |
306
- |--------|------|------|
307
- | Cyclomatic Complexity | โ‰ค 10 | ๋…๋ฆฝ์  ์‹คํ–‰ ๊ฒฝ๋กœ |
308
- | Cognitive Complexity | โ‰ค 15 | ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›€ |
309
- | Function Length | โ‰ค 20 lines | ์งง๊ณ  ์ง‘์ค‘๋œ ํ•จ์ˆ˜ |
310
- | Nesting Depth | โ‰ค 3 levels | ํ‰ํƒ„ํ•œ ๊ตฌ์กฐ |
311
- | Parameters | โ‰ค 5 | ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ œํ•œ |
312
- | Dependencies | โ‰ค 7 | ๋ชจ๋“ˆ ์˜์กด์„ฑ ์ œํ•œ |
@@ -1,198 +0,0 @@
1
- # ๐Ÿ“– ์ž๋™ ๋„ค์ด๋ฐ ๊ทœ์น™
2
-
3
- ## ๊ธฐ๋ณธ ๊ทœ์น™
4
-
5
- ```
6
- ๋ณ€์ˆ˜: ๋ช…์‚ฌ (userList, userData)
7
- ํ•จ์ˆ˜: ๋™์‚ฌ+๋ช…์‚ฌ (fetchData, updateUser)
8
- ์ด๋ฒคํŠธ: handle ์ ‘๋‘์‚ฌ (handleClick, handleSubmit)
9
- Boolean: is/has/can ์ ‘๋‘์‚ฌ (isLoading, hasError, canEdit)
10
- ์ƒ์ˆ˜: UPPER_SNAKE_CASE (MAX_RETRY_COUNT, API_TIMEOUT)
11
- ์ปดํฌ๋„ŒํŠธ: PascalCase (UserProfile, HeaderSection)
12
- ํ›…: use ์ ‘๋‘์‚ฌ (useUserData, useAuth)
13
- ```
14
-
15
- ## ๋ณ€์ˆ˜ ๋„ค์ด๋ฐ
16
-
17
- ### โœ… ์ข‹์€ ์˜ˆ
18
-
19
- ```typescript
20
- const userList = [...];
21
- const totalAmount = 0;
22
- const currentPage = 1;
23
- ```
24
-
25
- ### โŒ ๋‚˜์œ ์˜ˆ
26
-
27
- ```typescript
28
- const list = [...]; // ๋ฌด์—‡์˜ ๋ฆฌ์ŠคํŠธ?
29
- const total = 0; // ๋ฌด์—‡์˜ ์ดํ•ฉ?
30
- const page = 1; // ๋ช…ํ™•ํ•˜์ง€ ์•Š์Œ
31
- ```
32
-
33
- ## ํ•จ์ˆ˜ ๋„ค์ด๋ฐ
34
-
35
- ### โœ… ์ข‹์€ ์˜ˆ
36
-
37
- ```typescript
38
- function fetchUserData() { }
39
- function updateProfile() { }
40
- function validateEmail() { }
41
- function calculateTotal() { }
42
- ```
43
-
44
- ### โŒ ๋‚˜์œ ์˜ˆ
45
-
46
- ```typescript
47
- function user() { } // ๋™์‚ฌ ์—†์Œ
48
- function data() { } // ๋ถˆ๋ช…ํ™•
49
- function process() { } // ๋ฌด์—‡์„ ์ฒ˜๋ฆฌ?
50
- ```
51
-
52
- ## ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
53
-
54
- ### โœ… ์ข‹์€ ์˜ˆ
55
-
56
- ```typescript
57
- function handleClick() { }
58
- function handleSubmit() { }
59
- function handleInputChange() { }
60
- ```
61
-
62
- ### โŒ ๋‚˜์œ ์˜ˆ
63
-
64
- ```typescript
65
- function onClick() { } // handle ์ ‘๋‘์‚ฌ ๊ถŒ์žฅ
66
- function submit() { } // ์ด๋ฒคํŠธ์ž„์ด ๋ถˆ๋ช…ํ™•
67
- function change() { } // ๋ฌด์—‡์˜ ๋ณ€๊ฒฝ?
68
- ```
69
-
70
- ## Boolean ๋ณ€์ˆ˜
71
-
72
- ### โœ… ์ข‹์€ ์˜ˆ
73
-
74
- ```typescript
75
- const isLoading = false;
76
- const hasError = false;
77
- const canEdit = true;
78
- const shouldUpdate = false;
79
- ```
80
-
81
- ### โŒ ๋‚˜์œ ์˜ˆ
82
-
83
- ```typescript
84
- const loading = false; // is ์ ‘๋‘์‚ฌ ๊ถŒ์žฅ
85
- const error = false; // has ๊ถŒ์žฅ
86
- const editable = true; // can ๊ถŒ์žฅ
87
- ```
88
-
89
- ## ์ƒ์ˆ˜
90
-
91
- ### โœ… ์ข‹์€ ์˜ˆ
92
-
93
- ```typescript
94
- const MAX_RETRY_COUNT = 3;
95
- const API_TIMEOUT_MS = 5000;
96
- const DEFAULT_PAGE_SIZE = 20;
97
- ```
98
-
99
- ### โŒ ๋‚˜์œ ์˜ˆ
100
-
101
- ```typescript
102
- const maxRetry = 3; // UPPER_SNAKE_CASE ์‚ฌ์šฉ
103
- const timeout = 5000; // ๋‹จ์œ„ ๋ช…์‹œ ๋ถ€์กฑ
104
- ```
105
-
106
- ## ์ปดํฌ๋„ŒํŠธ & ํด๋ž˜์Šค
107
-
108
- ### โœ… ์ข‹์€ ์˜ˆ
109
-
110
- ```typescript
111
- class UserProfile { }
112
- class DataRepository { }
113
- function ProfileCard() { }
114
- function NavigationBar() { }
115
- ```
116
-
117
- ### โŒ ๋‚˜์œ ์˜ˆ
118
-
119
- ```typescript
120
- class userProfile { } // PascalCase ์‚ฌ์šฉ
121
- class data { } // ๋ถˆ๋ช…ํ™•
122
- function profile() { } // PascalCase ๊ถŒ์žฅ
123
- ```
124
-
125
- ## ์ปค์Šคํ…€ ํ›… (React)
126
-
127
- ### โœ… ์ข‹์€ ์˜ˆ
128
-
129
- ```typescript
130
- function useUserData() { }
131
- function useAuth() { }
132
- function useLocalStorage() { }
133
- ```
134
-
135
- ### โŒ ๋‚˜์œ ์˜ˆ
136
-
137
- ```typescript
138
- function getUserData() { } // use ์ ‘๋‘์‚ฌ ํ•„์ˆ˜
139
- function auth() { } // use ์ ‘๋‘์‚ฌ ํ•„์ˆ˜
140
- ```
141
-
142
- ## ํƒ€์ž… & ์ธํ„ฐํŽ˜์ด์Šค (TypeScript)
143
-
144
- ### โœ… ์ข‹์€ ์˜ˆ
145
-
146
- ```typescript
147
- interface User { }
148
- type UserRole = 'admin' | 'user';
149
- interface ApiResponse<T> { }
150
- ```
151
-
152
- ### โŒ ๋‚˜์œ ์˜ˆ
153
-
154
- ```typescript
155
- interface IUser { } // I ์ ‘๋‘์‚ฌ ๋ถˆํ•„์š” (TypeScript)
156
- type user = { }; // PascalCase ์‚ฌ์šฉ
157
- ```
158
-
159
- ## ํŒŒ์ผ ๋„ค์ด๋ฐ
160
-
161
- ### โœ… ์ข‹์€ ์˜ˆ
162
-
163
- ```
164
- user-profile.component.tsx
165
- user.service.ts
166
- auth.utils.ts
167
- constants.ts
168
- ```
169
-
170
- ### โŒ ๋‚˜์œ ์˜ˆ
171
-
172
- ```
173
- UserProfile.tsx // kebab-case ๊ถŒ์žฅ
174
- user_service.ts // kebab-case ๊ถŒ์žฅ
175
- utils.ts // ๋ถˆ๋ช…ํ™•
176
- ```
177
-
178
- ## ์•ฝ์–ด ์‚ฌ์šฉ ์›์น™
179
-
180
- - ์ผ๋ฐ˜์ ์ธ ์•ฝ์–ด๋งŒ ์‚ฌ์šฉ (URL, API, ID, HTML, CSS)
181
- - ํ”„๋กœ์ ํŠธ ํŠน์ • ์•ฝ์–ด๋Š” ๋ฌธ์„œํ™” ํ•„์ˆ˜
182
- - ์˜๋ฏธ๊ฐ€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์œผ๋ฉด ์ „์ฒด ๋‹จ์–ด ์‚ฌ์šฉ
183
-
184
- ### โœ… ์ข‹์€ ์˜ˆ
185
-
186
- ```typescript
187
- const userId = '123';
188
- const apiEndpoint = '/users';
189
- const htmlContent = '<div>';
190
- ```
191
-
192
- ### โŒ ๋‚˜์œ ์˜ˆ
193
-
194
- ```typescript
195
- const usrId = '123'; // ๋ถˆ๋ช…ํ™•ํ•œ ์•ฝ์–ด
196
- const endpt = '/users'; // ๊ณผ๋„ํ•œ ์ถ•์•ฝ
197
- const cnt = '<div>'; // content๋กœ ๋ช…ํ™•ํžˆ
198
- ```