Skip to content
ย 
ย 

Latest commit

ย 

History

129 Commits

Folders and files

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

Repository files navigation

WishBoard

๋ชฉํ‘œ๋ฅผ ๊ธฐ๋กํ•˜๊ณ , ํ•จ๊ป˜ ๋„์ „ํ•˜๋ฉฐ, ๋‹ค์Œ ๋ชฉํ‘œ๊นŒ์ง€ ๋ฐœ๊ฒฌํ•˜๋Š” ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ํ”Œ๋žซํผ

๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ๋“ฑ๋ก๋ถ€ํ„ฐ ์ง„ํ–‰ ๊ณผ์ • ๊ณต์œ , ๋‹ฌ์„ฑ ์ธ์ฆ, AI ๊ธฐ๋ฐ˜ ๋‹ค์Œ ๋ชฉํ‘œ ์ถ”์ฒœ๊นŒ์ง€
๋ชฉํ‘œ ๋‹ฌ์„ฑ์˜ ์ „ ๊ณผ์ •์„ ํ•˜๋‚˜์˜ ์„œ๋น„์Šค์—์„œ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.




WishBoard ๋Œ€ํ‘œ ํ™”๋ฉด

๋ชฉ์ฐจ

  1. ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ
  2. ๊ธฐํš ๋ฐฐ๊ฒฝ
  3. ์„œ๋น„์Šค ์ด์šฉ ํ๋ฆ„
  4. ์ฃผ์š” ๊ธฐ๋Šฅ
  5. ํ”„๋กœ์ ํŠธ ์ •๋ณด
  6. ๊ธฐ์ˆ  ์Šคํƒ
  7. ๊ธฐ์ˆ  ์„ ํƒ ๋ฐ ํ™œ์šฉ
  8. ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜
  9. ๋‹ด๋‹น ์—ญํ• 
  10. ํ•ต์‹ฌ ๊ตฌํ˜„
  11. ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๋ฐ ์„ค๊ณ„ ๊ฐœ์„ 
  12. API
  13. ๋ฐ์ดํ„ฐ ๋ชจ๋ธ
  14. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ
  15. ์‹คํ–‰ ๋ฐฉ๋ฒ•
  16. ์„ฑ๊ณผ์™€ ํšŒ๊ณ 

ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

WishBoard๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์˜ ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ๋ฅผ ๊ตฌ์ฒด์ ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ , ์ง„ํ–‰ ๊ณผ์ •๊ณผ ๋‹ฌ์„ฑ ๊ฒฐ๊ณผ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•˜๋Š” ๋ชฉํ‘œ ๊ด€๋ฆฌ ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๋Š” ๋ชฉํ‘œ๋ฅผ ๋‹ค์Œ 5๊ฐ€์ง€ ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๋ถ„๋ฅ˜ํ•˜๊ณ  ์ง„ํ–‰๋ฅ , ๋งˆ๊ฐ ๊ธฐํ•œ, ์ฐธ๊ณ  ์ž๋ฃŒ์™€ ์‚ฌ์ง„์„ ํ•จ๊ป˜ ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•ด๋ณด๊ณ  ์‹ถ๋‹ค
  • ๋˜๊ณ  ์‹ถ๋‹ค
  • ๊ฐ–๊ณ  ์‹ถ๋‹ค
  • ๊ฐ€๋ณด๊ณ  ์‹ถ๋‹ค
  • ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‹ค

๊ฐ™์€ ๋ชฉํ‘œ๋ฅผ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž๋“ค์€ ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ํŒ€ ํ™œ๋™์„ ํ†ตํ•ด ๊ฒฝํ—˜๊ณผ ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๊ณ  ์„œ๋กœ ์‘์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๋ฉด ํŠธ๋กœํ”ผ์™€ ์ธ์ฆ ๊ฒŒ์‹œ๊ธ€๋กœ ์„ฑ๊ณผ๋ฅผ ๋‚จ๊ธธ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์™„๋ฃŒํ•œ ๋ชฉํ‘œ ์ด๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ AI๊ฐ€ ์ƒˆ๋กœ์šด ๋ชฉํ‘œ๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

WishBoard๋Š” ๋‹จ์ˆœํžˆ ๋ชฉํ‘œ์˜ ์™„๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š” ๋„๊ตฌ๊ฐ€ ์•„๋‹ˆ๋ผ,

๋ชฉํ‘œ ์„ค์ • โ†’ ๊ณผ์ • ๊ธฐ๋ก โ†’ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ณต์œ  โ†’ ๋‹ฌ์„ฑ ์ธ์ฆ โ†’ ๋‹ค์Œ ๋ชฉํ‘œ ์ถ”์ฒœ

์œผ๋กœ ์ด์–ด์ง€๋Š” ์ˆœํ™˜ํ˜• ๋ชฉํ‘œ ๋‹ฌ์„ฑ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.


๊ธฐํš ๋ฐฐ๊ฒฝ

๊ธฐ์กด ๋ชฉํ‘œ ๊ด€๋ฆฌ ์„œ๋น„์Šค๋Š” ๋ชฉํ‘œ๋ฅผ ๋“ฑ๋กํ•˜๊ณ  ์™„๋ฃŒ ์—ฌ๋ถ€๋ฅผ ์ฒดํฌํ•˜๋Š” ๊ธฐ๋Šฅ์— ์ง‘์ค‘๋˜์–ด ์žˆ์–ด, ์‚ฌ์šฉ์ž๊ฐ€ ๋ชฉํ‘œ๋ฅผ ์ง€์†ํ•˜๋„๋ก ๋•๊ฑฐ๋‚˜ ๊ฐ™์€ ๋ชฉํ‘œ๋ฅผ ๊ฐ€์ง„ ์‚ฌ๋žŒ๋“ค๊ณผ ์—ฐ๊ฒฐํ•˜๋Š” ๊ธฐ๋Šฅ์ด ๋ถ€์กฑํ–ˆ์Šต๋‹ˆ๋‹ค.

WishBoard๋Š” ๋‹ค์Œ ์„ธ ๊ฐ€์ง€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ ์ž ๊ธฐํšํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ WishBoard์˜ ํ•ด๊ฒฐ ๋ฐฉ์‹
๋ชฉํ‘œ๋ฅผ ์„ธ์›Œ๋„ ๊พธ์ค€ํžˆ ์œ ์ง€ํ•˜๊ธฐ ์–ด๋ ค์›€ ์ง„ํ–‰๋ฅ , ํ™œ๋™ ๊ธฐ๋ก, D-Day๋ฅผ ํ†ตํ•ด ๊ณผ์ •์„ ์‹œ๊ฐํ™”
๋น„์Šทํ•œ ๋ชฉํ‘œ๋ฅผ ๊ฐ€์ง„ ์‚ฌ๋žŒ๊ณผ ์ •๋ณด๋ฅผ ๋‚˜๋ˆ„๊ธฐ ์–ด๋ ค์›€ ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ์ปค๋ฎค๋‹ˆํ‹ฐ, ๋Œ“๊ธ€ยท๋Œ€๋Œ“๊ธ€, ์ข‹์•„์š”, ํŒ€ ํ™œ๋™ ์ œ๊ณต
๋ชฉํ‘œ ๋‹ฌ์„ฑ ํ›„ ๋‹ค์Œ ๋ชฉํ‘œ๋ฅผ ์ฐพ๊ธฐ ์–ด๋ ค์›€ ์™„๋ฃŒ ์ด๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ AI๊ฐ€ ์ƒˆ๋กœ์šด ๋ชฉํ‘œ ์ถ”์ฒœ

์„œ๋น„์Šค ์ด์šฉ ํ๋ฆ„

flowchart LR
    A["๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ๋“ฑ๋ก"] --> B["์ง„ํ–‰๋ฅ ยทํ™œ๋™ ๊ธฐ๋ก"]
    B --> C["์ปค๋ฎค๋‹ˆํ‹ฐยทํŒ€ ํ™œ๋™"]
    C --> D["๋ชฉํ‘œ ๋‹ฌ์„ฑ ๋ฐ ์ธ์ฆ"]
    D --> E["ํŠธ๋กœํ”ผ ์ƒ์„ฑ"]
    E --> F["AI ๊ธฐ๋ฐ˜ ๋‹ค์Œ ๋ชฉํ‘œ ์ถ”์ฒœ"]
    F --> A
Loading

์ฃผ์š” ๊ธฐ๋Šฅ

1. ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ๋“ฑ๋ก ๋ฐ ๊ด€๋ฆฌ

  • ๋ชฉํ‘œ๋ฅผ 5๊ฐ€์ง€ ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๋ถ„๋ฅ˜
  • ์ง„ํ–‰ ์ƒํƒœ์™€ ๋ชฉํ‘œ๋ณ„ ์ง„ํ–‰๋ฅ  ๊ด€๋ฆฌ
  • ๋งˆ๊ฐ ๊ธฐํ•œ๊ณผ D-Day ํ‘œ์‹œ
  • ๋ชฉํ‘œ ์„ค์ • ์ด์œ , ๋‹ค์ง, ์ฐธ๊ณ  ์ž๋ฃŒ ๋ฐ ์ด๋ฏธ์ง€ ๋“ฑ๋ก
  • ์ตœ๋Œ€ 3๊ฐœ์˜ ๋ชฉํ‘œ ์ƒ๋‹จ ๊ณ ์ •
  • ๋ชฉํ‘œ ๋‹ฌ์„ฑ ์‹œ ์™„๋ฃŒ ์ผ์‹œ ๊ธฐ๋ก

2. ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ์ปค๋ฎค๋‹ˆํ‹ฐ

  • ๊ฐ™์€ ๋ชฉํ‘œ๋ฅผ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž ๊ฐ„ ์ •๋ณด ๊ณต์œ 
  • ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰ยท์กฐํšŒยท์ž‘์„ฑยท์ˆ˜์ •ยท์‚ญ์ œ
  • ์ด๋ฏธ์ง€๊ฐ€ ํฌํ•จ๋œ ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ
  • ๋Œ“๊ธ€ยท๋Œ€๋Œ“๊ธ€ ์ž‘์„ฑ๊ณผ ์ข‹์•„์š”
  • ๊ด€์‹ฌ ๊ฒŒ์‹œ๊ธ€ ์ฆ๊ฒจ์ฐพ๊ธฐ
  • ์ปค๋ฎค๋‹ˆํ‹ฐ ์œ ํ˜•๊ณผ ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜ ๊ฒŒ์‹œ๊ธ€ ํ•„ํ„ฐ๋ง

3. ๋ชฉํ‘œ ๋‹ฌ์„ฑ ๋ณด์ƒ

  • ๋ชฉํ‘œ ๋‹ฌ์„ฑ ์‹œ ํŠธ๋กœํ”ผ ์ƒ์„ฑ
  • ์™„๋ฃŒํ•œ ๋ชฉํ‘œ๋ฅผ ์ธ์ฆ ๊ฒŒ์‹œ๊ธ€๋กœ ๊ธฐ๋ก
  • ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์˜ ์‘์›๊ณผ ํ”ผ๋“œ๋ฐฑ ์ œ๊ณต
  • ๋‹ฌ์„ฑ ๊ธฐ๋ก์„ ํ†ตํ•ด ์„ฑ์ทจ ๊ณผ์ • ์‹œ๊ฐํ™”

4. AI ๊ธฐ๋ฐ˜ ๋ชฉํ‘œ ์ถ”์ฒœ

  • ์‚ฌ์šฉ์ž๊ฐ€ ์™„๋ฃŒํ•œ ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ๋ถ„์„
  • OpenAI API๋ฅผ ํ™œ์šฉํ•œ ๋‹ค์Œ ๋ชฉํ‘œ ํ‚ค์›Œ๋“œ ์ถ”์ฒœ
  • ์ถ”์ฒœ ํ‚ค์›Œ๋“œ์™€ ๊ด€๋ จ๋œ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€ ์—ฐ๊ฒฐ
  • ๋งค์นญ ๊ฒŒ์‹œ๊ธ€์ด ์—†์„ ๊ฒฝ์šฐ ์ถ”์ฒœ ํ‚ค์›Œ๋“œ ์ž์ฒด ์ œ๊ณต

5. ๋ช…์˜ˆ์˜ ์ „๋‹น

  • ํŠธ๋กœํ”ผ ๊ฒŒ์‹œ๊ธ€ ์ค‘ ์ข‹์•„์š”๊ฐ€ ๋งŽ์€ ์ด๋‹ฌ์˜ ๊ฒŒ์‹œ๊ธ€ ์ œ๊ณต
  • ์›”๊ฐ„ ์ธ๊ธฐ ๊ฒŒ์‹œ๊ธ€ Top 10 ์กฐํšŒ
  • ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์˜ ์„ฑ๊ณต ๊ฒฝํ—˜์„ ํ†ตํ•œ ๋™๊ธฐ๋ถ€์—ฌ

ํ”„๋กœ์ ํŠธ ์ •๋ณด

ํ•ญ๋ชฉ ๋‚ด์šฉ
์„œ๋น„์Šค๋ช… WishBoard
๊ฐœ๋ฐœ ๊ธฐ๊ฐ„ 2025.03 ~ 2025.06
์ฐธ์—ฌ ์ธ์› 4๋ช…
ํ”„๋กœ์ ํŠธ ํ˜•ํƒœ ํ’€์Šคํƒ ํŒ€ ํ”„๋กœ์ ํŠธ
์ฃผ์š” ์‚ฌ์šฉ์ž ๋ชฉํ‘œ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์™€ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•˜๊ณ  ์‹ถ์€ ์‚ฌ๋žŒ
๋‹ด๋‹น ์˜์—ญ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ธฐ๋Šฅ ํ”„๋ก ํŠธ์—”๋“œยท๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ ๋ฐ API ์—ฐ๋™
์ฃผ์š” ๋‹ด๋‹น ๊ธฐ๋Šฅ ์ฆ๊ฒจ์ฐพ๊ธฐ, ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰ยท์กฐํšŒยท์ž‘์„ฑ, ๋Œ“๊ธ€ยท๋Œ€๋Œ“๊ธ€, ํ™”๋ฉด ๊ธฐํš ๋ฐ ๊ตฌํ˜„

๊ธฐ์ˆ  ์Šคํƒ

Frontend

๊ธฐ์ˆ  ๋ฒ„์ „ยท๊ตฌ๋ถ„ ํ”„๋กœ์ ํŠธ์—์„œ์˜ ํ™œ์šฉ
React Native Mobile App ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธยท์ปค๋ฎค๋‹ˆํ‹ฐยท๋Œ“๊ธ€ ๋“ฑ ๋ชจ๋ฐ”์ผ ํ™”๋ฉด ๊ตฌํ˜„
JavaScript Language ํ™”๋ฉด ์ƒํƒœ ๊ด€๋ฆฌ, ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฐ REST API ์—ฐ๋™
React Navigation Navigation ํ™”๋ฉด ์ด๋™, ์ปค๋ฎค๋‹ˆํ‹ฐ ํƒญ ์ •๋ณด์™€ ๋ผ์šฐํŒ… ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌ
Figma UI/UX ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™”๋ฉด ๊ธฐํš, ์™€์ด์–ดํ”„๋ ˆ์ž„ ๋ฐ ํ”„๋กœํ† ํƒ€์ž… ์ œ์ž‘

Backend

๊ธฐ์ˆ  ๋ฒ„์ „ยท๊ตฌ๋ถ„ ํ”„๋กœ์ ํŠธ์—์„œ์˜ ํ™œ์šฉ
Java 17 ์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๋„๋ฉ”์ธ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ตฌํ˜„
Spring Boot 3.4.5 REST API, ์˜์กด์„ฑ ์ฃผ์ž…, ์„ค์ • ๋ฐ ๊ณ„์ธตํ˜• ์„œ๋ฒ„ ๊ตฌ์กฐ ๊ตฌ์„ฑ
Spring Data JPA / Hibernate ORM ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘, ์ž๊ธฐ์ฐธ์กฐ ๋Œ“๊ธ€ ๊ตฌ์กฐ, ์—ฐ๊ด€๊ด€๊ณ„ ๋ฐ ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ๊ตฌํ˜„
Spring Security Security URL ์ ‘๊ทผ ์ œ์–ด ๋ฐ ์ธ์ฆ ํ•„ํ„ฐ ์ฒด์ธ ๊ตฌ์„ฑ
JJWT 0.12.3 Stateless JWT ์ƒ์„ฑยท๊ฒ€์ฆ๊ณผ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ฒ˜๋ฆฌ
JdbcTemplate SQL ์ข‹์•„์š” ์ค‘๋ณต ๊ฒ€์ฆ๊ณผ ์ง์ ‘ SQL ๊ธฐ๋ฐ˜ ์นด์šดํŠธ ์ฒ˜๋ฆฌ
Spring WebClient HTTP Client OpenAI Chat Completion API ํ˜ธ์ถœ
Spring Multipart File Upload ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์ฒ˜๋ฆฌ
Spring Validation Validation ์š”์ฒญ DTO ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ
SpringDoc OpenAPI 2.5.0 Swagger UI ๊ธฐ๋ฐ˜ API ๋ฌธ์„œ ์ž๋™ ์ƒ์„ฑ ๋ฐ ํ…Œ์ŠคํŠธ
Lombok Productivity ์ƒ์„ฑ์ž ์ฃผ์ž…, ๋กœ๊น… ๋ฐ ๋ฐ˜๋ณต ์ฝ”๋“œ ์ถ•์†Œ

Database ยท Infrastructure ยท Collaboration

