์ฌ์ฌ์ฉ ์ฝ๋ ์ฝ๋ฉ ์ปจ๋ฒค์
02-reusable-code/(TypeScript/React),02-reusable-code-python/(Python),02-reusable-code-java/(Java/Spring Boot) ๊ณตํต ๊ท์น
๊ณตํต ๊ท์น
ํ์ผ ๋ฉํ๋ฐ์ดํฐ
๋ชจ๋ ์ปค์คํ ํ์ผ์ ์ถ์ฒยท๋ฒ์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ค.
TypeScript โ JSDoc ํค๋:
/**
* ํ์ผ ์ค๋ช
*
* @source ์ถ์ฒ-ํ๋ก์ ํธ๋ช
* @extracted YYYY-MM-DD
* @version X.Y.Z
*
* @dependencies ์์กด์ฑ ๋ชฉ๋ก
*/
Python โ ๋ชจ๋ ๋ ์คํธ๋ง:
"""
ํ์ค ์์ฝ - ๋ชจ๋์ ํต์ฌ ๊ธฐ๋ฅ ์ค๋ช
@source ์ถ์ฒ-ํ๋ก์ ํธ๋ช
@extracted YYYY-MM-DD
@version X.Y.Z
์์กด์ฑ:
- ํจํค์ง๋ช
(ํ์/๊ถ์ฅ/์ ํ)
- ํจํค์ง๋ช
(pip install ํจํค์ง๋ช
)
์ฌ์ฉ๋ฒ:
from module import function
result = function(args)
"""
@source: ์ฝ๋๊ฐ ์ถ์ถ๋ ์๋ณธ ํ๋ก์ ํธ๋ช@extracted: ์ถ์ถ ๋ ์ง@version: ์๋งจํฑ ๋ฒ์ - Python์ ์์กด์ฑ(ํ์/๊ถ์ฅ/์ ํ ๊ตฌ๋ถ)๊ณผ ์ฌ์ฉ๋ฒ(์ต์ 1๊ฐ ์คํ ๊ฐ๋ฅ ์์ ) ํฌํจ
์ฃผ์ ์ธ์ด
- ํ๊ตญ์ด ์ฌ์ฉ
- ์๋ฌ ๋ฉ์์ง ๋ฌธ์์ด์ ์์ด ํ์ฉ
import ์์ ์์น
๊ทธ๋ฃน ๊ฐ ๋น ์ค๋ก ๊ตฌ๋ถ:
| ์์ | TypeScript | Python |
|---|---|---|
| 1 | ์ธ๋ถ ํจํค์ง | ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ |
| 2 | type import | ์๋ํํฐ |
| 3 | ์๋ ๊ฒฝ๋ก | ๋ก์ปฌ |
TypeScript / React ๊ท์น
์ผ๋ฐ ๊ท์น
| ํญ๋ชฉ | ๊ท์น | ๋น๊ณ |
|---|---|---|
| ๋ฐ์ดํ | ์ปค์คํ
์ฝ๋: ์์๋ฐ์ดํ ' / shadcn: ํฐ๋ฐ์ดํ " ์ ์ง | shadcn ์ ์คํธ๋ฆผ ์ ์ง |
| ์ธ๋ฏธ์ฝ๋ก | ์ปค์คํ ์ฝ๋: ์ฌ์ฉ / shadcn: ์๋ต ์ ์ง | |
| export ํจํด | export function, export const (Named Export๋ง) | export default ์ง์ |
| type vs interface | ๊ฐ์ฒด ํํ: interface / ์ ๋์จยท์ ํธ๋ฆฌํฐ: type | |
| type import | import type { X } (์ต์์ ๋ถ๋ฆฌ) | import { type X } ์ง์ |
| ์ปดํฌ๋ํธ ์ ์ธ | export function ComponentName() | ํ์ดํ ํจ์ ์ง์ |
| ํ์ผ๋ช | hooks: camelCase (useDebounce.ts) / ๋๋จธ์ง: kebab-case | |
| ์น์ ๊ตฌ๋ถ์ | // ============================================ | ์ ๋์ฝ๋ ๋ฐ์ค๋ฌธ์ ์ง์ |
| 'use client' | ์ปค์คํ
: 'use client'; / shadcn: "use client" |
shadcn ์ปดํฌ๋ํธ ์์ธ ์ ์ฑ
01-ui-components/shadcn-*ํ์ ๊ฐ๋ณ ์ปดํฌ๋ํธ ํ์ผ์ ์ ์คํธ๋ฆผ ์คํ์ผ ์ ์ง- ์ด์ : ํฅํ ์ ์คํธ๋ฆผ ์ ๋ฐ์ดํธ ์ diff/merge ์ฉ์ด
index.ts๋ฐฐ๋ด ํ์ผ๋ง ํ๊ตญ์ด ์ฃผ์ + ์ถ์ฒ ํ์
Python ๊ท์น
import ์์
PEP8 ๊ธฐ์ค, ๊ทธ๋ฃน ๊ฐ ๋น ์ค:
# 1. ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ
import logging
import zipfile
from pathlib import Path
# 2. ์๋ํํฐ
import numpy as np
import pandas as pd
# 3. ๋ก์ปฌ
from .utils import helper_function
ํ์ ํํธ
Python 3.10+ ๋ด์ฅ ํ์ ๋ฌธ๋ฒ ์ฌ์ฉ:
# ์ฌ๋ฐ๋ฅธ ์
def process(items: list[str]) -> dict[str, int]: ...
def load(path: str | Path) -> bytes | None: ...
# ๊ธ์ง (๊ตฌ์)
from typing import Dict, List, Tuple, Union
dict,list,tuple,setโ ๋ด์ฅ ํ์ ์ฌ์ฉUnion[A, B]โA | B์ฌ์ฉOptional[T]โT | None์ฌ์ฉAnyโ typing์์ import ํ์ฉ (๋์ ์์)
๋ ์คํธ๋ง (ํจ์/ํด๋์ค)
Google ์คํ์ผ, ํ๊ตญ์ด:
def function_name(param: str, count: int = 0) -> list[str]:
"""ํจ์ ํ์ค ์์ฝ
Args:
param: ๋งค๊ฐ๋ณ์ ์ค๋ช
count: ๋งค๊ฐ๋ณ์ ์ค๋ช
(๊ธฐ๋ณธ๊ฐ: 0)
Returns:
๋ฐํ๊ฐ ์ค๋ช
Raises:
ValueError: ๋ฐ์ ์กฐ๊ฑด
"""
๋ก๊น
๋ชจ๋ ๋ชจ๋์ ๋ก๊ฑฐ ์ค์ :
import logging
logger = logging.getLogger(__name__)
- ๋ฉ์์ง๋ ํ๊ตญ์ด
print()๊ธ์ง (__main__๋ธ๋ก ์ ์ธ)- ๋ ๋ฒจ:
debug(๋๋ฒ๊ทธ),info(์ ์ ๋์),warning(์ฃผ์),error(์ค๋ฅ)
์๋ฌ ์ฒ๋ฆฌ
try:
result = risky_operation()
except SpecificError as e:
logger.error("์์
์คํจ: %s", e)
raise # ๋๋ ์ ์ ํ ๋ณต๊ตฌ
- ๋ฒ์ฉ
except Exception์ต์ํ - ๋ฆฌ์์ค๋
try/finally๋๋ ์ปจํ ์คํธ ๋งค๋์ ๋ก ๋ฐ๋์ ์ ๋ฆฌ - ํ์ผ ์กด์ฌ/์ ํจ์ฑ ๊ฒ์ฆ์ ํธ์ถ์ ์ฑ ์ (๋ชจ๋ ๋ด๋ถ์์ ์ค๋ณต ๊ฒ์ฆํ์ง ์์)
๋ค์ด๋ฐ ๊ท์น
| ๋์ | ๊ท์น | ์์ |
|---|---|---|
| ํจ์/๋ณ์ | snake_case | read_excel_file, file_path |
| ํด๋์ค | PascalCase | WhisperSTTEngine, SQLiteSessionManager |
| ์์ | UPPER_SNAKE_CASE | MIMETYPE, VERSION_XML |
| ํ๋ผ์ด๋น | _ ์ ๋์ฌ | _instance, _parse_row |
๋ฐ์ดํ
- ํฐ๋ฐ์ดํ
"์ฌ์ฉ
์ค ๊ธธ์ด
- ๊ธฐ์ค: 88์ (Black ๊ธฐ๋ณธ๊ฐ)
- ํจ์ ์๊ทธ๋์ฒ๊ฐ ๊ธธ ๊ฒฝ์ฐ ๋งค๊ฐ๋ณ์๋ณ ์ค๋ฐ๊ฟ:
def generate_section_xml(
title: str,
content: str,
tables: list[dict[str, Any]] | None = None,
header_org: str = "๊ธฐ๋ณธ๊ฐ",
) -> str:
__init__.py
- ๋ช
์์ import +
__all__๋ฆฌ์คํธ ํ์ - ๋ชจ๋ ๋ ์คํธ๋ง ํฌํจ (๋ฉํ๋ฐ์ดํฐ ํ๊ทธ)
"""
ํจํค์ง ์ค๋ช
@source ์ถ์ฒ
@extracted YYYY-MM-DD
@version X.Y.Z
"""
from .module import function_a, function_b
__all__ = [
"function_a",
"function_b",
]
์ฑ๊ธํค ํจํด
๋ชจ๋ ๋ ๋ฒจ _instance + get_*() ํฉํ ๋ฆฌ ํจ์:
_instance: MyClass | None = None
def get_instance(**kwargs) -> MyClass:
"""์ฑ๊ธํค ์ธ์คํด์ค ๋ฐํ"""
global _instance
if _instance is None:
_instance = MyClass(**kwargs)
return _instance
๋ฆฌ์์ค ๊ด๋ฆฌ
- ํ์ผ/๋คํธ์ํฌ/DB ์ฐ๊ฒฐ์ ๋ฐ๋์
with๋๋try/finally๋ก ์ ๋ฆฌ read_only=True์ํฌ๋ถ๋ ๋ฐ๋์.close()ํธ์ถ
# ์ฌ๋ฐ๋ฅธ ์
wb = load_workbook(path, read_only=True)
try:
return wb.sheetnames
finally:
wb.close()
Java / Spring Boot ๊ท์น
ํ์ผ ๋ฉํ๋ฐ์ดํฐ
Javadoc ํค๋:
/**
* ํ์ผ ์ค๋ช
(ํ๊ตญ์ด)
*
* @source ์ถ์ฒ-ํ๋ก์ ํธ๋ช
* @extracted YYYY-MM-DD
* @version X.Y.Z
*
* @dependencies ์์กด์ฑ ๋ชฉ๋ก
*/
ํจํค์ง ๊ท์น
- ๋ฒ์ฉ ํจํค์ง:
com.example.app.*(์ค์ ํ๋ก์ ํธ ์ ์ฉ ์ ๋ณ๊ฒฝ) - ์นดํ
๊ณ ๋ฆฌ๋ณ ํ์ ํจํค์ง:
config,security,exception,util,service,domain
๋ค์ด๋ฐ ๊ท์น
| ๋์ | ๊ท์น | ์์ |
|---|---|---|
| ํด๋์ค | PascalCase | SecurityConfig, FileUtil |
| ๋ฉ์๋/๋ณ์ | camelCase | uploadFile, maxFileSize |
| ์์ | UPPER_SNAKE_CASE | ALLOWED_MIME_TYPES, USER_PRINCIPAL |
| ํจํค์ง | lowercase | com.example.app.config |
์ฃผ์ ์ธ์ด
- ํ๊ตญ์ด ์ฌ์ฉ (Javadoc, ์ธ๋ผ์ธ ์ฃผ์ ๋ชจ๋)
- ์๋ฌ ๋ฉ์์ง ๋ฌธ์์ด์ ์์ด ํ์ฉ
import ์์
๊ทธ๋ฃน ๊ฐ ๋น ์ค๋ก ๊ตฌ๋ถ:
// 1. java/jakarta ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ
import java.time.LocalDateTime;
import jakarta.servlet.http.HttpServletRequest;
// 2. Spring ํ๋ ์์ํฌ
import org.springframework.stereotype.Service;
import org.springframework.security.core.userdetails.UserDetails;
// 3. ์๋ํํฐ
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.RequiredArgsConstructor;
// 4. ํ๋ก์ ํธ ๋ด๋ถ
import com.example.app.domain.User;
import com.example.app.exception.BusinessException;
Lombok ์ฌ์ฉ ๊ท์น
@RequiredArgsConstructor+private finalํ๋ (์์ฑ์ ์ฃผ์ )@Getter,@Builderํ์ฉ@Data์ง์ (DTO์๋ง ์ ํ์ ํ์ฉ)@Setter๊ธ์ง (๋๋ฉ์ธ ์ํฐํฐ)
์์ธ ์ฒ๋ฆฌ
// ๋น์ฆ๋์ค ์์ธ๋ ์ปค์คํ
์์ธ ์ฌ์ฉ
throw new BusinessException("์ ํจํ์ง ์์ ์์ฒญ์
๋๋ค");
// ๋ฆฌ์์ค ๋ฏธ๋ฐ๊ฒฌ
throw new ResourceNotFoundException("์ฌ์ฉ์๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค: " + id);
์ค์ ํ์ผ ํจํด
@Value๋๋@ConfigurationProperties๋ก ์ธ๋ถ ์ค์ ์ฃผ์- ํ๋์ฝ๋ฉ ๊ธ์ง (URL, ํฌํธ, ๊ฒฝ๋ก, ์๊ฒฉ์ฆ๋ช )
- ํ๋กํ์ผ๋ณ ์ค์ ๋ถ๋ฆฌ (
application-{profile}.yml)
๋ฒ์ ์ ๋ต
์๋งจํฑ ๋ฒ์ (@version)
| ๋ณ๊ฒฝ ์ ํ | ๋ฒ์ ์ | ์์ |
|---|---|---|
| ๋ฒ๊ทธ ์์ , ์ฃผ์ ์์ | Patch (1.0.x) | ํ์ ์ค๋ฅ ์์ |
| ๊ธฐ๋ฅ ์ถ๊ฐ (ํ์ ํธํ) | Minor (1.x.0) | ์ ์ต์ ํ๋ผ๋ฏธํฐ ์ถ๊ฐ |
| ํ๋ผ๋ฏธํฐ ๋ณ๊ฒฝ, API ๋ณ๊ฒฝ | Major (x.0.0) | ํจ์ ์๊ทธ๋์ฒ ๋ณ๊ฒฝ |
shadcn ์ปดํฌ๋ํธ ๋ฒ์
@version์ shadcn/ui ๋ฆด๋ฆฌ์ค ๋ฒ์ ์ ๋ฐ๋ฆ (ํ์ฌ v4)- ์ปค์คํ
์์ ์
@version 4.0.0-custom.1ํํ ์ฌ์ฉ
ํธํ์ฑ
| ํญ๋ชฉ | ์ต์ ๋ฒ์ |
|---|---|
| TypeScript | 5.0+ |
| React | 18+ |
| Next.js | 14+ (App Router) |
| Python | 3.10+ |
| Node.js | 18+ |
| Java | 21+ |
| Spring Boot | 3.0+ |
์ ์ฉ ์ด๋ ฅ
| ๋ ์ง | ๋ด์ฉ |
|---|---|
| 2026-02-16 | ์ดํ ์์ฑ. ๋ฉํ๋ฐ์ดํฐ ํค๋ ํต์ผ, ์ฃผ์ ํ๊ตญ์ดํ, ์ธ๋ฏธ์ฝ๋ก /๋ฐ์ดํ/export ํต์ผ ์ ์ฉ |
| 2026-02-16 | TS + Python ๋จ์ผ ๋ฌธ์๋ก ํตํฉ. Optional[T] โ T | None ํต์ผ, ์ค๋ณต ๊ท์น ๊ณตํต ์น์
์ผ๋ก ๋ณํฉ |
| 2026-02-16 | ๋ฒ์ ์ ๋ตยทํธํ์ฑ ์น์
์ถ๊ฐ. docs/conventions/ โ docs/rules/๋ก ์ด๋ |
| 2026-03-08 | Java / Spring Boot ์น์ ์ถ๊ฐ. ํจํค์งยทLombokยท์์ธยท์ค์ ๊ท์น ํฌํจ |