|
1 | | -# EasyToFind Backend - ETF 상세 페이지 API |
| 1 | +# 📈 ETF: Easy To Find |
| 2 | +ETF의 모든 것, Easy To Find에서 쉽고 간편하게<br> |
| 3 | +찾고, 비교하고, 추천받고, 직접 시뮬레이션 해보는 과정을 통해<br> |
| 4 | +단순한 추천을 넘어, ETF 선택의 기준을 재정의합니다. |
| 5 | +<br><br><br> |
| 6 | + |
| 7 | +## 프로젝트 개요 |
| 8 | + |
| 9 | +### 기획 의도 |
| 10 | +**1000개가 넘는 ETF 중에서, 어떤 ETF를, 어떻게 골라야 할까요?** |
2 | 11 |
|
3 | | -## 개요 |
| 12 | +Easy To Find는 투자 판단까지 걸리는 복잡한 고민의 시간을 줄일 수 있도록 돕는<br> |
| 13 | +개인화 기반 ETF 탐색·추천·시뮬레이션 플랫폼입니다. |
| 14 | +<br><br> |
| 15 | + |
| 16 | +### 개발 기간 |
| 17 | +2025.07.03 - 2025.07.29 |
| 18 | +<br><br> |
| 19 | + |
| 20 | +### 팀 소개 |
| 21 | + |
| 22 | +| <img src="https://github.com/todayiswindy.png" width="460px"/> | <img src="https://github.com/slay1379.png" width="460px"/> | <img src="https://github.com/hiwonwon.png" width="460px"/> | <img src="https://github.com/Dayoung331.png" width="460px"/> | |
| 23 | +|:----------------------:|:-------------------:|:------------------------:|:---------------------------:| |
| 24 | +| **김지연** | **김태헌** | **박혜원** | **정다영** | |
| 25 | +| [@todayiswindy](http://github.com/todayiswindy) | [@slay1379](http://github.com/slay1379) | [@hiwonwon](http://github.com/hiwonwon) | [@Dayoung331](http://github.com/Dayoung331) | |
| 26 | +| PM / FE / BE | FE / BE | FE / BE | FE / BE / Infra | |
| 27 | +| 상세 페이지,<br>메인 페이지 | 시뮬레이션 로직,<br>시뮬레이션 / 결과 페이지 | 스코어링 로직,<br>성향 테스트 / 결과 페이지 | 탐색 / 비교 페이지,<br>마이페이지, 배포 | |
| 28 | + |
| 29 | +<br><br> |
| 30 | +## 사용 기술 및 도구 |
| 31 | + |
| 32 | +### Frontend |
| 33 | +- `JavaScript` |
| 34 | +- `React` |
| 35 | +- `Tailwind CSS` / `CSS-in-JS` |
| 36 | +- `Shadcn` |
| 37 | +- `Lightweight charts` |
| 38 | + |
| 39 | +### Backend |
| 40 | +- `Node.js` |
| 41 | +- `AWS RDS` |
| 42 | +- `PostgreSQL` |
| 43 | +- `JWT` 기반 인증 및 사용자 세션 관리 |
| 44 | + |
| 45 | +### Infra / DevOps |
| 46 | +- `AWS EC2` (Ubuntu + PM2 + Nginx + GitHub Actions) |
| 47 | +- `GitHub Actions` (CI/CD 자동 배포) |
| 48 | + |
| 49 | +### 협업 도구 |
| 50 | +- `GitHub` (버전 관리) |
| 51 | +- `Notion` (기획 및 일정 공유) |
| 52 | +- `Figma` (UI/UX 설계) |
| 53 | + |
| 54 | +### API |
| 55 | +- 한국투자증권 API |
| 56 | +- KRX |
| 57 | +- ETF check |
| 58 | + |
| 59 | +<br><br> |
| 60 | + |
| 61 | +## 주요 기능 소개 |
| 62 | + |
| 63 | +| **기능 및 로직 구분** | **상세 설명** | |
| 64 | +|:-----------:|-----------| |
| 65 | +| ETF 탐색 | 상품명 뿐만 아니라 종목명으로도 검색 가능, 유형별·테마별·종목별로 분류해 확인 가능 | |
| 66 | +| ETF 비교 | 최대 5개의 ETF를 동시에 비교 가능, 사용자별 종합 점수와 다양한 지표를 한눈에 확인 가능 | |
| 67 | +| 맞춤 추천 | 단순한 리스크 기반 추천을 넘어 사용자별 가중치 알고리즘으로 산출된 맞춤형 ETF 추천 | |
| 68 | +| 스코어링 로직 | 지표를 더 다양화하여 기존 5개이던 투자자 유형을 10개 유형으로 확장 | |
| 69 | +| 시뮬레이터 | 정량적 분석 리포트 제공, 목표 달성률 제시, 투자 성향과 리스크 허용도를 반영한 개인화 점수 + 리스크 점수 = 종합 점수 제공,<br>가장 적합한 상위 ETF 리스트 추천 | |
| 70 | +| 시뮬레이션 로직 | Monte-Carlo 시뮬레이션 도입, 총 5000개의 시나리오를 바탕으로 예상 가치의 변동 범위를 시각화하여<br>사용자에게 현실적인 투자 기대 범위를 직관적으로 전달 | |
| 71 | +| 마이페이지 | 관심 있는 ETF 목록을 기간별로 확인할 수 있도록 구성 | |
| 72 | + |
| 73 | +<br><br> |
| 74 | + |
| 75 | +## 실행 화면 |
| 76 | + <img width="1889" height="1105" alt= |
| 77 | +| **목록** | **실행 화면** | |
| 78 | +|:-----------:|-----------| |
| 79 | +| 메인 화면 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 39 01" src="https://github.com/user-attachments/assets/e37d3d5c-480a-40c4-a2c9-0777e56cd8ec" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 39 24" src="https://github.com/user-attachments/assets/4efe5435-f671-447f-a602-8f9ea6fefdf5" /><br><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 39 27" src="https://github.com/user-attachments/assets/4377d295-f865-4724-badd-d21a4395d3d1" /> | |
| 80 | +| 회원가입 / 로그인 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 46 06" src="https://github.com/user-attachments/assets/7304a16c-238a-43fe-ae51-dc2d467c6a32" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 46 10" src="https://github.com/user-attachments/assets/0d8c4b2e-3932-4268-822c-06cd89594bd1" /> | |
| 81 | +| ETF 탐색 페이지 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 40 09" src="https://github.com/user-attachments/assets/80d45736-4361-49e3-a030-f3c843286040" />| |
| 82 | +| ETF 비교 페이지 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 45 08" src="https://github.com/user-attachments/assets/f079e791-cd98-4a9d-a4c5-bee69e04d4e4" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 45 23" src="https://github.com/user-attachments/assets/f7eabb4c-b559-4946-a267-d14e24feac3b" /> | |
| 83 | +| ETF 상세 페이지 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 41 03" src="https://github.com/user-attachments/assets/b568cdc2-b7bf-46b8-9e0e-67212e24e34a" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 41 06" src="https://github.com/user-attachments/assets/2f15edb3-8859-4b2f-a28b-f847003893bb" /><br><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 41 10" src="https://github.com/user-attachments/assets/ef09f5c6-1993-4f81-9050-5ac422754a57" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 41 15" src="https://github.com/user-attachments/assets/be9f4aed-ceda-4030-a09a-448e0112248e" /><br><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 41 19" src="https://github.com/user-attachments/assets/63062d05-eaa3-4e3a-ac84-3ae92b08ce0c" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 41 25" src="https://github.com/user-attachments/assets/1dfff5ba-faa6-4ac2-98f7-2d1e46e64b60" /> | |
| 84 | +| 맞춤 추천 페이지 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 42 03" src="https://github.com/user-attachments/assets/eb8de90b-9514-415d-8529-e2bbf40281b7" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 42 06" src="https://github.com/user-attachments/assets/143928de-6b2c-40e8-9d5b-84f4708b21ae" /><br><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 42 09" src="https://github.com/user-attachments/assets/3d3f4e75-e826-43fa-97a1-872e4d7beeaf" /> | |
| 85 | +| 맞춤 추천 결과 페이지 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 42 37" src="https://github.com/user-attachments/assets/cb85a8bf-5d94-4d14-9b8e-d047c6976c87" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 42 39" src="https://github.com/user-attachments/assets/2ee87f5d-9689-4c50-a327-801d7219db4f" /> | |
| 86 | +| 시뮬레이터 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 42 45" src="https://github.com/user-attachments/assets/ca972ce3-1de6-4ff4-b35c-b554fe6b9977" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 43 00" src="https://github.com/user-attachments/assets/cbf3d938-8e91-4cc8-ac83-613f7fc64bf1" /> | |
| 87 | +| 시뮬레이터 결과 페이지 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 43 27" src="https://github.com/user-attachments/assets/2ac4be07-2113-4ccd-a526-eda495933c32" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 43 31" src="https://github.com/user-attachments/assets/68068159-6262-4aa1-8289-59037ba5838d" /><br><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 43 42" src="https://github.com/user-attachments/assets/298c85b5-907e-47b0-8b69-30ac7236447f" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 43 46" src="https://github.com/user-attachments/assets/eefc0458-3032-485e-b30c-57cb20d9741e" /> | |
| 88 | +| 마이페이지 | <img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 45 46" src="https://github.com/user-attachments/assets/ad8a30d9-3425-43a1-829e-5d8b35f98c8f" /><img width="400" height="300" alt="스크린샷 2025-07-29 오후 4 45 50" src="https://github.com/user-attachments/assets/28c4ef70-fdcc-4522-bd6e-7956c3b5f708" /> | |
| 89 | + |
| 90 | +<br><br> |
| 91 | + |
| 92 | +## ERD |
| 93 | +<img width="1250" height="760" alt="스크린샷 2025-08-03 오후 8 52 08" src="https://github.com/user-attachments/assets/fd6f1446-db77-491c-bb07-cde850d9f5f7" /> |
| 94 | + |
| 95 | +<br><br> |
| 96 | + |
| 97 | +## API 명세서 |
| 98 | +<img width="1035" height="726" alt="스크린샷 2025-08-03 오후 8 54 39" src="https://github.com/user-attachments/assets/09f20f50-a688-4d0b-9071-0afaa55b5e4e" /> |
| 99 | + |
| 100 | +<br><br> |
| 101 | + |
| 102 | +## Figma |
| 103 | +<img width="1010" height="710" alt="스크린샷 2025-08-03 오후 8 55 39" src="https://github.com/user-attachments/assets/09602c04-5c3e-459e-a4f4-a4b34a8308db" /> |
4 | 104 |
|
5 | | -이 프로젝트는 ETF 데이터를 수집하고 상세 정보를 제공하는 백엔드 API입니다. |
| 105 | +<br><br> |
6 | 106 |
|
7 | | -## 설치 및 실행 |
8 | | - |
9 | | -### 1. 의존성 설치 |
| 107 | +## 아키텍처 구성 |
| 108 | +<img width="1316" height="615" alt="image" src="https://github.com/user-attachments/assets/ee70afe3-dfbc-45f9-a787-5044b4c38449" /> |
| 109 | + |
| 110 | +<br><br> |
10 | 111 |
|
| 112 | +## 구성도 |
11 | 113 | ```bash |
12 | | -npm install |
| 114 | +/ |
| 115 | +├── 회원가입 및 로그인 |
| 116 | +│ ├── 이메일 기반 회원가입 / 로그인 |
| 117 | +│ └── 약관 및 개인정보 수집 동의 |
| 118 | +│ |
| 119 | +├── / |
| 120 | +│ ├── ETF 탐색 배너 |
| 121 | +│ │ ├── 상품명 / 종목명으로 ETF 검색 |
| 122 | +│ │ └── /find 페이지로 이동 |
| 123 | +│ │ |
| 124 | +│ ├── ETF 트렌드 한눈에 보기 |
| 125 | +│ │ ├── 순자산 / 수익률 / 누적 거래량 을 바탕으로 TOP5 ETF 목록 확인 가능 |
| 126 | +│ │ └── 전체 운용상품 보러 가기 버튼 클릭 시 /find 로 이동 |
| 127 | +│ │ |
| 128 | +│ └── 하단 메뉴 버튼 |
| 129 | +│ ├── What's your ETF? 클릭 시 /me/mbti 로 이동 |
| 130 | +│ └── 전략 시뮬레이션 클릭 시 /goal 로 이동 |
| 131 | +│ |
| 132 | +├── /find |
| 133 | +│ ├── ETF 탐색 |
| 134 | +│ │ ├── 상품명 / 종목명으로 ETF 검색 |
| 135 | +│ │ ├── 여러 탭 버튼을 클릭해 원하는 유형 / 테마로 검색 가능 |
| 136 | +│ │ ├── ETF별 / 종목별 sorting 기능 제공 |
| 137 | +│ │ ├── 유형별 / 테마별 / 관심별 로 분류된 결과 확인 |
| 138 | +│ │ └── 각 ETF 클릭 시 상세 페이지로 이동 (/etfs/{종목코드}) |
| 139 | +│ │ |
| 140 | +│ └── ETF 비교 |
| 141 | +│ ├── 체크 박스를 선택한 후 비교하기 버튼을 클릭하면 팝업창 뜸 |
| 142 | +│ ├── 최대 5개의 ETF 비교 가능 |
| 143 | +│ └── 종합점수, 핵심 지표, 기간별 수익률을 한눈에 파악 가능 |
| 144 | +│ |
| 145 | +├── /etfs/{종목코드} |
| 146 | +│ └── 상세 페이지 |
| 147 | +│ ├── 상품정보, 수익률, 위험도, 기준가, 구성종목 정보를 세세하게 확인 가능 |
| 148 | +│ ├── 수익률은 기간별 그래프를 함께 제공 |
| 149 | +│ ├── 위험도는 투자위험도, 최대낙폭, 변동성 그래프를 함께 제공 |
| 150 | +│ └── 구성종목은 구성 비율 그래프와 상세 목록 제공 |
| 151 | +│ |
| 152 | +├── /me/mbti |
| 153 | +│ ├── 맞춤 추천 |
| 154 | +│ │ └── 투자 성향 + 관심 테마 기반 질문 |
| 155 | +│ │ |
| 156 | +│ └── 맞춤 추천 결과 페이지 |
| 157 | +│ ├── 개인화 점수를 반영한 ETF 추천 리스트 제공 |
| 158 | +│ └── 안정성, 유동성, 성장도, 분산도 지표 제공 |
| 159 | +│ |
| 160 | +├── /goal |
| 161 | +│ └── 시뮬레이터 |
| 162 | +│ ├── 목표 금액, 기간, 초기금액, 월 적립 입력 |
| 163 | +│ ├── 수익률 기반 달성 가능성 예측 |
| 164 | +│ ├── 몬테카를로 기반 가치 예측 그래프 시각화 |
| 165 | +│ └── 종합 점수 기반 최적 ETF 리스트 제공 |
| 166 | +│ |
| 167 | +├── /mypage |
| 168 | +│ ├── 내 투자 성향 / 관심 테마 확인 |
| 169 | +│ └── 저장한 ETF 확인 (기간별 수익률) |
| 170 | +│ |
| 171 | +└── Cf) 사용자 흐름 요약 |
| 172 | + ├── 1단계: 회원가입 / 로그인 |
| 173 | + ├── 2단계: ETF 탐색 or 맞춤 추천 or 시뮬레이터 이용 |
| 174 | + ├── 3단계: ETF 탐색 / 비교 및 관심 ETF 저장 or 추천 결과 확인 or 결과 리포트 확인 |
| 175 | + └── 4단계: /mypage에서 나의 관심 ETF 확인 및 관리 |
13 | 176 | ``` |
14 | | - |
15 | | -### 2. 환경 설정 |
16 | | - |
17 | | -`.env` 파일을 생성하고 데이터베이스 연결 정보를 설정하세요: |
18 | | - |
19 | | -``` |
20 | | -DB_HOST=localhost |
21 | | -DB_PORT=5432 |
22 | | -DB_NAME=your_database_name |
23 | | -DB_USER=your_username |
24 | | -DB_PASSWORD=your_password |
25 | | -``` |
26 | | - |
27 | | -### 3. CSV 데이터를 데이터베이스로 가져오기 |
28 | | - |
29 | | -```bash |
30 | | -npm run import-csv |
31 | | -``` |
32 | | - |
33 | | -### 4. 서버 실행 |
34 | | - |
35 | | -```bash |
36 | | -npm start |
37 | | -``` |
38 | | - |
39 | | -## API 엔드포인트 |
40 | | - |
41 | | -### ETF 상세 정보 조회 |
42 | | - |
43 | | -``` |
44 | | -GET /api/etfs/{etfCode} |
45 | | -``` |
46 | | - |
47 | | -**응답 예시:** |
48 | | - |
49 | | -```json |
50 | | -{ |
51 | | - "status": 200, |
52 | | - "message": "조회 성공", |
53 | | - "data": { |
54 | | - "etf_code": "069500", |
55 | | - "etf_name": "ETF_069500", |
56 | | - "fund_type": "Stock ETF", |
57 | | - "benchmark": "KOSPI 200", |
58 | | - "expense_ratio": 0.05, |
59 | | - "inception_date": "2020-01-01", |
60 | | - "fund_size": 1000000000, |
61 | | - "issuer": "Unknown", |
62 | | - "recentPrices": [ |
63 | | - { |
64 | | - "trade_date": "2024-01-01", |
65 | | - "open_price": 50000, |
66 | | - "high_price": 51000, |
67 | | - "low_price": 49000, |
68 | | - "close_price": 50500, |
69 | | - "volume": 1000000, |
70 | | - "nav_price": 505.50, |
71 | | - "change_rate": 1.0, |
72 | | - "aum": 1000000000 |
73 | | - } |
74 | | - ], |
75 | | - "performance": { |
76 | | - "1y": { |
77 | | - "start_date": "2023-01-01", |
78 | | - "end_date": "2024-01-01", |
79 | | - "current_price": 50500, |
80 | | - "start_price": 45000, |
81 | | - "total_return_percent": 12.22, |
82 | | - "max_gain_percent": 15.00, |
83 | | - "max_loss_percent": -5.00, |
84 | | - "avg_volume": 1200000, |
85 | | - "trading_days": 250 |
86 | | - }, |
87 | | - "3y": { ... }, |
88 | | - "5y": { ... } |
89 | | - } |
90 | | - } |
91 | | -} |
92 | | -``` |
93 | | - |
94 | | -## 데이터베이스 스키마 |
95 | | - |
96 | | -### ETF 테이블 |
97 | | - |
98 | | -- `id`: 기본키 |
99 | | -- `etf_code`: ETF 코드 (고유) |
100 | | -- `etf_name`: ETF 이름 |
101 | | -- `fund_type`: 펀드 유형 |
102 | | -- `benchmark`: 벤치마크 |
103 | | -- `expense_ratio`: 총보수율 |
104 | | -- `inception_date`: 설립일 |
105 | | -- `fund_size`: 펀드 규모 |
106 | | -- `issuer`: 발행사 |
107 | | - |
108 | | -### ETF_PRICES 테이블 |
109 | | - |
110 | | -- `id`: 기본키 |
111 | | -- `trade_date`: 거래일 |
112 | | -- `etf_code`: ETF 코드 |
113 | | -- `open_price`: 시가 |
114 | | -- `high_price`: 고가 |
115 | | -- `low_price`: 저가 |
116 | | -- `close_price`: 종가 |
117 | | -- `volume`: 거래량 |
118 | | -- `nav_price`: NAV |
119 | | -- `change_rate`: 등락률 |
120 | | -- `aum`: 자산규모 |
121 | | - |
122 | | -## 사용 예시 |
123 | | - |
124 | | -### Frontend에서 API 호출 |
125 | | - |
126 | | -```javascript |
127 | | -// ETF 상세 정보 가져오기 |
128 | | -const response = await fetch("/api/etfs/069500"); |
129 | | -const data = await response.json(); |
130 | | - |
131 | | -if (data.status === 200) { |
132 | | - const etfDetail = data.data; |
133 | | - console.log("ETF 이름:", etfDetail.etf_name); |
134 | | - console.log( |
135 | | - "현재가:", |
136 | | - etfDetail.recentPrices[etfDetail.recentPrices.length - 1].close_price |
137 | | - ); |
138 | | - console.log("1년 수익률:", etfDetail.performance["1y"].total_return_percent); |
139 | | -} |
140 | | -``` |
141 | | - |
142 | | -## 주의사항 |
143 | | - |
144 | | -- CSV 데이터를 먼저 데이터베이스로 가져와야 API가 정상 작동합니다. |
145 | | -- ETF 코드는 실제 상장된 ETF 코드를 사용해야 합니다. |
146 | | -- 성과 지표는 최근 거래 데이터를 기반으로 계산됩니다. |
|
0 commit comments