๊ธฐ์ˆ  ๋ฒ„์ „ยท๊ตฌ๋ถ„ ํ”„๋กœ์ ํŠธ์—์„œ์˜ ํ™œ์šฉ
MySQL 8.0 ์‚ฌ์šฉ์ž, ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ, ์ปค๋ฎค๋‹ˆํ‹ฐ, ๋Œ“๊ธ€ ๋ฐ ์ถ”์ฒœ ๋ฐ์ดํ„ฐ ์ €์žฅ
AWS RDS Cloud DB ํŒ€ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์šด์˜
Gradle Kotlin DSL Build Tool ์˜์กด์„ฑ ๊ด€๋ฆฌ, ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ ์‹คํ–‰
Git / GitHub Version Control ๊ธฐ๋Šฅ ๋ธŒ๋žœ์น˜ ๊ธฐ๋ฐ˜ ํ˜‘์—…, ์ฝ”๋“œ ๋ฆฌ๋ทฐ ๋ฐ ๋ฒ„์ „ ๊ด€๋ฆฌ
Swagger UI API Collaboration ํ”„๋ก ํŠธ์—”๋“œ์™€ ์š”์ฒญยท์‘๋‹ต ๊ทœ๊ฒฉ ๊ณต์œ  ๋ฐ API ํ…Œ์ŠคํŠธ

๋‹ด๋‹น ๊ธฐ๋Šฅ๊ณผ ๊ธฐ์ˆ  ์—ฐ๊ฒฐ

๋‹ด๋‹น ๊ธฐ๋Šฅ ์ ์šฉ ๊ธฐ์ˆ  ๊ตฌํ˜„ ๋‚ด์šฉ
์ปค๋ฎค๋‹ˆํ‹ฐ ํƒญยทํ™”๋ฉด React Native, React Navigation ๋ผ์šฐํŒ… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ดˆ๊ธฐ ํƒญ ์ƒํƒœ์™€ API ํ•„ํ„ฐ์— ๋™๊ธฐํ™”
๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰ Spring Data JPA, MySQL ํ‚ค์›Œ๋“œ์™€ ์ปค๋ฎค๋‹ˆํ‹ฐ ์œ ํ˜•์„ ์กฐํ•ฉํ•œ ๊ฒ€์ƒ‰ยท๊ทธ๋ฃน ์ง‘๊ณ„
๋Œ“๊ธ€ยท๋Œ€๋Œ“๊ธ€ JPA, Lazy Loading, DTO ์ž๊ธฐ์ฐธ์กฐ ๊ณ„์ธต ๊ตฌ์กฐ์™€ ๋‹จ๊ณ„๋ณ„ ๋ถ€๋ถ„ ์กฐํšŒ ์„ค๊ณ„
๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ Spring Boot, Multipart ํ…์ŠคํŠธยท์ด๋ฏธ์ง€ ๊ฒŒ์‹œ๊ธ€ ์š”์ฒญ ์ฒ˜๋ฆฌ
์ข‹์•„์š”ยท์ฆ๊ฒจ์ฐพ๊ธฐ JdbcTemplate, JPA ์‚ฌ์šฉ์ž๋ณ„ ์ค‘๋ณต ์ฒ˜๋ฆฌ์™€ ๋งคํ•‘ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ
API ์—ฐ๋™ Swagger, REST API ํ”„๋ก ํŠธ์—”๋“œ ์ƒํƒœ์™€ ๋ฐฑ์—”๋“œ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ทœ๊ฒฉ ์กฐ์œจ

๊ธฐ์ˆ  ์„ ํƒ ๋ฐ ํ™œ์šฉ

React Native ยท React Navigation

๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ์™€ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด React Native๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™”๋ฉด์—์„œ๋Š” useRoute()๋กœ ์ด์ „ ํ™”๋ฉด์—์„œ ์ „๋‹ฌ๋œ initialTab์„ ๋ฐ›๊ณ , ์ด๋ฅผ ํ™”๋ฉด์˜ ์ดˆ๊ธฐ ์ƒํƒœ์™€ ๋ฐฑ์—”๋“œ communityType ํ•„ํ„ฐ์— ํ•จ๊ป˜ ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ํƒญ, ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋Š” ์ƒํƒœ, API ์š”์ฒญ ์กฐ๊ฑด์ด ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ์œ ์ง€๋˜๋„๋ก ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

Spring Boot ๊ณ„์ธตํ˜• ์•„ํ‚คํ…์ฒ˜

Controller, Service, Repository์˜ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

  • Controller: HTTP ์š”์ฒญยท์‘๋‹ต, ์š”์ฒญ DTO์™€ ์ธ์ฆ ์‚ฌ์šฉ์ž ์ •๋ณด ์ „๋‹ฌ
  • Service: ๊ฒŒ์‹œ๊ธ€ยท๊ฒ€์ƒ‰ยท๋Œ“๊ธ€ยท์ฆ๊ฒจ์ฐพ๊ธฐ ๊ด€๋ จ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ˆ˜ํ–‰
  • Repository: JPA ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ ์ €์žฅยท์กฐํšŒ์™€ ์ง‘๊ณ„ ์ฟผ๋ฆฌ ์‹คํ–‰

ํ™”๋ฉด์— ํ•„์š”ํ•œ ๊ฐ’์€ Entity๋ฅผ ์ง์ ‘ ๋…ธ์ถœํ•˜์ง€ ์•Š๊ณ  Response DTO๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

Spring Data JPA ยท ๊ณ„์ธตํ˜• ๋Œ“๊ธ€ ๋ชจ๋ธ๋ง

๋Œ“๊ธ€ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋ถ€๋ชจ ๋Œ“๊ธ€์„ ์ฐธ์กฐํ•˜๋Š” ์ž๊ธฐ์ฐธ์กฐ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์‚ฌ์šฉํ•ด ๋Œ“๊ธ€๊ณผ ๋Œ€๋Œ“๊ธ€์„ ํ•˜๋‚˜์˜ ํ…Œ์ด๋ธ”์—์„œ ๊ด€๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. parentCommentId๊ฐ€ ์—†๋Š” ๋ฐ์ดํ„ฐ๋Š” ์ตœ์ƒ์œ„ ๋Œ“๊ธ€, ๊ฐ’์ด ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋Š” ๋Œ€๋Œ“๊ธ€๋กœ ๊ตฌ๋ถ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

์—ฐ๊ด€ ์—”ํ‹ฐํ‹ฐ์—๋Š” ์ง€์—ฐ ๋กœ๋”ฉ์„ ์ ์šฉํ•˜๊ณ , ์ตœ์ดˆ ์š”์ฒญ์—์„œ๋Š” ์ตœ์ƒ์œ„ ๋Œ“๊ธ€๋งŒ ์กฐํšŒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋Œ“๊ธ€์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋Œ“๊ธ€์„ ํŽผ์น  ๋•Œ ๋ณ„๋„ API๋กœ ์กฐํšŒํ•ด ์ดˆ๊ธฐ ์‘๋‹ต์— ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

Spring Security ยท JWT

๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ LoginFilter์—์„œ JWT๋ฅผ ๋ฐœ๊ธ‰ํ•˜๊ณ , ์ดํ›„ ์š”์ฒญ์€ JwtFilter๊ฐ€ Authorization: Bearer {token} ํ—ค๋”๋ฅผ ๊ฒ€์ฆํ•˜๋„๋ก ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์„ธ์…˜์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š” Stateless ์ •์ฑ…์„ ์ ์šฉํ–ˆ์œผ๋ฉฐ, ๊ฒŒ์‹œ๊ธ€ยท๋Œ“๊ธ€ ์ˆ˜์ • ๋ฐ ์‚ญ์ œ ์‹œ ์ธ์ฆ ์‚ฌ์šฉ์ž์™€ ์ž‘์„ฑ์ž๋ฅผ ๋น„๊ตํ•ด ๊ถŒํ•œ์„ ๊ฒ€์ฆํ–ˆ์Šต๋‹ˆ๋‹ค.

JPA์™€ JdbcTemplate์˜ ๋ณ‘ํ–‰ ์‚ฌ์šฉ

์ผ๋ฐ˜์ ์ธ ์—”ํ‹ฐํ‹ฐ ์ €์žฅ๊ณผ ์—ฐ๊ด€๊ด€๊ณ„ ์ฒ˜๋ฆฌ๋Š” JPA๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด ์ข‹์•„์š” ์ค‘๋ณต ์—ฌ๋ถ€ ํ™•์ธ๊ณผ ์นด์šดํŠธ์ฒ˜๋Ÿผ SQL์„ ์ง์ ‘ ์ œ์–ดํ•˜๋Š” ํŽธ์ด ๋‹จ์ˆœํ•œ ๋กœ์ง์€ JdbcTemplate๋กœ ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

๋„๋ฉ”์ธ ์ค‘์‹ฌ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋Š” ORM์œผ๋กœ ์œ ์ง€ํ•˜๋ฉด์„œ, ์ง์ ‘ ์ฟผ๋ฆฌ๊ฐ€ ์ ํ•ฉํ•œ ๊ธฐ๋Šฅ์—๋Š” JdbcTemplate๋ฅผ ์„ ํƒํ•ด ๊ตฌํ˜„ ๋ณต์žก๋„๋ฅผ ์ค„์˜€์Šต๋‹ˆ๋‹ค.

