HDC-BE-REAL/ESG_Dashboard

ESG Web Application with PDF Extraction

Python

0

365 commits

updated Mar 3, 2026

See the code

README

๐ŸŒฟ ESG Carbon Dashboard (Carbon Strategic OS)

AI ๊ธฐ๋ฐ˜ ํƒ„์†Œ ๋ฐฐ์ถœ ๊ด€๋ฆฌ ๋ฐ ์ „๋žต์  ์˜์‚ฌ๊ฒฐ์ • ์ง€์› ํ”Œ๋žซํผ


๐Ÿ“– 1. ํ”„๋กœ์ ํŠธ ๊ฐœ์š” (Project Overview)

ESG Carbon Dashboard๋Š” ๊ธฐ์—…์˜ ํ™˜๊ฒฝ์  ์ฑ…์ž„(Environmental)์„ ๋ฐ์ดํ„ฐ ์ค‘์‹ฌ์˜ ์ „๋žต์  ์ž์‚ฐ์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐœ๋ฐœ๋œ Carbon Strategic OS์ž…๋‹ˆ๋‹ค.

๋‹จ์ˆœํžˆ ๊ณผ๊ฑฐ์˜ ๋ฐฐ์ถœ๋Ÿ‰์„ ๊ธฐ๋กํ•˜๋Š” ๋ฐ ๊ทธ์น˜์ง€ ์•Š๊ณ , ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•ต์‹ฌ ๊ฐ€์น˜๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

  • ์‹ค์‹œ๊ฐ„ ํŠธ๋ž˜ํ‚น: ๊ธ€๋กœ๋ฒŒ ํƒ„์†Œ ์‹œ์žฅ(EU-ETS, K-ETS)๊ณผ ์—๋„ˆ์ง€ ๊ฐ€๊ฒฉ(WTI)์„ ์—ฐ๋™ํ•œ ์‹ค์‹œ๊ฐ„ ๋ฆฌ์Šคํฌ ๋ถ„์„.
  • ๊ฒฝ์Ÿ์‚ฌ ๋ฒค์น˜๋งˆํ‚น: ํƒ„์†Œ ์ง‘์•ฝ๋„(Carbon Intensity) ๊ธฐ์ค€ ๋™์ข… ์—…๊ณ„ ๋‚ด ์ˆœ์œ„ ๋ฐ ๊ฒฉ์ฐจ ์‹œ๊ฐํ™”.
  • K-ETS ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ: ๊ตญ๋‚ด/ํ•ด์™ธ ๋ฐฐ์ถœ์„ ๋ถ„๋ฆฌํ•ด ์ˆœ๋…ธ์ถœ๋Ÿ‰, ์ค€์ˆ˜๋น„์šฉ, ํ†ตํ•ฉ ์˜ˆ์‚ฐ ๋ฆฌ์Šคํฌ๋ฅผ ๋‹จ๊ณ„์ ์œผ๋กœ ๊ณ„์‚ฐ.
  • ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ์˜์‚ฌ๊ฒฐ์ •: SBTi ๊ธฐ๋ฐ˜ ๊ฐ์ถ• ๊ฒฝ๋กœ์™€ ๋ชฉํ‘œ ๋‹ฌ์„ฑ ํ™•๋ฅ (Monte Carlo)์„ ์ •๋Ÿ‰์ ์œผ๋กœ ์ œ์‹œํ•˜์—ฌ ์‹คํ–‰ ์šฐ์„ ์ˆœ์œ„ ๊ฒฐ์ • ์ง€์›.
  • ์ง€์‹ ์ฆ๊ฐ• ์งˆ์˜์‘๋‹ต: RAG(Retrieval-Augmented Generation) ๊ธฐ์ˆ ์„ ํ†ตํ•ด ๋น„์ •ํ˜• ESG ๋ณด๊ณ ์„œ์—์„œ ์ฆ‰๊ฐ์ ์ธ ์ „๋žต ์ธ์‚ฌ์ดํŠธ๋ฅผ ์ถ”์ถœ.

์ด ํ”„๋กœ์ ํŠธ๋Š” ๊ฐœ๋ฐœ์ž๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ESG ์‹ค๋ฌด์ž, CFO, ๊ทธ๋ฆฌ๊ณ  ์ง€์† ๊ฐ€๋Šฅ์„ฑ ์ „๋žต๊ฐ€๊ฐ€ ์‹ค๋ฌด์—์„œ ์ฆ‰์‹œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์˜ ์ „๋ฌธ ๊ธฐ์ˆ  ๋„๊ตฌ๋ฅผ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ“‘ 2. ๋ชฉ์ฐจ (Table of Contents)

  1. ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜
  2. ํ•ต์‹ฌ ๊ธฐ๋Šฅ ๋ฐ ์„ค๊ณ„ ์˜๋„
  3. ๊ธฐ์ˆ  ์Šคํƒ ๋ฐ ๋ชจ๋“ˆ ์—ฐ๋™
  4. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ
  5. ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ๊ตฌ์กฐ
  6. ์„ค์น˜ ๋ฐ ์„ค์ •
  7. API ๋ช…์„ธ
  8. AI ๋ชจ๋ธ ํ‰๊ฐ€

๐Ÿ“ 3. ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ (System Architecture)

3.1 ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ

graph TB
    subgraph "Client Layer"
        Browser[์›น ๋ธŒ๋ผ์šฐ์ €]
    end

    subgraph "Frontend (React 18 + TypeScript + Vite)"
        UI[UI Components<br/>Recharts / TailwindCSS 4]
        State[State Management<br/>React Hooks + localStorage]
        Router[View State Router<br/>URL Query Params + History API]
    end

    subgraph "Backend (FastAPI + Uvicorn, Port 8000)"
        Auth[Auth Router<br/>/auth]
        Profile[Profile Router<br/>/profile]
        Dashboard[Dashboard Router<br/>/api/v1/dashboard]
        Sim[Simulator Router<br/>/api/v1/sim]
        AI[AI Router<br/>/api/v1/ai]
    end

    subgraph "Data & AI Layer"
        MySQL[(MySQL DB<br/>users / dashboard_emissions)]
        ChromaDB[(ChromaDB<br/>Vector Store / RAG)]
        OpenAI[OpenAI API<br/>gpt-4o / gpt-4o-mini]
        BGE[BGE Embedding / Reranker<br/>bge-m3, bge-reranker-v2-m3]
    end

    subgraph "External Data Sources"
        yfinance[yfinance / yahoo_fin<br/>EU-ETS ๊ฐ€๊ฒฉ]
        FDR[FinanceDataReader<br/>K-ETS KAU ๊ฐ€๊ฒฉ]
    end

    Browser --> UI
    UI --> State --> Router
    Router -->|Axios HTTP/REST| Auth & Profile & Dashboard & Sim & AI
    Auth --> MySQL
    Profile --> MySQL
    Dashboard --> MySQL
    Sim --> yfinance & FDR
    AI --> ChromaDB & OpenAI
    ChromaDB --> BGE

๐Ÿš€ 4. ํ•ต์‹ฌ ๊ธฐ๋Šฅ ๋ฐ ์„ค๊ณ„ ์˜๋„ (Core Features)

4.1 Dashboard Tab (๋ฐฐ์ถœ๋Ÿ‰ ํ†ตํ•ฉ ๋Œ€์‹œ๋ณด๋“œ)

image
  • ์—ญํ• (Role): ๊ธฐ์—…์˜ Scope 1, 2, 3 ๋ฐฐ์ถœ ํ˜„ํ™ฉ ๋ฐ ์žฌ๋ฌด ๋ฆฌ์Šคํฌ ์ง€ํ‘œ๋ฅผ ํ•œ๋ˆˆ์— ์‹œ๊ฐํ™”.
  • ์˜๋„(Purpose):
    • ์ฆ‰๊ฐ์ ์ธ ํ˜„ํ™ฉ ํŒŒ์•…: ๊ฒฝ์˜์ง„์ด 4๊ฐœ์˜ KPI ์นด๋“œ(์ด ํƒ„์†Œ ๋ฐฐ์ถœ๋Ÿ‰, ํƒ„์†Œ ์ง‘์•ฝ๋„, ๋ฐฐ์ถœ๊ถŒ ๊ฑฐ๋ž˜ ๋‹จ๊ฐ€, SBTi ๋‹ฌ์„ฑ ํ™•๋ฅ )๋ฅผ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•˜๋„๋ก ์„ค๊ณ„.
    • Scope๋ณ„ ๋ฐฐ์ถœ ๊ธฐ์—ฌ๋„: Scope๋ณ„ ๋ฐฐ์ถœ๋Ÿ‰ ์ˆ˜์น˜์™€ ๋น„์ค‘(%)์„ ์‹œ๊ฐํ™”.
    • ๊ถค์  ์‹œ๊ฐํ™”: 2021๋…„๋ถ€ํ„ฐ์˜ ์‹ค์ œ ๋ฐฐ์ถœ๋Ÿ‰ ์ถ”์ด์™€ ํšŒ๊ท€ ์˜ˆ์ธก๊ฐ’์„ Scope๋ณ„๋กœ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋„๋ก ์‹œ๊ฐํ™”.
    • ๋ฐ”๋กœ๊ฐ€๊ธฐ ์นด๋“œ: KPI ์นด๋“œ ํด๋ฆญ ์‹œ ๊ด€๋ จ ํƒญ(๊ฒฝ์Ÿ์‚ฌ ๋น„๊ต, ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ, ๋ชฉํ‘œ ๊ด€๋ฆฌ)์œผ๋กœ ์ฆ‰์‹œ ์ด๋™.
  • KPI ์นด๋“œ ๊ตฌ์„ฑ:
    1. ์ด ๋ฐฐ์ถœ๋Ÿ‰ (Scope 1+2): tCOโ‚‚e
    2. ํƒ„์†Œ ์ง‘์•ฝ๋„: ํ•ด๋‹น ๊ธฐ์—…์˜ ํƒ„์†Œ ์ง‘์•ฝ๋„(tCOโ‚‚e / ๋งค์ถœ 1์–ต์›) ๋˜๋Š” ์—๋„ˆ์ง€ ์ง‘์•ฝ๋„(TJ/์–ต์›)๋กœ ์ „ํ™˜ ๊ฐ€๋Šฅ
    3. K-ETS: ์‹ค์‹œ๊ฐ„ ํ•œ๊ตญ ๋ฐฐ์ถœ๊ถŒ ๊ฑฐ๋ž˜ ๋‹จ๊ฐ€
    4. SBTi ๋‹ฌ์„ฑ ํ™•๋ฅ : SBTi ๊ตญ์ œ ํ‘œ์ค€ ๊ธฐ์ค€์œผ๋กœ Monte Carlo ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๊ฒฐ๊ณผ (%) ๊ฐ์ถ• ๋‹ฌ์„ฑ ํ™•๋ฅ ์„ ํ‘œ๊ธฐ

4.2 Compare Tab (๊ฒฝ์Ÿ์‚ฌ ๋น„๊ต ๋ถ„์„)

image
  • ์—ญํ• (Role): ๋™์ผ ์—…์ข… ๊ธฐ์—…์˜ ํƒ„์†Œ/์—๋„ˆ์ง€ ์ง‘์•ฝ๋„๋ฅผ ์ •๋ ฌํ•˜์—ฌ ์ƒ๋Œ€ ํฌ์ง€์…˜์„ ๋น ๋ฅด๊ฒŒ ํŒŒ์•….
  • ํ•ต์‹ฌ ๋™์ž‘:
    • ์ง‘์•ฝ๋„ ๋ชจ๋“œ ์ „ํ™˜: revenue(ํƒ„์†Œ ์ง‘์•ฝ๋„), energy(์—๋„ˆ์ง€ ์ง‘์•ฝ๋„)
    • Scope ํ† ๊ธ€: S1/S2 ๋ฐ˜์˜ ์—ฌ๋ถ€๋ฅผ ์ฆ‰์‹œ ์ฐจํŠธ ๊ณ„์‚ฐ์— ๋ฐ˜์˜
    • ๊ธฐ์ค€์„  ์ž๋™ ๊ณ„์‚ฐ: ์ƒ์œ„ 10% ๋ฐ ์ค‘์•™๊ฐ’ ์ž„๊ณ„์„  ์˜ค๋ฒ„๋ ˆ์ด
    • ์นด๋“œ ์„ ํƒ ์—ฐ๋™: ์„ ํƒ ๊ธฐ์—… ๊ฐ•์กฐ + ์ธ์‚ฌ์ดํŠธ ๋‚ด์šฉ ๋™๊ธฐํ™”
    • ์‹คํ–‰ ์—ฐ๊ณ„: ์„ธ๋ถ€ ์‹คํ–‰ ๊ณ„ํš ๋ฒ„ํŠผ์œผ๋กœ Simulator ํƒญ ์ด๋™
  • ๊ธฐ์ˆ  ์š”์†Œ:
    • CompareTab.tsx: Recharts BarChart, ReferenceLine, ๋™์  ์ƒ‰์ƒ ์…€ ๋ Œ๋”๋ง
    • ๋ฐฑ์—”๋“œ ์—ฐ๊ณ„: POST /api/v1/dashboard/compare/insight๋กœ AI ์ธ์‚ฌ์ดํŠธ ์ƒ์„ฑ
    • ๋„ค๋น„๊ฒŒ์ด์…˜: navigateTo('dashboard', 'simulator')

4.3 Simulator Tab (K-ETS ์ค€์ˆ˜ ๋น„์šฉ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ)

image image
  • ์—ญํ• (Role): ๊ตญ๋‚ด ์ง์ ‘ ๋ฐฐ์ถœ ์ดํ–‰๋น„์šฉ๊ณผ ํ•ด์™ธ ๋…ธ์ถœ๋น„์šฉ์„ ํ†ตํ•ฉํ•ด ์—ฐ๊ฐ„ ํƒ„์†Œ ์˜ˆ์‚ฐ ๊ด€์ ์˜ ์˜์‚ฌ๊ฒฐ์ •์„ ์ง€์›.
  • 4๋‹จ๊ณ„ ๊ตฌ์กฐ:
    1. ๊ตญ๋‚ด ์ง์ ‘ ํƒ„์†Œ๋Ÿ‰: ์˜ˆ์ƒ๋ฐฐ์ถœ๋Ÿ‰, ๋ฌด์ƒํ• ๋‹น, ์ˆœ๋…ธ์ถœ๋Ÿ‰(Net Exposure), ์ปดํ”Œ๋ผ์ด์–ธ์Šค ๋น„์šฉ ๊ณ„์‚ฐ
    2. ์ „๋žต ๋ฐฐ๋ถ„: ์ˆœ๋…ธ์ถœ๋Ÿ‰ ์ค‘ ์šฐ์„  ์ง‘ํ–‰/์ž”์—ฌ ์ดํ–‰ ๋น„์œจ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
    3. ํ•ด์™ธ ํƒ„์†Œ ๋ฐฐ์ถœ๋Ÿ‰: ํ•ด์™ธ S1+S2์™€ EUA, EUR/KRW ํ™˜์œจ๋กœ ํ•ด์™ธ ์˜ˆ์ƒ๋น„์šฉ ์‚ฐ์ถœ
    4. ๊ฒฐ๊ณผ ์š”์•ฝ: ๊ตญ๋‚ด+ํ•ด์™ธ ํ†ตํ•ฉ ์ด๊ณ„์™€ ์˜ˆ์‚ฐ ๋Œ€๋น„ ๋ฆฌ์Šคํฌ ๋“ฑ๊ธ‰ ์ œ๊ณต
  • ์‹œ๋‚˜๋ฆฌ์˜ค ์ž…๋ ฅ๊ฐ’:
    • ETS ๊ฐ€๊ฒฉ(์‹ค์‹œ๊ฐ„/์ง์ ‘ ์ž…๋ ฅ)
    • ๋ฐฐ์ถœ๋Ÿ‰ ๋ณ€๋™(%)
    • ๋ฌด์ƒํ• ๋‹น ์ •์ฑ… ๋ณ€๋™
    • ๊ฒฝ๋งค ์กฐ๋‹ฌ ๋น„์ค‘
    • ์—ฐ๊ฐ„ ํƒ„์†Œ ์˜ˆ์‚ฐ(์‚ฌ์šฉ์ž ์ง์ ‘ ์ž…๋ ฅ)
  • ๊ณ„์‚ฐ ๊ธฐ์ค€(ํ•ต์‹ฌ):
    • ์ˆœ๋…ธ์ถœ๋Ÿ‰ = ์กฐ์ • ๋ฐฐ์ถœ๋Ÿ‰ - ์กฐ์ • ๋ฌด์ƒํ• ๋‹น๋Ÿ‰
    • ์ปดํ”Œ๋ผ์ด์–ธ์Šค ๋น„์šฉ = ์ˆœ๋…ธ์ถœ๋Ÿ‰ ร— ์‹คํšจ ํƒ„์†Œ๊ฐ€๊ฒฉ(๊ฒฝ๋งค ํ• ์ธ ๋ฐ˜์˜)
    • ํ•ด์™ธ ์˜ˆ์ƒ๋น„์šฉ = ํ•ด์™ธ S1+S2 ร— EUA ร— EUR/KRW
    • ํ†ตํ•ฉ ์ด๊ณ„ = ๊ตญ๋‚ด ์ด ํƒ„์†Œ๋น„์šฉ + ํ•ด์™ธ ์˜ˆ์ƒ๋น„์šฉ
  • ๋ฐ์ดํ„ฐ ๊ธฐ์ค€ ๋ถ„๋ฆฌ:
    • Simulator: ๊ตญ๋‚ด ์ง์ ‘ ๋ฐฐ์ถœ(s1Domestic, s2Domestic) ์šฐ์„  ์‚ฌ์šฉ
    • Dashboard/Compare/Target: ์ „์ฒด ๋ฐฐ์ถœ(s1, s2, s3) ์‚ฌ์šฉ
  • ๊ธฐ์ˆ  ์š”์†Œ:
    • ํ”„๋ก ํŠธ: SimulatorTab.tsx (์ƒํƒœ ๊ธฐ๋ฐ˜ ์ฆ‰์‹œ ์žฌ๊ณ„์‚ฐ)
    • ๋ฐฑ์—”๋“œ: GET /api/v1/sim/dashboard/market-trends
    • ์‹œ์žฅ ๋ฐ์ดํ„ฐ: yfinance(EU-ETS), FinanceDataReader(K-ETS)
    • ํ™˜์œจ ๋ฐ์ดํ„ฐ: open.er-api.com EUR ๊ธฐ์ค€ ์‹ค์‹œ๊ฐ„ ์กฐํšŒ + fallback(1450)

4.4 Target Tab (SBTi ๋ชฉํ‘œ ๊ด€๋ฆฌ)

image
  • ์—ญํ• (Role): SBTi ๊ธฐ์ค€์—ฐ๋„(2021) ๋Œ€๋น„ ๊ฐ์ถ• ๊ฒฝ๋กœ์™€ ํ˜„์žฌ ์‹ค์  ๊ฐ„ ๊ฒฉ์ฐจ๋ฅผ ์‹œ๊ฐํ™”ํ•˜๊ณ  2030/2050 ๋ชฉํ‘œ ๋‹ฌ์„ฑ ๊ฐ€๋Šฅ์„ฑ์„ ์ •๋Ÿ‰ํ™”.

  • ์˜๋„(Purpose):

    • ๋ชฉํ‘œ ์ •๋ ฌ: ๊ธฐ์ค€ ๋ฐฐ์ถœ๋Ÿ‰(2021), ํ˜„์žฌ(์ตœ์‹ ) ๋ฐฐ์ถœ๋Ÿ‰, SBTi ๋ชฉํ‘œ ๋‹ฌ์„ฑ ์—ฌ๋ถ€๋ฅผ ํ•œ ํ™”๋ฉด์—์„œ ํ™•์ธ.
    • ํ™•๋ฅ  ๊ธฐ๋ฐ˜ ํŒ๋‹จ: ๋กœ๊ทธ ํšŒ๊ท€ Monte Carlo(10,000ํšŒ) ๊ธฐ๋ฐ˜ 2030 ๋ชฉํ‘œ ๋‹ฌ์„ฑ ํ™•๋ฅ  ์ œ๊ณต.
    • Net Zero 2050 ์ถ”์ : ํ˜„์žฌ ๊ฐ์ถ•๋ฅ ๊ณผ 2050 ๋ชฉํ‘œ(90%+ ๊ฐ์ถ•) ๊ฐ„ ๊ฒฉ์ฐจ ์‹ค์‹œ๊ฐ„ ํ‘œ์‹œ.
    • ์ •ํ™•ํ•œ ๋ชฉํ‘œ๋‹ฌ์„ฑ๋„ ํŒ์ •: ํ˜„์žฌ ์—ฐ๋„(2026)๊ฐ€ ์•„๋‹Œ ์ตœ์‹  ๋ฐ์ดํ„ฐ ์—ฐ๋„(latestDataYear, ์ตœ์‹  ๋ฐœ๊ฐ„๋œ ESG๋ณด๊ณ ์„œ์—์„œ์˜ ์—ฐ๋„ ๊ธฐ์ค€์ด๋ฉฐ ํ˜„์žฌ๋Š” 2024๋…„)๋กœ ์„ค์ •ํ•˜์—ฌ ๋™์ผ ์—ฐ๋„ ๊ธฐ์ค€์œผ๋กœ ์ •ํ™•ํžˆ ํŒ์ •.
  • KPI ์นด๋“œ ๊ตฌ์„ฑ:

    1. ๊ธฐ์ค€ ๋ฐฐ์ถœ๋Ÿ‰ (2021): tCOโ‚‚e
    2. ์ตœ์‹  ๋ฐฐ์ถœ๋Ÿ‰: tCOโ‚‚e + 2021๋…„ ๋Œ€๋น„ % ๊ฐ์ถ•
    3. SBTi ๋‹ฌ์„ฑ ์—ฌ๋ถ€: ๋ชฉํ‘œ ๋Œ€๋น„ ๊ฒฉ์ฐจ๋ฅผ ํŒ๋‹จํ•˜์—ฌ ๋ช…์‹œ
    4. Net Zero 2050: ํ•„์š” ์ด ๊ฐ์ถ•๋Ÿ‰(90%+), ํ˜„์žฌ ๋‹ฌ์„ฑ(%), ์ž”์—ฌ ๊ฒฉ์ฐจ(%)
  • ์˜ˆ์ธก ๋ฐฉ๋ฒ•๋ก :

    ๋ชจ๋ธ: log(E_t) = ฮฑ + ฮฒ*t  (๋กœ๊ทธ-์„ ํ˜• OLS ํšŒ๊ท€)
    ๊ฐ์ถ• ๋ชฉํ‘œ: ์—ฐ๊ฐ„ 4.2% (SBTi ์ ˆ๋Œ€ ๊ฐ์ถ• ๊ธฐ์ค€)
    Monte Carlo: 10,000ํšŒ ์ƒ˜ํ”Œ๋ง โ†’ 2030 ๋‹ฌ์„ฑ ํ™•๋ฅ  ๊ณ„์‚ฐ
    
  • ๊ธฐ์ˆ  ์š”์†Œ: OLS ํšŒ๊ท€, Monte Carlo ์‹œ๋ฎฌ๋ ˆ์ด์…˜(10,000ํšŒ), Recharts(๊ถค์  ์ฐจํŠธ).


4.5 ChatBot (AI ์ „๋žต ์—์ด์ „ํŠธ)

image
  • ์—ญํ• (Role): ESG ๋ฌธ์„œ ๊ธฐ๋ฐ˜ ์งˆ์˜์‘๋‹ต + ์‹œ์žฅ/์ „๋žต ๋งฅ๋ฝํ˜• ๋‹ต๋ณ€ ์ œ๊ณต

  • ํ•ต์‹ฌ ๋™์ž‘:

    • ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต: ํ† ํฐ ๋‹จ์œ„ ์ถœ๋ ฅ์œผ๋กœ ์ฒด๊ฐ ์‘๋‹ต ์ง€์—ฐ ์ตœ์†Œํ™”
    • ๋Œ€ํ™” ๋ฌธ๋งฅ ์œ ์ง€: ์ด์ „ ๋Œ€ํ™”(history)์™€ ์„ ํƒ ํšŒ์‚ฌ ์ปจํ…์ŠคํŠธ ์ „๋‹ฌ
    • ๋ฆฌํฌํŠธ ์Šค์ฝ”ํ”„ ์ œ์–ด: ์ตœ์‹ /์ „์ฒด ๋ณด๊ณ ์„œ ๋ฒ”์œ„ ์„ ํƒ ๊ฐ€๋Šฅ
    • ์ „๋žต ๋ณด์กฐ: ๋ณ„๋„ strategy ์—”๋“œํฌ์ธํŠธ๋กœ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ ์ „๋žต ๋ฌธ์•ˆ ์ƒ์„ฑ
  • ๊ธฐ์ˆ  ์š”์†Œ:

    • API: POST /api/v1/ai/chat (StreamingResponse), POST /api/v1/ai/strategy, POST /api/v1/ai/text-to-sql
    • RAG: ์งˆ๋ฌธ ์˜๋„ ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ… ํ›„ ChromaDB ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰(semantic+BM25) + rerank
    • LLM: OpenAI(gpt-4o, gpt-4o-mini) ์‘๋‹ต ์ƒ์„ฑ
  • RAG ํŒŒ์ดํ”„๋ผ์ธ:

    ์‚ฌ์šฉ์ž ์งˆ๋ฌธ
      โ†’ ์˜๋„ ํŒ๋ณ„(RAG ํ•„์š” ์—ฌ๋ถ€)
      โ†’ [RAG ON] ChromaDB ๊ฒ€์ƒ‰(semantic/BM25 + rerank) + ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•„ํ„ฐ
      โ†’ ์ปจํ…์ŠคํŠธ + ๋Œ€ํ™” ํžˆ์Šคํ† ๋ฆฌ + ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ
      โ†’ OpenAI ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต
    
  • ๊ธฐ์ˆ  ์š”์†Œ: ChromaDB, Sentence-Transformers(BAAI/bge-m3), CrossEncoder reranker, FastAPI StreamingResponse, ํ”„๋ก ํŠธ ReadableStream ์ฒ˜๋ฆฌ.


4.6 ์ธ์ฆ ์‹œ์Šคํ…œ (Authentication)

image image
  • ์—ญํ• (Role): ์‚ฌ์šฉ์ž ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ, JWT ์„ธ์…˜ ๊ด€๋ฆฌ.

  • ์˜๋„(Purpose):

    • ์ ‘๊ทผ ์ œ์–ด: ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋งŒ ๋Œ€์‹œ๋ณด๋“œ ๊ธฐ๋Šฅ์— ์ ‘๊ทผ ๊ฐ€๋Šฅ.
    • ๊ฐœ์ธํ™”: ์‚ฌ์šฉ์ž๋ณ„ ํ”„๋กœํ•„ ์„ค์ • ๋ฐ ๊ธฐ์—… ์ปจํ…์ŠคํŠธ ์—ฐ๋™.
  • ์ธ์ฆ ํ๋ฆ„:

    Signup โ†’ pbkdf2_sha256 ํ•ด์‹œ ์ €์žฅ โ†’ User ์ €์žฅ(MySQL)
    Login  โ†’ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์ฆ โ†’ JWT ๋ฐœ๊ธ‰ (HS256, ๊ธฐ๋ณธ 60๋ถ„)
           โ†’ localStorage ์ €์žฅ โ†’ WelcomePage ์ด๋™ (3์ดˆ ์ž๋™)
    Refresh โ†’ token ์กด์žฌ ์‹œ dashboard ์ž๋™ ๋ณต์›
    
  • ๊ธฐ์ˆ  ์š”์†Œ: passlib(pbkdf2_sha256), JWT(python-jose), SQLAlchemy (User ๋ชจ๋ธ).


4.7 ํ”„๋กœํ•„ ์„ค์ • (Profile Settings)

image
  • ์—ญํ• (Role): ์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„, ๋ถ„๋ฅ˜, ์ž๊ธฐ์†Œ๊ฐœ, ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋“ฑ ๊ฐœ์ธ ์ •๋ณด ๊ด€๋ฆฌ.
  • ์˜๋„(Purpose):
    • ESG ์•„์ด๋ดํ‹ฐํ‹ฐ: ๋ฉธ์ข…์œ„๊ธฐ์ข…(ํฌ์œ ๋ฅ˜/์กฐ๋ฅ˜/์–‘์„œ๋ฅ˜ ๋“ฑ) ํ…Œ๋งˆ๋ฅผ ์ ์šฉํ•˜์—ฌ ํ™˜๊ฒฝ์  ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ.
    • ๋™์  ํ€ด์ฆˆ ๋ฑƒ์ง€(QuizBadge): ๋‹‰๋„ค์ž„์—์„œ ๋™๋ฌผ ํ‚ค์›Œ๋“œ(๋ˆˆํ‘œ๋ฒ”/๋ฌผ๋ฐฉ๊ฐœ/ํŒ๋‹ค/ํ˜ธ๋ž‘์ด/๋…์ˆ˜๋ฆฌ) ๊ฐ์ง€ ์‹œ ํ•ด๋‹น ๋ฉธ์ข…์œ„๊ธฐ ๋™๋ฌผ ํ€ด์ฆˆ ํ‘œ์‹œ, ๋ฏธ๊ฐ์ง€ ์‹œ ํƒ„์†Œ์ค‘๋ฆฝ ๊ธฐ๋ณธ ํ€ด์ฆˆ ํ‘œ์‹œ.
    • ํšŒ์› ํƒˆํ‡ด: ํ™•์ธ ๋ชจ๋‹ฌ(๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌํ™•์ธ)๊ณผ ํ•จ๊ป˜ ๊ณ„์ • ์‚ญ์ œ ์ง€์›.
  • ํ”„๋กœํ•„ ํ•„๋“œ: ๋‹‰๋„ค์ž„, ๋ฉธ์ข…์œ„๊ธฐ์ข… ๋ถ„๋ฅ˜(๋“œ๋กญ๋‹ค์šด), ์†Œ์† ๊ธฐ์—…๋ช…(API ๋ชฉ๋ก ๋“œ๋กญ๋‹ค์šด ์„ ํƒ), ์ž๊ธฐ์†Œ๊ฐœ(500์ž), ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL.

๐Ÿ› ๏ธ 5. ๊ธฐ์ˆ  ์Šคํƒ ๋ฐ ๋ชจ๋“ˆ ์—ฐ๋™ (Tech Stack & Implementation)

5.1 Frontend

๊ธฐ์ˆ ๋ฒ„์ „์šฉ๋„
React18์„ ์–ธ์  UI ๋ฐ ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜
TypeScript5.2๊ฐ•ํ•œ ํƒ€์ž… ์ฒดํฌ๋กœ ๋Œ€๊ทœ๋ชจ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ๋„ ๋ Œ๋”๋ง ์•ˆ์ •์„ฑ ํ™•๋ณด
Vite5.1๋น ๋ฅธ HMR ๋ฐ ์ตœ์ ํ™”๋œ ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ
TailwindCSS4.0์œ ํ‹ธ๋ฆฌํ‹ฐ ๊ธฐ๋ฐ˜ ์Šคํƒ€์ผ๋ง ๋ฐ ์ปดํฌ๋„ŒํŠธ UI ์ผ๊ด€์„ฑ ๊ด€๋ฆฌ
Recharts2.12์‹œ๊ณ„์—ด ์‹œ์žฅ ๋ฐ์ดํ„ฐ ๋ฐ ๋น„๊ต ์ฐจํŠธ (Line, Bar, Pie, Area)
Axios + Fetch-์ผ๋ฐ˜ REST ํ†ต์‹  + ์ฑ—๋ด‡ ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต ์ฒ˜๋ฆฌ
Framer Motion-ํŽ˜์ด์ง€ ์ „ํ™˜ ๋ฐ ์ปดํฌ๋„ŒํŠธ ์• ๋‹ˆ๋ฉ”์ด์…˜
Lucide React-์•„์ด์ฝ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
CVA (class-variance-authority)-์กฐ๊ฑด๋ถ€ Tailwind ํด๋ž˜์Šค ๊ด€๋ฆฌ

5.2 Backend & Data

๊ธฐ์ˆ ์šฉ๋„
FastAPI & UvicornAPI ์„œ๋ฒ„ ๋ฐ ๋น„๋™๊ธฐ ์š”์ฒญ ์ฒ˜๋ฆฌ
SQLAlchemy & MySQL (PyMySQL)์‚ฌ์šฉ์ž/๋ฐฐ์ถœ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฐ ORM ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ
yfinance / yahoo_finEU-ETS ๊ฐ€๊ฒฉ ๋ฐ์ดํ„ฐ ์กฐํšŒ ๋ฐ fallback
FinanceDataReaderK-ETS(KAU) ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ ์กฐํšŒ
passlib + python-jose๋น„๋ฐ€๋ฒˆํ˜ธ ํ•ด์‹ฑ(pbkdf2_sha256) ๋ฐ JWT ์ธ์ฆ
python-joseJWT ํ† ํฐ ์ƒ์„ฑ ๋ฐ ๊ฒ€์ฆ (HS256)

5.3 AI & NLP

๊ธฐ์ˆ ์šฉ๋„
OpenAI API์ฑ—๋ด‡/์ „๋žต ์ƒ์„ฑ LLM ์‘๋‹ต ์—”์ง„ (gpt-4o, gpt-4o-mini)
ChromaDBRAG ๋ฒกํ„ฐ ์ €์žฅ์†Œ (๋กœ์ปฌ Persistent ๋˜๋Š” ์›๊ฒฉ HTTP ์„œ๋ฒ„)
Sentence-Transformers์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ (BAAI/bge-m3)
CrossEncoder๋ฆฌ๋žญํ‚น ๋ชจ๋ธ (BAAI/bge-reranker-v2-m3)
Docling & PyMuPDFPDF ๊ตฌ์กฐ ์ถ”์ถœ ๋ฐ ๋ฒกํ„ฐํ™” ์ „์ฒ˜๋ฆฌ

๐Ÿ“‚ 6. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ (Project Structure)

ESG_Dashboard/
โ”œโ”€โ”€ requirements.txt                  # ๊ณตํ†ต Python ์˜์กด์„ฑ (backend/PDF ๊ณต์šฉ)
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ ํŽ˜์ด์ง€_๋ผ์šฐํŒ…_๊ตฌ์กฐ.md
โ”œโ”€โ”€ start_all.sh                      # ๋กœ์ปฌ ๋™์‹œ ์‹คํ–‰ ์Šคํฌ๋ฆฝํŠธ
โ”œโ”€โ”€ backend/
โ”‚   โ”œโ”€โ”€ requirements.txt              # ๋ฐฑ์—”๋“œ ์ „์šฉ ์˜์กด์„ฑ
โ”‚   โ”œโ”€โ”€ main.py                       # ํ†ตํ•ฉ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ (RAG ๋ณด์กฐ ์—”๋“œํฌ์ธํŠธ ํฌํ•จ)
โ”‚   โ””โ”€โ”€ app/
โ”‚       โ”œโ”€โ”€ main.py                   # ์ฝ”์–ด API ์„œ๋ฒ„ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ
โ”‚       โ”œโ”€โ”€ config.py                 # .env ๊ธฐ๋ฐ˜ ์„ค์ • ๋กœ๋”
โ”‚       โ”œโ”€โ”€ database.py
โ”‚       โ”œโ”€โ”€ models.py                 # User, DashboardEmission
โ”‚       โ”œโ”€โ”€ schemas.py
โ”‚       โ”œโ”€โ”€ init_db.py
โ”‚       โ”œโ”€โ”€ routers/                  # auth/profile/dashboard/simulator/ai
โ”‚       โ”œโ”€โ”€ services/                 # ai_service, market_data ๋“ฑ
โ”‚       โ””โ”€โ”€ static/profile/           # ์—…๋กœ๋“œ๋œ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€
โ”œโ”€โ”€ frontend/
โ”‚   โ”œโ”€โ”€ package.json
โ”‚   โ”œโ”€โ”€ package-lock.json
โ”‚   โ”œโ”€โ”€ vite.config.ts
โ”‚   โ””โ”€โ”€ src/
โ”‚       โ”œโ”€โ”€ App.tsx                   # react-router-dom ๊ฒฝ๋กœ ๋ผ์šฐํŒ… + ํƒญ ์ƒํƒœ ๊ด€๋ฆฌ
โ”‚       โ”œโ”€โ”€ config.ts                 # API base URL ๊ตฌ์„ฑ
โ”‚       โ”œโ”€โ”€ services/                 # auth/profile/market/ai API ํ˜ธ์ถœ
โ”‚       โ”œโ”€โ”€ features/                 # ํƒญ/ํŽ˜์ด์ง€๋ณ„ UI
โ”‚       โ””โ”€โ”€ types/
โ”œโ”€โ”€ PDF_Extraction/
โ”‚   โ”œโ”€โ”€ requirements.txt              # PDF/RAG ํŒŒ์ดํ”„๋ผ์ธ ์˜์กด์„ฑ
โ”‚   โ”œโ”€โ”€ src/                          # ์ถ”์ถœ/์ ์žฌ/๋ฒกํ„ฐDB ๊ตฌ์ถ• ์Šคํฌ๋ฆฝํŠธ
โ”‚   โ”œโ”€โ”€ docs/
โ”‚   โ””โ”€โ”€ vector_db/                    # (์„ ํƒ) ๋กœ์ปฌ Chroma Persistent ์ €์žฅ ๊ฒฝ๋กœ
โ””โ”€โ”€ evaluation/
    โ””โ”€โ”€ evaluate_models.py

[!NOTE] PDF_Extraction/vector_db/๋Š” ๋กœ์ปฌ Persistent Chroma๋ฅผ ์“ธ ๋•Œ์˜ ๊ธฐ๋ณธ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค. ์›๊ฒฉ Chroma ์„œ๋ฒ„(CHROMA_HOST, CHROMA_PORT)๋ฅผ ์“ฐ๋ฉด ์ด ํด๋”๊ฐ€ ์—†์–ด๋„ ์ฑ—๋ด‡์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ—บ๏ธ 7. ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ๊ตฌ์กฐ (Page Routing)

react-router-dom ๊ธฐ๋ฐ˜ ๊ฒฝ๋กœ ๋ผ์šฐํŒ… + activeTab ์ƒํƒœ ๋™๊ธฐํ™” ์ƒ์„ธ ์„ค๊ณ„์„œ: ํŽ˜์ด์ง€_๋ผ์šฐํŒ…_๊ตฌ์กฐ.md

7.1 ํŽ˜์ด์ง€ ๊ฒฝ๋กœ

๊ฒฝ๋กœํ™”๋ฉด์„ค๋ช…
/login<Login>๋กœ๊ทธ์ธ
/signup<Signup>ํšŒ์›๊ฐ€์ž…
/welcome<WelcomePage>๋กœ๊ทธ์ธ ์งํ›„ ํ™˜์˜ ํ™”๋ฉด
/dashboard<DashboardTab>๋ฉ”์ธ ๋Œ€์‹œ๋ณด๋“œ ํƒญ
/dashboard/compare<CompareTab>Compare ํƒญ
/dashboard/simulator<SimulatorTab>Simulator ํƒญ
/dashboard/target<TargetTab>Target ํƒญ
/profile<Profile>ํ”„๋กœํ•„ ์„ค์ •
/data-input<DataInput>๋ฐ์ดํ„ฐ ์ž…๋ ฅ
/reports<Reports>๋ฆฌํฌํŠธ
/analytics<Analytics>๋ถ„์„ ํ™”๋ฉด

7.2 ์ธ์ฆ ๊ฐ€๋“œ ๋™์ž‘

  • ํ† ํฐ์ด ์—†์œผ๋ฉด ๋ณดํ˜ธ ๊ฒฝ๋กœ ์ ‘๊ทผ ์‹œ /login์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
  • ํ† ํฐ์ด ์žˆ์œผ๋ฉด /, /login, /signup ์ ‘๊ทผ ์‹œ /dashboard๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
  • ์•Œ ์ˆ˜ ์—†๋Š” ๊ฒฝ๋กœ๋Š” ํ† ํฐ ์—ฌ๋ถ€์— ๋”ฐ๋ผ /dashboard ๋˜๋Š” /login์œผ๋กœ ์ •๋ฆฌ

7.3 ํƒญ ์ƒํƒœ ๋™๊ธฐํ™”

  • URL ๊ฒฝ๋กœ(/dashboard/*)์—์„œ activeTab์„ ์—ญ๋งคํ•‘ํ•ด ํ—ค๋” ํƒญ UI์™€ ๋™๊ธฐํ™”
  • ํƒญ ํด๋ฆญ ์‹œ navigate('/dashboard/...') ํ˜ธ์ถœ๋กœ ๋ธŒ๋ผ์šฐ์ € ํžˆ์Šคํ† ๋ฆฌ์™€ ์ž๋™ ์—ฐ๋™
  • ๋ธŒ๋ผ์šฐ์ € ๋’ค๋กœ๊ฐ€๊ธฐ/์•ž์œผ๋กœ๊ฐ€๊ธฐ๋Š” router history๋กœ ์ฒ˜๋ฆฌ

โš™๏ธ 8. ์„ค์น˜ ๋ฐ ์„ค์ • (Installation & Setup)

8.0 ์‚ฌ์ „ ์š”๊ตฌ์‚ฌํ•ญ (Prerequisites)

์†Œํ”„ํŠธ์›จ์–ด๊ถŒ์žฅ ๋ฒ„์ „์šฉ๋„
Python3.11.x๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ๋ฐ PDF/RAG ํŒŒ์ดํ”„๋ผ์ธ
Node.js18+ํ”„๋ก ํŠธ์—”๋“œ ๋นŒ๋“œ
MySQL5.7+์‚ฌ์šฉ์ž ๋ฐ ๋ฐฐ์ถœ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ €์žฅ
OpenAI API Key์œ ํšจ ํ‚ค์ฑ—๋ด‡/์ „๋žต ์ƒ์„ฑ LLM ํ˜ธ์ถœ

8.1 ๋ฐฑ์—”๋“œ ๊ฐ€๋™

# ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๊ธฐ์ค€
python3.11 -m venv .venv
source .venv/bin/activate

pip install -r requirements.txt
pip install -r backend/requirements.txt

# DB ์ดˆ๊ธฐํ™” (์ตœ์ดˆ 1ํšŒ)
cd backend/app
python init_db.py
cd ../..

# ์„œ๋ฒ„ ์‹คํ–‰ (๊ถŒ์žฅ: app ์—”ํŠธ๋ฆฌํฌ์ธํŠธ)
cd backend
uvicorn app.main:app --reload --port 8000

backend/main.py๋Š” PDF ๊ฒ€์ƒ‰/ํ†ต๊ณ„ ๋ณด์กฐ ์—”๋“œํฌ์ธํŠธ๊นŒ์ง€ ํ•จ๊ป˜ ์“ฐ๋Š” ํ†ตํ•ฉ ๋ชจ๋“œ์ž…๋‹ˆ๋‹ค.

8.2 ํ”„๋ก ํŠธ์—”๋“œ ๊ฐ€๋™

cd frontend
npm install
npm run dev

๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:5173 ์ ‘์†

8.3 AI/RAG ์„ค์ •

์˜ต์…˜ A: ์›๊ฒฉ Chroma ์„œ๋ฒ„ ์‚ฌ์šฉ (์šด์˜ ๊ถŒ์žฅ)

CHROMA_HOST=your-chroma-host
CHROMA_PORT=8000
RAG_EMBEDDING_MODEL=BAAI/bge-m3
  • ์ด ๊ฒฝ์šฐ ๋กœ์ปฌ PDF_Extraction/vector_db ํด๋”๊ฐ€ ์—†์–ด๋„ ๋ฉ๋‹ˆ๋‹ค.
  • ์ฑ—๋ด‡์€ ์›๊ฒฉ ์ปฌ๋ ‰์…˜(esg_chunks, esg_pages ๋˜๋Š” esg_documents)์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ B: ๋กœ์ปฌ Persistent Chroma ์‚ฌ์šฉ (๊ฐœ๋ฐœ์šฉ)

pip install -r PDF_Extraction/requirements.txt
cd PDF_Extraction
python src/build_vector_db.py
  • ๊ธฐ๋ณธ ๋กœ์ปฌ ๊ฒฝ๋กœ๋Š” PDF_Extraction/vector_db์ž…๋‹ˆ๋‹ค.
  • ๋ฒกํ„ฐDB๊ฐ€ ์—†์œผ๋ฉด ์ฑ—๋ด‡ API๋Š” ์‹คํ–‰๋˜์ง€๋งŒ RAG ๊ทผ๊ฑฐ ๊ฒ€์ƒ‰ ํ’ˆ์งˆ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ safetensors ๋ณ€ํ™˜/๋ฐฐํฌ (๊ถŒ์žฅ)

BAAI/bge-m3 ์›๋ณธ์€ pytorch_model.bin ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ, ํŒ€ ๊ณต์šฉ ํ™˜๊ฒฝ์—์„œ๋Š” safetensors ๋ณ€ํ™˜๋ณธ์„ ์‚ฌ๋‚ด ๊ฒฝ๋กœ/์•„ํ‹ฐํŒฉํŠธ๋กœ ๋ฐฐํฌํ•ด ์“ฐ๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

cd PDF_Extraction
python src/convert_embedding_to_safetensors.py \
  --source-model BAAI/bge-m3 \
  --output-dir models/bge-m3-safetensors

๋ฐฐํฌ ํ›„ .env์— ๋™์ผ ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

RAG_EMBEDDING_MODEL=/absolute/path/to/models/bge-m3-safetensors

8.4 ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •

ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ .env ์˜ˆ์‹œ:

# --- Database (MySQL) ---
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=esg

# --- Frontend API URL ---
VITE_API_BASE_URL=http://127.0.0.1:8000

# --- JWT ---
JWT_SECRET_KEY=your_jwt_secret_key_here
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60

# --- RAG/LLM ---
VECTOR_DB_PATH=/absolute/path/to/vector_db   # ์„ ํƒ
CHROMA_HOST=                                  # ์›๊ฒฉ ์‚ฌ์šฉ ์‹œ ์„ค์ •
CHROMA_PORT=8000
RAG_EMBEDDING_MODEL=BAAI/bge-m3

# --- Market Data ---
Alpha_Vantage_API=your_alpha_vantage_key
USE_MOCK_DATA=true

# --- Optional ---
OPENAI_API_KEY=sk-...
HF_TOKEN=hf_...

๐Ÿ“Š 9. API ๋ช…์„ธ (API Specification)

FastAPI Swagger UI: http://127.0.0.1:8000/docs

9.1 ์ธ์ฆ API (/auth)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/auth/signupPOSTํšŒ์›๊ฐ€์ž…
/auth/loginPOST๋กœ๊ทธ์ธ(JWT access token ๋ฐœ๊ธ‰)
/auth/meGETํ˜„์žฌ ์‚ฌ์šฉ์ž ์กฐํšŒ (Authorization: Bearer <token>)

9.2 ํ”„๋กœํ•„ API (/profile)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/profile/meGETํ”„๋กœํ•„ ์กฐํšŒ
/profile/mePUTํ”„๋กœํ•„ ์ˆ˜์ • (nickname, company_name, classification, bio)
/profile/me/passwordPOST๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ
/profile/me/emailPOST์ด๋ฉ”์ผ ๋ณ€๊ฒฝ
/profile/me/deletePOST๊ณ„์ • ์‚ญ์ œ
/profile/me/avatarPOST์•„๋ฐ”ํƒ€ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ(multipart/form-data)

9.3 ๋Œ€์‹œ๋ณด๋“œ API (/api/v1/dashboard)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/api/v1/dashboard/companiesGET๊ธฐ์—…๋ณ„ ์ตœ์‹ /์—ฐ๋„๋ณ„ ๋ฐฐ์ถœ ๋ฐ์ดํ„ฐ ๋ชฉ๋ก(์ „์ฒด ๋ฐฐ์ถœ + ๊ตญ๋‚ด/ํ•ด์™ธ ๋ถ„๋ฆฌ ํ•„๋“œ ํฌํ•จ)
/api/v1/dashboard/compare/insightPOSTCompare ํƒญ AI ์ธ์‚ฌ์ดํŠธ ์ƒ์„ฑ

9.4 ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ API (/api/v1/sim)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ์„ค๋ช…
/api/v1/sim/dashboard/market-trendsGET`period=1m3m
/api/v1/sim/dashboard/trend-combinedGETcompany, period, start_year, end_year๋ฆฌ์Šคํฌ ๋น„์šฉ ์ถ”์ด ๊ณ„์‚ฐ

9.5 AI API (/api/v1/ai)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/api/v1/ai/chatPOSTRAG ๊ธฐ๋ฐ˜ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฑ—๋ด‡
/api/v1/ai/strategyPOST์‹œ์žฅ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์ „๋žต ์ƒ์„ฑ
/api/v1/ai/text-to-sqlPOST์ž์—ฐ์–ด ์งˆ์˜ SQL ๋ณ€ํ™˜

9.6 ํ†ตํ•ฉ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ ์ „์šฉ API (backend/main.py)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/GET์„œ๋ฒ„ ์ƒํƒœ
/api/healthGETํ—ฌ์Šค์ฒดํฌ
/api/searchGET๋ฒกํ„ฐ ๊ฒ€์ƒ‰
/api/companiesGET๋ฒกํ„ฐ DB ๊ธฐ์ค€ ๊ธฐ์—… ๋ชฉ๋ก
/api/statsGET๋ฒกํ„ฐ DB ํ†ต๊ณ„

๐Ÿค– 10. AI ๋ชจ๋ธ ํ‰๊ฐ€ (AI Model Evaluation)

ํ”Œ๋žซํผ์˜ ์‹ ๋ขฐ์„ฑ์„ ์œ„ํ•ด ํƒ‘์žฌ๋œ ๋ชจ๋ธ๋“ค์„ ์ •๊ธฐ์ ์œผ๋กœ ์ž๋™ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

  • ์‹คํ–‰ ๋ฐฉ๋ฒ•: python evaluation/evaluate_models.py
  • ํ‰๊ฐ€ ํ•ญ๋ชฉ:
    • RAG ๋‹ต๋ณ€์˜ ์ •๋‹ต์ง€(Answer Key) ๋Œ€๋น„ ์ผ์น˜์œจ
    • Monte Carlo ์ˆ˜๋ ด ์•ˆ์ •์„ฑ (10,000ํšŒ)
    • OLS ํšŒ๊ท€ ๊ณ„์ˆ˜ ์œ ์˜์„ฑ ๋ฐ ์ž”์ฐจ ๋ถ„์„
    • ์ถ”๋ก  ์‹œ๊ฐ„ ๋ฐ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ

๐Ÿ“Œ DB ์Šคํ‚ค๋งˆ ์ฃผ์š” ํ…Œ์ด๋ธ”

users

์ปฌ๋Ÿผ๋ช…ํƒ€์ž…์„ค๋ช…
idINT (PK)์‚ฌ์šฉ์ž ID
emailVARCHAR(255) UNIQUE๋กœ๊ทธ์ธ ์‹๋ณ„์ž
company_nameVARCHAR(255)์†Œ์† ๊ธฐ์—…๋ช…
hashed_passwordVARCHAR(255)ํ•ด์‹œ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ
nicknameVARCHAR(100)ํ‘œ์‹œ ์ด๋ฆ„
classificationVARCHAR(50)๋ถ„๋ฅ˜ ํ…Œ๋งˆ
bioVARCHAR(500)์ž๊ธฐ์†Œ๊ฐœ
profile_image_urlVARCHAR(500) NULLํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ
roleVARCHAR(20)์‚ฌ์šฉ์ž ๊ถŒํ•œ ๋ฌธ์ž์—ด
is_adminBOOLEAN๊ด€๋ฆฌ์ž ์—ฌ๋ถ€
created_atDATETIME์ƒ์„ฑ ์‹œ๊ฐ
updated_atDATETIME์ˆ˜์ • ์‹œ๊ฐ

dashboard_emissions

์ปฌ๋Ÿผ๋ช…ํƒ€์ž…์„ค๋ช…
idINT (PK)๋ ˆ์ฝ”๋“œ ID
company_idINT INDEX๊ธฐ์—… ์‹๋ณ„์ž
company_nameVARCHAR(100) INDEX๊ธฐ์—…๋ช…
yearINT INDEX์—ฐ๋„
scope1 scope2 scope3FLOATScope๋ณ„ ๋ฐฐ์ถœ๋Ÿ‰(์›๋ณธ ์ด๋Ÿ‰)
s1_domestic s2_domestic s3_domesticFLOAT๊ตญ๋‚ด Scope ๋ฐฐ์ถœ๋Ÿ‰(์„ ํƒ ์ปฌ๋Ÿผ)
s1_abroad s2_abroad s3_abroadFLOATํ•ด์™ธ Scope ๋ฐฐ์ถœ๋Ÿ‰(์„ ํƒ ์ปฌ๋Ÿผ)
allowanceFLOAT NULL๋ฌด์ƒ ํ• ๋‹น๋Ÿ‰
revenueBIGINT๋งค์ถœ
energy_intensityFLOAT์—๋„ˆ์ง€ ์ง‘์•ฝ๋„
carbon_intensityFLOAT(S1+S2) ํƒ„์†Œ ์ง‘์•ฝ๋„
carbon_intensity_scope1FLOATScope1 ์ง‘์•ฝ๋„
carbon_intensity_scope2FLOATScope2 ์ง‘์•ฝ๋„
carbon_intensity_scope3FLOATScope3 ์ง‘์•ฝ๋„
base_yearINT๊ธฐ์ค€ ์—ฐ๋„
base_emissionsFLOAT๊ธฐ์ค€ ๋ฐฐ์ถœ๋Ÿ‰
source_doc_idINT์›๋ณธ ๋ฌธ์„œ ID
data_sourceVARCHAR(500)๋ฐ์ดํ„ฐ ์ถœ์ฒ˜
extraction_methodVARCHAR(50)์ถ”์ถœ ๋ฐฉ์‹
is_verifiedBOOLEAN๊ฒ€์ฆ ์—ฌ๋ถ€
created_atDATETIME์ƒ์„ฑ ์‹œ๊ฐ
updated_atDATETIME์ˆ˜์ • ์‹œ๊ฐ

๐Ÿ“… Last Updated: 2026-02-24 ๐Ÿ“„ License: Educational & Research Purpose Only

HDC-BE-REAL/ESG_Dashboard

ESG Web Application with PDF Extraction

Python

0

365 commits

updated Mar 3, 2026

See the code

README

๐ŸŒฟ ESG Carbon Dashboard (Carbon Strategic OS)

AI ๊ธฐ๋ฐ˜ ํƒ„์†Œ ๋ฐฐ์ถœ ๊ด€๋ฆฌ ๋ฐ ์ „๋žต์  ์˜์‚ฌ๊ฒฐ์ • ์ง€์› ํ”Œ๋žซํผ


๐Ÿ“– 1. ํ”„๋กœ์ ํŠธ ๊ฐœ์š” (Project Overview)

ESG Carbon Dashboard๋Š” ๊ธฐ์—…์˜ ํ™˜๊ฒฝ์  ์ฑ…์ž„(Environmental)์„ ๋ฐ์ดํ„ฐ ์ค‘์‹ฌ์˜ ์ „๋žต์  ์ž์‚ฐ์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐœ๋ฐœ๋œ Carbon Strategic OS์ž…๋‹ˆ๋‹ค.

๋‹จ์ˆœํžˆ ๊ณผ๊ฑฐ์˜ ๋ฐฐ์ถœ๋Ÿ‰์„ ๊ธฐ๋กํ•˜๋Š” ๋ฐ ๊ทธ์น˜์ง€ ์•Š๊ณ , ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•ต์‹ฌ ๊ฐ€์น˜๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

  • ์‹ค์‹œ๊ฐ„ ํŠธ๋ž˜ํ‚น: ๊ธ€๋กœ๋ฒŒ ํƒ„์†Œ ์‹œ์žฅ(EU-ETS, K-ETS)๊ณผ ์—๋„ˆ์ง€ ๊ฐ€๊ฒฉ(WTI)์„ ์—ฐ๋™ํ•œ ์‹ค์‹œ๊ฐ„ ๋ฆฌ์Šคํฌ ๋ถ„์„.
  • ๊ฒฝ์Ÿ์‚ฌ ๋ฒค์น˜๋งˆํ‚น: ํƒ„์†Œ ์ง‘์•ฝ๋„(Carbon Intensity) ๊ธฐ์ค€ ๋™์ข… ์—…๊ณ„ ๋‚ด ์ˆœ์œ„ ๋ฐ ๊ฒฉ์ฐจ ์‹œ๊ฐํ™”.
  • K-ETS ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ: ๊ตญ๋‚ด/ํ•ด์™ธ ๋ฐฐ์ถœ์„ ๋ถ„๋ฆฌํ•ด ์ˆœ๋…ธ์ถœ๋Ÿ‰, ์ค€์ˆ˜๋น„์šฉ, ํ†ตํ•ฉ ์˜ˆ์‚ฐ ๋ฆฌ์Šคํฌ๋ฅผ ๋‹จ๊ณ„์ ์œผ๋กœ ๊ณ„์‚ฐ.
  • ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ์˜์‚ฌ๊ฒฐ์ •: SBTi ๊ธฐ๋ฐ˜ ๊ฐ์ถ• ๊ฒฝ๋กœ์™€ ๋ชฉํ‘œ ๋‹ฌ์„ฑ ํ™•๋ฅ (Monte Carlo)์„ ์ •๋Ÿ‰์ ์œผ๋กœ ์ œ์‹œํ•˜์—ฌ ์‹คํ–‰ ์šฐ์„ ์ˆœ์œ„ ๊ฒฐ์ • ์ง€์›.
  • ์ง€์‹ ์ฆ๊ฐ• ์งˆ์˜์‘๋‹ต: RAG(Retrieval-Augmented Generation) ๊ธฐ์ˆ ์„ ํ†ตํ•ด ๋น„์ •ํ˜• ESG ๋ณด๊ณ ์„œ์—์„œ ์ฆ‰๊ฐ์ ์ธ ์ „๋žต ์ธ์‚ฌ์ดํŠธ๋ฅผ ์ถ”์ถœ.

์ด ํ”„๋กœ์ ํŠธ๋Š” ๊ฐœ๋ฐœ์ž๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ESG ์‹ค๋ฌด์ž, CFO, ๊ทธ๋ฆฌ๊ณ  ์ง€์† ๊ฐ€๋Šฅ์„ฑ ์ „๋žต๊ฐ€๊ฐ€ ์‹ค๋ฌด์—์„œ ์ฆ‰์‹œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์˜ ์ „๋ฌธ ๊ธฐ์ˆ  ๋„๊ตฌ๋ฅผ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ“‘ 2. ๋ชฉ์ฐจ (Table of Contents)

  1. ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜
  2. ํ•ต์‹ฌ ๊ธฐ๋Šฅ ๋ฐ ์„ค๊ณ„ ์˜๋„
  3. ๊ธฐ์ˆ  ์Šคํƒ ๋ฐ ๋ชจ๋“ˆ ์—ฐ๋™
  4. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ
  5. ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ๊ตฌ์กฐ
  6. ์„ค์น˜ ๋ฐ ์„ค์ •
  7. API ๋ช…์„ธ
  8. AI ๋ชจ๋ธ ํ‰๊ฐ€

๐Ÿ“ 3. ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ (System Architecture)

3.1 ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ

graph TB
    subgraph "Client Layer"
        Browser[์›น ๋ธŒ๋ผ์šฐ์ €]
    end

    subgraph "Frontend (React 18 + TypeScript + Vite)"
        UI[UI Components<br/>Recharts / TailwindCSS 4]
        State[State Management<br/>React Hooks + localStorage]
        Router[View State Router<br/>URL Query Params + History API]
    end

    subgraph "Backend (FastAPI + Uvicorn, Port 8000)"
        Auth[Auth Router<br/>/auth]
        Profile[Profile Router<br/>/profile]
        Dashboard[Dashboard Router<br/>/api/v1/dashboard]
        Sim[Simulator Router<br/>/api/v1/sim]
        AI[AI Router<br/>/api/v1/ai]
    end

    subgraph "Data & AI Layer"
        MySQL[(MySQL DB<br/>users / dashboard_emissions)]
        ChromaDB[(ChromaDB<br/>Vector Store / RAG)]
        OpenAI[OpenAI API<br/>gpt-4o / gpt-4o-mini]
        BGE[BGE Embedding / Reranker<br/>bge-m3, bge-reranker-v2-m3]
    end

    subgraph "External Data Sources"
        yfinance[yfinance / yahoo_fin<br/>EU-ETS ๊ฐ€๊ฒฉ]
        FDR[FinanceDataReader<br/>K-ETS KAU ๊ฐ€๊ฒฉ]
    end

    Browser --> UI
    UI --> State --> Router
    Router -->|Axios HTTP/REST| Auth & Profile & Dashboard & Sim & AI
    Auth --> MySQL
    Profile --> MySQL
    Dashboard --> MySQL
    Sim --> yfinance & FDR
    AI --> ChromaDB & OpenAI
    ChromaDB --> BGE

๐Ÿš€ 4. ํ•ต์‹ฌ ๊ธฐ๋Šฅ ๋ฐ ์„ค๊ณ„ ์˜๋„ (Core Features)

4.1 Dashboard Tab (๋ฐฐ์ถœ๋Ÿ‰ ํ†ตํ•ฉ ๋Œ€์‹œ๋ณด๋“œ)

image
  • ์—ญํ• (Role): ๊ธฐ์—…์˜ Scope 1, 2, 3 ๋ฐฐ์ถœ ํ˜„ํ™ฉ ๋ฐ ์žฌ๋ฌด ๋ฆฌ์Šคํฌ ์ง€ํ‘œ๋ฅผ ํ•œ๋ˆˆ์— ์‹œ๊ฐํ™”.
  • ์˜๋„(Purpose):
    • ์ฆ‰๊ฐ์ ์ธ ํ˜„ํ™ฉ ํŒŒ์•…: ๊ฒฝ์˜์ง„์ด 4๊ฐœ์˜ KPI ์นด๋“œ(์ด ํƒ„์†Œ ๋ฐฐ์ถœ๋Ÿ‰, ํƒ„์†Œ ์ง‘์•ฝ๋„, ๋ฐฐ์ถœ๊ถŒ ๊ฑฐ๋ž˜ ๋‹จ๊ฐ€, SBTi ๋‹ฌ์„ฑ ํ™•๋ฅ )๋ฅผ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•˜๋„๋ก ์„ค๊ณ„.
    • Scope๋ณ„ ๋ฐฐ์ถœ ๊ธฐ์—ฌ๋„: Scope๋ณ„ ๋ฐฐ์ถœ๋Ÿ‰ ์ˆ˜์น˜์™€ ๋น„์ค‘(%)์„ ์‹œ๊ฐํ™”.
    • ๊ถค์  ์‹œ๊ฐํ™”: 2021๋…„๋ถ€ํ„ฐ์˜ ์‹ค์ œ ๋ฐฐ์ถœ๋Ÿ‰ ์ถ”์ด์™€ ํšŒ๊ท€ ์˜ˆ์ธก๊ฐ’์„ Scope๋ณ„๋กœ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋„๋ก ์‹œ๊ฐํ™”.
    • ๋ฐ”๋กœ๊ฐ€๊ธฐ ์นด๋“œ: KPI ์นด๋“œ ํด๋ฆญ ์‹œ ๊ด€๋ จ ํƒญ(๊ฒฝ์Ÿ์‚ฌ ๋น„๊ต, ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ, ๋ชฉํ‘œ ๊ด€๋ฆฌ)์œผ๋กœ ์ฆ‰์‹œ ์ด๋™.
  • KPI ์นด๋“œ ๊ตฌ์„ฑ:
    1. ์ด ๋ฐฐ์ถœ๋Ÿ‰ (Scope 1+2): tCOโ‚‚e
    2. ํƒ„์†Œ ์ง‘์•ฝ๋„: ํ•ด๋‹น ๊ธฐ์—…์˜ ํƒ„์†Œ ์ง‘์•ฝ๋„(tCOโ‚‚e / ๋งค์ถœ 1์–ต์›) ๋˜๋Š” ์—๋„ˆ์ง€ ์ง‘์•ฝ๋„(TJ/์–ต์›)๋กœ ์ „ํ™˜ ๊ฐ€๋Šฅ
    3. K-ETS: ์‹ค์‹œ๊ฐ„ ํ•œ๊ตญ ๋ฐฐ์ถœ๊ถŒ ๊ฑฐ๋ž˜ ๋‹จ๊ฐ€
    4. SBTi ๋‹ฌ์„ฑ ํ™•๋ฅ : SBTi ๊ตญ์ œ ํ‘œ์ค€ ๊ธฐ์ค€์œผ๋กœ Monte Carlo ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๊ฒฐ๊ณผ (%) ๊ฐ์ถ• ๋‹ฌ์„ฑ ํ™•๋ฅ ์„ ํ‘œ๊ธฐ

4.2 Compare Tab (๊ฒฝ์Ÿ์‚ฌ ๋น„๊ต ๋ถ„์„)

image
  • ์—ญํ• (Role): ๋™์ผ ์—…์ข… ๊ธฐ์—…์˜ ํƒ„์†Œ/์—๋„ˆ์ง€ ์ง‘์•ฝ๋„๋ฅผ ์ •๋ ฌํ•˜์—ฌ ์ƒ๋Œ€ ํฌ์ง€์…˜์„ ๋น ๋ฅด๊ฒŒ ํŒŒ์•….
  • ํ•ต์‹ฌ ๋™์ž‘:
    • ์ง‘์•ฝ๋„ ๋ชจ๋“œ ์ „ํ™˜: revenue(ํƒ„์†Œ ์ง‘์•ฝ๋„), energy(์—๋„ˆ์ง€ ์ง‘์•ฝ๋„)
    • Scope ํ† ๊ธ€: S1/S2 ๋ฐ˜์˜ ์—ฌ๋ถ€๋ฅผ ์ฆ‰์‹œ ์ฐจํŠธ ๊ณ„์‚ฐ์— ๋ฐ˜์˜
    • ๊ธฐ์ค€์„  ์ž๋™ ๊ณ„์‚ฐ: ์ƒ์œ„ 10% ๋ฐ ์ค‘์•™๊ฐ’ ์ž„๊ณ„์„  ์˜ค๋ฒ„๋ ˆ์ด
    • ์นด๋“œ ์„ ํƒ ์—ฐ๋™: ์„ ํƒ ๊ธฐ์—… ๊ฐ•์กฐ + ์ธ์‚ฌ์ดํŠธ ๋‚ด์šฉ ๋™๊ธฐํ™”
    • ์‹คํ–‰ ์—ฐ๊ณ„: ์„ธ๋ถ€ ์‹คํ–‰ ๊ณ„ํš ๋ฒ„ํŠผ์œผ๋กœ Simulator ํƒญ ์ด๋™
  • ๊ธฐ์ˆ  ์š”์†Œ:
    • CompareTab.tsx: Recharts BarChart, ReferenceLine, ๋™์  ์ƒ‰์ƒ ์…€ ๋ Œ๋”๋ง
    • ๋ฐฑ์—”๋“œ ์—ฐ๊ณ„: POST /api/v1/dashboard/compare/insight๋กœ AI ์ธ์‚ฌ์ดํŠธ ์ƒ์„ฑ
    • ๋„ค๋น„๊ฒŒ์ด์…˜: navigateTo('dashboard', 'simulator')

4.3 Simulator Tab (K-ETS ์ค€์ˆ˜ ๋น„์šฉ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ)

image image
  • ์—ญํ• (Role): ๊ตญ๋‚ด ์ง์ ‘ ๋ฐฐ์ถœ ์ดํ–‰๋น„์šฉ๊ณผ ํ•ด์™ธ ๋…ธ์ถœ๋น„์šฉ์„ ํ†ตํ•ฉํ•ด ์—ฐ๊ฐ„ ํƒ„์†Œ ์˜ˆ์‚ฐ ๊ด€์ ์˜ ์˜์‚ฌ๊ฒฐ์ •์„ ์ง€์›.
  • 4๋‹จ๊ณ„ ๊ตฌ์กฐ:
    1. ๊ตญ๋‚ด ์ง์ ‘ ํƒ„์†Œ๋Ÿ‰: ์˜ˆ์ƒ๋ฐฐ์ถœ๋Ÿ‰, ๋ฌด์ƒํ• ๋‹น, ์ˆœ๋…ธ์ถœ๋Ÿ‰(Net Exposure), ์ปดํ”Œ๋ผ์ด์–ธ์Šค ๋น„์šฉ ๊ณ„์‚ฐ
    2. ์ „๋žต ๋ฐฐ๋ถ„: ์ˆœ๋…ธ์ถœ๋Ÿ‰ ์ค‘ ์šฐ์„  ์ง‘ํ–‰/์ž”์—ฌ ์ดํ–‰ ๋น„์œจ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
    3. ํ•ด์™ธ ํƒ„์†Œ ๋ฐฐ์ถœ๋Ÿ‰: ํ•ด์™ธ S1+S2์™€ EUA, EUR/KRW ํ™˜์œจ๋กœ ํ•ด์™ธ ์˜ˆ์ƒ๋น„์šฉ ์‚ฐ์ถœ
    4. ๊ฒฐ๊ณผ ์š”์•ฝ: ๊ตญ๋‚ด+ํ•ด์™ธ ํ†ตํ•ฉ ์ด๊ณ„์™€ ์˜ˆ์‚ฐ ๋Œ€๋น„ ๋ฆฌ์Šคํฌ ๋“ฑ๊ธ‰ ์ œ๊ณต
  • ์‹œ๋‚˜๋ฆฌ์˜ค ์ž…๋ ฅ๊ฐ’:
    • ETS ๊ฐ€๊ฒฉ(์‹ค์‹œ๊ฐ„/์ง์ ‘ ์ž…๋ ฅ)
    • ๋ฐฐ์ถœ๋Ÿ‰ ๋ณ€๋™(%)
    • ๋ฌด์ƒํ• ๋‹น ์ •์ฑ… ๋ณ€๋™
    • ๊ฒฝ๋งค ์กฐ๋‹ฌ ๋น„์ค‘
    • ์—ฐ๊ฐ„ ํƒ„์†Œ ์˜ˆ์‚ฐ(์‚ฌ์šฉ์ž ์ง์ ‘ ์ž…๋ ฅ)
  • ๊ณ„์‚ฐ ๊ธฐ์ค€(ํ•ต์‹ฌ):
    • ์ˆœ๋…ธ์ถœ๋Ÿ‰ = ์กฐ์ • ๋ฐฐ์ถœ๋Ÿ‰ - ์กฐ์ • ๋ฌด์ƒํ• ๋‹น๋Ÿ‰
    • ์ปดํ”Œ๋ผ์ด์–ธ์Šค ๋น„์šฉ = ์ˆœ๋…ธ์ถœ๋Ÿ‰ ร— ์‹คํšจ ํƒ„์†Œ๊ฐ€๊ฒฉ(๊ฒฝ๋งค ํ• ์ธ ๋ฐ˜์˜)
    • ํ•ด์™ธ ์˜ˆ์ƒ๋น„์šฉ = ํ•ด์™ธ S1+S2 ร— EUA ร— EUR/KRW
    • ํ†ตํ•ฉ ์ด๊ณ„ = ๊ตญ๋‚ด ์ด ํƒ„์†Œ๋น„์šฉ + ํ•ด์™ธ ์˜ˆ์ƒ๋น„์šฉ
  • ๋ฐ์ดํ„ฐ ๊ธฐ์ค€ ๋ถ„๋ฆฌ:
    • Simulator: ๊ตญ๋‚ด ์ง์ ‘ ๋ฐฐ์ถœ(s1Domestic, s2Domestic) ์šฐ์„  ์‚ฌ์šฉ
    • Dashboard/Compare/Target: ์ „์ฒด ๋ฐฐ์ถœ(s1, s2, s3) ์‚ฌ์šฉ
  • ๊ธฐ์ˆ  ์š”์†Œ:
    • ํ”„๋ก ํŠธ: SimulatorTab.tsx (์ƒํƒœ ๊ธฐ๋ฐ˜ ์ฆ‰์‹œ ์žฌ๊ณ„์‚ฐ)
    • ๋ฐฑ์—”๋“œ: GET /api/v1/sim/dashboard/market-trends
    • ์‹œ์žฅ ๋ฐ์ดํ„ฐ: yfinance(EU-ETS), FinanceDataReader(K-ETS)
    • ํ™˜์œจ ๋ฐ์ดํ„ฐ: open.er-api.com EUR ๊ธฐ์ค€ ์‹ค์‹œ๊ฐ„ ์กฐํšŒ + fallback(1450)

4.4 Target Tab (SBTi ๋ชฉํ‘œ ๊ด€๋ฆฌ)

image
  • ์—ญํ• (Role): SBTi ๊ธฐ์ค€์—ฐ๋„(2021) ๋Œ€๋น„ ๊ฐ์ถ• ๊ฒฝ๋กœ์™€ ํ˜„์žฌ ์‹ค์  ๊ฐ„ ๊ฒฉ์ฐจ๋ฅผ ์‹œ๊ฐํ™”ํ•˜๊ณ  2030/2050 ๋ชฉํ‘œ ๋‹ฌ์„ฑ ๊ฐ€๋Šฅ์„ฑ์„ ์ •๋Ÿ‰ํ™”.

  • ์˜๋„(Purpose):

    • ๋ชฉํ‘œ ์ •๋ ฌ: ๊ธฐ์ค€ ๋ฐฐ์ถœ๋Ÿ‰(2021), ํ˜„์žฌ(์ตœ์‹ ) ๋ฐฐ์ถœ๋Ÿ‰, SBTi ๋ชฉํ‘œ ๋‹ฌ์„ฑ ์—ฌ๋ถ€๋ฅผ ํ•œ ํ™”๋ฉด์—์„œ ํ™•์ธ.
    • ํ™•๋ฅ  ๊ธฐ๋ฐ˜ ํŒ๋‹จ: ๋กœ๊ทธ ํšŒ๊ท€ Monte Carlo(10,000ํšŒ) ๊ธฐ๋ฐ˜ 2030 ๋ชฉํ‘œ ๋‹ฌ์„ฑ ํ™•๋ฅ  ์ œ๊ณต.
    • Net Zero 2050 ์ถ”์ : ํ˜„์žฌ ๊ฐ์ถ•๋ฅ ๊ณผ 2050 ๋ชฉํ‘œ(90%+ ๊ฐ์ถ•) ๊ฐ„ ๊ฒฉ์ฐจ ์‹ค์‹œ๊ฐ„ ํ‘œ์‹œ.
    • ์ •ํ™•ํ•œ ๋ชฉํ‘œ๋‹ฌ์„ฑ๋„ ํŒ์ •: ํ˜„์žฌ ์—ฐ๋„(2026)๊ฐ€ ์•„๋‹Œ ์ตœ์‹  ๋ฐ์ดํ„ฐ ์—ฐ๋„(latestDataYear, ์ตœ์‹  ๋ฐœ๊ฐ„๋œ ESG๋ณด๊ณ ์„œ์—์„œ์˜ ์—ฐ๋„ ๊ธฐ์ค€์ด๋ฉฐ ํ˜„์žฌ๋Š” 2024๋…„)๋กœ ์„ค์ •ํ•˜์—ฌ ๋™์ผ ์—ฐ๋„ ๊ธฐ์ค€์œผ๋กœ ์ •ํ™•ํžˆ ํŒ์ •.
  • KPI ์นด๋“œ ๊ตฌ์„ฑ:

    1. ๊ธฐ์ค€ ๋ฐฐ์ถœ๋Ÿ‰ (2021): tCOโ‚‚e
    2. ์ตœ์‹  ๋ฐฐ์ถœ๋Ÿ‰: tCOโ‚‚e + 2021๋…„ ๋Œ€๋น„ % ๊ฐ์ถ•
    3. SBTi ๋‹ฌ์„ฑ ์—ฌ๋ถ€: ๋ชฉํ‘œ ๋Œ€๋น„ ๊ฒฉ์ฐจ๋ฅผ ํŒ๋‹จํ•˜์—ฌ ๋ช…์‹œ
    4. Net Zero 2050: ํ•„์š” ์ด ๊ฐ์ถ•๋Ÿ‰(90%+), ํ˜„์žฌ ๋‹ฌ์„ฑ(%), ์ž”์—ฌ ๊ฒฉ์ฐจ(%)
  • ์˜ˆ์ธก ๋ฐฉ๋ฒ•๋ก :

    ๋ชจ๋ธ: log(E_t) = ฮฑ + ฮฒ*t  (๋กœ๊ทธ-์„ ํ˜• OLS ํšŒ๊ท€)
    ๊ฐ์ถ• ๋ชฉํ‘œ: ์—ฐ๊ฐ„ 4.2% (SBTi ์ ˆ๋Œ€ ๊ฐ์ถ• ๊ธฐ์ค€)
    Monte Carlo: 10,000ํšŒ ์ƒ˜ํ”Œ๋ง โ†’ 2030 ๋‹ฌ์„ฑ ํ™•๋ฅ  ๊ณ„์‚ฐ
    
  • ๊ธฐ์ˆ  ์š”์†Œ: OLS ํšŒ๊ท€, Monte Carlo ์‹œ๋ฎฌ๋ ˆ์ด์…˜(10,000ํšŒ), Recharts(๊ถค์  ์ฐจํŠธ).


4.5 ChatBot (AI ์ „๋žต ์—์ด์ „ํŠธ)

image
  • ์—ญํ• (Role): ESG ๋ฌธ์„œ ๊ธฐ๋ฐ˜ ์งˆ์˜์‘๋‹ต + ์‹œ์žฅ/์ „๋žต ๋งฅ๋ฝํ˜• ๋‹ต๋ณ€ ์ œ๊ณต

  • ํ•ต์‹ฌ ๋™์ž‘:

    • ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต: ํ† ํฐ ๋‹จ์œ„ ์ถœ๋ ฅ์œผ๋กœ ์ฒด๊ฐ ์‘๋‹ต ์ง€์—ฐ ์ตœ์†Œํ™”
    • ๋Œ€ํ™” ๋ฌธ๋งฅ ์œ ์ง€: ์ด์ „ ๋Œ€ํ™”(history)์™€ ์„ ํƒ ํšŒ์‚ฌ ์ปจํ…์ŠคํŠธ ์ „๋‹ฌ
    • ๋ฆฌํฌํŠธ ์Šค์ฝ”ํ”„ ์ œ์–ด: ์ตœ์‹ /์ „์ฒด ๋ณด๊ณ ์„œ ๋ฒ”์œ„ ์„ ํƒ ๊ฐ€๋Šฅ
    • ์ „๋žต ๋ณด์กฐ: ๋ณ„๋„ strategy ์—”๋“œํฌ์ธํŠธ๋กœ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ ์ „๋žต ๋ฌธ์•ˆ ์ƒ์„ฑ
  • ๊ธฐ์ˆ  ์š”์†Œ:

    • API: POST /api/v1/ai/chat (StreamingResponse), POST /api/v1/ai/strategy, POST /api/v1/ai/text-to-sql
    • RAG: ์งˆ๋ฌธ ์˜๋„ ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ… ํ›„ ChromaDB ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰(semantic+BM25) + rerank
    • LLM: OpenAI(gpt-4o, gpt-4o-mini) ์‘๋‹ต ์ƒ์„ฑ
  • RAG ํŒŒ์ดํ”„๋ผ์ธ:

    ์‚ฌ์šฉ์ž ์งˆ๋ฌธ
      โ†’ ์˜๋„ ํŒ๋ณ„(RAG ํ•„์š” ์—ฌ๋ถ€)
      โ†’ [RAG ON] ChromaDB ๊ฒ€์ƒ‰(semantic/BM25 + rerank) + ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•„ํ„ฐ
      โ†’ ์ปจํ…์ŠคํŠธ + ๋Œ€ํ™” ํžˆ์Šคํ† ๋ฆฌ + ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ
      โ†’ OpenAI ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต
    
  • ๊ธฐ์ˆ  ์š”์†Œ: ChromaDB, Sentence-Transformers(BAAI/bge-m3), CrossEncoder reranker, FastAPI StreamingResponse, ํ”„๋ก ํŠธ ReadableStream ์ฒ˜๋ฆฌ.


4.6 ์ธ์ฆ ์‹œ์Šคํ…œ (Authentication)

image image
  • ์—ญํ• (Role): ์‚ฌ์šฉ์ž ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ, JWT ์„ธ์…˜ ๊ด€๋ฆฌ.

  • ์˜๋„(Purpose):

    • ์ ‘๊ทผ ์ œ์–ด: ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋งŒ ๋Œ€์‹œ๋ณด๋“œ ๊ธฐ๋Šฅ์— ์ ‘๊ทผ ๊ฐ€๋Šฅ.
    • ๊ฐœ์ธํ™”: ์‚ฌ์šฉ์ž๋ณ„ ํ”„๋กœํ•„ ์„ค์ • ๋ฐ ๊ธฐ์—… ์ปจํ…์ŠคํŠธ ์—ฐ๋™.
  • ์ธ์ฆ ํ๋ฆ„:

    Signup โ†’ pbkdf2_sha256 ํ•ด์‹œ ์ €์žฅ โ†’ User ์ €์žฅ(MySQL)
    Login  โ†’ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์ฆ โ†’ JWT ๋ฐœ๊ธ‰ (HS256, ๊ธฐ๋ณธ 60๋ถ„)
           โ†’ localStorage ์ €์žฅ โ†’ WelcomePage ์ด๋™ (3์ดˆ ์ž๋™)
    Refresh โ†’ token ์กด์žฌ ์‹œ dashboard ์ž๋™ ๋ณต์›
    
  • ๊ธฐ์ˆ  ์š”์†Œ: passlib(pbkdf2_sha256), JWT(python-jose), SQLAlchemy (User ๋ชจ๋ธ).


4.7 ํ”„๋กœํ•„ ์„ค์ • (Profile Settings)

image
  • ์—ญํ• (Role): ์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„, ๋ถ„๋ฅ˜, ์ž๊ธฐ์†Œ๊ฐœ, ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋“ฑ ๊ฐœ์ธ ์ •๋ณด ๊ด€๋ฆฌ.
  • ์˜๋„(Purpose):
    • ESG ์•„์ด๋ดํ‹ฐํ‹ฐ: ๋ฉธ์ข…์œ„๊ธฐ์ข…(ํฌ์œ ๋ฅ˜/์กฐ๋ฅ˜/์–‘์„œ๋ฅ˜ ๋“ฑ) ํ…Œ๋งˆ๋ฅผ ์ ์šฉํ•˜์—ฌ ํ™˜๊ฒฝ์  ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ.
    • ๋™์  ํ€ด์ฆˆ ๋ฑƒ์ง€(QuizBadge): ๋‹‰๋„ค์ž„์—์„œ ๋™๋ฌผ ํ‚ค์›Œ๋“œ(๋ˆˆํ‘œ๋ฒ”/๋ฌผ๋ฐฉ๊ฐœ/ํŒ๋‹ค/ํ˜ธ๋ž‘์ด/๋…์ˆ˜๋ฆฌ) ๊ฐ์ง€ ์‹œ ํ•ด๋‹น ๋ฉธ์ข…์œ„๊ธฐ ๋™๋ฌผ ํ€ด์ฆˆ ํ‘œ์‹œ, ๋ฏธ๊ฐ์ง€ ์‹œ ํƒ„์†Œ์ค‘๋ฆฝ ๊ธฐ๋ณธ ํ€ด์ฆˆ ํ‘œ์‹œ.
    • ํšŒ์› ํƒˆํ‡ด: ํ™•์ธ ๋ชจ๋‹ฌ(๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌํ™•์ธ)๊ณผ ํ•จ๊ป˜ ๊ณ„์ • ์‚ญ์ œ ์ง€์›.
  • ํ”„๋กœํ•„ ํ•„๋“œ: ๋‹‰๋„ค์ž„, ๋ฉธ์ข…์œ„๊ธฐ์ข… ๋ถ„๋ฅ˜(๋“œ๋กญ๋‹ค์šด), ์†Œ์† ๊ธฐ์—…๋ช…(API ๋ชฉ๋ก ๋“œ๋กญ๋‹ค์šด ์„ ํƒ), ์ž๊ธฐ์†Œ๊ฐœ(500์ž), ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL.

๐Ÿ› ๏ธ 5. ๊ธฐ์ˆ  ์Šคํƒ ๋ฐ ๋ชจ๋“ˆ ์—ฐ๋™ (Tech Stack & Implementation)

5.1 Frontend

๊ธฐ์ˆ ๋ฒ„์ „์šฉ๋„
React18์„ ์–ธ์  UI ๋ฐ ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜
TypeScript5.2๊ฐ•ํ•œ ํƒ€์ž… ์ฒดํฌ๋กœ ๋Œ€๊ทœ๋ชจ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ๋„ ๋ Œ๋”๋ง ์•ˆ์ •์„ฑ ํ™•๋ณด
Vite5.1๋น ๋ฅธ HMR ๋ฐ ์ตœ์ ํ™”๋œ ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ
TailwindCSS4.0์œ ํ‹ธ๋ฆฌํ‹ฐ ๊ธฐ๋ฐ˜ ์Šคํƒ€์ผ๋ง ๋ฐ ์ปดํฌ๋„ŒํŠธ UI ์ผ๊ด€์„ฑ ๊ด€๋ฆฌ
Recharts2.12์‹œ๊ณ„์—ด ์‹œ์žฅ ๋ฐ์ดํ„ฐ ๋ฐ ๋น„๊ต ์ฐจํŠธ (Line, Bar, Pie, Area)
Axios + Fetch-์ผ๋ฐ˜ REST ํ†ต์‹  + ์ฑ—๋ด‡ ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต ์ฒ˜๋ฆฌ
Framer Motion-ํŽ˜์ด์ง€ ์ „ํ™˜ ๋ฐ ์ปดํฌ๋„ŒํŠธ ์• ๋‹ˆ๋ฉ”์ด์…˜
Lucide React-์•„์ด์ฝ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
CVA (class-variance-authority)-์กฐ๊ฑด๋ถ€ Tailwind ํด๋ž˜์Šค ๊ด€๋ฆฌ

5.2 Backend & Data

๊ธฐ์ˆ ์šฉ๋„
FastAPI & UvicornAPI ์„œ๋ฒ„ ๋ฐ ๋น„๋™๊ธฐ ์š”์ฒญ ์ฒ˜๋ฆฌ
SQLAlchemy & MySQL (PyMySQL)์‚ฌ์šฉ์ž/๋ฐฐ์ถœ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฐ ORM ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ
yfinance / yahoo_finEU-ETS ๊ฐ€๊ฒฉ ๋ฐ์ดํ„ฐ ์กฐํšŒ ๋ฐ fallback
FinanceDataReaderK-ETS(KAU) ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ ์กฐํšŒ
passlib + python-jose๋น„๋ฐ€๋ฒˆํ˜ธ ํ•ด์‹ฑ(pbkdf2_sha256) ๋ฐ JWT ์ธ์ฆ
python-joseJWT ํ† ํฐ ์ƒ์„ฑ ๋ฐ ๊ฒ€์ฆ (HS256)

5.3 AI & NLP

๊ธฐ์ˆ ์šฉ๋„
OpenAI API์ฑ—๋ด‡/์ „๋žต ์ƒ์„ฑ LLM ์‘๋‹ต ์—”์ง„ (gpt-4o, gpt-4o-mini)
ChromaDBRAG ๋ฒกํ„ฐ ์ €์žฅ์†Œ (๋กœ์ปฌ Persistent ๋˜๋Š” ์›๊ฒฉ HTTP ์„œ๋ฒ„)
Sentence-Transformers์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ (BAAI/bge-m3)
CrossEncoder๋ฆฌ๋žญํ‚น ๋ชจ๋ธ (BAAI/bge-reranker-v2-m3)
Docling & PyMuPDFPDF ๊ตฌ์กฐ ์ถ”์ถœ ๋ฐ ๋ฒกํ„ฐํ™” ์ „์ฒ˜๋ฆฌ

๐Ÿ“‚ 6. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ (Project Structure)

ESG_Dashboard/
โ”œโ”€โ”€ requirements.txt                  # ๊ณตํ†ต Python ์˜์กด์„ฑ (backend/PDF ๊ณต์šฉ)
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ ํŽ˜์ด์ง€_๋ผ์šฐํŒ…_๊ตฌ์กฐ.md
โ”œโ”€โ”€ start_all.sh                      # ๋กœ์ปฌ ๋™์‹œ ์‹คํ–‰ ์Šคํฌ๋ฆฝํŠธ
โ”œโ”€โ”€ backend/
โ”‚   โ”œโ”€โ”€ requirements.txt              # ๋ฐฑ์—”๋“œ ์ „์šฉ ์˜์กด์„ฑ
โ”‚   โ”œโ”€โ”€ main.py                       # ํ†ตํ•ฉ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ (RAG ๋ณด์กฐ ์—”๋“œํฌ์ธํŠธ ํฌํ•จ)
โ”‚   โ””โ”€โ”€ app/
โ”‚       โ”œโ”€โ”€ main.py                   # ์ฝ”์–ด API ์„œ๋ฒ„ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ
โ”‚       โ”œโ”€โ”€ config.py                 # .env ๊ธฐ๋ฐ˜ ์„ค์ • ๋กœ๋”
โ”‚       โ”œโ”€โ”€ database.py
โ”‚       โ”œโ”€โ”€ models.py                 # User, DashboardEmission
โ”‚       โ”œโ”€โ”€ schemas.py
โ”‚       โ”œโ”€โ”€ init_db.py
โ”‚       โ”œโ”€โ”€ routers/                  # auth/profile/dashboard/simulator/ai
โ”‚       โ”œโ”€โ”€ services/                 # ai_service, market_data ๋“ฑ
โ”‚       โ””โ”€โ”€ static/profile/           # ์—…๋กœ๋“œ๋œ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€
โ”œโ”€โ”€ frontend/
โ”‚   โ”œโ”€โ”€ package.json
โ”‚   โ”œโ”€โ”€ package-lock.json
โ”‚   โ”œโ”€โ”€ vite.config.ts
โ”‚   โ””โ”€โ”€ src/
โ”‚       โ”œโ”€โ”€ App.tsx                   # react-router-dom ๊ฒฝ๋กœ ๋ผ์šฐํŒ… + ํƒญ ์ƒํƒœ ๊ด€๋ฆฌ
โ”‚       โ”œโ”€โ”€ config.ts                 # API base URL ๊ตฌ์„ฑ
โ”‚       โ”œโ”€โ”€ services/                 # auth/profile/market/ai API ํ˜ธ์ถœ
โ”‚       โ”œโ”€โ”€ features/                 # ํƒญ/ํŽ˜์ด์ง€๋ณ„ UI
โ”‚       โ””โ”€โ”€ types/
โ”œโ”€โ”€ PDF_Extraction/
โ”‚   โ”œโ”€โ”€ requirements.txt              # PDF/RAG ํŒŒ์ดํ”„๋ผ์ธ ์˜์กด์„ฑ
โ”‚   โ”œโ”€โ”€ src/                          # ์ถ”์ถœ/์ ์žฌ/๋ฒกํ„ฐDB ๊ตฌ์ถ• ์Šคํฌ๋ฆฝํŠธ
โ”‚   โ”œโ”€โ”€ docs/
โ”‚   โ””โ”€โ”€ vector_db/                    # (์„ ํƒ) ๋กœ์ปฌ Chroma Persistent ์ €์žฅ ๊ฒฝ๋กœ
โ””โ”€โ”€ evaluation/
    โ””โ”€โ”€ evaluate_models.py

[!NOTE] PDF_Extraction/vector_db/๋Š” ๋กœ์ปฌ Persistent Chroma๋ฅผ ์“ธ ๋•Œ์˜ ๊ธฐ๋ณธ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค. ์›๊ฒฉ Chroma ์„œ๋ฒ„(CHROMA_HOST, CHROMA_PORT)๋ฅผ ์“ฐ๋ฉด ์ด ํด๋”๊ฐ€ ์—†์–ด๋„ ์ฑ—๋ด‡์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ—บ๏ธ 7. ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ๊ตฌ์กฐ (Page Routing)

react-router-dom ๊ธฐ๋ฐ˜ ๊ฒฝ๋กœ ๋ผ์šฐํŒ… + activeTab ์ƒํƒœ ๋™๊ธฐํ™” ์ƒ์„ธ ์„ค๊ณ„์„œ: ํŽ˜์ด์ง€_๋ผ์šฐํŒ…_๊ตฌ์กฐ.md

7.1 ํŽ˜์ด์ง€ ๊ฒฝ๋กœ

๊ฒฝ๋กœํ™”๋ฉด์„ค๋ช…
/login<Login>๋กœ๊ทธ์ธ
/signup<Signup>ํšŒ์›๊ฐ€์ž…
/welcome<WelcomePage>๋กœ๊ทธ์ธ ์งํ›„ ํ™˜์˜ ํ™”๋ฉด
/dashboard<DashboardTab>๋ฉ”์ธ ๋Œ€์‹œ๋ณด๋“œ ํƒญ
/dashboard/compare<CompareTab>Compare ํƒญ
/dashboard/simulator<SimulatorTab>Simulator ํƒญ
/dashboard/target<TargetTab>Target ํƒญ
/profile<Profile>ํ”„๋กœํ•„ ์„ค์ •
/data-input<DataInput>๋ฐ์ดํ„ฐ ์ž…๋ ฅ
/reports<Reports>๋ฆฌํฌํŠธ
/analytics<Analytics>๋ถ„์„ ํ™”๋ฉด

7.2 ์ธ์ฆ ๊ฐ€๋“œ ๋™์ž‘

  • ํ† ํฐ์ด ์—†์œผ๋ฉด ๋ณดํ˜ธ ๊ฒฝ๋กœ ์ ‘๊ทผ ์‹œ /login์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
  • ํ† ํฐ์ด ์žˆ์œผ๋ฉด /, /login, /signup ์ ‘๊ทผ ์‹œ /dashboard๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
  • ์•Œ ์ˆ˜ ์—†๋Š” ๊ฒฝ๋กœ๋Š” ํ† ํฐ ์—ฌ๋ถ€์— ๋”ฐ๋ผ /dashboard ๋˜๋Š” /login์œผ๋กœ ์ •๋ฆฌ

7.3 ํƒญ ์ƒํƒœ ๋™๊ธฐํ™”

  • URL ๊ฒฝ๋กœ(/dashboard/*)์—์„œ activeTab์„ ์—ญ๋งคํ•‘ํ•ด ํ—ค๋” ํƒญ UI์™€ ๋™๊ธฐํ™”
  • ํƒญ ํด๋ฆญ ์‹œ navigate('/dashboard/...') ํ˜ธ์ถœ๋กœ ๋ธŒ๋ผ์šฐ์ € ํžˆ์Šคํ† ๋ฆฌ์™€ ์ž๋™ ์—ฐ๋™
  • ๋ธŒ๋ผ์šฐ์ € ๋’ค๋กœ๊ฐ€๊ธฐ/์•ž์œผ๋กœ๊ฐ€๊ธฐ๋Š” router history๋กœ ์ฒ˜๋ฆฌ

โš™๏ธ 8. ์„ค์น˜ ๋ฐ ์„ค์ • (Installation & Setup)

8.0 ์‚ฌ์ „ ์š”๊ตฌ์‚ฌํ•ญ (Prerequisites)

์†Œํ”„ํŠธ์›จ์–ด๊ถŒ์žฅ ๋ฒ„์ „์šฉ๋„
Python3.11.x๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ๋ฐ PDF/RAG ํŒŒ์ดํ”„๋ผ์ธ
Node.js18+ํ”„๋ก ํŠธ์—”๋“œ ๋นŒ๋“œ
MySQL5.7+์‚ฌ์šฉ์ž ๋ฐ ๋ฐฐ์ถœ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ €์žฅ
OpenAI API Key์œ ํšจ ํ‚ค์ฑ—๋ด‡/์ „๋žต ์ƒ์„ฑ LLM ํ˜ธ์ถœ

8.1 ๋ฐฑ์—”๋“œ ๊ฐ€๋™

# ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๊ธฐ์ค€
python3.11 -m venv .venv
source .venv/bin/activate

pip install -r requirements.txt
pip install -r backend/requirements.txt

# DB ์ดˆ๊ธฐํ™” (์ตœ์ดˆ 1ํšŒ)
cd backend/app
python init_db.py
cd ../..

# ์„œ๋ฒ„ ์‹คํ–‰ (๊ถŒ์žฅ: app ์—”ํŠธ๋ฆฌํฌ์ธํŠธ)
cd backend
uvicorn app.main:app --reload --port 8000

backend/main.py๋Š” PDF ๊ฒ€์ƒ‰/ํ†ต๊ณ„ ๋ณด์กฐ ์—”๋“œํฌ์ธํŠธ๊นŒ์ง€ ํ•จ๊ป˜ ์“ฐ๋Š” ํ†ตํ•ฉ ๋ชจ๋“œ์ž…๋‹ˆ๋‹ค.

8.2 ํ”„๋ก ํŠธ์—”๋“œ ๊ฐ€๋™

cd frontend
npm install
npm run dev

๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:5173 ์ ‘์†

8.3 AI/RAG ์„ค์ •

์˜ต์…˜ A: ์›๊ฒฉ Chroma ์„œ๋ฒ„ ์‚ฌ์šฉ (์šด์˜ ๊ถŒ์žฅ)

CHROMA_HOST=your-chroma-host
CHROMA_PORT=8000
RAG_EMBEDDING_MODEL=BAAI/bge-m3
  • ์ด ๊ฒฝ์šฐ ๋กœ์ปฌ PDF_Extraction/vector_db ํด๋”๊ฐ€ ์—†์–ด๋„ ๋ฉ๋‹ˆ๋‹ค.
  • ์ฑ—๋ด‡์€ ์›๊ฒฉ ์ปฌ๋ ‰์…˜(esg_chunks, esg_pages ๋˜๋Š” esg_documents)์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ B: ๋กœ์ปฌ Persistent Chroma ์‚ฌ์šฉ (๊ฐœ๋ฐœ์šฉ)

pip install -r PDF_Extraction/requirements.txt
cd PDF_Extraction
python src/build_vector_db.py
  • ๊ธฐ๋ณธ ๋กœ์ปฌ ๊ฒฝ๋กœ๋Š” PDF_Extraction/vector_db์ž…๋‹ˆ๋‹ค.
  • ๋ฒกํ„ฐDB๊ฐ€ ์—†์œผ๋ฉด ์ฑ—๋ด‡ API๋Š” ์‹คํ–‰๋˜์ง€๋งŒ RAG ๊ทผ๊ฑฐ ๊ฒ€์ƒ‰ ํ’ˆ์งˆ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ safetensors ๋ณ€ํ™˜/๋ฐฐํฌ (๊ถŒ์žฅ)

BAAI/bge-m3 ์›๋ณธ์€ pytorch_model.bin ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ, ํŒ€ ๊ณต์šฉ ํ™˜๊ฒฝ์—์„œ๋Š” safetensors ๋ณ€ํ™˜๋ณธ์„ ์‚ฌ๋‚ด ๊ฒฝ๋กœ/์•„ํ‹ฐํŒฉํŠธ๋กœ ๋ฐฐํฌํ•ด ์“ฐ๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

cd PDF_Extraction
python src/convert_embedding_to_safetensors.py \
  --source-model BAAI/bge-m3 \
  --output-dir models/bge-m3-safetensors

๋ฐฐํฌ ํ›„ .env์— ๋™์ผ ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

RAG_EMBEDDING_MODEL=/absolute/path/to/models/bge-m3-safetensors

8.4 ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •

ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ .env ์˜ˆ์‹œ:

# --- Database (MySQL) ---
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=esg

# --- Frontend API URL ---
VITE_API_BASE_URL=http://127.0.0.1:8000

# --- JWT ---
JWT_SECRET_KEY=your_jwt_secret_key_here
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60

# --- RAG/LLM ---
VECTOR_DB_PATH=/absolute/path/to/vector_db   # ์„ ํƒ
CHROMA_HOST=                                  # ์›๊ฒฉ ์‚ฌ์šฉ ์‹œ ์„ค์ •
CHROMA_PORT=8000
RAG_EMBEDDING_MODEL=BAAI/bge-m3

# --- Market Data ---
Alpha_Vantage_API=your_alpha_vantage_key
USE_MOCK_DATA=true

# --- Optional ---
OPENAI_API_KEY=sk-...
HF_TOKEN=hf_...

๐Ÿ“Š 9. API ๋ช…์„ธ (API Specification)

FastAPI Swagger UI: http://127.0.0.1:8000/docs

9.1 ์ธ์ฆ API (/auth)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/auth/signupPOSTํšŒ์›๊ฐ€์ž…
/auth/loginPOST๋กœ๊ทธ์ธ(JWT access token ๋ฐœ๊ธ‰)
/auth/meGETํ˜„์žฌ ์‚ฌ์šฉ์ž ์กฐํšŒ (Authorization: Bearer <token>)

9.2 ํ”„๋กœํ•„ API (/profile)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/profile/meGETํ”„๋กœํ•„ ์กฐํšŒ
/profile/mePUTํ”„๋กœํ•„ ์ˆ˜์ • (nickname, company_name, classification, bio)
/profile/me/passwordPOST๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ
/profile/me/emailPOST์ด๋ฉ”์ผ ๋ณ€๊ฒฝ
/profile/me/deletePOST๊ณ„์ • ์‚ญ์ œ
/profile/me/avatarPOST์•„๋ฐ”ํƒ€ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ(multipart/form-data)

9.3 ๋Œ€์‹œ๋ณด๋“œ API (/api/v1/dashboard)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/api/v1/dashboard/companiesGET๊ธฐ์—…๋ณ„ ์ตœ์‹ /์—ฐ๋„๋ณ„ ๋ฐฐ์ถœ ๋ฐ์ดํ„ฐ ๋ชฉ๋ก(์ „์ฒด ๋ฐฐ์ถœ + ๊ตญ๋‚ด/ํ•ด์™ธ ๋ถ„๋ฆฌ ํ•„๋“œ ํฌํ•จ)
/api/v1/dashboard/compare/insightPOSTCompare ํƒญ AI ์ธ์‚ฌ์ดํŠธ ์ƒ์„ฑ

9.4 ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ API (/api/v1/sim)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์ฃผ์š” ํŒŒ๋ผ๋ฏธํ„ฐ์„ค๋ช…
/api/v1/sim/dashboard/market-trendsGET`period=1m3m
/api/v1/sim/dashboard/trend-combinedGETcompany, period, start_year, end_year๋ฆฌ์Šคํฌ ๋น„์šฉ ์ถ”์ด ๊ณ„์‚ฐ

9.5 AI API (/api/v1/ai)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/api/v1/ai/chatPOSTRAG ๊ธฐ๋ฐ˜ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฑ—๋ด‡
/api/v1/ai/strategyPOST์‹œ์žฅ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์ „๋žต ์ƒ์„ฑ
/api/v1/ai/text-to-sqlPOST์ž์—ฐ์–ด ์งˆ์˜ SQL ๋ณ€ํ™˜

9.6 ํ†ตํ•ฉ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ ์ „์šฉ API (backend/main.py)

์—”๋“œํฌ์ธํŠธ๋ฉ”์„œ๋“œ์„ค๋ช…
/GET์„œ๋ฒ„ ์ƒํƒœ
/api/healthGETํ—ฌ์Šค์ฒดํฌ
/api/searchGET๋ฒกํ„ฐ ๊ฒ€์ƒ‰
/api/companiesGET๋ฒกํ„ฐ DB ๊ธฐ์ค€ ๊ธฐ์—… ๋ชฉ๋ก
/api/statsGET๋ฒกํ„ฐ DB ํ†ต๊ณ„

๐Ÿค– 10. AI ๋ชจ๋ธ ํ‰๊ฐ€ (AI Model Evaluation)

ํ”Œ๋žซํผ์˜ ์‹ ๋ขฐ์„ฑ์„ ์œ„ํ•ด ํƒ‘์žฌ๋œ ๋ชจ๋ธ๋“ค์„ ์ •๊ธฐ์ ์œผ๋กœ ์ž๋™ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

  • ์‹คํ–‰ ๋ฐฉ๋ฒ•: python evaluation/evaluate_models.py
  • ํ‰๊ฐ€ ํ•ญ๋ชฉ:
    • RAG ๋‹ต๋ณ€์˜ ์ •๋‹ต์ง€(Answer Key) ๋Œ€๋น„ ์ผ์น˜์œจ
    • Monte Carlo ์ˆ˜๋ ด ์•ˆ์ •์„ฑ (10,000ํšŒ)
    • OLS ํšŒ๊ท€ ๊ณ„์ˆ˜ ์œ ์˜์„ฑ ๋ฐ ์ž”์ฐจ ๋ถ„์„
    • ์ถ”๋ก  ์‹œ๊ฐ„ ๋ฐ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ

๐Ÿ“Œ DB ์Šคํ‚ค๋งˆ ์ฃผ์š” ํ…Œ์ด๋ธ”

users

์ปฌ๋Ÿผ๋ช…ํƒ€์ž…์„ค๋ช…
idINT (PK)์‚ฌ์šฉ์ž ID
emailVARCHAR(255) UNIQUE๋กœ๊ทธ์ธ ์‹๋ณ„์ž
company_nameVARCHAR(255)์†Œ์† ๊ธฐ์—…๋ช…
hashed_passwordVARCHAR(255)ํ•ด์‹œ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ
nicknameVARCHAR(100)ํ‘œ์‹œ ์ด๋ฆ„
classificationVARCHAR(50)๋ถ„๋ฅ˜ ํ…Œ๋งˆ
bioVARCHAR(500)์ž๊ธฐ์†Œ๊ฐœ
profile_image_urlVARCHAR(500) NULLํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ
roleVARCHAR(20)์‚ฌ์šฉ์ž ๊ถŒํ•œ ๋ฌธ์ž์—ด
is_adminBOOLEAN๊ด€๋ฆฌ์ž ์—ฌ๋ถ€
created_atDATETIME์ƒ์„ฑ ์‹œ๊ฐ
updated_atDATETIME์ˆ˜์ • ์‹œ๊ฐ

dashboard_emissions

์ปฌ๋Ÿผ๋ช…ํƒ€์ž…์„ค๋ช…
idINT (PK)๋ ˆ์ฝ”๋“œ ID
company_idINT INDEX๊ธฐ์—… ์‹๋ณ„์ž
company_nameVARCHAR(100) INDEX๊ธฐ์—…๋ช…
yearINT INDEX์—ฐ๋„
scope1 scope2 scope3FLOATScope๋ณ„ ๋ฐฐ์ถœ๋Ÿ‰(์›๋ณธ ์ด๋Ÿ‰)
s1_domestic s2_domestic s3_domesticFLOAT๊ตญ๋‚ด Scope ๋ฐฐ์ถœ๋Ÿ‰(์„ ํƒ ์ปฌ๋Ÿผ)
s1_abroad s2_abroad s3_abroadFLOATํ•ด์™ธ Scope ๋ฐฐ์ถœ๋Ÿ‰(์„ ํƒ ์ปฌ๋Ÿผ)
allowanceFLOAT NULL๋ฌด์ƒ ํ• ๋‹น๋Ÿ‰
revenueBIGINT๋งค์ถœ
energy_intensityFLOAT์—๋„ˆ์ง€ ์ง‘์•ฝ๋„
carbon_intensityFLOAT(S1+S2) ํƒ„์†Œ ์ง‘์•ฝ๋„
carbon_intensity_scope1FLOATScope1 ์ง‘์•ฝ๋„
carbon_intensity_scope2FLOATScope2 ์ง‘์•ฝ๋„
carbon_intensity_scope3FLOATScope3 ์ง‘์•ฝ๋„
base_yearINT๊ธฐ์ค€ ์—ฐ๋„
base_emissionsFLOAT๊ธฐ์ค€ ๋ฐฐ์ถœ๋Ÿ‰
source_doc_idINT์›๋ณธ ๋ฌธ์„œ ID
data_sourceVARCHAR(500)๋ฐ์ดํ„ฐ ์ถœ์ฒ˜
extraction_methodVARCHAR(50)์ถ”์ถœ ๋ฐฉ์‹
is_verifiedBOOLEAN๊ฒ€์ฆ ์—ฌ๋ถ€
created_atDATETIME์ƒ์„ฑ ์‹œ๊ฐ
updated_atDATETIME์ˆ˜์ • ์‹œ๊ฐ

๐Ÿ“… Last Updated: 2026-02-24 ๐Ÿ“„ License: Educational & Research Purpose Only