kiwoom-rest-trade

πŸ€– kiwoom-rest-trade μ½”λ“œ 생성기 μ„€κ³„μ„œ (CODEGEN_GUIDE.md)

λ³Έ λ¬Έμ„œλŠ” kiwoom_api_spec.json 데이터λ₯Ό 읽어 337개의 킀움 REST API μš”μ²­/응닡에 λŒ€μ‘ν•˜λŠ” 파이썬 μ½”λ“œ(Pydantic λͺ¨λΈ 및 ν΄λΌμ΄μ–ΈνŠΈ λ©”μ„œλ“œ)λ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•˜λŠ” μ½”λ“œ 생성기(Codegen)의 섀계 및 κ΅¬ν˜„ κ°€μ΄λ“œμž…λ‹ˆλ‹€.


1. μ½”λ“œ 생성기(Codegen)의 μž‘λ™ 흐름

μ½”λ“œ μƒμ„±κΈ°λŠ” 개발 단계 λ˜λŠ” API μŠ€νŽ™ λ³€κ²½ μ‹œ 1νšŒμ„±μœΌλ‘œ μ‹€ν–‰λ˜λŠ” λ…λ¦½ν˜• μŠ€ν¬λ¦½νŠΈμž…λ‹ˆλ‹€.

flowchart LR
    Spec[kiwoom_api_spec.json] --> Parser[codegen.py νŒŒμ„œ]
    Parser -->|1. λͺ¨λΈ ν…œν”Œλ¦Ώ 적용| Models[kiwoom/models/..]
    Parser -->|2. API ν•¨μˆ˜ ν…œν”Œλ¦Ώ 적용| APIs[kiwoom/api/..]
  1. μŠ€νŽ™ 파일 λ‘œλ“œ: data/kiwoom_api_spec.json νŒŒμΌμ„ νŒŒμ‹±ν•˜μ—¬ λ©”λͺ¨λ¦¬μ— λ‘œλ“œν•©λ‹ˆλ‹€.
  2. μΉ΄ν…Œκ³ λ¦¬λ³„ λΆ„λ₯˜: category_large ν•„λ“œλ₯Ό κΈ°μ€€μœΌλ‘œ ꡭ내주식(domestic), 미ꡭ주식(overseas), 인증(auth)으둜 λΆ„λ₯˜ν•©λ‹ˆλ‹€.
  3. Pydantic λͺ¨λΈ 생성: 각 TR의 request.body 및 response.body λͺ…μ„Έλ₯Ό 기반으둜 kiwoom/models/ 폴더에 검증 클래슀λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.
  4. API λ©”μ„œλ“œ μ½”λ“œ 생성: 각 TR의 HTTP Method, URL, Header, Body ꡬ쑰λ₯Ό μ‘°ν•©ν•˜μ—¬ kiwoom/api/ 폴더에 비동기 λ©”μ„œλ“œλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

2. μ„ΈλΆ€ 섀계 κ·œμΉ™

2.1. νƒ€μž… λ§€ν•‘ κ·œμΉ™ (Type Mapping)

킀움 API μŠ€νŽ™μ˜ νƒ€μž…μ„ 파이썬 및 Pydantic ν˜•μ‹μœΌλ‘œ λ§€ν•‘ν•©λ‹ˆλ‹€. 킀움 μŠ€νŽ™μ˜ ν•„λ“œ μ„€λͺ…μ΄λ‚˜ 데이터 μ˜ˆμ‹œλ₯Ό μ°Έκ³ ν•˜μ—¬ νŒŒμ•…ν•©λ‹ˆλ‹€.

킀움 μŠ€νŽ™ νƒ€μž… 파이썬 νƒ€μž… λΉ„κ³ 
String str κΈ°λ³Έ λ¬Έμžμ—΄
Integer / Long int 숫자
Float / Double float μ†Œμˆ˜μ 
Array / List list[NestedModel] 쀑첩 데이터 ꡬ쑰
null λ˜λŠ” λ―Έμ§€μ • str κΈ°λ³Έκ°’ str둜 μ•ˆμ „ν•˜κ²Œ 폴백

2.2. ν•„λ“œ 넀이밍 κ·œμΉ™


3. μ½”λ“œ ν…œν”Œλ¦Ώ ꡬ쑰 (Templates)

κ°€μž₯ 직관적이고 κ°€λ²Όμš΄ 파이썬 f-string λ˜λŠ” Jinja2 ν…œν”Œλ¦Ώμ„ μ‚¬μš©ν•˜μ—¬ μ½”λ“œλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

3.1. Pydantic λͺ¨λΈ ν…œν”Œλ¦Ώ μ˜ˆμ‹œ

# {category}.py λͺ¨λΈ 파일의 헀더
from pydantic import BaseModel, Field
from typing import Optional, List

# 각 TR에 λŒ€ν•΄ 반볡 생성될 클래슀 포맷
class {ClassName}Request(BaseModel):
    """
    {api_name} ({api_id}) μš”μ²­ λͺ¨λΈ
    """
    {RequestFields}

class {ClassName}Response(BaseModel):
    """
    {api_name} ({api_id}) 응닡 λͺ¨λΈ
    """
    {ResponseFields}

3.2. API λ©”μ„œλ“œ ν…œν”Œλ¦Ώ μ˜ˆμ‹œ

# api/{category}.py 에 μ •μ˜λ  비동기 API 클래슀의 λ©”μ„œλ“œ 포맷
class {CategoryClassName}API:
    
    async def {method_name}(self, request: {ClassName}Request) -> {ClassName}Response:
        """
        {api_name} ({api_id})
        
        URL: {url} (Method: {http_method})
        """
        # API 호좜 전솑 곡톡 둜직 μ‹€ν–‰
        response_json = await self._request(
            method="{http_method}",
            path="{url}",
            headers={headers_dict},
            json=request.model_dump(exclude_none=True)
        )
        return {ClassName}Response.model_validate(response_json)

4. μ½”λ“œ 생성기 κ΅¬ν˜„ μ˜ˆμ‹œ (tools/codegen.py)

μ‹€μ œ ν”„λ‘œμ νŠΈ 루트 μ•„λž˜ tools/codegen.py둜 생성할 파이썬 슀크립트의 κΈ°λ³Έ λΌˆλŒ€μž…λ‹ˆλ‹€.

import json
from pathlib import Path

def load_spec():
    with open("data/kiwoom_api_spec.json", encoding="utf-8") as f:
        return json.load(f)

def clean_desc(desc):
    if not desc:
        return ""
    return desc.replace("\n", " ").replace('"', '\\"')

def generate_models(spec):
    # categoryλ³„λ‘œ λΆ„λ₯˜ν•΄μ„œ Pydantic λͺ¨λΈ μ½”λ“œ λ¬Έμžμ—΄μ„ μƒμ„±ν•˜κ³  νŒŒμΌμ— 씀
    print("Generating Pydantic models...")
    # ... 상세 루프 κ΅¬ν˜„

def generate_apis(spec):
    # categoryλ³„λ‘œ λΆ„λ₯˜ν•΄μ„œ ν΄λΌμ΄μ–ΈνŠΈ λ©”μ„œλ“œ μ½”λ“œλ₯Ό μƒμ„±ν•˜κ³  νŒŒμΌμ— 씀
    print("Generating API endpoints...")
    # ... 상세 루프 κ΅¬ν˜„

def main():
    spec = load_spec()
    generate_models(spec)
    generate_apis(spec)
    print("✨ Code Generation Completed!")

if __name__ == "__main__":
    main()

5. μ½”λ“œ 생성기 μ‹€ν–‰ 및 검증 절차

μ½”λ“œ 생성기가 μ™„μ„±λ˜λ©΄ μ•„λž˜ λͺ…λ Ήμ–΄λ₯Ό 톡해 μ½”λ“œλ₯Ό μ¦‰μ‹œ 찍어내고 ν’ˆμ§ˆ κ²€μ‚¬κΉŒμ§€ 일괄 μˆ˜ν–‰ν•©λ‹ˆλ‹€.

# 1. κ°€μƒν™˜κ²½ μ§„μž… μƒνƒœμ—μ„œ μ½”λ“œ 생성 슀크립트 μ‹€ν–‰
uv run python tools/codegen.py

# 2. μžλ™ μƒμ„±λœ μ½”λ“œμ˜ ν¬λ§·νŒ… 및 정적 뢄석 μˆ˜ν–‰
uv run ruff format kiwoom/
uv run ruff check kiwoom/ --fix

# 3. νƒ€μž… 힌트 μ—λŸ¬ 검사
uv run mypy kiwoom/