WebClient ยท OpenAI API

์‚ฌ์šฉ์ž๊ฐ€ ์™„๋ฃŒํ•œ ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ์ œ๋ชฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์Œ ๋ชฉํ‘œ ํ‚ค์›Œ๋“œ๋ฅผ ์ถ”์ฒœํ•˜๊ธฐ ์œ„ํ•ด Spring WebClient๋กœ OpenAI API๋ฅผ ํ˜ธ์ถœํ–ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กฌํ”„ํŠธ์— ์—ญํ• , ์ถœ๋ ฅ ํ˜•์‹๊ณผ ๊ธˆ์ง€ ์กฐ๊ฑด์„ ๋ช…์‹œํ•˜๊ณ , ๋ฐ˜ํ™˜๋œ ํ‚ค์›Œ๋“œ๋ฅผ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰์— ๋‹ค์‹œ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

Swagger ยท ํ˜‘์—…

SpringDoc OpenAPI๋กœ Controller์˜ API ๋ฌธ์„œ๋ฅผ ์ž๋™ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์‘๋‹ต DTO๋ฅผ ์ง์ ‘ ํ™•์ธํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋„๋ก Swagger UI๋ฅผ ์ œ๊ณตํ•˜์—ฌ API ์—ฐ๋™ ๊ณผ์ •์˜ ์˜์‚ฌ์†Œํ†ต ๋น„์šฉ์„ ์ค„์˜€์Šต๋‹ˆ๋‹ค.


์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜

flowchart LR
    Client["React Native Client"]
    Security["Spring Security Filter Chain"]
    Controller["Controller"]
    Service["Service"]
    Repository["Spring Data JPA"]
    Jdbc["JdbcTemplate"]
    DB[("MySQL / AWS RDS")]
    OpenAI["OpenAI API"]

    Client -->|"HTTP Request + Bearer Token"| Security
    Security --> Controller
    Controller --> Service
    Service --> Repository
    Service --> Jdbc
    Service --> OpenAI
    Repository --> DB
    Jdbc --> DB
    Controller -->|"DTO Response"| Client
Loading

์š”์ฒญ ์ฒ˜๋ฆฌ ๊ตฌ์กฐ

React Native
    โ†“ API ์š”์ฒญ
Spring Security / JWT
    โ†“ ์ธ์ฆ ์ •๋ณด ์ „๋‹ฌ
Controller
    โ†“ ์š”์ฒญ DTO ์ „๋‹ฌ
Service
    โ†“ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ˆ˜ํ–‰
Repository / JdbcTemplate
    โ†“ ์กฐํšŒยท์ €์žฅ
MySQL
    โ†“
Response DTO

Controller, Service, Repository ๊ณ„์ธต์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์š”์ฒญ ์ฒ˜๋ฆฌ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง, ๋ฐ์ดํ„ฐ ์ ‘๊ทผ์˜ ์ฑ…์ž„์„ ๊ตฌ๋ถ„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด๋Š” Spring Security Context๋ฅผ ํ†ตํ•ด ๊ฒ€์ฆํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ์—๋Š” Entity๊ฐ€ ์•„๋‹Œ DTO ํ˜•ํƒœ์˜ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.


๋‹ด๋‹น ์—ญํ• 

์ปค๋ฎค๋‹ˆํ‹ฐ ๊ธฐ๋Šฅ ํ”„๋ก ํŠธ์—”๋“œยท๋ฐฑ์—”๋“œ ๊ตฌํ˜„

  • ์ปค๋ฎค๋‹ˆํ‹ฐ ์ฆ๊ฒจ์ฐพ๊ธฐ ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ
  • ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰ยท์กฐํšŒยท์ž‘์„ฑ ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ
  • ๋Œ“๊ธ€ยท๋Œ€๋Œ“๊ธ€ ์ž‘์„ฑ ๋ฐ ์กฐํšŒ ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ
  • ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ ๊ฐ„ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์„ค๊ณ„
  • ์ปค๋ฎค๋‹ˆํ‹ฐ API ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ ์‘๋‹ต DTO ์—ฐ๋™
  • Figma๋ฅผ ํ™œ์šฉํ•œ UI ๊ธฐํš๋ถ€ํ„ฐ React Native ํ™”๋ฉด ๊ตฌํ˜„๊นŒ์ง€ ์ˆ˜ํ–‰
  • ์‚ฌ์šฉ์ž ์„ ํƒ ํƒญ๊ณผ ๋ฐฑ์—”๋“œ ํ•„ํ„ฐ ์กฐ๊ฑด ๋™๊ธฐํ™”
  • ํ‚ค์›Œ๋“œ ๋ฐ ์ปค๋ฎค๋‹ˆํ‹ฐ ์œ ํ˜• ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ๊ตฌํ˜„

๋‹ด๋‹น ๊ธฐ๋Šฅ ํ๋ฆ„

flowchart LR
    A["์ปค๋ฎค๋‹ˆํ‹ฐ ํƒญ ์„ ํƒ"] --> B["๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ์กฐํšŒ"]
    B --> C["ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰"]
    C --> D["๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ ์กฐํšŒ"]
    D --> E["๋Œ“๊ธ€ยท๋Œ€๋Œ“๊ธ€ ์ž‘์„ฑ"]
    D --> F["์ข‹์•„์š”ยท์ฆ๊ฒจ์ฐพ๊ธฐ"]
Loading

ํ•ต์‹ฌ ๊ตฌํ˜„

1. ๊ณ„์ธตํ˜• ๋Œ“๊ธ€ ๊ตฌ์กฐ์™€ ๋ถ€๋ถ„ ์กฐํšŒ

๋Œ“๊ธ€๊ณผ ๋Œ€๋Œ“๊ธ€์„ ํ•˜๋‚˜์˜ ๋Œ“๊ธ€ ์—”ํ‹ฐํ‹ฐ๋กœ ๊ด€๋ฆฌํ•˜๊ณ , parentCommentId๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ํ‘œํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒŒ์‹œ๊ธ€
 โ”œโ”€ ๋Œ“๊ธ€ A
 โ”‚   โ”œโ”€ ๋Œ€๋Œ“๊ธ€ A-1
 โ”‚   โ””โ”€ ๋Œ€๋Œ“๊ธ€ A-2
 โ””โ”€ ๋Œ“๊ธ€ B
     โ””โ”€ ๋Œ€๋Œ“๊ธ€ B-1
  • parentCommentId = null: ์ตœ์ƒ์œ„ ๋Œ“๊ธ€
  • parentCommentId != null: ํŠน์ • ๋Œ“๊ธ€์— ์†ํ•œ ๋Œ€๋Œ“๊ธ€
  • ์ตœ์ดˆ ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ ์‹œ ์ตœ์ƒ์œ„ ๋Œ“๊ธ€๋งŒ ์กฐํšŒ
  • ์‚ฌ์šฉ์ž๊ฐ€ ๋Œ“๊ธ€์„ ํŽผ์น  ๋•Œ ๋Œ€๋Œ“๊ธ€์„ ๋ณ„๋„ API๋กœ ์กฐํšŒ
  • ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ๋ถ€๋ชจ ๋Œ“๊ธ€์˜ ์—ฐ๊ด€๊ด€๊ณ„์— ์ง€์—ฐ ๋กœ๋”ฉ ์ ์šฉ
  • DTO ๋ณ€ํ™˜์„ ํ†ตํ•ด ๋ถˆํ•„์š”ํ•œ ์—ฐ๊ด€ ๋ฐ์ดํ„ฐ ๋…ธ์ถœ ๋ฐฉ์ง€
flowchart LR
    A["๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ"] --> B["์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ์กฐํšŒ"]
    B --> C["์‚ฌ์šฉ์ž๊ฐ€ ๋Œ“๊ธ€ ํŽผ์น˜๊ธฐ"]
    C --> D["๋ถ€๋ชจ ๋Œ“๊ธ€ ID ์ „๋‹ฌ"]
    D --> E["๋Œ€๋Œ“๊ธ€ ๊ฐœ๋ณ„ ์กฐํšŒ"]
Loading

์ด ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด ๋Œ“๊ธ€ ์ˆ˜๊ฐ€ ์ฆ๊ฐ€ํ•˜๋”๋ผ๋„ ์ฒซ ํ™”๋ฉด์—์„œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.


2. DB ์ง‘๊ณ„ ๊ธฐ๋ฐ˜ ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฒ€์ƒ‰์–ด์™€ ์ปค๋ฎค๋‹ˆํ‹ฐ ์œ ํ˜•์„ API ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฒ€์ƒ‰๊ณผ ์ง‘๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ‚ค์›Œ๋“œ ์ž…๋ ฅ
    โ†“
๊ฒ€์ƒ‰ API ์š”์ฒญ
    โ†“
JPA ๊ฒ€์ƒ‰ยท์ง‘๊ณ„ ์ฟผ๋ฆฌ ์‹คํ–‰
    โ†“
CommunitySearchResponse DTO ๋ณ€ํ™˜
    โ†“
๋ชฉ๋ก ๋˜๋Š” ๊ทธ๋ž˜ํ”„ ์‹œ๊ฐํ™”

์ฃผ์š” ์ฒ˜๋ฆฌ ๋‚ด์šฉ:

  • communityDiversity ์ปฌ๋Ÿผ์— ํ‚ค์›Œ๋“œ๊ฐ€ ํฌํ•จ๋œ ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰
  • communityType์„ ํ•จ๊ป˜ ์ „๋‹ฌํ•˜์—ฌ ํ˜„์žฌ ๊ฒŒ์‹œํŒ ๋ฒ”์œ„๋กœ ๊ฒ€์ƒ‰ ๋Œ€์ƒ ์ œํ•œ
  • ์ปค๋ฎค๋‹ˆํ‹ฐ ์œ ํ˜•๋ณ„ ๊ฒŒ์‹œ๊ธ€ ์ˆ˜ ๊ทธ๋ฃนํ™”
  • ์ง‘๊ณ„ ๊ฒฐ๊ณผ๋ฅผ DTO๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ํ”„๋ก ํŠธ์—”๋“œ์— ๋ฐ˜ํ™˜
  • DB์—์„œ ํ•„ํ„ฐ๋ง๊ณผ ์ง‘๊ณ„๋ฅผ ์ฒ˜๋ฆฌํ•˜์—ฌ ์„œ๋ฒ„ยทํด๋ผ์ด์–ธํŠธ์˜ ์ถ”๊ฐ€ ์—ฐ์‚ฐ ์ตœ์†Œํ™”

์˜ˆ์‹œ ์š”์ฒญ:

GET /search?keyword=์—ฌํ–‰&communityType=TRAVEL

3. ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™”๋ฉด๊ณผ API ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์—ฐ๋™

Figma๋กœ ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™”๋ฉด์˜ ํƒญ, ๊ฒ€์ƒ‰์ฐฝ, ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก๊ณผ ๋Œ“๊ธ€ UI๋ฅผ ์„ค๊ณ„ํ•˜๊ณ  React Native๋กœ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

sequenceDiagram
    participant User as ์‚ฌ์šฉ์ž
    participant RN as React Native
    participant API as Spring Boot API
    participant DB as MySQL

    User->>RN: ์ปค๋ฎค๋‹ˆํ‹ฐ ํƒญ ์„ ํƒ
    RN->>RN: ๋ผ์šฐํŒ… ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ initialTab ์„ค์ •
    RN->>API: communityType + ๊ฒ€์ƒ‰ ์กฐ๊ฑด ์š”์ฒญ
    API->>DB: ์กฐ๊ฑด์— ๋งž๋Š” ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ
    DB-->>API: ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก
    API-->>RN: Response DTO
    RN-->>User: ์„ ํƒํ•œ ํƒญ์˜ ๊ฒŒ์‹œ๊ธ€ ๋ Œ๋”๋ง
Loading

ํ”„๋ก ํŠธ์—”๋“œ์˜ ํ™”๋ฉด ์ƒํƒœ์™€ ๋ฐฑ์—”๋“œ์˜ ๊ฒ€์ƒ‰ ์กฐ๊ฑด์ด ๋™์ผํ•œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค๊ณ„ํ•ด, ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ฒ”์œ„์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์ผ๊ด€๋˜๊ฒŒ ํ‘œ์‹œ๋˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.


4. ๊ฒŒ์‹œ๊ธ€๊ณผ ์—ฐ๊ด€ ๋ฐ์ดํ„ฐ์˜ ์ƒ๋ช…์ฃผ๊ธฐ ๊ด€๋ฆฌ

์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€์€ ์ด๋ฏธ์ง€, ๋Œ“๊ธ€, ์ข‹์•„์š”์™€ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

Community ์—”ํ‹ฐํ‹ฐ์˜ ์—ฐ๊ด€ ์ปฌ๋ ‰์…˜์— cascade = CascadeType.ALL๊ณผ orphanRemoval = true๋ฅผ ์ ์šฉํ•˜์—ฌ ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ ์‹œ ์—ฐ๊ด€ ๋ฐ์ดํ„ฐ๋„ ํ•จ๊ป˜ ์ •๋ฆฌ๋˜๋„๋ก ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ์„œ๋น„์Šค ๋กœ์ง์—์„œ ์—ฐ๊ด€ ๋ฐ์ดํ„ฐ๋งˆ๋‹ค ๋ณ„๋„์˜ ์‚ญ์ œ ์ฝ”๋“œ๋ฅผ ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๊ณ , ๊ฒŒ์‹œ๊ธ€์„ ์ค‘์‹ฌ์œผ๋กœ ๋ฐ์ดํ„ฐ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ํ™˜๊ฒฝ์—์„œ๋Š” Cascade ์‚ญ์ œ ๋ฒ”์œ„์™€ ์ฟผ๋ฆฌ ์ˆ˜๋ฅผ ์ ๊ฒ€ํ•  ํ•„์š”๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ํ–ฅํ›„ ์„ฑ๋Šฅ ๊ฐœ์„  ํ•ญ๋ชฉ์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.


ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๋ฐ ์„ค๊ณ„ ๊ฐœ์„ 

01. ์ดˆ๊ธฐ ํƒญ ์ƒํƒœ์™€ ๋ฐฑ์—”๋“œ ํ•„ํ„ฐ ๋ถˆ์ผ์น˜ ํ•ด๊ฒฐ

๋ฌธ์ œ

์ปค๋ฎค๋‹ˆํ‹ฐ ํ™”๋ฉด์˜ ์ดˆ๊ธฐ ํƒญ์ด All๋กœ ๊ณ ์ •๋˜์–ด ์žˆ์–ด, ์ด์ „ ํ™”๋ฉด์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ ์œ ํ˜•์ด ๋ฐ˜์˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™”๋ฉด์— ํ‘œ์‹œ๋œ ํƒญ๊ณผ API์— ์ „๋‹ฌ๋˜๋Š” ํ•„ํ„ฐ๊ฐ’์ด ๋‹ฌ๋ผ ๋‹ค๋ฅธ ๊ฒŒ์‹œ๊ธ€์ด ์กฐํšŒ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์›์ธ

๋ผ์šฐํŒ… ๊ณผ์ •์—์„œ ์ „๋‹ฌ๋œ ํƒญ ์ •๋ณด๊ฐ€ ํ™”๋ฉด์˜ ์ดˆ๊ธฐ ์ƒํƒœ์— ๋ฐ˜์˜๋˜์ง€ ์•Š์•˜๊ณ , ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ํ•ญ์ƒ ๋™์ผํ•œ ๊ฐ’์œผ๋กœ API๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ

  • useRoute()๋กœ ๋ผ์šฐํŒ… ํŒŒ๋ผ๋ฏธํ„ฐ์˜ initialTab ์ˆ˜์‹ 
  • useState(initialTab)์œผ๋กœ ์ดˆ๊ธฐ ํƒญ ์ƒํƒœ ๋™์  ์„ค์ •
  • ํ˜„์žฌ ํƒญ ๊ฐ’์„ ๋ฐฑ์—”๋“œ์˜ communityType ํ•„ํ„ฐ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ
  • ํ™”๋ฉด ์ƒํƒœ์™€ API ์š”์ฒญ ์กฐ๊ฑด์„ ํ•˜๋‚˜์˜ ๊ธฐ์ค€์œผ๋กœ ๋™๊ธฐํ™”

๊ฒฐ๊ณผ

์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ ํƒญ๊ณผ ์‹ค์ œ ์กฐํšŒ ๊ฒฐ๊ณผ๊ฐ€ ์ผ์น˜ํ•˜๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ™”๋ฉด ์ง„์ž… ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ์˜ฌ๋ฐ”๋ฅธ ์ดˆ๊ธฐ ํƒญ์ด ํ‘œ์‹œ๋˜๊ณ , ํ•ด๋‹น ๋ฒ”์œ„์˜ ๊ฒŒ์‹œ๊ธ€๋งŒ ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค.

Before
ํ™”๋ฉด ํƒญ: TRAVEL
API ํ•„ํ„ฐ: ALL

After
ํ™”๋ฉด ํƒญ: TRAVEL
API ํ•„ํ„ฐ: TRAVEL

02. ๊ฒ€์ƒ‰ ํ•„ํ„ฐ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ˆ„๋ฝ ๋ฌธ์ œ ํ•ด๊ฒฐ

๋ฌธ์ œ

ํŠน์ • ๊ฒŒ์‹œํŒ์—์„œ ํ‚ค์›Œ๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•ด๋„ ๊ฒ€์ƒ‰ ์กฐ๊ฑด๊ณผ ๊ด€๊ณ„์—†์ด ์ „์ฒด ๊ฒŒ์‹œ๊ธ€์ด ์ถœ๋ ฅ๋˜๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์›์ธ

API ์š”์ฒญ์— ๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ์ธ communityDiversity๋งŒ ํฌํ•จ๋˜๊ณ , ๊ฒŒ์‹œํŒ ๋ฒ”์œ„๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” communityType์ด ๋ˆ„๋ฝ๋˜์–ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ

  • ๊ฒ€์ƒ‰ ์š”์ฒญ์— communityDiversity์™€ communityType์„ ํ•จ๊ป˜ ์ „๋‹ฌ
  • ๋ฐฑ์—”๋“œ ์ฟผ๋ฆฌ์—์„œ ๋‘ ์กฐ๊ฑด์„ ๋™์‹œ์— ์ ์šฉ
  • ํ”„๋ก ํŠธ์—”๋“œ์˜ ์„ ํƒ ํƒญ๊ณผ ๊ฒ€์ƒ‰ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋™์ผํ•œ ์ƒํƒœ๊ฐ’์—์„œ ์ƒ์„ฑ

๊ฒฐ๊ณผ

์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ๊ฒŒ์‹œํŒ ๋ฒ”์œ„ ์•ˆ์—์„œ ํ‚ค์›Œ๋“œ์™€ ์ผ์น˜ํ•˜๋Š” ๊ฒŒ์‹œ๊ธ€๋งŒ ์ •ํ™•ํ•˜๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์„ ์ •์ƒํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค.

Before
keyword=์—ฌํ–‰

After
communityDiversity=์—ฌํ–‰
communityType=TRAVEL

03. ์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•œ ๊ณ„์ธตํ˜• ๋Œ“๊ธ€ ์กฐํšŒ ์„ค๊ณ„

๊ณ ๋ ค ์‚ฌํ•ญ

๊ฒŒ์‹œ๊ธ€์„ ์กฐํšŒํ•  ๋•Œ ๋Œ“๊ธ€๊ณผ ๋ชจ๋“  ๋Œ€๋Œ“๊ธ€์„ ํ•œ ๋ฒˆ์— ๋ถˆ๋Ÿฌ์˜ค๋ฉด ์ดˆ๊ธฐ ์‘๋‹ต ๋ฐ์ดํ„ฐ๊ฐ€ ์ปค์ง€๊ณ , ๋Œ“๊ธ€ ์ˆ˜๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก DB ์กฐํšŒ์™€ ๋„คํŠธ์›Œํฌ ๋ถ€ํ•˜๊ฐ€ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ค๊ณ„

  • parentCommentId ๊ธฐ๋ฐ˜์˜ ์ž๊ธฐ์ฐธ์กฐํ˜• ๋Œ“๊ธ€ ๊ตฌ์กฐ ์ ์šฉ
  • ์ตœ์ดˆ ์กฐํšŒ ์‹œ ์ตœ์ƒ์œ„ ๋Œ“๊ธ€๋งŒ ๋ฐ˜ํ™˜
  • ๋Œ€๋Œ“๊ธ€์€ ์‚ฌ์šฉ์ž๊ฐ€ ํŽผ์น  ๋•Œ ๋ถ€๋ชจ ๋Œ“๊ธ€ ID๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ณ„๋„ ์กฐํšŒ
  • ์—ฐ๊ด€ ์—”ํ‹ฐํ‹ฐ์— Lazy Loading ์ ์šฉ
  • DTO๋ฅผ ํ†ตํ•ด ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ์‘๋‹ต

๊ฒฐ๊ณผ

ํ•„์š”ํ•œ ๋Œ“๊ธ€๋งŒ ๋‹จ๊ณ„์ ์œผ๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์ดˆ๊ธฐ ํ™”๋ฉด์—์„œ ๋ถˆํ•„์š”ํ•œ ๋Œ€๋Œ“๊ธ€๊ณผ ์—ฐ๊ด€ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋”ฉํ•˜์ง€ ์•Š์œผ๋ฉฐ, ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ์œ ์ง€ํ•ด ๊ธฐ๋Šฅ ํ™•์žฅ๊ณผ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•ด์กŒ์Šต๋‹ˆ๋‹ค.


API

์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€

๊ธฐ๋Šฅ Method Endpoint ์„ค๋ช… ์ธ์ฆ
๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ์กฐํšŒ GET /api/posts ์œ ํ˜•๋ณ„ ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ๋ฐ ํŽ˜์ด์ง€๋„ค์ด์…˜ ์„ ํƒ
๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ ์กฐํšŒ GET /api/posts/{communityId} ๊ฒŒ์‹œ๊ธ€๊ณผ ์ด๋ฏธ์ง€ ์ •๋ณด ์กฐํšŒ ์„ ํƒ
๊ฒŒ์‹œ๊ธ€ ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰ GET /search ํ‚ค์›Œ๋“œ์™€ ์ปค๋ฎค๋‹ˆํ‹ฐ ์œ ํ˜• ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰ ์„ ํƒ
๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ POST /api/posts ํ…์ŠคํŠธ ๋˜๋Š” ์ด๋ฏธ์ง€ ํฌํ•จ ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก ํ•„์š”
๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • PATCH /api/posts/{communityId} ์ž‘์„ฑ์ž ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ํ•„์š”
๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ DELETE /api/posts/{communityId} ์ž‘์„ฑ์ž ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ ํ•„์š”
๊ฒŒ์‹œ๊ธ€ ์ข‹์•„์š” POST /api/posts/{communityId}/like ์ข‹์•„์š” ์ค‘๋ณต ๊ฒ€์ฆ ๋ฐ ์นด์šดํŠธ ๋ฐ˜ํ™˜ ํ•„์š”
์ฆ๊ฒจ์ฐพ๊ธฐ ์ถ”๊ฐ€ยทํ•ด์ œ POST /api/posts/{communityId}/scrap ๊ด€์‹ฌ ๊ฒŒ์‹œ๊ธ€ ์ €์žฅ ๋˜๋Š” ํ•ด์ œ ํ•„์š”

๋Œ“๊ธ€

๊ธฐ๋Šฅ Method Endpoint ์„ค๋ช… ์ธ์ฆ
์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ์กฐํšŒ GET /api/posts/{communityId}/comments ๊ฒŒ์‹œ๊ธ€์˜ ์ตœ์ƒ์œ„ ๋Œ“๊ธ€๋งŒ ์กฐํšŒ ์„ ํƒ
๋Œ“๊ธ€ ์ž‘์„ฑ POST /api/posts/{communityId}/comments ์ƒˆ ๋Œ“๊ธ€ ๋“ฑ๋ก ํ•„์š”
๋Œ€๋Œ“๊ธ€ ์กฐํšŒ GET /api/comments/{commentId}/replies ๋ถ€๋ชจ ๋Œ“๊ธ€์˜ ๋Œ€๋Œ“๊ธ€ ์กฐํšŒ ์„ ํƒ
๋Œ€๋Œ“๊ธ€ ์ž‘์„ฑ POST /api/comments/{commentId}/replies ํŠน์ • ๋Œ“๊ธ€์— ๋Œ€๋Œ“๊ธ€ ๋“ฑ๋ก ํ•„์š”
๋Œ“๊ธ€ ์ˆ˜์ • PATCH /api/comments/{commentId} ์ž‘์„ฑ์ž ๋Œ“๊ธ€ ์ˆ˜์ • ํ•„์š”
๋Œ“๊ธ€ ์‚ญ์ œ DELETE /api/comments/{commentId} ์ž‘์„ฑ์ž ๋Œ“๊ธ€ ์‚ญ์ œ ํ•„์š”
๋Œ“๊ธ€ ์ข‹์•„์š” POST /api/comments/{commentId}/like ๋Œ“๊ธ€ ์ข‹์•„์š” ์ฒ˜๋ฆฌ ํ•„์š”

์ฃผ์š” ์„œ๋น„์Šค API

๊ธฐ๋Šฅ Method Endpoint ์„ค๋ช…
๋กœ๊ทธ์ธ POST /login JWT ๋ฐœ๊ธ‰
๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ POST /api/bucketlist ์ƒˆ ๋ชฉํ‘œ ๋“ฑ๋ก
๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ๋ชฉ๋ก GET /api/bucketlist ํ•€ ๊ณ ์ •ยท๋ชฉํ‘œ์ผ ๊ธฐ์ค€ ์กฐํšŒ
๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ์™„๋ฃŒ PUT /api/bucketlist/{id}/achieve ๋ชฉํ‘œ ์™„๋ฃŒ ๋ฐ ๋‹ฌ์„ฑ์ผ ๊ธฐ๋ก
AI ๋ชฉํ‘œ ์ถ”์ฒœ POST /ai/recommend ์™„๋ฃŒ ์ด๋ ฅ ๊ธฐ๋ฐ˜ ๋‹ค์Œ ๋ชฉํ‘œ ์ถ”์ฒœ
๋ช…์˜ˆ์˜ ์ „๋‹น GET /api/hall-of-fame ์ธ๊ธฐ ํŠธ๋กœํ”ผ ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ

์‹ค์ œ ์ €์žฅ์†Œ์˜ Controller ๋งคํ•‘๊ณผ ๋‹ค๋ฅผ ๊ฒฝ์šฐ Endpoint๋ฅผ ์ตœ์ข… ์ฝ”๋“œ ๊ธฐ์ค€์œผ๋กœ ์ˆ˜์ •ํ•ด ์ฃผ์„ธ์š”.


๋ฐ์ดํ„ฐ ๋ชจ๋ธ

erDiagram
    User ||--o{ BucketList : owns
    User ||--o{ Community : writes
    User ||--o{ Comment : writes
    User ||--o{ CommunityScrap : scraps

    BucketList ||--o{ BucketListLog : records
    BucketList ||--o{ Community : shares

    Community ||--o{ Image : contains
    Community ||--o{ Comment : contains
    Community ||--o{ CommunityLike : receives
    Community ||--o{ CommunityScrap : receives

    Comment ||--o{ Comment : replies
    Comment ||--o{ CommentLike : receives
Loading

์„ค๊ณ„ ํŠน์ง•

  • Community์™€ BucketList๋Š” ์„ ํƒ์  ์—ฐ๊ด€๊ด€๊ณ„๋กœ ๊ตฌ์„ฑ
  • ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ๊ฐ€ ์—†๋Š” ์ผ๋ฐ˜ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€๋„ ์ž‘์„ฑ ๊ฐ€๋Šฅ
  • Comment.parentCommentId๋กœ ๋Œ“๊ธ€ยท๋Œ€๋Œ“๊ธ€ ๊ณ„์ธต ๊ตฌ์กฐ ํ‘œํ˜„
  • ๊ฒŒ์‹œ๊ธ€ยท๋Œ“๊ธ€ ์ข‹์•„์š”๋ฅผ ๋ณ„๋„ ํ…Œ์ด๋ธ”๋กœ ๊ด€๋ฆฌํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ณ„ ์ค‘๋ณต ๋ฐฉ์ง€
  • ์ฆ๊ฒจ์ฐพ๊ธฐ๋ฅผ ์‚ฌ์šฉ์ž์™€ ๊ฒŒ์‹œ๊ธ€ ๊ฐ„ ๋งคํ•‘ ํ…Œ์ด๋ธ”๋กœ ๊ด€๋ฆฌ
  • ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ ์‹œ ์ด๋ฏธ์ง€, ๋Œ“๊ธ€ ๋“ฑ ์—ฐ๊ด€ ๋ฐ์ดํ„ฐ ์ƒ๋ช…์ฃผ๊ธฐ ๊ด€๋ฆฌ

์ธ์ฆ ๋ฐ ์ธ๊ฐ€

Spring Security์™€ JWT๋ฅผ ์‚ฌ์šฉํ•œ Stateless ์ธ์ฆ ๋ฐฉ์‹์„ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

sequenceDiagram
    participant Client as React Native
    participant JwtFilter as JwtFilter
    participant JwtUtil as JwtUtil
    participant UserService as UserDetailsService
    participant Context as SecurityContextHolder

    Client->>JwtFilter: Authorization: Bearer {token}
    JwtFilter->>JwtUtil: ํ† ํฐ ๊ฒ€์ฆ ๋ฐ ์‚ฌ์šฉ์ž๋ช… ์ถ”์ถœ
    JwtUtil-->>JwtFilter: username
    JwtFilter->>UserService: ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ
    UserService-->>JwtFilter: UserDetails
    JwtFilter->>Context: Authentication ์ €์žฅ
    JwtFilter->>Client: ๋‹ค์Œ ํ•„ํ„ฐ ๋ฐ API ์ฒ˜๋ฆฌ
Loading
  • BCrypt ๊ธฐ๋ฐ˜ ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™”
  • JWT HS256 ์„œ๋ช…
  • ์„œ๋ฒ„ ์„ธ์…˜์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š” Stateless ์ •์ฑ…
  • URL ๋‹จ์œ„ ๊ณต๊ฐœยท์ธ์ฆ API ๋ถ„๋ฆฌ
  • ์ธ์ฆ ์‚ฌ์šฉ์ž๋Š” SecurityContext์—์„œ ์กฐํšŒ
  • ๊ฒŒ์‹œ๊ธ€ ๋ฐ ๋Œ“๊ธ€ ์ˆ˜์ •ยท์‚ญ์ œ ์‹œ ์ž‘์„ฑ์ž ๊ฒ€์ฆ

๊ณตํ†ต ์‘๋‹ต ๊ตฌ์กฐ

{
  "status": "SUCCESS",
  "message": null,
  "data": {
    "example": "response"
  }
}

ApiResponsTemplate<T>๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ API ์„ฑ๊ณต ์‘๋‹ต ํ˜•์‹์„ ํ†ต์ผํ–ˆ์Šต๋‹ˆ๋‹ค. Controller๋Š” Entity๋ฅผ ์ง์ ‘ ๋…ธ์ถœํ•˜์ง€ ์•Š๊ณ , ํ™”๋ฉด์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์‘๋‹ต DTO๋กœ ๋ณ€ํ™˜ํ•ด ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.


ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

src/
โ””โ”€โ”€ main/
    โ”œโ”€โ”€ java/
    โ”‚   โ””โ”€โ”€ com/guesthouse/wishboard/
    โ”‚       โ”œโ”€โ”€ config/
    โ”‚       โ”‚   โ”œโ”€โ”€ SecurityConfig.java
    โ”‚       โ”‚   โ”œโ”€โ”€ SwaggerConfig.java
    โ”‚       โ”‚   โ””โ”€โ”€ WebConfig.java
    โ”‚       โ”œโ”€โ”€ controller/
    โ”‚       โ”‚   โ”œโ”€โ”€ PostController.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommentController.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommunityController.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommunityScrapController.java
    โ”‚       โ”‚   โ”œโ”€โ”€ KeywordController.java
    โ”‚       โ”‚   โ”œโ”€โ”€ BucketListController.java
    โ”‚       โ”‚   โ”œโ”€โ”€ AIController.java
    โ”‚       โ”‚   โ””โ”€โ”€ TrophyController.java
    โ”‚       โ”œโ”€โ”€ service/
    โ”‚       โ”‚   โ”œโ”€โ”€ PostService.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommentService.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommunityService.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommunityScrapService.java
    โ”‚       โ”‚   โ”œโ”€โ”€ BucketListService.java
    โ”‚       โ”‚   โ””โ”€โ”€ AIService.java
    โ”‚       โ”œโ”€โ”€ repository/
    โ”‚       โ”‚   โ”œโ”€โ”€ CommunityRepository.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommentRepository.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommunityScrapRepository.java
    โ”‚       โ”‚   โ””โ”€โ”€ BucketListRepository.java
    โ”‚       โ”œโ”€โ”€ entity/
    โ”‚       โ”‚   โ”œโ”€โ”€ User.java
    โ”‚       โ”‚   โ”œโ”€โ”€ Community.java
    โ”‚       โ”‚   โ”œโ”€โ”€ Comment.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommunityScrap.java
    โ”‚       โ”‚   โ””โ”€โ”€ BucketList.java
    โ”‚       โ”œโ”€โ”€ dto/
    โ”‚       โ”‚   โ”œโ”€โ”€ PostRequest.java
    โ”‚       โ”‚   โ”œโ”€โ”€ PostResponse.java
    โ”‚       โ”‚   โ”œโ”€โ”€ CommunitySearchResponse.java
    โ”‚       โ”‚   โ””โ”€โ”€ CommentResponse.java
    โ”‚       โ”œโ”€โ”€ global/
    โ”‚       โ”‚   โ””โ”€โ”€ ApiResponsTemplate.java
    โ”‚       โ””โ”€โ”€ jwt/
    โ”‚           โ”œโ”€โ”€ JwtUtil.java
    โ”‚           โ”œโ”€โ”€ JwtFilter.java
    โ”‚           โ””โ”€โ”€ LoginFilter.java
    โ””โ”€โ”€ resources/
        โ””โ”€โ”€ application.yml

์‹คํ–‰ ๋ฐฉ๋ฒ•

์š”๊ตฌ ํ™˜๊ฒฝ

  • Java 17
  • MySQL 8.0
  • Gradle
  • Node.js ๋ฐ React Native ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

๋ฐฑ์—”๋“œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜

application.yml ๋˜๋Š” ์šด์˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜์— ๋‹ค์Œ ๊ฐ’์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

spring:
  datasource:
    url: ${DB_URL:jdbc:mysql://localhost:3306/wishboard_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul}
    username: ${DB_USERNAME:root}
    password: ${DB_PASSWORD}

  jwt:
    secret: ${JWT_SECRET}

openai:
  api-key: ${OPENAI_API_KEY}

DB ๋น„๋ฐ€๋ฒˆํ˜ธ, JWT Secret, OpenAI API Key์™€ ๊ฐ™์€ ๋ฏผ๊ฐ ์ •๋ณด๋Š” ์ €์žฅ์†Œ์— ์ง์ ‘ ์ปค๋ฐ‹ํ•˜์ง€ ์•Š๊ณ  ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ๊ด€๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฐฑ์—”๋“œ ์‹คํ–‰

# ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ
./gradlew build

# ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰
./gradlew bootRun

# ํ…Œ์ŠคํŠธ ์‹คํ–‰
./gradlew test

Swagger

http://localhost:8080/swagger-ui/index.html

ํ”„๋ก ํŠธ์—”๋“œ ์‹คํ–‰

npm install
npm start

React Native ์‹คํ–‰ ๋ช…๋ น์€ Expo ์‚ฌ์šฉ ์—ฌ๋ถ€์™€ ์‹ค์ œ package.json ์Šคํฌ๋ฆฝํŠธ์— ๋งž๊ฒŒ ์ˆ˜์ •ํ•ด ์ฃผ์„ธ์š”.


ํ™”๋ฉด ์˜ˆ์‹œ

์„œ๋น„์Šค ํ™”๋ฉด

WishBoard์˜ ์ฃผ์š” ์‚ฌ์šฉ์ž ํ๋ฆ„๊ณผ ๊ธฐ๋Šฅ์„ ํ™”๋ฉด๋ณ„๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

01. ์˜จ๋ณด๋”ฉ ยท ๋กœ๊ทธ์ธ ยท ํšŒ์›๊ฐ€์ž…
์„œ๋น„์Šค ์†Œ๊ฐœ๋ถ€ํ„ฐ ๊ณ„์ • ์ƒ์„ฑ ๋ฐ ๋กœ๊ทธ์ธ๊นŒ์ง€์˜ ์ดˆ๊ธฐ ์‚ฌ์šฉ์ž ํ๋ฆ„

WishBoard ์˜จ๋ณด๋”ฉ ๋กœ๊ทธ์ธ ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด
02. ๋งˆ์ดํŽ˜์ด์ง€ ยท ์•Œ๋ฆผ
์‚ฌ์šฉ์ž ์ •๋ณด์™€ ํ™œ๋™ ๋‚ด์—ญ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์ฃผ์š” ์•Œ๋ฆผ์„ ํ™•์ธํ•˜๋Š” ํ™”๋ฉด

WishBoard ๋งˆ์ดํŽ˜์ด์ง€ ์•Œ๋ฆผ ํ™”๋ฉด
03. ํ™ˆ ยท ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ
์ง„ํ–‰ ์ค‘์ธ ๋ชฉํ‘œ์™€ D-Day๋ฅผ ํ•œ๋ˆˆ์— ํ™•์ธํ•˜๋Š” ๋ฉ”์ธ ํ™”๋ฉด

WishBoard ํ™ˆ ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ํ™”๋ฉด
04. ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ๊ด€๋ฆฌ ยท ํ™œ๋™ ๊ธฐ๋ก
๋ชฉํ‘œ ๋ชฉ๋ก ์กฐํšŒ, ์‹ ๊ทœ ๋ชฉํ‘œ ์ž‘์„ฑ ๋ฐ ์ง„ํ–‰ ๊ณผ์ • ๊ธฐ๋ก ํ™”๋ฉด

WishBoard ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ๋ชฉ๋ก ์ž‘์„ฑ ๊ธฐ๋ก ํ™”๋ฉด
05. ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ์ปค๋ฎค๋‹ˆํ‹ฐ
๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰๊ณผ ์ž‘์„ฑ, ๋Œ“๊ธ€ยท๋Œ€๋Œ“๊ธ€์„ ํ†ตํ•ด ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๋Š” ํ™”๋ฉด

WishBoard ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™”๋ฉด
06. ๋ชฉํ‘œ ๋‹ฌ์„ฑ ํŠธ๋กœํ”ผ
์™„๋ฃŒํ•œ ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ๋ฅผ ํŠธ๋กœํ”ผ์™€ ์ธ์ฆ ๊ฒŒ์‹œ๊ธ€๋กœ ๊ธฐ๋กํ•˜๋Š” ํ™”๋ฉด

WishBoard ํŠธ๋กœํ”ผ ํ™”๋ฉด
07. ๋ช…์˜ˆ์˜ ์ „๋‹น
์ข‹์•„์š”๋ฅผ ๋งŽ์ด ๋ฐ›์€ ๋ชฉํ‘œ ๋‹ฌ์„ฑ ๊ฒŒ์‹œ๊ธ€์„ ํ™•์ธํ•˜๋Š” ์ธ๊ธฐ ์ฝ˜ํ…์ธ  ํ™”๋ฉด

WishBoard ๋ช…์˜ˆ์˜ ์ „๋‹น ํ™”๋ฉด
08. AI ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ์ถ”์ฒœ
์™„๋ฃŒํ•œ ๋ชฉํ‘œ ์ด๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒˆ๋กœ์šด ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”์ฒœํ•˜๋Š” ํ™”๋ฉด

WishBoard AI ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ์ถ”์ฒœ ํ™”๋ฉด

์„ฑ๊ณผ์™€ ํšŒ๊ณ 

ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด ๊ฒฝํ—˜ํ•œ ๊ฒƒ

  • React Native์™€ Spring Boot ๊ฐ„ REST API ์—ฐ๋™
  • Figma ๊ธฐํš๋ถ€ํ„ฐ ๋ชจ๋ฐ”์ผ ํ™”๋ฉด ๊ตฌํ˜„๊นŒ์ง€์˜ ์ „์ฒด ๊ณผ์ •
  • ์‚ฌ์šฉ์ž ํ™”๋ฉด ์ƒํƒœ์™€ ๋ฐฑ์—”๋“œ ๊ฒ€์ƒ‰ ์กฐ๊ฑด ๋™๊ธฐํ™”
  • Spring Data JPA๋ฅผ ํ™œ์šฉํ•œ ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰๊ณผ ๊ทธ๋ฃน ์ง‘๊ณ„
  • ์ž๊ธฐ์ฐธ์กฐ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ํ™œ์šฉํ•œ ๋Œ“๊ธ€ยท๋Œ€๋Œ“๊ธ€ ๋ชจ๋ธ๋ง
  • ์ง€์—ฐ ๋กœ๋”ฉ๊ณผ ๋ถ€๋ถ„ ์กฐํšŒ๋ฅผ ๊ณ ๋ คํ•œ ๋Œ“๊ธ€ ์กฐํšŒ ๊ตฌ์กฐ ์„ค๊ณ„
  • Spring Security์™€ JWT ๊ธฐ๋ฐ˜ ์ธ์ฆ ํ๋ฆ„ ์ดํ•ด
  • ํŒ€์›๊ณผ API ์š”์ฒญยท์‘๋‹ต ๊ทœ๊ฒฉ์„ ์กฐ์œจํ•œ ํ˜‘์—… ๊ฒฝํ—˜

๊ฐœ์„  ๊ณ„ํš

  • ๋Œ“๊ธ€ ๋ชฉ๋ก ์ฟผ๋ฆฌ์˜ N+1 ๋ฐœ์ƒ ์—ฌ๋ถ€ ์ธก์ • ๋ฐ Fetch JoinยทEntityGraph ์ ์šฉ ๊ฒ€ํ† 
  • ๋Œ“๊ธ€ ์ˆ˜์™€ ์‘๋‹ต ํฌ๊ธฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ถ€๋ถ„ ์กฐํšŒ ํšจ๊ณผ ์ •๋Ÿ‰ํ™”
  • ๊ฒ€์ƒ‰ ์กฐ๊ฑด ์ฆ๊ฐ€์— ๋Œ€๋น„ํ•œ QueryDSL ๊ธฐ๋ฐ˜ ๋™์  ์ฟผ๋ฆฌ ์ „ํ™˜
  • ์ปค๋ฎค๋‹ˆํ‹ฐ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด์™€ ๊ฒŒ์‹œ๊ธ€ ๊ฒฐ๊ณผ ์บ์‹ฑ
  • Refresh Token ๊ธฐ๋ฐ˜ ์ธ์ฆ ๊ตฌ์กฐ ๋ณด์™„
  • ์ด๋ฏธ์ง€ ์ €์žฅ์†Œ๋ฅผ ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ Object Storage๋กœ ์ด์ „
  • @ControllerAdvice ๊ธฐ๋ฐ˜ ์ „์—ญ ์˜ˆ์™ธ ์‘๋‹ต ํ‘œ์ค€ํ™”
  • Service ๋ ˆ์ด์–ด ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ API ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ๊ฐ•ํ™”

๋ชฉํ‘œ๋ฅผ ๊ธฐ๋กํ•˜๊ณ , ํ•จ๊ป˜ ๋‹ฌ์„ฑํ•˜๋ฉฐ, ๋‹ค์Œ ๋„์ „์œผ๋กœ ์ด์–ด์ง€๋Š” WishBoard

About

๐ŸŽฏ ์œ„์‹œ๋ณด๋“œ : ๋ฒ„ํ‚ท๋ฆฌ์ŠคํŠธ ๋‹ฌ์„ฑ ๋…๋ ค๋ฅผ ์œ„ํ•œ ๋™๊ธฐ๋ถ€์—ฌ ์•ฑ

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages