Skip to content

Latest commit

ย 

History

454 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽ“ WishConnect โ€” API Server

ํฉ์–ด์ง„ ์žฅํ•™๊ธˆ ์ •๋ณด๋ฅผ ํ•œ๊ณณ์—, ๋‚˜์—๊ฒŒ ๋งž๋Š” ์žฅํ•™๊ธˆ๋งŒ ๊ณจ๋ผ์ฃผ๋Š” ์žฅํ•™๊ธˆ ํ๋ ˆ์ดํŒ… ํ”Œ๋žซํผ WishConnect ๋ฐ”๋กœ๊ฐ€๊ธฐ ยท API ์„œ๋ฒ„

๋Œ€ํ•™์ƒ์ด ์žฅํ•™๊ธˆ์„ ๋†“์น˜๋Š” ์ด์œ ๋Š” ์ •๋ณด๊ฐ€ ์—†์–ด์„œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋„ˆ๋ฌด ํฉ์–ด์ ธ ์žˆ์–ด์„œ์ž…๋‹ˆ๋‹ค. WishConnect๋Š” ํ•œ๊ตญ์žฅํ•™์žฌ๋‹จ ๊ณต๊ณต๋ฐ์ดํ„ฐ์™€ ์ „๊ตญ ๋Œ€ํ•™ ์žฅํ•™๊ณต์ง€๋ฅผ ๋งค์ผ ์ž๋™ ์ˆ˜์ง‘ยท์ •์ œํ•˜๊ณ , ์‚ฌ์šฉ์ž์˜ ํ•™์ ยท์†Œ๋“ยท๊ด€์‹ฌ๋ถ„์•ผ์— ๋งž๋Š” ๊ณต๊ณ ๋งŒ ์ถ”๋ ค์„œ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์ง€์›๊นŒ์ง€ ์ด์–ด์ง€๋„๋ก ๋งˆ๊ฐ ์•Œ๋ฆผ, ์Šคํฌ๋žฉ ์•„์นด์ด๋น™, AI ์ž๊ธฐ์†Œ๊ฐœ์„œ ์ž‘์„ฑ, ๋ฉด์ ‘ ์ค€๋น„๊นŒ์ง€ ํ•œ ํ๋ฆ„์œผ๋กœ ๋ฌถ์—ˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ“ƒ Contents

  1. ๐Ÿ“Œ ์ œ์ถœ ์ž๋ฃŒ (ERD ยท API ๋ช…์„ธ์„œ ยท ์•„ํ‚คํ…์ฒ˜)
  2. ๐ŸŒฑ Developers
  3. ๐ŸŒŸ Services
  4. ๐Ÿ—‚ ERD
  5. ๐Ÿ“– API ๋ช…์„ธ์„œ
  6. ๐Ÿ’ป Architecture & Deploy
  7. ๐Ÿ”ง Tech Stack
  8. ๐Ÿงฑ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ
  9. โš™๏ธ Getting Started

๐Ÿ“Œ ์ œ์ถœ ์ž๋ฃŒ

์ž๋ฃŒ ์œ„์น˜
ERD ๋ฐ”๋กœ๊ฐ€๊ธฐ โ†“ ยท ์›๋ณธ ์ด๋ฏธ์ง€
API ๋ช…์„ธ์„œ ๋ฐ”๋กœ๊ฐ€๊ธฐ โ†“ ยท Notion ๋ช…์„ธ์„œ (๊ณต๊ฐœ)
์•„ํ‚คํ…์ฒ˜ ๋‹ค์ด์–ด๊ทธ๋žจ ๋ฐ”๋กœ๊ฐ€๊ธฐ โ†“ ยท ์›๋ณธ ์ด๋ฏธ์ง€

๐ŸŒฑ Developers

ํŒ€์› ์—ญํ•  ์ฃผ์š” ์—…๋ฌด

์œค๊ธฐ์ฐฌ
BE (๋ฆฌ๋“œ)
  • ์ธ์ฆยท์˜จ๋ณด๋”ฉยท๋งˆ์ดํŽ˜์ด์ง€ ์ „ ๊ตฌ๊ฐ„ (LOCAL/์นด์นด์˜ค/๊ตฌ๊ธ€/๋„ค์ด๋ฒ„ ๋กœ๊ทธ์ธ, JWT, ์ด๋ฉ”์ผ ์ธ์ฆ)
  • ์žฅํ•™๊ธˆ ํ๋ ˆ์ดํŒ…ยท๊ฒ€์ƒ‰ยท์ƒ์„ธยท๋‹ฌ๋ ฅยทํ™ˆ ์š”์•ฝ
  • ์•Œ๋ฆผ์„ผํ„ฐ ๋ฐ ์•Œ๋ฆผ ์Šค์ผ€์ค„๋Ÿฌ
  • ์žฅํ•™๊ธˆ ์ˆ˜์ง‘ ํŒŒ์ดํ”„๋ผ์ธ, ๊ด€๋ฆฌ์ž ์ฝ˜์†”, ์ธํ”„๋ผยท๋ฐฐํฌ(EC2ยทRDSยทCI/CD)

ํ˜„์ข…ํ™”
BE
  • ๋Œ€ํ•™ ์žฅํ•™๊ณต์ง€ LLM ํŒŒ์„œ ๋ฐ ์ „์šฉ ์ˆ˜์ง‘๊ธฐ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ
  • ์ค‘๋ณต ์žฅํ•™๊ธˆ ํŒ์ •ยท๋ณ‘ํ•ฉ ์Šน์ธ ํ
  • ์žฅํ•™๊ธˆ๋ณ„ ์ž๊ธฐ์†Œ๊ฐœ์„œ ๋ฌธํ•ญ ์ƒ์„ฑ
  • ๋ฉด์ ‘ ์˜ˆ์ƒ ์งˆ๋ฌธยท๋ฉด์ ‘ ์ค€๋น„ ์ž๋ฃŒ ์ƒ์„ฑ

hahahanjihun
BE
  • ์žฅํ•™๊ธˆ ๊ฒ€์ƒ‰ ํ’ˆ์งˆ ๊ฐœ์„  (์œ ํ˜• ํ‚ค์›Œ๋“œ ํ† ํฐํ™”, ๋Œ€ํ•™ ์ถ•์•ฝ์–ด, ๋งˆ๊ฐ ๊ณต๊ณ  ์ œ์™ธ)
  • ์†Œ์…œ ์˜จ๋ณด๋”ฉ ๊ธฐ๋ณธ์ •๋ณด ๋‹จ๊ณ„ ๋ณด์™„
  • ๊ฐ€๊ตฌ์ •๋ณด(household) ์ €์žฅ ์ •ํ•ฉ์„ฑ ์ˆ˜์ •
ajm6238 BE
  • ์ธ์‚ฌ์ดํŠธ ์ฝ˜ํ…์ธ  ์ž๋™ ์ˆ˜์ง‘ ํŒŒ์ดํ”„๋ผ์ธ ๋ฐ ๋ชฉ๋ก ์กฐํšŒ API
  • ์•„์นด์ด๋น™ ๋ชฉ๋ก ์กฐํšŒ API (์ƒํƒœ ํ•„ํ„ฐยทํŽ˜์ด์ง€๋„ค์ด์…˜ยทisScrapped)
  • ์žฅํ•™๊ธˆ ๊ฒ€์ƒ‰ ์ถ”์ฒœ ํ‚ค์›Œ๋“œ API

๐ŸŒŸ Services

๐Ÿ” ์ธ์ฆ ยท ์˜จ๋ณด๋”ฉ

  • LOCAL ํšŒ์›๊ฐ€์ž…(์ด๋ฉ”์ผ 6์ž๋ฆฌ ์ธ์ฆ์ฝ”๋“œ, AWS SES) + ์นด์นด์˜ค / ๊ตฌ๊ธ€ / ๋„ค์ด๋ฒ„ ์†Œ์…œ ๋กœ๊ทธ์ธ 3์ข…
  • ๋ชจ๋‘ ๋™์ผํ•œ ์ž์ฒด JWT๋ฅผ ๋ฐœ๊ธ‰ํ•˜๊ณ  (loginType, providerId)๋กœ ๊ณ„์ •์„ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜จ๋ณด๋”ฉ 4๋‹จ๊ณ„ โ€” ๊ธฐ๋ณธ์ •๋ณด โ†’ ํ•™์ ์ •๋ณด โ†’ ๊ฐ€๊ตฌ์ •๋ณดยท๊ด€์‹ฌ์‚ฌ โ†’ ์™„๋ฃŒ. ๋‹จ๊ณ„๋ณ„ ์ €์žฅ์ด๋ผ ์ด์–ด์„œ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŽ“ ์žฅํ•™๊ธˆ ํ๋ ˆ์ดํŒ… ยท ๊ฒ€์ƒ‰

  • ์˜จ๋ณด๋”ฉ์—์„œ ๋ฐ›์€ ํ•™์ ยท์†Œ๋“๋ถ„์œ„ยท๊ฑฐ์ฃผ์ง€์—ญยท๊ด€์‹ฌ๋ถ„์•ผ๋กœ ์กฐ๊ฑด์„ ํŒ์ •ํ•ด ์ž๊ฒฉ์ด ๋˜๋Š” ๊ณต๊ณ ๋งŒ ํ๋ ˆ์ดํŒ…ํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒ์„ธ ํ™”๋ฉด์—์„œ ์กฐ๊ฑด๋ณ„ ์ถฉ์กฑ/๋ฏธ์ถฉ์กฑ ํŒ์ •๊ณผ ์ถ”์ฒœ ์ด์œ ๋ฅผ ํ•จ๊ป˜ ๋‚ด๋ ค์ค๋‹ˆ๋‹ค.
  • ํ‚ค์›Œ๋“œยท์นดํ…Œ๊ณ ๋ฆฌยท์ •๋ ฌ(๋งˆ๊ฐ์ž„๋ฐ•/์ตœ์‹ /๊ธˆ์•ก/์ •ํ™•๋„) ๊ฒ€์ƒ‰, ์ถ”์ฒœ ๊ฒ€์ƒ‰์–ด, ์›”๋ณ„ ์ผ์ • ๋‹ฌ๋ ฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ํ•œ๊ตญ์žฅํ•™์žฌ๋‹จ ๊ณต๊ณต API + ์ „๊ตญ ๋Œ€ํ•™ ์žฅํ•™๊ณต์ง€ ํฌ๋กค๋ง์„ ๋งค์ผ ๋ฐฐ์น˜๋กœ ์ˆ˜์ง‘ํ•˜๊ณ , LLM์œผ๋กœ ์ž๊ฒฉ์กฐ๊ฑด์„ ๊ตฌ์กฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ์•„์นด์ด๋น™ ยท ์•Œ๋ฆผ

  • ๊ด€์‹ฌ ๊ณต๊ณ ๋ฅผ ์Šคํฌ๋žฉํ•ด ์ง„ํ–‰ ์ƒํƒœ์™€ D-Day๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ๋งˆ๊ฐ ์ž„๋ฐ•, ์‹ ๊ทœ ๋งž์ถค ์žฅํ•™๊ธˆ, ์ž‘์„ฑ ์ค‘ ์ง€์›์„œ ์ด์–ด์“ฐ๊ธฐ๋ฅผ ์•Œ๋ฆผ์„ผํ„ฐ๋กœ ๋ณด๋‚ด๊ณ  ์œ ํ˜•๋ณ„๋กœ ์ผœ๊ณ  ๋Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โœ๏ธ AI ์ž๊ธฐ์†Œ๊ฐœ์„œ ยท ๋ฉด์ ‘ ์ค€๋น„

  • ๊ณต๊ณ  ๋ณธ๋ฌธ์—์„œ ๊ทธ ์žฅํ•™๊ธˆ์˜ ์‹ค์ œ ๋ฌธํ•ญ์„ ๋ฝ‘์•„๋‚ด๊ณ , ์—†์œผ๋ฉด ๊ธฐ๋ณธ ๋ฌธํ•ญ์œผ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.
  • STEP 1 ์‚ฌ์ „ ์ธํ„ฐ๋ทฐ โ†’ STEP 2 ์ดˆ์•ˆ ์ƒ์„ฑยท์ˆ˜์ •ยท์ €์žฅ โ†’ ์™„๋ฃŒ์˜ 3๋‹จ๊ณ„๋กœ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฉด์ ‘์ด ์žˆ๋Š” ์žฅํ•™๊ธˆ์€ ์˜ˆ์ƒ ์งˆ๋ฌธ๊ณผ ์งˆ๋ฌธ์˜๋„ยท๋‹ต๋ณ€ Tipยท์˜ˆ์‹œ๋‹ต๋ณ€ยท๊ตฌ์„ฑ๊ฐ€์ด๋“œ๋ฅผ ํ•จ๊ป˜ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ์ธ์‚ฌ์ดํŠธ

  • ์žฅํ•™๊ธˆ ํ›„๊ธฐยท์ •๋ณดยทํŒ ์ฝ˜ํ…์ธ ๋ฅผ ์™ธ๋ถ€์—์„œ ์ˆ˜์ง‘ํ•ด ์นดํ…Œ๊ณ ๋ฆฌยท์ถœ์ฒ˜ยทํƒœ๊ทธ๋กœ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ›  ๊ด€๋ฆฌ์ž ์ฝ˜์†”

  • ์ˆ˜์ง‘ ํ˜„ํ™ฉยท์ด์ƒ ํƒ์ง€ยทํŒŒ์‹ฑ ์‹คํŒจ ์›๋ณธ ํ™•์ธ, ์ˆ˜๊ธฐ ๋“ฑ๋ก/์ˆ˜์ •, ์—‘์…€ ์ผ๊ด„ ๋ฐ˜์˜, ์˜ค๋“ฑ๋ก ์‹ ๊ณ  ์ฒ˜๋ฆฌ, ๊ฐ์‚ฌ ๋กœ๊ทธ.
  • ๊ด€๋ฆฌ์ž ํ™”๋ฉด์€ ์ธํ„ฐ๋„ท์— ์—ด์ง€ ์•Š๊ณ  SSH ํ„ฐ๋„๋กœ๋งŒ ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค. (deploy/README.md)

๐Ÿ—‚ ERD

42๊ฐœ ์—”ํ‹ฐํ‹ฐ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž(usersยทuser_profile)๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์žฅํ•™๊ธˆ(scholarshipยทraw_scholarshipยทscholarship_condition), ์ง€์›์„œ(essayยทessay_questionยทessay_answerยทai_interview), ์•„์นด์ด๋น™(scrap), ์•Œ๋ฆผ(notification), ์ธ์‚ฌ์ดํŠธ(insight) ๋„๋ฉ”์ธ์ด ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

WishConnect ERD

์ด๋ฏธ์ง€๊ฐ€ ์ž‘๊ฒŒ ๋ณด์ด๋ฉด ํด๋ฆญํ•ด์„œ ์›๋ณธ ํฌ๊ธฐ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โ†’ docs/images/erd.png


๐Ÿ“– API ๋ช…์„ธ์„œ

  • ๐Ÿ“Ž Notion API ๋ช…์„ธ์„œ (๊ณตํ†ต ๊ทœ์น™ ยท ๋„๋ฉ”์ธ๋ณ„ ์ƒ์„ธ Request/Response ยท ์‹คํŒจ ์ผ€์ด์Šค) โ†’ https://app.notion.com/p/API-a480adbca4ca824ba1ce810b83a1e6e7
  • Swagger UI โ€” /swagger-ui/index.html (Swagger ๋Š” ๋กœ์ปฌยท์šด์˜ ๋ชจ๋‘ ADMIN ๊ถŒํ•œ ๋’ค์— ์žˆ์Šต๋‹ˆ๋‹ค. /admin/login.html ์—์„œ ๊ด€๋ฆฌ์ž ๋กœ๊ทธ์ธ ํ›„ ์ ‘๊ทผํ•˜์„ธ์š”. ์™ธ๋ถ€ ์—ด๋žŒ์€ ์œ„ Notion ๋ช…์„ธ์„œ๋ฅผ ์‚ฌ์šฉํ•ด ์ฃผ์„ธ์š”.)

๊ณตํ†ต ๊ทœ์น™

ํ•ญ๋ชฉ ๊ทœ์น™
Base URL https://api.wish-connect.com (๋ชจ๋“  ์—”๋“œํฌ์ธํŠธ๋Š” /api/v1 ํ•˜์œ„)
์ธ์ฆ Authorization: Bearer {accessToken} โ€” Access Token 30๋ถ„ / Refresh Token 14์ผ(Redis ์ €์žฅ)
์‘๋‹ต ํฌ๋งท ๋ชจ๋“  ์‘๋‹ต์„ ApiResponse<T> { success, data, message } ๋กœ ๊ฐ์Œˆ
์—๋Ÿฌ ์ฒ˜๋ฆฌ CustomException + ErrorCode enum, ์ „์—ญ @RestControllerAdvice
ํŽ˜์ด์ง€๋„ค์ด์…˜ page(1๋ถ€ํ„ฐ), size ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ
๋„ค์ด๋ฐ ๋ฆฌ์†Œ์Šค๋Š” ์†Œ๋ฌธ์ž ๋ณต์ˆ˜ํ˜•, ์š”์ฒญ DTO ~Request / ์‘๋‹ต DTO ~Response, ์ƒํƒœ๊ฐ’์€ ๋Œ€๋ฌธ์ž Enum

๋„๋ฉ”์ธ๋ณ„ ์—”๋“œํฌ์ธํŠธ

๐Ÿ” ์ธ์ฆ (Auth)
๊ธฐ๋Šฅ ๋ฉ”์†Œ๋“œ ์—”๋“œํฌ์ธํŠธ
LOCAL ํšŒ์›๊ฐ€์ž… POST /api/v1/auth/signup
LOCAL ๋กœ๊ทธ์ธ POST /api/v1/auth/login
๋กœ๊ทธ์•„์›ƒ POST /api/v1/auth/logout
ํ† ํฐ ์žฌ๋ฐœ๊ธ‰ POST /api/v1/auth/refresh
์นด์นด์˜ค / ๊ตฌ๊ธ€ / ๋„ค์ด๋ฒ„ ๋กœ๊ทธ์ธ POST /api/v1/auth/{kakao|google|naver}/login
์ด๋ฉ”์ผ ์ค‘๋ณต ํ™•์ธ GET /api/v1/auth/email/check
์ด๋ฉ”์ผ ์ธ์ฆ์ฝ”๋“œ ๋ฐœ์†ก POST /api/v1/auth/email/verification-code
์ด๋ฉ”์ผ ์ธ์ฆ์ฝ”๋“œ ํ™•์ธ POST /api/v1/auth/email/verify
๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ • ์š”์ฒญ POST /api/v1/auth/password/reset-request
๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ • ์ฝ”๋“œ ํ™•์ธ POST /api/v1/auth/password/verify
๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ • POST /api/v1/auth/password/reset
๋กœ๊ทธ์ธ ์•„์ด๋”” ์ค‘๋ณต ํ™•์ธ GET /api/v1/auth/login-id/check
์•„์ด๋”” ์ฐพ๊ธฐ ์š”์ฒญ / ํ™•์ธ POST /api/v1/auth/login-id/find-request, /find
๐Ÿ“ ์˜จ๋ณด๋”ฉ ยท ํ”„๋กœํ•„ (Onboarding)
๊ธฐ๋Šฅ ๋ฉ”์†Œ๋“œ ์—”๋“œํฌ์ธํŠธ
๋‚ด ํ”„๋กœํ•„ ์กฐํšŒ GET /api/v1/users/me/profile
STEP 1 ๊ธฐ๋ณธ ์ •๋ณด ์ €์žฅ PUT /api/v1/users/me/profile/basic
STEP 2 ํ•™์  ์ •๋ณด ์ €์žฅ PUT /api/v1/users/me/profile/academic
STEP 3 ๊ฐ€๊ตฌ ์ •๋ณดยท๊ด€์‹ฌ์‚ฌ ์ €์žฅ PUT /api/v1/users/me/profile/household
STEP 4 ์˜จ๋ณด๋”ฉ ์™„๋ฃŒ POST /api/v1/users/me/profile/complete
ํ•™๊ต ๊ฒ€์ƒ‰ (์ž๋™์™„์„ฑ) GET /api/v1/universities/search
์ „๊ณต ๊ฒ€์ƒ‰ GET /api/v1/majors/search
์‹œ๋„ / ์‹œ๊ตฐ๊ตฌ ๋ชฉ๋ก GET /api/v1/regions, /api/v1/regions/{regionId}/children
๐Ÿ‘ค ๋งˆ์ดํŽ˜์ด์ง€ (MyPage)
๊ธฐ๋Šฅ ๋ฉ”์†Œ๋“œ ์—”๋“œํฌ์ธํŠธ
๋‚ด ์ •๋ณด ์กฐํšŒ GET /api/v1/users/me
๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ PATCH /api/v1/users/me/password
์ด๋ฉ”์ผ ์ค‘๋ณต ํ™•์ธ POST /api/v1/users/me/email/check
์ด๋ฉ”์ผ ๋ณ€๊ฒฝ ์ธ์ฆ์ฝ”๋“œ ๋ฐœ์†ก / ํ™•์ธ POST /api/v1/users/me/email/verification, /email/verify
์ด๋ฉ”์ผ ๋ณ€๊ฒฝ PATCH /api/v1/users/me/email
ํšŒ์› ํƒˆํ‡ด (soft delete) DELETE /api/v1/users/me
๐ŸŽ“ ์žฅํ•™๊ธˆ (Scholarship)
๊ธฐ๋Šฅ ๋ฉ”์†Œ๋“œ ์—”๋“œํฌ์ธํŠธ
๋งž์ถค ์ถ”์ฒœ ๋ชฉ๋ก (๋ฉ”์ธ) GET /api/v1/scholarships/curated
์žฅํ•™๊ธˆ ๊ฒ€์ƒ‰ GET /api/v1/scholarships/search
์ถ”์ฒœ ๊ฒ€์ƒ‰์–ด GET /api/v1/scholarships/search/popular-keywords
์žฅํ•™๊ธˆ ์ƒ์„ธ GET /api/v1/scholarships/{scholarshipId}
์žฅํ•™๊ธˆ ์ผ์ • ๋‹ฌ๋ ฅ GET /api/v1/scholarships/calendar
ํ™ˆ ์žฅํ•™๊ธˆ ์†Œ์‹ ์š”์•ฝ GET /api/v1/scholarships/home-summary
์ถ”์ฒœ ๋…ธ์ถœยทํด๋ฆญ ๊ธฐ๋ก POST /api/v1/scholarships/events
์˜ค๋“ฑ๋ก ์‹ ๊ณ  / ๋‚ด ์‹ ๊ณ  ๋ชฉ๋ก POST / GET /api/v1/scholarships/{scholarshipId}/reports, /my-reports
๋ฉด์ ‘ ์˜ˆ์ƒ ์งˆ๋ฌธ ์กฐํšŒยท์ƒ์„ฑยท์‚ญ์ œ GET / POST / DELETE /api/v1/scholarships/{scholarshipId}/interview-questions
๐Ÿ“ ์•„์นด์ด๋น™ (Archive)
๊ธฐ๋Šฅ ๋ฉ”์†Œ๋“œ ์—”๋“œํฌ์ธํŠธ
์•„์นด์ด๋น™ ๋ชฉ๋ก ์กฐํšŒ GET /api/v1/archive
์žฅํ•™๊ธˆ ์Šคํฌ๋žฉ POST /api/v1/archive/{scholarshipId}/scrap
์Šคํฌ๋žฉ ํ•ด์ œ DELETE /api/v1/archive/{scholarshipId}/scrap
โœ๏ธ AI ์ž๊ธฐ์†Œ๊ฐœ์„œ (Application)
๊ธฐ๋Šฅ ๋ฉ”์†Œ๋“œ ์—”๋“œํฌ์ธํŠธ
์ง€์›์„œ ๋ชฉ๋ก ์กฐํšŒ GET /api/v1/applications
์ง€์›์„œ ์ž‘์„ฑ ์‹œ์ž‘ POST /api/v1/applications
์ง€์›์„œ ํ†ตํ•ฉ ์ƒ์„ธ ์กฐํšŒ GET /api/v1/applications/{applicationId}
์žฅํ•™๊ธˆ ๋งž์ถค ๋ฌธํ•ญ ์ƒ์„ฑ POST /api/v1/applications/{applicationId}/questions/generate
STEP 1 ์‚ฌ์ „ ์ธํ„ฐ๋ทฐ POST /api/v1/applications/{applicationId}/questions/{questionId}/interview
STEP 2 ๋‹ต๋ณ€ ๊ด€๋ฆฌ (draft/save/confirm) PUT /api/v1/applications/{applicationId}/questions/{questionId}/answer
๋ฉด์ ‘ ์ค€๋น„ ์ž๋ฃŒ ์กฐํšŒ / ์˜ˆ์‹œ๋‹ต๋ณ€ ์ƒ์„ฑ GET / POST /api/v1/applications/{applicationId}/interview-prep
๐Ÿ”” ์•Œ๋ฆผ (Notification) ยท ๐Ÿ’ก ์ธ์‚ฌ์ดํŠธ (Insight) ยท ๐Ÿ“ฎ ๋ฌธ์˜
๊ธฐ๋Šฅ ๋ฉ”์†Œ๋“œ ์—”๋“œํฌ์ธํŠธ
์•Œ๋ฆผ ๋ชฉ๋ก GET /api/v1/notifications
์•Œ๋ฆผ ์ฝ์Œ ์ฒ˜๋ฆฌ PUT / PATCH /api/v1/notifications/{notificationId}/read
์•Œ๋ฆผ ์ „์ฒด ์‚ญ์ œ DELETE /api/v1/notifications
์•Œ๋ฆผ ์„ค์ • ์กฐํšŒ / ๋ณ€๊ฒฝ GET / PUT /api/v1/notifications/settings
์ธ์‚ฌ์ดํŠธ ๋ชฉ๋ก ์กฐํšŒ GET /api/v1/insights
์ฝ˜ํ…์ธ  ์ด์šฉ ๋ฌธ์˜ ์ ‘์ˆ˜ POST /api/v1/content-inquiries
๐Ÿ›  ๊ด€๋ฆฌ์ž (ADMIN ์ „์šฉ)

ROLE_ADMIN ํ† ํฐ์ด ์žˆ์–ด์•ผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜์—ญ ์—”๋“œํฌ์ธํŠธ
๊ด€๋ฆฌ์ž ์ธ์ฆ /api/v1/admin/auth/login, /logout
๋ฐ์ดํ„ฐ ํ˜„ํ™ฉยท์ˆ˜์ง‘ ์›๋ณธยท์ด์ƒ ํƒ์ง€ /api/v1/scholarships/admin/**
์ˆ˜์ง‘ยท๋ณด์™„ยทํŒŒ์‹ฑ ๋ฐฐ์น˜ ์ˆ˜๋™ ์‹คํ–‰ /api/v1/scholarships/{sync|collect|enrich|parse|conditions}/**
์ค‘๋ณต ์žฅํ•™๊ธˆ ํƒ์ง€ยท๋ณ‘ํ•ฉ ์Šน์ธ /api/v1/scholarships/merge/**
์žฅํ•™๊ธˆ ์ˆ˜๊ธฐ ๋“ฑ๋กยท์ˆ˜์ •ยท์‚ญ์ œ, ์—‘์…€ ์ผ๊ด„ ๋ฐ˜์˜ /api/v1/scholarships/manual/**, /admin/manual-excel
์˜ค๋“ฑ๋ก ์‹ ๊ณ  ์ฒ˜๋ฆฌ /api/v1/scholarships/reports/**
์ฝ˜ํ…์ธ  ๋ฌธ์˜ ์ฒ˜๋ฆฌ /api/v1/admin/content-inquiries/**
๋ฐฐ์น˜ ์‹คํ–‰ ์ด๋ ฅ ยท ์‹œ์Šคํ…œ ์ƒํƒœ ยท ๊ฐ์‚ฌ ๋กœ๊ทธ /api/v1/admin/jobs, /admin/system/**, /admin/audit-log
ํ•™๊ตยท์ „๊ณต ๋™๊ธฐํ™”, ์ธ์‚ฌ์ดํŠธ ์ˆ˜์ง‘ /api/v1/universities/sync, /api/v1/insights/sync

๐Ÿ’ป Architecture & Deploy

WishConnect Architecture

๊ตฌ์„ฑ ๋‚ด์šฉ
CI/CD GitHub Actions โ€” main push ์‹œ build ยท test โ†’ jar SCP โ†’ SSH ์žฌ๊ธฐ๋™
Compute AWS EC2 (Ubuntu, ap-northeast-2) ยท systemd wishconnect.service ยท -Xms512m -Xmx1g
Web Nginx :443 (Let's Encrypt) โ†’ Spring Boot :8080 ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ
DB AWS RDS PostgreSQL
Cache Redis (EC2 ๋กœ์ปฌ) โ€” Refresh Token, ์ด๋ฉ”์ผ ์ธ์ฆ์ฝ”๋“œ TTL, ๋ถ„์‚ฐ ๋ฝ
Storage / Mail AWS S3 (ํฌ์Šคํ„ฐยท์ฒจ๋ถ€ ์ด๋ฏธ์ง€) ยท AWS SES (์ธ์ฆ ๋ฉ”์ผ)
DNS Route 53 โ€” wish-connect.com(Vercel, FE) / api.wish-connect.com(EC2, BE)
External Anthropic Claude, ์นด์นด์˜คยท๊ตฌ๊ธ€ยท๋„ค์ด๋ฒ„ OAuth, ๋„ค์ด๋ฒ„ ๊ฒ€์ƒ‰, ํ•œ๊ตญ์žฅํ•™์žฌ๋‹จ ๊ณต๊ณต API, ํ•™์ˆ ์ •๋ณด API, ๋Œ€ํ•™ ๊ณต์ง€ ํฌ๋กค๋ง

์šด์˜ ์„œ๋ฒ„ ์„ค์ •(systemdยทlogrotateยท์Šค์™‘ยท๊ด€๋ฆฌ์ž SSH ํ„ฐ๋„)์€ deploy/README.md์— ์ •๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ”ง Tech Stack

๊ตฌ๋ถ„ ๊ธฐ์ˆ 
Language Java 17
Framework Spring Boot 3.3.5 (Web, Data JPA, Security, Validation, Mail, Actuator)
Database PostgreSQL ยท Redis
Auth Spring Security + JWT (jjwt 0.12.6) ยท OAuth 2.0 (Kakao / Google / Naver)
AI Anthropic Claude Java SDK
Docs springdoc-openapi (Swagger UI) + therapi-runtime-javadoc
Infra AWS EC2 ยท RDS ยท S3 ยท SES ยท Route 53 ยท Nginx ยท GitHub Actions
Etc Jsoup(ํฌ๋กค๋ง) ยท Apache POI(์—‘์…€) ยท AWS SDK v2 ยท Lombok

๐Ÿงฑ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

src/main/java/com/wishconnect
โ”œโ”€โ”€ domain
โ”‚   โ”œโ”€โ”€ auth            # ํšŒ์›๊ฐ€์ž…ยท๋กœ๊ทธ์ธยท์†Œ์…œยทํ† ํฐยท์ด๋ฉ”์ผ ์ธ์ฆ
โ”‚   โ”œโ”€โ”€ user            # ๋งˆ์ดํŽ˜์ด์ง€ยทํ”„๋กœํ•„ยท์˜จ๋ณด๋”ฉ
โ”‚   โ”œโ”€โ”€ scholarship     # ์ˆ˜์ง‘ยท์ •์ œยทํ๋ ˆ์ดํŒ…ยท๊ฒ€์ƒ‰ยท์ƒ์„ธยท์‹ ๊ณ ยท๊ด€๋ฆฌ์ž
โ”‚   โ”œโ”€โ”€ application     # AI ์ž๊ธฐ์†Œ๊ฐœ์„œ(์ธํ„ฐ๋ทฐยท์ดˆ์•ˆยท๋ฉด์ ‘ ์ค€๋น„)
โ”‚   โ”œโ”€โ”€ archive         # ์Šคํฌ๋žฉ ์•„์นด์ด๋น™
โ”‚   โ”œโ”€โ”€ notification    # ์•Œ๋ฆผ์„ผํ„ฐยท์„ค์ •ยท์Šค์ผ€์ค„๋Ÿฌ
โ”‚   โ”œโ”€โ”€ insight         # ์ธ์‚ฌ์ดํŠธ ์ฝ˜ํ…์ธ  ์ˆ˜์ง‘ยท์กฐํšŒ
โ”‚   โ”œโ”€โ”€ inquiry         # ์ฝ˜ํ…์ธ  ์ด์šฉ ๋ฌธ์˜
โ”‚   โ”œโ”€โ”€ search          # ์ถ”์ฒœ ๊ฒ€์ƒ‰์–ด
โ”‚   โ””โ”€โ”€ common          # ์ง€์—ญยทํ•™๊ตยท์ „๊ณต ๋งˆ์Šคํ„ฐ
โ””โ”€โ”€ global
    โ”œโ”€โ”€ config          # Security, CORS, Swagger, Scheduling
    โ”œโ”€โ”€ jwt             # ํ† ํฐ ๋ฐœ๊ธ‰ยท๊ฒ€์ฆ ํ•„ํ„ฐ
    โ”œโ”€โ”€ exception       # CustomException ยท ErrorCode ยท ์ „์—ญ ํ•ธ๋“ค๋Ÿฌ
    โ”œโ”€โ”€ lock            # ๋ฐฐ์น˜ ๋ถ„์‚ฐ ๋ฝ
    โ”œโ”€โ”€ audit           # ๊ด€๋ฆฌ์ž ๊ฐ์‚ฌ ๋กœ๊ทธ
    โ”œโ”€โ”€ operation       # ๋ฐฐ์น˜ ์‹คํ–‰ ์ด๋ ฅยท์‹œ์Šคํ…œ ์ƒํƒœ
    โ”œโ”€โ”€ common          # ApiResponse ๋“ฑ ๊ณตํ†ต ์‘๋‹ต
    โ””โ”€โ”€ util
  • Java ํŒŒ์ผ 417๊ฐœ ยท ์—”ํ‹ฐํ‹ฐ 42๊ฐœ ยท ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค 78๊ฐœ


sitemap.xml ยท robots.txt (๊ฒ€์ƒ‰์—”์ง„ ์ƒ‰์ธ)

๋„ค์ด๋ฒ„ ์„œ์น˜์–ด๋“œ๋ฐ”์ด์ € ์›น๋งˆ์Šคํ„ฐ ๊ฐ€์ด๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋งž์ท„๋‹ค. ๊ณต๊ณ ๋Š” ๋งค์ผ ์ˆ˜์ง‘ ๋ฐฐ์น˜๋กœ ๊ฐˆ๋ฆฌ๋ฏ€๋กœ ์ •์  ํŒŒ์ผ ๋Œ€์‹  DB ๋ฅผ ์ฝ์–ด ์ฆ‰์„์—์„œ ๋งŒ๋“ ๋‹ค.

์—”๋“œํฌ์ธํŠธ ๋‚ด์šฉ
GET /sitemap.xml ๊ณ ์ • ํŽ˜์ด์ง€ + ์žฅํ•™๊ธˆ ์ƒ์„ธ URL. ๋ชจ์ง‘ ์ค‘ priority 0.8, ๋งˆ๊ฐ๋ถ„ 0.3
GET /robots.txt ๋„ค์ด๋ฒ„ ๊ฒ€์ƒ‰๋กœ๋ด‡(Yeti) ํ—ˆ์šฉ, ๊ด€๋ฆฌ์žยทAPI ๊ฒฝ๋กœ ์ฐจ๋‹จ, Sitemap: ์œ„์น˜ ๋ช…์‹œ

๋‘˜ ๋‹ค ์ธ์ฆ ์—†์ด ์—ด๋ ค ์žˆ๊ณ (ํฌ๋กค๋Ÿฌ๋Š” ํ† ํฐ์ด ์—†๋‹ค), ๊ฒฐ๊ณผ๋Š” ์„œ๋ฒ„์—์„œ 1์‹œ๊ฐ„ ์บ์‹œํ•œ๋‹ค. ์„ค์ •์€ app.sitemap.* / app.robots.* (application.yml). ํ”„๋ก ํŠธ ๋ผ์šฐํŒ…์ด ๋ฐ”๋€Œ๋ฉด SITEMAP_SCHOLARSHIP_PATH / SITEMAP_STATIC_PATHS ํ™˜๊ฒฝ๋ณ€์ˆ˜๋งŒ ๊ณ ์น˜๋ฉด ๋œ๋‹ค.

๊ฐ€์ด๋“œ์—์„œ ์ง€ํ‚จ ๊ฒƒ:

  • URL ๋„๋ฉ”์ธ ์ผ์น˜ โ€” ์‚ฌ์ดํŠธ๋งต ๋‚ด URL ์ด ์†Œ์œ ํ™•์ธํ•œ ํ˜ธ์ŠคํŠธ์™€ ๋‹ค๋ฅด๊ฑฐ๋‚˜ ์ƒ๋Œ€๊ฒฝ๋กœ๋ฉด ๋„ค์ด๋ฒ„๊ฐ€ ํ†ต์งธ๋กœ ๋ฒ„๋ฆฐ๋‹ค. ๊ทธ๋ž˜์„œ app.sitemap.base-url ์€ ์ ˆ๋Œ€์ฃผ์†Œ๋งŒ ํ—ˆ์šฉํ•˜๊ณ , ์•„๋‹ˆ๋ฉด ๊ธฐ๋™ ์‹œ์ ์— ์˜ˆ์™ธ๋กœ ๋ง‰๋Š”๋‹ค. www ์œ ๋ฌด๊นŒ์ง€ ์„œ์น˜์–ด๋“œ๋ฐ”์ด์ €์— ๋“ฑ๋กํ•œ ํ˜ธ์ŠคํŠธ์™€ ๋˜‘๊ฐ™์ด ๋งž์ถฐ์•ผ ํ•œ๋‹ค.
  • ์šฉ๋Ÿ‰ยท๊ฑด์ˆ˜ ์ƒํ•œ โ€” 10MB ๋ฏธ๋งŒ, ํ•œ ํŒŒ์ผ๋‹น 50,000 URL ๋ฏธ๋งŒ. ์ƒํ•œ์— ๋‹ฟ์œผ๋ฉด WARN ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธด๋‹ค.
  • ์‘๋‹ต ์†๋„ โ€” ํ”ผ๋“œ๊ฐ€ ๋А๋ฆฌ๋ฉด ์ œ์ถœ์ด ์ œํ•œ๋˜๋ฏ€๋กœ ์ƒ์„ฑ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œํ•œ๋‹ค.
  • lastmod โ€” ๋„ค์ด๋ฒ„ ์˜ˆ์‹œ์™€ ๊ฐ™์€ W3C Datetime(2026-08-18T01:13:19+09:00).
  • ๋ชจ๋“  URL ์ˆ˜๋ก ๊ถŒ์žฅ โ€” ๋งˆ๊ฐ ๊ณต๊ณ ๋„ ์ƒ์„ธ ํŽ˜์ด์ง€๊ฐ€ ์‚ด์•„ ์žˆ์œผ๋ฏ€๋กœ ๋‹ด๋˜ priority ๋ฅผ ๋‚ฎ์ถ˜๋‹ค (SITEMAP_INCLUDE_CLOSED=false ๋กœ ์ œ์™ธ ๊ฐ€๋Šฅ).
  • robots.txt ๋Š” text/plain + 2xx โ€” HTML ๋กœ ๋‚˜๊ฐ€๋ฉด ๊ทœ์น™์ด ๋ฌด์‹œ๋˜๊ณ , 5xx ๋ฉด ์‚ฌ์ดํŠธ ์ „์ฒด๊ฐ€ ์ˆ˜์ง‘ ์ฐจ๋‹จ์œผ๋กœ ํ•ด์„๋œ๋‹ค. Yeti ๊ทธ๋ฃน์—๋„ ๊ฐ™์€ ๊ทœ์น™์„ ๋ฐ˜๋ณตํ•ด ์ ๋Š”๋‹ค(ํ‘œ์ค€์ƒ ๊ฐ€์žฅ ๊ตฌ์ฒด์ ์ธ ๊ทธ๋ฃน ํ•˜๋‚˜๋งŒ ์ ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ).

โš ๏ธ ๋‚จ์€ ์ž‘์—…์€ ๋ฐฑ์—”๋“œ ๋ฐ–์— ์žˆ๋‹ค.

  1. ํ”„๋ก ํŠธ/nginx ํ”„๋ก์‹œ โ€” ๋‘ ํŒŒ์ผ ๋ชจ๋‘ ์‚ฌ์ดํŠธ ๋ฃจํŠธ์— ์žˆ์–ด์•ผ ํ•œ๋‹ค. https://wish-connect.com/sitemap.xml, /robots.txt ์š”์ฒญ์„ ์ด ์—”๋“œํฌ์ธํŠธ๋กœ rewrite ํ•ด์•ผ ํ•œ๋‹ค. robots.txt ๊ทœ์น™์€ ํ˜ธ์ŠคํŠธ๋ณ„๋กœ ์ ์šฉ๋˜๋ฏ€๋กœ API ๋„๋ฉ”์ธ์—๋งŒ ์žˆ์œผ๋ฉด ํ”„๋ก ํŠธ ์ˆ˜์ง‘์—๋Š” ์•„๋ฌด ์˜ํ–ฅ์ด ์—†๋‹ค.
  2. ์„œ์น˜์–ด๋“œ๋ฐ”์ด์ € ๋“ฑ๋ก โ€” ์‚ฌ์ดํŠธ ๋“ฑ๋ก โ†’ ์†Œ์œ ํ™•์ธ(meta ํƒœ๊ทธ ๋˜๋Š” HTML ํŒŒ์ผ) โ†’ "์š”์ฒญ-์‚ฌ์ดํŠธ๋งต ์ œ์ถœ".
  3. ํ”„๋ก ํŠธ HTML ๋งˆํฌ์—… โ€” ํŽ˜์ด์ง€๋ณ„ titleยทmeta description, ํ‘œ์ค€ <a href> ๋งํฌ, noindex/nofollow ๋ฏธ์‚ฌ์šฉ. ์ฝ˜ํ…์ธ ๋ฅผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ๋งŒ ๊ทธ๋ฆฌ๋ฉด ์ˆ˜์ง‘๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ƒ์„ธ ํŽ˜์ด์ง€๋Š” SSR ์ด์–ด์•ผ ํ•œ๋‹ค.

RSS ํ”ผ๋“œ๋Š” ๋งŒ๋“ค์ง€ ์•Š์•˜๋‹ค. ๊ฐ€์ด๋“œ๋„ "๋ณธ๋ฌธ์„ ๋‹ด์•„์•ผ ํ•ด์„œ URL ์„ ๋งŽ์ด ๋„ฃ๊ธฐ ์–ด๋ ค์šฐ๋‹ˆ ์‚ฌ์ดํŠธ๋งต์„ ์šฐ์„  ํ™œ์šฉ"ํ•˜๋ผ๊ณ  ๊ถŒํ•œ๋‹ค.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages