@su-record/vibe 0.4.6 โ 0.4.7
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.
- package/.vibe/rules/core/communication-guide.md +104 -0
- package/.vibe/rules/core/development-philosophy.md +53 -0
- package/.vibe/rules/core/quick-start.md +121 -0
- package/.vibe/rules/languages/dart-flutter.md +509 -0
- package/.vibe/rules/languages/go.md +396 -0
- package/.vibe/rules/languages/java-spring.md +586 -0
- package/.vibe/rules/languages/kotlin-android.md +491 -0
- package/.vibe/rules/languages/python-django.md +371 -0
- package/.vibe/rules/languages/python-fastapi.md +386 -0
- package/.vibe/rules/languages/rust.md +425 -0
- package/.vibe/rules/languages/swift-ios.md +516 -0
- package/.vibe/rules/languages/typescript-nextjs.md +441 -0
- package/.vibe/rules/languages/typescript-node.md +375 -0
- package/.vibe/rules/languages/typescript-react-native.md +446 -0
- package/.vibe/rules/languages/typescript-react.md +525 -0
- package/.vibe/rules/languages/typescript-vue.md +353 -0
- package/.vibe/rules/quality/bdd-contract-testing.md +388 -0
- package/.vibe/rules/quality/checklist.md +276 -0
- package/.vibe/rules/quality/testing-strategy.md +437 -0
- package/.vibe/rules/standards/anti-patterns.md +369 -0
- package/.vibe/rules/standards/code-structure.md +291 -0
- package/.vibe/rules/standards/complexity-metrics.md +312 -0
- package/.vibe/rules/standards/naming-conventions.md +198 -0
- package/.vibe/rules/tools/mcp-hi-ai-guide.md +665 -0
- package/.vibe/rules/tools/mcp-workflow.md +51 -0
- package/package.json +2 -2
|
@@ -0,0 +1,312 @@
|
|
|
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 | ๋ชจ๋ ์์กด์ฑ ์ ํ |
|
|
@@ -0,0 +1,198 @@
|
|
|
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
|
+
```
|