Skip to content

Latest commit

ย 

History

223 Commits

Folders and files

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

Repository files navigation

โ™ป๏ธ ReDO Backend Repository

๋ถ„๋ฆฌ๋ฐฐ์ถœ์€ ์‰ฝ๊ฒŒ, ์‹ค์ฒœ์€ ๋ณด์ƒ์œผ๋กœ ์ด์–ด์ง€๋„๋ก ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์˜ ํ๋ฆ„์„ ์•ˆ์ •์ ์œผ๋กœ ๋’ท๋ฐ›์นจํ•˜๋Š” ReDO Backend์ž…๋‹ˆ๋‹ค.


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

ReDO๋Š” ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด๋ฅผ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ์ œ๊ณตํ•˜๊ณ , ์‹ค์ฒœ์— ๋Œ€ํ•œ ๋ณด์ƒ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž์˜ ํ–‰๋™์„ ์œ ๋„ํ•˜๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.

  • ๊ธฐ๊ฐ„ : 2026.06.29 ~ 2026.08.21
  • ์ธ์› : Backend 5๋ช…
  • ๋ชฉํ‘œ : AI ๊ธฐ๋ฐ˜ ์ •๋ณด ์ œ๊ณต๊ณผ ๋ฆฌ์›Œ๋“œ ์‹œ์Šคํ…œ์„ ๊ฒฐํ•ฉํ•˜์—ฌ ๋ถ„๋ฆฌ๋ฐฐ์ถœ์„ ์ผ์ƒ์˜ ์Šต๊ด€์œผ๋กœ ๋งŒ๋“ค์–ด ์ง€์†์ ์ธ ํ™˜๊ฒฝ ๋ณดํ˜ธ ์ฐธ์—ฌ๋ฅผ ์ด๋Œ์–ด๋‚ด๋Š” ๊ฒƒ
  • ํ•ต์‹ฌ ํ๋ฆ„ : AI ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด โ†’ AI ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ธ์ฆ โ†’ ํฌ์ธํŠธ ์ ๋ฆฝ โ†’ ๋ฆฌ์›Œ๋“œ ๊ตฌ๋งค โ†’ ๊ธฐ์—ฌ๋„ ์‹œ๊ฐํ™”

๐Ÿง‘๐Ÿปโ€๐Ÿ’ป ํŒ€์› ๋ฐ ์—ญํ• 

์ฒœ์ง„ํ•˜ ์•ˆ๋™ํœ˜ ์ฑ„๋ฏผ์ˆ˜ ํ—ˆ๊ฑด์šฐ ์ด์ •์šฐ
์ฒœ์ง„ํ•˜ ํ”„๋กœํ•„ ์•ˆ๋™ํœ˜ ํ”„๋กœํ•„ ์ฑ„๋ฏผ์ˆ˜ ํ”„๋กœํ•„ ํ—ˆ๊ฑด์šฐ ํ”„๋กœํ•„ ์ด์ •์šฐ ํ”„๋กœํ•„
ํšŒ์›๊ฐ€์ž…ยท๋กœ๊ทธ์ธยทํ”„๋กœํ•„ AI ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด AI ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ธ์ฆ ์ธํ”„๋ผยทํฌ์ธํŠธยท๋ฆฌ์›Œ๋“œยท๊ธฐ์—ฌ๋„ ์ปค๋ฎค๋‹ˆํ‹ฐ

โœจ ์ฃผ์š” ๊ธฐ๋Šฅ

ํšŒ์›๊ฐ€์ž…ยท๋กœ๊ทธ์ธยทํ”„๋กœํ•„

  • ์•„์ด๋”” ์ค‘๋ณต ํ™•์ธ๊ณผ ์ด๋ฉ”์ผ ์ธ์ฆ์„ ํ†ตํ•œ ์ผ๋ฐ˜ ํšŒ์›๊ฐ€์ž…
  • ์„œ๋น„์Šค ์•ฝ๊ด€ ์กฐํšŒ ๋ฐ ํ•„์ˆ˜ ์•ฝ๊ด€ ๋™์˜ ์ฒ˜๋ฆฌ
  • Google, Kakao, Naver ์†Œ์…œ ํšŒ์›๊ฐ€์ž… ๋ฐ ๋กœ๊ทธ์ธ
  • JWT ๊ธฐ๋ฐ˜ Access Token ๋ฐœ๊ธ‰๊ณผ Refresh Token์„ ์ด์šฉํ•œ ํ† ํฐ ์žฌ๋ฐœ๊ธ‰
  • HttpOnly Cookie์™€ Redis๋ฅผ ํ™œ์šฉํ•œ Refresh Token ๊ด€๋ฆฌ ๋ฐ ๋กœ๊ทธ์•„์›ƒ
  • Redis ์›์ž ์—ฐ์‚ฐ์œผ๋กœ ๋กœ๊ทธ์ธ ์‹คํŒจ ํšŸ์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•˜์—ฌ ๋ฐ˜๋ณต์ ์ธ ๋กœ๊ทธ์ธ ์‹œ๋„ ์ œํ•œ
  • ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์ƒ์„ฑ ๋ฐ ์กฐํšŒ
  • ๋‹‰๋„ค์ž„, ํ”„๋กœํ•„ ์ด๋ฏธ์ง€, ์บ๋ฆญํ„ฐ ์ˆ˜์ •
  • ํšŒ์› ํƒˆํ‡ด ์‚ฌ์œ  ์กฐํšŒ ๋ฐ ํšŒ์› ํƒˆํ‡ด ์ฒ˜๋ฆฌ

AI ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด

  • ํ’ˆ๋ชฉ๋ช…์„ ์ด์šฉํ•œ ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด ์กฐํšŒ
  • ์ดฌ์˜ํ•˜๊ฑฐ๋‚˜ ์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€๋ฅผ AI๊ฐ€ ๋ถ„์„ํ•˜์—ฌ ํ’ˆ๋ชฉ ์‹๋ณ„
  • ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋ฌธ์ œ ์ƒํ™ฉ์„ ๋ถ„์„ํ•˜์—ฌ ์ ํ•ฉํ•œ ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด ์ œ๊ณต
  • Spring AI์™€ Gemini๋ฅผ ํ™œ์šฉํ•œ ์ด๋ฏธ์ง€ยทํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ์ •๋ณด ํƒ์ƒ‰
  • JSON Schema ๊ธฐ๋ฐ˜์˜ ๊ตฌ์กฐํ™”๋œ AI ์‘๋‹ต ๊ฒ€์ฆ
  • AI ๋ถ„์„ ๊ฒฐ๊ณผ๋ฅผ ์„œ๋น„์Šค์— ๋“ฑ๋ก๋œ ํ’ˆ๋ชฉ ๋ฐ ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด์™€ ์—ฐ๊ฒฐ
  • ํ’ˆ๋ชฉ๋ณ„ ๋ฐฐ์ถœ ๋ฐฉ๋ฒ•๊ณผ ๋‹จ๊ณ„๋ณ„ ์ฃผ์˜์‚ฌํ•ญ ์ œ๊ณต
  • ์ž์ฃผ ํ™•์ธํ•˜๋Š” ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด ์ฆ๊ฒจ์ฐพ๊ธฐ
  • ํƒ์ƒ‰ ๊ฒฐ๊ณผ์—์„œ ํ•ด๋‹น ํ’ˆ๋ชฉ์˜ ๋ฐฐ์ถœ ์ธ์ฆ ๊ธฐ๋Šฅ์œผ๋กœ ์—ฐ๊ฒฐ

AI ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ธ์ฆ

  • ๋‹น์ผ ์ธ์ฆ ์„ฑ๊ณต ํšŸ์ˆ˜์™€ ๋‚จ์€ ์ธ์ฆ ๊ฐ€๋Šฅ ํšŸ์ˆ˜ ์กฐํšŒ
  • ์ผ๋ฐ˜ ์ธ์ฆ๊ณผ ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด ํƒ์ƒ‰ ํ›„ ์ธ์ฆ ์ง€์›
  • ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ดฌ์˜ํ•œ ๋ฐฐ์ถœ ์™„๋ฃŒ ์ด๋ฏธ์ง€๋ฅผ Gemini VLM์œผ๋กœ ํŒ์ •
  • ์ธ์ฆ ์„ฑ๊ณต ์—ฌ๋ถ€์™€ ์ธ์ฆ ํ’ˆ๋ชฉ, ํŒ์ • ๊ฒฐ๊ณผ ๋ฐ ์ธ์ฆ ์ผ์‹œ ์ œ๊ณต
  • ์ธ์ฆ ๋ฐฉ์‹์— ๋”ฐ๋ฅธ ํฌ์ธํŠธ ์ž๋™ ์ ๋ฆฝ
    • ์ผ๋ฐ˜ ์ธ์ฆ: 50P
    • ์ •๋ณด ํƒ์ƒ‰ ํ›„ ์ธ์ฆ: 100P
  • ์ผ์ผ ์ตœ๋Œ€ 3ํšŒ ๋ฐ ๋™์ผ ํ’ˆ๋ชฉ ์ค‘๋ณต ์ธ์ฆ ์ œํ•œ
  • ์ธ์ฆ ์„ฑ๊ณต ํ›„ 5๋ถ„๊ฐ„ ์‹ ๊ทœ ์ธ์ฆ ์ œํ•œ
  • AI ํŒ์ • ์‹คํŒจ ์‚ฌ์œ ์™€ ์žฌ์ดฌ์˜ ๋ฐฉ๋ฒ• ์ œ๊ณต
  • ์‹คํŒจํ•œ ์ธ์ฆ ์ด๋ฏธ์ง€์˜ ์žฌ์ดฌ์˜ ๋ฐ AI ์žฌ๊ฒ€์ˆ˜
  • ์ธ์ฆ ์ „์šฉ ๋น„๋™๊ธฐ ์‹คํ–‰๊ธฐ์™€ ํƒ€์ž„์•„์›ƒ์„ ์ ์šฉํ•˜์—ฌ ์žฅ์‹œ๊ฐ„ AI ์š”์ฒญ ์ œ์–ด
  • ์ธ์ฆ ์ƒํƒœ ๋ณ€๊ฒฝ, AI ํŒ์ • ์ €์žฅ, ํฌ์ธํŠธ ์ ๋ฆฝ ๋ฐ ๊ธฐ์—ฌ๋„ ์ด๋ฒคํŠธ๋ฅผ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ์ฒ˜๋ฆฌ

ํฌ์ธํŠธยท๋ฆฌ์›Œ๋“œ

  • ์‚ฌ์šฉ์ž์˜ ๋ณด์œ  ํฌ์ธํŠธ์™€ ์ด๋ฒˆ ๋‹ฌ ์ ๋ฆฝ ํฌ์ธํŠธ ์กฐํšŒ
  • ํฌ์ธํŠธ ์ ๋ฆฝ ๋ฐ ์‚ฌ์šฉ ๊ฑฐ๋ž˜ ๋‚ด์—ญ ์กฐํšŒ
  • ์ œํœด ๋ธŒ๋žœ๋“œ ๋ฐฐ์†ก ์ƒํ’ˆ๊ณผ ์ฟ ํฐยท๊ธฐํ”„ํ‹ฐ์ฝ˜ ์ƒํ’ˆ ์ œ๊ณต
  • ์ƒํ’ˆ ์œ ํ˜•๋ณ„ ๋ชฉ๋ก, ์ƒ์„ธ ์ •๋ณด ๋ฐ ์‚ฌ์šฉ์ž๋ณ„ ์ผ์ผ ์ถ”์ฒœ ์ƒํ’ˆ ์กฐํšŒ
  • ์ฃผ์†Œ๊ธฐ๋ฐ˜์‚ฐ์—…์ง€์›์„œ๋น„์Šค API๋ฅผ ์ด์šฉํ•œ ๋ฐฐ์†ก์ง€ ์ฃผ์†Œ ๊ฒ€์ƒ‰
  • ๋ฐฐ์†ก์ง€ ์ƒ์„ฑ, ์กฐํšŒ, ์ˆ˜์ • ๋ฐ ์‚ญ์ œ
  • ํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•œ ๋ฆฌ์›Œ๋“œ ๊ตฌ๋งค
  • ๋ฆฌ์›Œ๋“œ ๊ตํ™˜ ๋‚ด์—ญ๊ณผ ๋ฐฐ์†กยท์ฟ ํฐ ์ฒ˜๋ฆฌ ์ƒํƒœ ์กฐํšŒ
  • Idempotency-Key์™€ DB ์œ ๋‹ˆํฌ ์ œ์•ฝ์„ ํ™œ์šฉํ•œ ๋™์ผ ๊ตฌ๋งค ์š”์ฒญ์˜ ์ค‘๋ณต ์ฒ˜๋ฆฌ ๋ฐฉ์ง€
  • ์ƒํ’ˆ ๋‹จ์œ„ Redisson ๋ถ„์‚ฐ ๋ฝ์œผ๋กœ ๋™์ผ ์ƒํ’ˆ์˜ ๋™์‹œ ๊ตฌ๋งค ์š”์ฒญ ์ œ์–ด
  • ์‚ฌ์šฉ์ž์™€ ์ƒํ’ˆ ๋ฐ์ดํ„ฐ์— DB ๋น„๊ด€์  ๋ฝ์„ ์ ์šฉํ•˜์—ฌ ํฌ์ธํŠธ์™€ ์žฌ๊ณ  ์ •ํ•ฉ์„ฑ ๋ณด์žฅ

๊ธฐ์—ฌ๋„

  • ์‚ฌ์šฉ์ž์˜ ๋ˆ„์  ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ธ์ฆ ํšŸ์ˆ˜ ์กฐํšŒ
  • ์ธ์ฆ ํšŸ์ˆ˜์— ๋”ฐ๋ฅธ 8๋‹จ๊ณ„ ํ™˜๊ฒฝ ๊ธฐ์—ฌ ๋งˆ์ผ์Šคํ†ค ์ œ๊ณต
  • ํ˜„์žฌ ๋‹ฌ์„ฑํ•œ ๊ฒฐ๊ณผ๋ฌผ๊ณผ ๋‹ค์Œ ๋ชฉํ‘œ๊นŒ์ง€ ๋‚จ์€ ์ธ์ฆ ํšŸ์ˆ˜ ํ‘œ์‹œ
  • ์ „์ฒด ์„œ๋น„์Šค ์ฐธ์—ฌ์ž ์ˆ˜ ์กฐํšŒ
  • ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์˜ ์ตœ๊ทผ ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ธ์ฆ ํ™œ๋™์„ ํ”ผ๋“œ ํ˜•ํƒœ๋กœ ์ œ๊ณต
  • ์ปค์„œ ๊ธฐ๋ฐ˜ ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ํ™œ์šฉํ•œ ๊ธฐ์—ฌ๋„ ํ”ผ๋“œ ์ด์–ด๋ณด๊ธฐ
  • Cache-Aside ๋ฐฉ์‹์œผ๋กœ ๊ธฐ์—ฌ๋„ ์ด๋ฒคํŠธ์™€ ์ฐธ์—ฌ์ž ์ˆ˜๋ฅผ Redis์— ์บ์‹ฑ
  • ๋ฐ์ดํ„ฐ ํŠน์„ฑ์— ๋”ฐ๋ผ ์„œ๋กœ ๋‹ค๋ฅธ TTL์„ ์ ์šฉํ•˜์—ฌ ์บ์‹œ ์ตœ์‹ ์„ฑ๊ณผ ์กฐํšŒ ์„ฑ๋Šฅ ๊ด€๋ฆฌ
  • Redis ์žฅ์•  ์‹œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์กฐํšŒ๋กœ ์ „ํ™˜ํ•˜์—ฌ ๊ธฐ์—ฌ๋„ ๊ธฐ๋Šฅ ์œ ์ง€

์ปค๋ฎค๋‹ˆํ‹ฐ

  • ์ •๋ณด ๊ณต์œ , ํ™˜๊ฒฝ ์‹ค์ฒœ, ๋ฆฌ์›Œ๋“œ ํ›„๊ธฐ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ
  • ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ๋ฐ ์ƒ์„ธ ์ •๋ณด ์กฐํšŒ
  • ์ œ๋ชฉ, ๋‚ด์šฉ ๋ฐ ์—ฌ๋Ÿฌ ์žฅ์˜ ์ด๋ฏธ์ง€๋ฅผ ํฌํ•จํ•œ ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก
  • ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ๋ฐ ์‚ญ์ œ
  • ๊ฒŒ์‹œ๊ธ€๋ณ„ ๋Œ“๊ธ€ ์กฐํšŒ, ๋“ฑ๋ก, ์ˆ˜์ • ๋ฐ ์‚ญ์ œ
  • ๊ฒŒ์‹œ๊ธ€ ์ข‹์•„์š” ๋ฐ ์ข‹์•„์š” ์ทจ์†Œ
  • ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๊ฒŒ์‹œ๊ธ€๊ณผ ๋Œ“๊ธ€ ๋ชจ์•„๋ณด๊ธฐ
  • ๊ฒŒ์‹œ๊ธ€ ์ตœ์‹ ์ˆœ ํŽ˜์ด์ง€๋„ค์ด์…˜๊ณผ ๋Œ“๊ธ€ ์ปค์„œ ํŽ˜์ด์ง€๋„ค์ด์…˜
  • ๊ฒŒ์‹œ๊ธ€๋ณ„ ๋Œ“๊ธ€ ์ˆ˜์™€ ๋Œ€ํ‘œ ์ด๋ฏธ์ง€๋ฅผ ์ผ๊ด„ ์กฐํšŒํ•˜์—ฌ N+1 ๋ฌธ์ œ ๋ฐฉ์ง€
  • ์ปค๋ฎค๋‹ˆํ‹ฐ ์ด๋ฏธ์ง€๋ฅผ AWS S3์— ์ €์žฅํ•˜๊ณ  ๋‹ค์ค‘ ์—…๋กœ๋“œ ์‹คํŒจ ์‹œ ๋ณด์ƒ ์‚ญ์ œ ์ฒ˜๋ฆฌ

๐Ÿงฉ ํ•ต์‹ฌ ๊ธฐ์ˆ  ๋ฐ ์„ค๊ณ„

AI ์š”์ฒญ ๊ฒฉ๋ฆฌ์™€ ์‘๋‹ต ์‹ ๋ขฐ์„ฑ ํ™•๋ณด (AI)

  • ๋ฌธ์ œ
    • Gemini API๋Š” ๋„คํŠธ์›Œํฌ์™€ ๋ชจ๋ธ ์ƒํƒœ์— ๋”ฐ๋ผ ์‘๋‹ต์ด ์ง€์—ฐ๋˜์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์š”์ฒญ ์ฒ˜๋ฆฌ ์ž์›์„ ์žฅ์‹œ๊ฐ„ ์ ์œ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
    • AI๊ฐ€ ์„œ๋น„์Šค์— ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ’ˆ๋ชฉ์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์•ฝ์†๋œ JSON ํ˜•์‹๊ณผ ๋‹ค๋ฅธ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ
    • AI ํ˜ธ์ถœ ์ „์šฉ Executor์™€ ๋ฐฐ์ถœ ์ธ์ฆ ์ „์šฉ Thread Pool์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ผ๋ฐ˜ API ์š”์ฒญ๊ณผ AI ํŒ์ • ์ž‘์—…์˜ ์‹คํ–‰ ์ž์›์„ ๊ฒฉ๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ํ˜ธ์ถœ ์ œํ•œ ์‹œ๊ฐ„๊ณผ ์ธ์ฆ ์ „์ฒด ์ œํ•œ ์‹œ๊ฐ„์„ ๋ณ„๋„๋กœ ์„ค์ •ํ•˜๊ณ , ์‹œ๊ฐ„ ์ดˆ๊ณผ์™€ Provider ์˜ค๋ฅ˜๋ฅผ ๋„๋ฉ”์ธ ์˜ˆ์™ธ๋กœ ๋ณ€ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์„œ๋น„์Šค DB์— ๋“ฑ๋ก๋œ ํ’ˆ๋ชฉ ๋ชฉ๋ก์„ ํ”„๋กฌํ”„ํŠธ์— ์ œ๊ณตํ•˜์—ฌ ํ•ด๋‹น ๋ชฉ๋ก์—์„œ๋งŒ ๊ฒฐ๊ณผ๋ฅผ ์„ ํƒํ•˜๋„๋ก ์ œํ•œํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์ ํ•ฉํ•œ ํ’ˆ๋ชฉ์ด ์—†์œผ๋ฉด NOT_FOUND๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•˜๊ณ , JSON Schema๋ฅผ ์ ์šฉํ•˜์—ฌ ์‘๋‹ต ํ˜•์‹์„ ๊ฒ€์ฆํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํšจ๊ณผ
    • ์™ธ๋ถ€ AI ์„œ๋น„์Šค์˜ ์‘๋‹ต ์ง€์—ฐ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด๋กœ ํ™•์‚ฐ๋˜๋Š” ๋ฒ”์œ„๋ฅผ ์ค„์˜€์Šต๋‹ˆ๋‹ค.
    • AI ํ• ๋ฃจ์‹œ๋„ค์ด์…˜๊ณผ ๋น„์ •ํ˜• ์‘๋‹ต์„ ์ œ์–ดํ•˜์—ฌ ์„œ๋น„์Šค ๋ฐ์ดํ„ฐ์™€ ์ผ์น˜ํ•˜๋Š” ๊ฒฐ๊ณผ๋งŒ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์›Œ๋“œ ๊ตฌ๋งค ๋™์‹œ์„ฑ ์ œ์–ด์™€ ๋ฉฑ๋“ฑ์„ฑ ํ™•๋ณด (๋™์‹œ์„ฑ)

  • ๋ฌธ์ œ
    • ๋™์ผ ์ƒํ’ˆ์— ๊ตฌ๋งค ์š”์ฒญ์ด ๋™์‹œ์— ๋“ค์–ด์˜ค๋ฉด ์ƒํ’ˆ ์žฌ๊ณ ๊ฐ€ ์Œ์ˆ˜๊ฐ€ ๋˜๊ฑฐ๋‚˜ ํฌ์ธํŠธ๊ฐ€ ์ค‘๋ณต ์ฐจ๊ฐ๋  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
    • ๋„คํŠธ์›Œํฌ ์ง€์—ฐ์ด๋‚˜ ์‚ฌ์šฉ์ž ์žฌ์š”์ฒญ์œผ๋กœ ๋™์ผํ•œ ๊ตฌ๋งค ์š”์ฒญ์ด ์—ฌ๋Ÿฌ ๋ฒˆ ์ฒ˜๋ฆฌ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ
    • ์ƒํ’ˆ ID ๋‹จ์œ„์˜ Redisson ๋ถ„์‚ฐ ๋ฝ์„ ์ ์šฉํ•˜์—ฌ ๋™์ผ ์ƒํ’ˆ์— ๋Œ€ํ•œ ๊ตฌ๋งค ์š”์ฒญ์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ํŠธ๋žœ์žญ์…˜ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉ์ž์™€ ์ƒํ’ˆ์— DB ๋น„๊ด€์  ๋ฝ์„ ์ ์šฉํ•˜๊ณ  ํฌ์ธํŠธ, ์ƒํ’ˆ ์ƒํƒœ ๋ฐ ์žฌ๊ณ ๋ฅผ ๋‹ค์‹œ ๊ฒ€์ฆํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์š”์ฒญ๋ณ„ Idempotency-Key๋ฅผ ๋ฐ›๊ณ  ์‚ฌ์šฉ์ž ID์™€ ๋ฉฑ๋“ฑ์„ฑ ํ‚ค ์กฐํ•ฉ์— DB ์œ ๋‹ˆํฌ ์ œ์•ฝ์„ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํšจ๊ณผ
    • ๋‹ค์ค‘ ์ธ์Šคํ„ด์Šค ํ™˜๊ฒฝ์—์„œ๋„ ์ƒํ’ˆ ์žฌ๊ณ ์™€ ์‚ฌ์šฉ์ž ํฌ์ธํŠธ์˜ ์ •ํ•ฉ์„ฑ์„ ์œ ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ๋™์ผ ์š”์ฒญ์˜ ์ค‘๋ณต ์ฒ˜๋ฆฌ์™€ ์„œ๋กœ ๋‹ค๋ฅธ ์ƒํ’ˆ์˜ ๋™์‹œ ๊ตฌ๋งค๋กœ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ํฌ์ธํŠธ ์ค‘๋ณต ์‚ฌ์šฉ์„ ๋ฐฉ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.

Cache-Aside ๊ธฐ๋ฐ˜ ๊ธฐ์—ฌ๋„ ํ”ผ๋“œ ์บ์‹ฑ๊ณผ Redis ์žฅ์•  ๋Œ€์‘ (์บ์‹ฑ)

  • ๋ฌธ์ œ
    • ๊ธฐ์—ฌ๋„ ํ”ผ๋“œ ์กฐํšŒ๋งˆ๋‹ค ์ด๋ฒคํŠธ์™€ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ๋ฐ ์ „์ฒด ์ฐธ์—ฌ์ž ์ˆ˜๋ฅผ ๋ฐ˜๋ณต ์กฐํšŒํ•˜์—ฌ DB ๋ถ€ํ•˜๊ฐ€ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
    • Redis ์žฅ์• ๊ฐ€ ๊ธฐ์—ฌ๋„ ๊ธฐ๋Šฅ ์ „์ฒด์˜ ์žฅ์• ๋กœ ์ด์–ด์ง€์ง€ ์•Š๋„๋ก ๋ณ„๋„์˜ ์‹คํŒจ ๊ฒฝ๋กœ๊ฐ€ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ
    • Cache-Aside ๋ฐฉ์‹์œผ๋กœ ๊ธฐ์—ฌ๋„ ์ด๋ฒคํŠธ๋ฅผ ์บ์‹ฑํ•˜๊ณ , ์บ์‹œ์— ์—†๋Š” ์ด๋ฒคํŠธ๋งŒ DB์—์„œ ์ผ๊ด„ ์กฐํšŒํ•œ ๋’ค ๋‹ค์‹œ ์ €์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ๊ธฐ์—ฌ๋„ ์ด๋ฒคํŠธ์—๋Š” 30๋ถ„, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์€ ์ „์ฒด ์ฐธ์—ฌ์ž ์ˆ˜์—๋Š” 1๋ถ„์˜ TTL์„ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ํ”ผ๋“œ์— ํ•„์š”ํ•œ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„์„ ์‚ฌ์šฉ์ž ID ๋ชฉ๋ก์œผ๋กœ ์ผ๊ด„ ์กฐํšŒํ–ˆ์Šต๋‹ˆ๋‹ค.
    • Redis ์กฐํšŒ ๋˜๋Š” ์ €์žฅ์— ์‹คํŒจํ•˜๋ฉด DB์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋„๋ก Fail-Open ๊ตฌ์กฐ๋ฅผ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํšจ๊ณผ
    • ๊ธฐ์—ฌ๋„ ๋ฐ์ดํ„ฐ์™€ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„์˜ ๋ฐ˜๋ณต ์กฐํšŒ๋ฅผ ์ค„์—ฌ DB ์ ‘๊ทผ๋Ÿ‰์„ ๊ฐ์†Œ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.
    • Redis ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ DB ์กฐํšŒ๋ฅผ ํ†ตํ•ด ๊ธฐ์—ฌ๋„ ๊ธฐ๋Šฅ์„ ๊ณ„์† ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ปค๋ฎค๋‹ˆํ‹ฐ ๋ชฉ๋ก ์กฐํšŒ N+1 ๋ฌธ์ œ ํ•ด๊ฒฐ (์ฟผ๋ฆฌ ์ตœ์ ํ™”)

  • ๋ฌธ์ œ
    • ๊ฒŒ์‹œ๊ธ€๋ณ„ ๋Œ“๊ธ€ ์ˆ˜์™€ ๋Œ€ํ‘œ ์ด๋ฏธ์ง€๋ฅผ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด ๊ฒŒ์‹œ๊ธ€๋งˆ๋‹ค ์ถ”๊ฐ€ ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
    • ๊ฒŒ์‹œ๊ธ€์ด N๊ฐœ์ผ ๋•Œ 1 + 2N๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ 10๊ฐœ ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ ์‹œ ์ด 21๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ
    • ๋จผ์ € ํŽ˜์ด์ง€์— ํ‘œ์‹œํ•  ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก์„ ํ™•์ •ํ•œ ๋’ค ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€์˜ ๋Œ“๊ธ€ ์ˆ˜์™€ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ๊ฐ ์ผ๊ด„ ์กฐํšŒํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ๋Œ“๊ธ€ ์ˆ˜๋Š” GROUP BY community_id ์ง‘๊ณ„ ๊ฒฐ๊ณผ๋ฅผ Projection์œผ๋กœ ์กฐํšŒํ•˜์—ฌ ๊ฒŒ์‹œ๊ธ€๋ณ„ Map์œผ๋กœ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€๋Š” displayOrder ์ˆœ์œผ๋กœ ์กฐํšŒํ•˜๊ณ  ๊ฒŒ์‹œ๊ธ€๋ณ„ ๊ฐ€์žฅ ์•ž์„  ์ด๋ฏธ์ง€๋ฅผ ๋Œ€ํ‘œ ์ด๋ฏธ์ง€๋กœ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํšจ๊ณผ
    • ํŽ˜์ด์ง€ ํฌ๊ธฐ์™€ ๊ด€๊ณ„์—†์ด ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ชฉ๋ก ์กฐํšŒ ์ฟผ๋ฆฌ๋ฅผ 3๊ฐœ๋กœ ๊ณ ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ๊ฒŒ์‹œ๊ธ€ ์ˆ˜๊ฐ€ ์ฆ๊ฐ€ํ•˜๋”๋ผ๋„ ์ถ”๊ฐ€ ์ฟผ๋ฆฌ๊ฐ€ ๋น„๋ก€ํ•˜์—ฌ ์ฆ๊ฐ€ํ•˜์ง€ ์•Š๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

S3์™€ DB ์‚ฌ์ด์˜ ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ ํ™•๋ณด (๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ)

  • ๋ฌธ์ œ
    • S3์™€ DB๋Š” ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๋ฌถ์„ ์ˆ˜ ์—†์–ด ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ์˜ ์ผ๋ถ€๋งŒ ์„ฑ๊ณตํ•˜๋ฉด ๊ณ ์•„ ๊ฐ์ฒด๊ฐ€ ๋‚จ์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
    • ํ”„๋กœํ•„ ์ด๋ฏธ์ง€๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ๊ธฐ์กด ์ด๋ฏธ์ง€๋ฅผ ๋จผ์ € ์‚ญ์ œํ•˜๋ฉด ์ดํ›„ DB ์ €์žฅ ์‹คํŒจ ์‹œ ์‚ฌ์šฉ์ž ์ด๋ฏธ์ง€๊ฐ€ ์œ ์‹ค๋  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ
    • ์—…๋กœ๋“œ์— ์„ฑ๊ณตํ•œ S3 ๊ฐ์ฒด ํ‚ค๋ฅผ ์ถ”์ ํ•˜๊ณ , ์ดํ›„ ์ฒ˜๋ฆฌ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋จผ์ € ์—…๋กœ๋“œ๋œ ๊ฐ์ฒด๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ณด์ƒ ๋กœ์ง์„ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ํ”„๋กœํ•„ ์ด๋ฏธ์ง€๋Š” ์‹ ๊ทœ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ โ†’ DB ๋ฐ˜์˜ ๋ฐ URL ์ƒ์„ฑ โ†’ ๊ธฐ์กด ์ด๋ฏธ์ง€ ์‚ญ์ œ ์ˆœ์„œ๋กœ ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.
    • DB ๋ฐ˜์˜์— ์‹คํŒจํ•˜๋ฉด ์ƒˆ๋กœ ์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€๋ฅผ ์ •๋ฆฌํ•˜๊ณ , ๋ณด์ƒ ์ฒ˜๋ฆฌ ์‹คํŒจ ์›์ธ์„ ๋กœ๊ทธ๋กœ ๋‚จ๊ธฐ๋„๋ก ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํšจ๊ณผ
    • ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ณผ์ •์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ ์•„ ๊ฐ์ฒด๋ฅผ ์ค„์˜€์Šต๋‹ˆ๋‹ค.
    • ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ ์‹คํŒจ ์‹œ ๊ธฐ์กด ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•˜์—ฌ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ ์œ ์‹ค ๊ฐ€๋Šฅ์„ฑ์„ ๋‚ฎ์ท„์Šต๋‹ˆ๋‹ค.

ํ†ตํ•ฉ ๋ชจ๋‹ˆํ„ฐ๋ง ๊ตฌ์ถ•๊ณผ ๋กœ๊ทธ ์ˆ˜์ง‘ ๋ณด์•ˆ ๊ฐ•ํ™” (์šด์˜ ์ธํ”„๋ผ)

  • ๋ฌธ์ œ
    • ์„œ๋ฒ„์— ์ง์ ‘ ์ ‘์†ํ•˜๊ธฐ ์ „๊นŒ์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์žฅ์• ์™€ EC2ยทRedis ์ž์› ๋ถ€์กฑ์„ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค.
    • ์ปจํ…Œ์ด๋„ˆ ๋กœ๊ทธ ์ˆ˜์ง‘์„ ์œ„ํ•œ Docker Socket ๊ถŒํ•œ ๋…ธ์ถœ๊ณผ EC2 ๊ฐ„ ๋กœ๊ทธ ์ „์†ก ๊ตฌ๊ฐ„์˜ ๋ณด์•ˆ์„ ๊ณ ๋ คํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์ผ์‹œ์ ์ธ ์ง€ํ‘œ ๋ˆ„๋ฝ์œผ๋กœ ๋™์ผํ•œ Grafana ์žฅ์•  ์•Œ๋ฆผ์ด ๋ฐ˜๋ณต๋˜๋Š” ๋ฌธ์ œ๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ
    • Prometheus๋กœ Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜, EC2 ๋ฐ Redis ๋ฉ”ํŠธ๋ฆญ์„ ํ†ตํ•ฉ ์ˆ˜์ง‘ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • Grafana Alloy, Loki, Grafana๋ฅผ ์ด์šฉํ•ด ์ปจํ…Œ์ด๋„ˆ ๋กœ๊ทธ ์ˆ˜์ง‘๊ณผ ์šด์˜ ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ๊ตฌ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • Docker Socket Proxy๋ฅผ ์ ์šฉํ•˜์—ฌ Alloy์— ํ•„์š”ํ•œ ์กฐํšŒ ๊ถŒํ•œ๋งŒ ์ œํ•œ์ ์œผ๋กœ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.
    • Service EC2์™€ Monitoring EC2 ์‚ฌ์ด์˜ ๋กœ๊ทธ ์ „์†ก์— TLS์™€ Basic Auth๋ฅผ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
    • Grafana์˜ No Data ์ฒ˜๋ฆฌ, ํ‰๊ฐ€ ๋Œ€๊ธฐ์‹œ๊ฐ„ ๋ฐ ์•Œ๋ฆผ ์ •์ฑ…์„ ์กฐ์ •ํ•˜๊ณ  ์žฅ์• ยท๋ณต๊ตฌ ์•Œ๋ฆผ์„ Discord๋กœ ์ „์†กํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํšจ๊ณผ
    • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ์™€ ์ธํ”„๋ผ ๋ฉ”ํŠธ๋ฆญ์„ ํ•˜๋‚˜์˜ ๋Œ€์‹œ๋ณด๋“œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
    • Docker Socket๊ณผ ๋กœ๊ทธ ์ „์†ก ๊ฒฝ๋กœ์˜ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜๊ณ  ์žฅ์•  ์•Œ๋ฆผ์˜ ์ •ํ™•๋„์™€ ์‹ ๋ขฐ๋„๋ฅผ ๋†’์˜€์Šต๋‹ˆ๋‹ค.

โš™๏ธ ๊ธฐ์ˆ  ์Šคํƒ

Backend

Database & Cache

AI & External API

Infrastructure & CI/CD

Monitoring & Test

API Documentation


๐Ÿ— ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜

ReDO ์ธํ”„๋ผ ์•„ํ‚คํ…์ฒ˜

๐Ÿ—„ ERD

ReDO ERD

๐Ÿ”Œ API ๊ตฌ์„ฑ

๋„๋ฉ”์ธ Base Path ์ฃผ์š” ๊ธฐ๋Šฅ
์ธ์ฆ /api/auth ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ, ์†Œ์…œ ๋กœ๊ทธ์ธ, ํ† ํฐ ์žฌ๋ฐœ๊ธ‰, ๋กœ๊ทธ์•„์›ƒ
์‚ฌ์šฉ์ž /api/users ํ”„๋กœํ•„ ๊ด€๋ฆฌ, ํšŒ์› ํƒˆํ‡ด
์•ฝ๊ด€ /api/terms ์„œ๋น„์Šค ์•ฝ๊ด€ ์กฐํšŒ
๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด /api/guides ๊ฐ€์ด๋“œ ์กฐํšŒ, AI ๊ฒ€์ƒ‰, ์ฆ๊ฒจ์ฐพ๊ธฐ
๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ธ์ฆ /api/certification ์ธ์ฆ ์ •์ฑ… ์กฐํšŒ, ์‹ ๊ทœ ์ธ์ฆ, ์žฌ์ดฌ์˜
ํฌ์ธํŠธ /api/rewards/points ๋ณด์œ  ํฌ์ธํŠธ ๋ฐ ๊ฑฐ๋ž˜ ๋‚ด์—ญ ์กฐํšŒ
๋ฆฌ์›Œ๋“œ ์ƒํ’ˆ /api/rewards/products ์ƒํ’ˆ ๋ชฉ๋ก, ์ƒ์„ธ, ๋ฏธ๋ฆฌ๋ณด๊ธฐ
๋ฆฌ์›Œ๋“œ ๊ตํ™˜ /api/rewards/redemptions ์ƒํ’ˆ ๊ตํ™˜ ๋ฐ ๊ตํ™˜ ๋‚ด์—ญ ์กฐํšŒ
๋ฐฐ์†ก์ง€ /api/shipping-addresses ์ฃผ์†Œ ๊ฒ€์ƒ‰ ๋ฐ ๋ฐฐ์†ก์ง€ ๊ด€๋ฆฌ
๊ธฐ์—ฌ๋„ /api/contributions ๋‚˜์˜ ๊ธฐ์—ฌ๋„, ์ „์ฒด ๊ธฐ์—ฌ๋„ ํ”ผ๋“œ
์ปค๋ฎค๋‹ˆํ‹ฐ /api/community ๊ฒŒ์‹œ๊ธ€, ๋Œ“๊ธ€, ์ข‹์•„์š”

์ „์ฒด API ๋ช…์„ธ์™€ ์š”์ฒญยท์‘๋‹ต ์˜ˆ์‹œ๋Š” Swagger์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


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

Back/
โ”œโ”€โ”€ .github/
โ”‚   โ”œโ”€โ”€ ISSUE_TEMPLATE/
โ”‚   โ”œโ”€โ”€ workflows/
โ”‚   โ”‚   โ””โ”€โ”€ ci-cd.yml
โ”‚   โ”œโ”€โ”€ CONTRIBUTING.md
โ”‚   โ””โ”€โ”€ PULL_REQUEST_TEMPLATE.md
โ”œโ”€โ”€ gradle/
โ”œโ”€โ”€ k6/
โ”‚   โ”œโ”€โ”€ config/                 # ์‹คํ–‰ ํ”„๋กœํ•„ ๋ฐ ์„ฑ๋Šฅ ๊ธฐ์ค€
โ”‚   โ”œโ”€โ”€ lib/                    # ์ธ์ฆ, HTTP ์š”์ฒญ, ์•ˆ์ „์žฅ์น˜
โ”‚   โ””โ”€โ”€ scenarios/              # ๋„๋ฉ”์ธ๋ณ„ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ
โ”œโ”€โ”€ monitoring/
โ”‚   โ”œโ”€โ”€ alloy/                  # ์ปจํ…Œ์ด๋„ˆ ๋กœ๊ทธ ์ˆ˜์ง‘
โ”‚   โ”œโ”€โ”€ grafana/                # ๋Œ€์‹œ๋ณด๋“œ ๋ฐ ์•Œ๋ฆผ ํ”„๋กœ๋น„์ €๋‹
โ”‚   โ”œโ”€โ”€ loki/                   # ๋กœ๊ทธ ์ €์žฅ์†Œ
โ”‚   โ”œโ”€โ”€ loki-proxy/             # Loki TLSยท์ธ์ฆ ํ”„๋ก์‹œ
โ”‚   โ””โ”€โ”€ prometheus/             # ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘ ์„ค์ •
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ main/
โ”‚   โ”‚   โ”œโ”€โ”€ java/com/redo/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ domain/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ certification/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ community/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ contribution/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ point/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ recycleGuide/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ reward/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ term/
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ user/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ global/
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ ai/
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ apiPayload/
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ config/
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ redis/
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ s3/
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ security/
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ util/
โ”‚   โ”‚   โ””โ”€โ”€ resources/
โ”‚   โ”‚       โ”œโ”€โ”€ application.yaml
โ”‚   โ”‚       โ””โ”€โ”€ application-certification.yaml
โ”‚   โ””โ”€โ”€ test/
โ”œโ”€โ”€ .env.example
โ”œโ”€โ”€ build.gradle
โ”œโ”€โ”€ compose.yaml
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ gradlew
โ””โ”€โ”€ settings.gradle

๐Ÿš€ ๋กœ์ปฌ ์‹คํ–‰ ๋ฐฉ๋ฒ•

์š”๊ตฌ์‚ฌํ•ญ

  • Java 17
  • MySQL
  • Redis
  • AWS S3 Bucket
  • Gmail SMTP ๊ณ„์ • ๋ฐ App Password
  • Gemini API Key (AI ๊ธฐ๋Šฅ ์‚ฌ์šฉ ์‹œ)
  • ๋„๋กœ๋ช…์ฃผ์†Œ API Key (๋ฐฐ์†ก์ง€ ์ฃผ์†Œ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ์‚ฌ์šฉ ์‹œ)

AI ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ GEMINI_ENABLED=false๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ด๋ฏธ์ง€ยทํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ๋ถ„๋ฆฌ๋ฐฐ์ถœ ์ •๋ณด ํƒ์ƒ‰๊ณผ AI ๋ฐฐ์ถœ ์ธ์ฆ ๊ธฐ๋Šฅ์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

1. ์ €์žฅ์†Œ ๋ณต์ œ

git clone https://github.com/REDO-Team/Back.git
cd Back

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

cp .env.example .env

์ฃผ์š” ํ™˜๊ฒฝ๋ณ€์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค๋ช…
DB_URL MySQL JDBC URL
DB_USERNAME MySQL ์‚ฌ์šฉ์ž๋ช…
DB_PASSWORD MySQL ๋น„๋ฐ€๋ฒˆํ˜ธ
JWT_SECRET JWT ์„œ๋ช… Secret
MAIL_USERNAME ์ด๋ฉ”์ผ ์ธ์ฆ ๋ฐœ์†ก ๊ณ„์ •
MAIL_PASSWORD Gmail App Password
S3_BUCKET ์ด๋ฏธ์ง€ ์ €์žฅ S3 Bucket
AWS_REGION AWS Region
JUSO_API_KEY ๋„๋กœ๋ช…์ฃผ์†Œ API ์Šน์ธ ํ‚ค
APP_BASE_URL CORS์™€ Swagger์— ์‚ฌ์šฉํ•  ์„œ๋น„์Šค URL
GEMINI_ENABLED Gemini ๊ธฐ๋Šฅ ํ™œ์„ฑํ™” ์—ฌ๋ถ€
GEMINI_API_KEY Gemini API Key
GEMINI_MODEL ์‚ฌ์šฉํ•  Gemini ๋ชจ๋ธ
GEMINI_TIMEOUT ๋‹จ์ผ Gemini ํ˜ธ์ถœ ์ œํ•œ ์‹œ๊ฐ„

AWS ์ธ์ฆ ์ •๋ณด๋Š” ๋กœ์ปฌ AWS Profile ๋˜๋Š” EC2 IAM Role ๋“ฑ AWS SDK ๊ธฐ๋ณธ ์ธ์ฆ ์ฒด์ธ์„ ํ†ตํ•ด ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

3. ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ ์šฉ ๋ฐ ์‹คํ–‰

set -a
source .env
set +a

./gradlew bootRun

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํฌํŠธ ์šฉ๋„
8080 Backend API
9101 Actuator Health ๋ฐ Prometheus Metrics
6379 Redis

๐Ÿงช ํ…Œ์ŠคํŠธ

์ผ๋ฐ˜ ํ…Œ์ŠคํŠธ๋Š” ์™ธ๋ถ€ Gemini API๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

./gradlew test

์‹ค์ œ Gemini API ์—ฐ๋™ ํ…Œ์ŠคํŠธ๋Š” ๋ณ„๋„ Gradle Task๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

./gradlew geminiIntegrationTest

Gemini ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด ์œ ํšจํ•œ API Key์™€ ๊ด€๋ จ ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ

k6 ํ…Œ์ŠคํŠธ๋Š” Docker ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰ํ•˜์—ฌ ํŒ€์›์ด ๋™์ผํ•œ ๋ฒ„์ „๊ณผ ์„ฑ๋Šฅ ๊ธฐ์ค€์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

cp k6/.env.example k6/.env
./k6/run.sh scenarios/examples/authenticated-read.js

์ œ๊ณตํ•˜๋Š” ์‹คํ–‰ ํ”„๋กœํ•„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํ”„๋กœํ•„ ์šฉ๋„
smoke API์™€ ์‹œ๋‚˜๋ฆฌ์˜ค ์ •์ƒ ๋™์ž‘ ํ™•์ธ
load ์˜ˆ์ƒ๋˜๋Š” ์ผ๋ฐ˜ ๋ถ€ํ•˜์—์„œ ์„ฑ๋Šฅ ์ธก์ •
stress ์‹œ์Šคํ…œ ํ•œ๊ณ„์™€ ๋ณ‘๋ชฉ ํ™•์ธ

๊ณตํ†ต ์„ฑ๋Šฅ ๊ธฐ์ค€์€ HTTP ์˜ค๋ฅ˜์œจ 1% ๋ฏธ๋งŒ, p95 500ms ๋ฏธ๋งŒ, p99 1,000ms ๋ฏธ๋งŒ์ž…๋‹ˆ๋‹ค.

์ž์„ธํ•œ ๊ตฌ์„ฑ๊ณผ ์šด์˜ ๋ฐฉ๋ฒ•์€ k6 ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์šด์˜ ๊ฐ€์ด๋“œ๋ฅผ ์ฐธ๊ณ ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ”„ CI/CD

develop ๋ธŒ๋žœ์น˜์— ์ฝ”๋“œ๊ฐ€ ๋ฐ˜์˜๋˜๋ฉด GitHub Actions๋ฅผ ํ†ตํ•ด ์ž๋™ ๋ฐฐํฌ๊ฐ€ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

  1. GitHub Actions๊ฐ€ Docker ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œ
  2. ์ด๋ฏธ์ง€๋ฅผ GitHub Container Registry์— Push
  3. Self-hosted Runner๊ฐ€ ๋ฐฐํฌ ์„œ๋ฒ„์˜ ์†Œ์Šค๋ฅผ ๊ฐฑ์‹ 
  4. Docker Compose๊ฐ€ ์ƒˆ ์ด๋ฏธ์ง€๋ฅผ Pull
  5. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ Redis ๋“ฑ ์šด์˜ ์ปจํ…Œ์ด๋„ˆ ์žฌ๊ธฐ๋™
  6. Swagger UI ์‘๋‹ต์„ ํ†ตํ•œ ๋ฐฐํฌ ์ƒํƒœ ํ™•์ธ
  7. ์ผ์ • ๊ธฐ๊ฐ„์ด ์ง€๋‚œ ๋ฏธ์‚ฌ์šฉ ์ด๋ฏธ์ง€ ์ •๋ฆฌ

๐Ÿ“Š ๋ชจ๋‹ˆํ„ฐ๋ง

Spring Boot Actuator์™€ Micrometer๋ฅผ ํ†ตํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฉ”ํŠธ๋ฆญ์„ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค.

  • Prometheus: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜, EC2, Redis ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘
  • Grafana: ์šด์˜ ํ˜„ํ™ฉ ๋ฐ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ๋Œ€์‹œ๋ณด๋“œ
  • Loki: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์ปจํ…Œ์ด๋„ˆ ๋กœ๊ทธ ์ €์žฅ
  • Grafana Alloy: Docker ์ปจํ…Œ์ด๋„ˆ ๋กœ๊ทธ ์ˆ˜์ง‘ ๋ฐ ์ „์†ก
  • Node Exporter: EC2 CPU, Memory, Disk ๋ฉ”ํŠธ๋ฆญ
  • Redis Exporter: Redis ์ƒํƒœ์™€ ๋ฉ”๋ชจ๋ฆฌ ๋ฉ”ํŠธ๋ฆญ
  • Discord: ์žฅ์•  ๋ฐœ์ƒ ๋ฐ ๋ณต๊ตฌ ์•Œ๋ฆผ

์šด์˜ ๋Œ€์‹œ๋ณด๋“œ๋Š” ๋‹ค์Œ ํ•ญ๋ชฉ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์š”์ฒญ ์ฒ˜๋ฆฌ๋Ÿ‰๊ณผ ์‘๋‹ต ์‹œ๊ฐ„
  • HTTP ์˜ค๋ฅ˜์œจ
  • JVM Heap๊ณผ Thread ์ƒํƒœ
  • EC2 CPU, Memory, Disk ์‚ฌ์šฉ๋Ÿ‰
  • Redis ๋ฉ”๋ชจ๋ฆฌ์™€ ์—ฐ๊ฒฐ ์ƒํƒœ
  • k6 ํ…Œ์ŠคํŠธ๋ณ„ p95ยทp99 ์‘๋‹ต ์‹œ๊ฐ„
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐ ์ธํ”„๋ผ ์žฅ์•  ์•Œ๋ฆผ

์ž์„ธํ•œ ๊ตฌ์„ฑ๊ณผ ์šด์˜ ๋ฐฉ๋ฒ•์€ ๋ชจ๋‹ˆํ„ฐ๋ง ์šด์˜ ๊ฐ€์ด๋“œ๋ฅผ ์ฐธ๊ณ ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿค ํ˜‘์—… ๊ทœ์น™

  • ๊ธฐ๋ณธ ํ†ตํ•ฉ ๋ธŒ๋žœ์น˜: develop
  • ์ด์Šˆ ๋‹จ์œ„ ๋ธŒ๋žœ์น˜ ๋ฐ Pull Request ์ƒ์„ฑ
  • CodeRabbit์„ ํ™œ์šฉํ•œ ์ฝ”๋“œ ๋ฆฌ๋ทฐ
  • ๊ณตํ†ต API ์‘๋‹ต๊ณผ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ทœ์น™ ์ ์šฉ

์ž์„ธํ•œ ํ˜‘์—… ๊ทœ์น™์€ .github/CONTRIBUTING.md๋ฅผ ์ฐธ๊ณ ํ•ฉ๋‹ˆ๋‹ค.


์˜ฌ๋ฐ”๋ฅธ ๋ถ„๋ฆฌ๋ฐฐ์ถœ์ด ์ผ์ƒ์˜ ์Šต๊ด€์ด ๋˜๋„๋ก, ReDO โ™ป๏ธ

About

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages