Skip to content

HelloWorld-14/GameMate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation


๐Ÿ‘€ image ๐Ÿ‘€

๋‹ค์–‘ํ•œ ๊ฒŒ์ž„ ์ •๋ณด์™€ ๋ฆฌ๋ทฐ๋ฅผ ๊ณต์œ ํ•˜๊ณ  ๊ฒŒ์ž„์„ ๊ฐ™์ด ํ•  ์นœ๊ตฌ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ ์‚ฌ์ดํŠธ


๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Our Team

์ด์˜ˆ์ง€ ์ „์ˆ˜์—ฐ ๊ณ ๊ฐ•ํ˜ ์–‘์ œํ›ˆ
@yeji-world @sumyeom @Newbiekk @89JHoon
BE BE BE BE

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

๐Ÿ›ก OAuth2 ์†Œ์…œ๋กœ๊ทธ์ธ (kakao, google)

  • Kakao์™€ google ํ†ตํ•œ ๊ฐ„ํŽธ ๋กœ๊ทธ์ธ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ง ์ด๋ฉ”์ผ ์ธ์ฆ

  • ์ด๋ฉ”์ผ ์ธ์ฆ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ‘ฅ ๊ฒŒ์ž„ ๋งค์นญ ์‹œ์Šคํ…œ ์ œ๊ณต

  • ํ˜„์žฌ '๋ฆฌ๊ทธ์˜ค๋ธŒ๋ ˆ์ „๋“œ' ๋ผ๋Š” ๊ฒŒ์ž„์— ๋Œ€ํ•ด ๋งค์นญ ์‹œ์Šคํ…œ์„ ํ†ตํ•ด ์นœ๊ตฌ๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋‚ด ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜๊ณ , ์›ํ•˜๋Š” ์ƒ๋Œ€๋ฐฉ์˜ ์กฐ๊ฑด์„ ์ž…๋ ฅํ•˜์—ฌ ๋งค์นญ ๋กœ์ง์„ ํ†ตํ•ด ์ตœ๋Œ€ 5์ธ์˜ ์ถ”์ฒœ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŽฎ ๊ฒŒ์ž„ ์ •๋ณด ํ™•์ธ

  • ๋‹ค์–‘ํ•œ ๊ฒŒ์ž„์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๊ณ , ๊ฐ ๊ฒŒ์ž„์— ๋Œ€ํ•ด ์‚ฌ์šฉ์ž๋“ค์ด ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ๋ฅผ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โ—๏ธ ๊ฒŒ์ž„ ์ถ”์ฒœ

  • ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์„ฑํ–ฅ์„ ๊ฐ€์ง„ ๊ฒŒ์ž„์„ ์ถ”์ฒœํ•˜๋Š” ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • Gemini API ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฒŒ์ž„์„ ์ถ”์ฒœํ•ด์ค๋‹ˆ๋‹ค.

๐Ÿ“– ๊ฒŒ์ž„ ์ปค๋ฎค๋‹ˆํ‹ฐ

  • ๊ฒŒ์ž„์— ๋Œ€ํ•œ ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•˜๊ณ , ๊ฒŒ์‹œ๊ธ€์— ๋Œ“๊ธ€ ๋Œ€๋Œ“๊ธ€์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์กฐํšŒ์ˆ˜ ์ƒ์œ„ 5๊ฐœ์˜ ๊ฒŒ์‹œ๊ธ€์„ ์˜ค๋Š˜์˜ ๊ฒŒ์‹œ๊ธ€๋กœ ์„ ์ •ํ•ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ ์†Œ์…œ ๊ธฐ๋Šฅ

  • ์‚ฌ์šฉ์ž๊ฐ„์˜ ํŒ”๋กœ์šฐ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒŒ์‹œ๋ฌผ / ๊ฒŒ์ž„ ๋ฆฌ๋ทฐ์— '์ข‹์•„์š”' ๋˜๋Š” '์‹ซ์–ด์š”'๋ฅผ ๋‹ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”” ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ๊ธฐ๋Šฅ

  • ์•Œ๋ฆผ์€ SSE๋ฅผ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.
  • ๋งค์นญ / ํŒ”๋กœ์šฐ / ๋Œ“๊ธ€ / ์ข‹์•„์š” ๋“ฑ์˜ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ์•Œ๋ฆผ์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

๐ŸŽซ ์ฟ ํฐ ๊ธฐ๋Šฅ

  • ์ž์ฒด ์ฟ ํฐ์„ ๋ฐœ๊ธ‰ํ•ด, ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ์—ฌ๋Ÿฌ ํ˜œํƒ๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.



๐Ÿ“š ์ ์šฉ ๊ธฐ์ˆ 

๋ถ„์•ผ ๊ธฐ์ˆ  ๋ฐ ๋„๊ตฌ ๋ชฉ์ 
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ JDK 17
Spring Boot 3.4.1
IntelliJ IDEA
1๏ธโƒฃย JDK 17
- ์„ฑ๋Šฅ, ๋ณด์•ˆ, ๊ฐœ๋ฐœ ํšจ์œจ์„ฑ์„ ์œ„ํ•œ ์•ˆ์ •์ ์ธ ์šด์˜ ํ™˜๊ฒฝ
2๏ธโƒฃย Spring Boot 3.4.1
- ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ์˜ ์•ˆ์ •์„ฑ๊ณผ ํด๋ผ์šฐ๋“œ ๋„ค์ดํ‹ฐ๋ธŒ ๊ธฐ๋Šฅ ๊ฐ•ํ™”
3๏ธโƒฃย IntelliJ IDEA
- ๊ฐœ๋ฐœ์ž ์ƒ์‚ฐ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ํ†ตํ•ฉ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ(IDE)
์ธ์ฆ / ์ธ๊ฐ€ Spring Security
JWT
OAuth 2.0
1๏ธโƒฃย Spring Security
- ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ณด์•ˆ ํ†ตํ•ฉ ๊ด€๋ฆฌ
2๏ธโƒฃย JWT
- ๋ฌด์ƒํƒœ(Stateless) ์ธ์ฆ ๊ตฌํ˜„
3๏ธโƒฃย OAuth 2.0
- ์ œ3์ž ์„œ๋น„์Šค์˜ ์•ˆ์ „ํ•œ ์ž์› ์ ‘๊ทผ ๊ด€๋ฆฌ
ํ˜‘์—… Git
GitHub
Slack
Notion
GitHub Project / Issue
Trello
WBS
1๏ธโƒฃย Git & GitHub
- ์ฝ”๋“œ ํ˜‘์—…๊ณผ ๋ฒ„์ „ ๊ด€๋ฆฌ
2๏ธโƒฃย Slack & Notion
- ์ง„ํ–‰ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ์†Œํ†ตํ•˜๊ณ , ๋ฌธ์„œํ™”
3๏ธโƒฃย GitHub Project / Issue & Trello & WBS
- ์š”๊ตฌ ์‚ฌํ•ญ์— ๋Œ€ํ•œ ์ผ์ • ๋ฐ ์šฐ์„ ์ˆœ์œ„ ํŒŒ์•…, ์ •๋ฆฌ
- ๊ฐ ์ผ์ •์— ๋Œ€ํ•œ ์ง„ํ–‰ ์‚ฌํ•ญ ์ฒดํฌ
Database RDS(MySQL)
Redis
1๏ธโƒฃย RDS(MySQL)
- RDS๋ฅผ ํ†ตํ•ด DB๋ฅผ ์œ„ํ•œ ์ธํ”„๋ผ ๊ตฌ์ถ•
- ์•ˆ์ •์ ์ธ ๊ด€๊ณ„ํ˜• DB๋กœ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ
2๏ธโƒฃย Redis
- ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ์ˆ˜ ์นด์šดํŒ…์„ ์บ์‹œ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌ
- Redisson ๊ธฐ๋ฐ˜ ๋ถ„์‚ฐ ๋ฝ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ ์œ ์ง€
- Redis Stream์„ ์‚ฌ์šฉํ•ด ๋‹ค์ค‘ WAS ํ™˜๊ฒฝ์—์„œ๋„ ์•Œ๋ฆผ์ด ์œ ์‹ค๋˜์ง€ ์•Š๊ณ  ์ „๋‹ฌ๋˜๋„๋ก ๊ด€๋ฆฌ
ํŒŒ์ผ ์ฒจ๋ถ€ AWS S3 1๏ธโƒฃย AWS S3
- ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์•ˆ์ •์ ์œผ๋กœ ์œ ์ง€ ๊ด€๋ฆฌ
CI/CD Docker
GitHub Action
AWS EC2
AWS
1๏ธโƒฃย Docker
- ์ผ๊ด€๋œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์ œ๊ณต
- ๋ฐฐํฌ ๋ฐ ํ™•์žฅ์ด ์šฉ์ด
2๏ธโƒฃย GitHub Action
- CI/CD ์ž๋™ํ™”๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ๋ฐฐํฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌ
3๏ธโƒฃย AWS
- ํด๋ผ์šฐ๋“œ ํ™˜๊ฒฝ์—์„œ ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค ์šด์˜
์™ธ๋ถ€ API Gemini API
Google OAuth 2.0 API
Kakao OAuth 2.0 API
JavaMail
1๏ธโƒฃย Gemini API
- ์‹ ๋ขฐ์„ฑ ์žˆ๋Š” ๊ฒŒ์ž„ ์ถ”์ฒœ์„ ์œ„ํ•œ API
2๏ธโƒฃย OAuth 2.0 API (Google & Kakao)
- ์†Œ์…œ ๋กœ๊ทธ์ธ์„ ์œ„ํ•œ API
3๏ธโƒฃย JavaMail
- ๋ฉ”์ผ ๋ฐœ์†ก์„ ์œ„ํ•œ API



๐Ÿ“ ๊ธฐ์ˆ ์  ์˜์‚ฌ ๊ฒฐ์ •

Gemini AI ํ™œ์šฉ ๋ฐฉ์•ˆ

1. ๋ฐฐ๊ฒฝ

  • ๊ฒŒ์ž„ ์ถ”์ฒœ ์‹œ์Šคํ…œ์€ ๋‹จ์ˆœํ•œ ๊ฒŒ์ž„ ์„ ํƒ์„ ๋„˜์–ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ์„ค๊ณ„๋ถ€ํ„ฐ ์œค๋ฆฌ์  ๊ฒ€์ฆ๊นŒ์ง€ ์ข…ํ•ฉ์ ์ธ ์ ‘๊ทผ์ด ํ•„์š”ํ•จ.
  • ํ”Œ๋ ˆ์ด์–ด์˜ ์„ธ์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์†์ ์œผ๋กœ ํ•™์Šต์— ๋ฐ˜์˜ํ•˜๋ฉด์„œ๋„, ์ถ”์ฒœ์˜ ๊ทผ๊ฑฐ๋ฅผ ํˆฌ๋ช…ํ•˜๊ฒŒ ์ œ์‹œํ•˜๋Š” ๊ฒƒ์ด ์žฅ๊ธฐ์  ์‹ ๋ขฐ ํ™•๋ณด์˜ ํ•ต์‹ฌ.
  • AI๋ฅผ ์ด์šฉํ•ด ๊ฒŒ์ž„์„ ์ถ”์ฒœํ•˜๋ ค๋ฉด ๋‹ค์Œ ์š”์†Œ๋“ค์„ ์ข…ํ•ฉ์ ์œผ๋กœ ๋ถ„์„ํ•ด์•ผ ํ•จ:
    • ์‚ฌ์šฉ์ž ์ทจํ–ฅ (์žฅ๋ฅด, ํ”Œ๋ ˆ์ด ์Šคํƒ€์ผ)
    • ๋ณด์œ  ๊ธฐ๊ธฐ (PC, ์ฝ˜์†”, ๋ชจ๋ฐ”์ผ)
    • ์ตœ์‹  ํŠธ๋ Œ๋“œ
    • ์†Œ์…œ ๋ฐ์ดํ„ฐ (์นœ๊ตฌ, ์ŠคํŠธ๋ฆฌ๋จธ ์ถ”์ฒœ)
    • ์ถ”์ฒœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (์ฝ˜ํ…์ธ  ๊ธฐ๋ฐ˜, ํ˜‘์—… ํ•„ํ„ฐ๋ง)
    • ํ• ์ธ ์ •๋ณด, ์—ฐ๋ น ๋“ฑ๊ธ‰ ๋“ฑ์˜ ์š”์†Œ ๊ณ ๋ ค
  • ๋˜ํ•œ, ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ˜์˜ํ•˜์—ฌ ์ง€์†์ ์œผ๋กœ ์ถ”์ฒœ ์‹œ์Šคํ…œ์„ ๊ฐœ์„ ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•จ.

2. ์„ ํƒ ์ด์œ 

  • ๊ตฌ๊ธ€์˜ Gemini AI๋Š” ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ๊ธฐ๋Šฅ(ํ…์ŠคํŠธ, ์ด๋ฏธ์ง€, ์Œ์„ฑ ๋“ฑ)์„ ์ง€์›ํ•˜๋ฉฐ, ๊ฐ•๋ ฅํ•œ **์ž์—ฐ์–ด ์ฒ˜๋ฆฌ(NLP)**์™€ ๋ฐ์ดํ„ฐ ๋ถ„์„ ๊ธฐ๋Šฅ์„ ์ œ๊ณต.
  • Gemini AI๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋‹จ์ˆœํ•œ ๊ฒŒ์ž„ ์ถ”์ฒœ์ด ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ์ž์™€ ๋Œ€ํ™”ํ•˜๋ฉฐ ์ทจํ–ฅ์„ ํŒŒ์•…ํ•˜๊ณ  ๋งž์ถคํ˜• ์ถ”์ฒœ์„ ์ œ๊ณตํ•˜๋Š” AI ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ• ๊ฐ€๋Šฅ.
  • ํŠนํžˆ, Google Cloud์˜ API์™€ ๊ฒฐํ•ฉํ•˜๋ฉด ๋” ์ •๊ตํ•œ ์ถ”์ฒœ ๋ชจ๋ธ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์–ด ์ง€์†์ ์ธ ๋ฐœ์ „์ด ๊ธฐ๋Œ€๋จ.
  • ๊ฒฐ๋ก ์ ์œผ๋กœ, Gemini AI๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋”์šฑ ์ •๋ฐ€ํ•˜๊ณ  ๊ฐœ์ธํ™”๋œ ๊ฒŒ์ž„ ์ถ”์ฒœ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์„ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ์Œ.

3. ๋Œ€์•ˆ ๋น„๊ต

๋Œ€์•ˆ ์žฅ์  ๋‹จ์ 
Microsoft Azure OpenAI + Game Pass ๋ฐ์ดํ„ฐ ์—ฐ๊ณ„ - Xbox Game Pass ๋ฐ์ดํ„ฐ์™€ ์—ฐ๊ณ„ ๊ฐ€๋Šฅ
- ํด๋ผ์šฐ๋“œ ๊ธฐ๋ฐ˜ ํ™•์žฅ์„ฑ ์šฐ์ˆ˜
- Microsoft ์ƒํƒœ๊ณ„ ๋‚ด์—์„œ ํ™œ์šฉ๋„๊ฐ€ ๋†’์Œ
- ๋ฒ”์šฉ์ ์ธ ์ถ”์ฒœ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์—๋Š” ํ•œ๊ณ„
Claude (Anthropic) - ๊ธด ๋ฌธ๋งฅ์„ ์œ ์ง€ํ•˜๋Š” ๋Œ€ํ™” ๋Šฅ๋ ฅ ์šฐ์ˆ˜
- ์นœํ™˜๊ฒฝ์ ์ด๊ณ  ์•ˆ์ „ํ•œ AI ์„ค๊ณ„
- ๊ฒŒ์ž„ ์ถ”์ฒœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌ์ถ•์—๋Š” ๋‹ค์†Œ ํ•œ๊ณ„
AWS S3 ํ™œ์šฉ ๋ฐฉ์•ˆ

1. ๋ฐฐ๊ฒฝ

  • ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์ฒจ๋ถ€ํŒŒ์ผ(์ด๋ฏธ์ง€) ๊ด€๋ฆฌ๋Š” ์—ฌ๋Ÿฌ ์ธก๋ฉด์—์„œ ์ค‘์š”ํ•จ:
    • ์‚ฌ์šฉ์ž ๊ฒฝํ—˜(UX) ํ–ฅ์ƒ: ์ด๋ฏธ์ง€๊ฐ€ ํฌํ•จ๋œ ๊ฒŒ์‹œ๊ธ€์€ ๊ฐ€๋…์„ฑ์„ ๋†’์ด๊ณ  ๋ชฐ์ž…๊ฐ์„ ์ œ๊ณต.
    • ์„œ๋ฒ„ ์„ฑ๋Šฅ ์ตœ์ ํ™”: ์ €์žฅ ๊ณต๊ฐ„๊ณผ ๋กœ๋”ฉ ์†๋„๋ฅผ ๊ณ ๋ คํ•œ ์ตœ์ ํ™” ํ•„์š”.
    • ๋ณด์•ˆ ๊ฐ•ํ™”: ๋ถˆ๋ฒ• ์ฝ˜ํ…์ธ  ํ•„ํ„ฐ๋ง ๋ฐ ์•…์„ฑ ์ฝ”๋“œ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ๋ณด์•ˆ ์กฐ์น˜ ํ•„์ˆ˜.
    • ๊ฒ€์ƒ‰ ์ตœ์ ํ™”: SEO ์ตœ์ ํ™”๋ฅผ ํ†ตํ•ด ์ ‘๊ทผ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Œ.
    • ๋ชจ๋ฐ”์ผ ๋Œ€์‘: ๋‹ค์–‘ํ•œ ๋„คํŠธ์›Œํฌ ํ™˜๊ฒฝ์—์„œ๋„ ์›ํ™œํ•œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ.
  • ํšจ๊ณผ์ ์ธ ์ด๋ฏธ์ง€ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์ด๋ฏธ์ง€ ์••์ถ•, AI ํ•„ํ„ฐ๋ง, CDN ํ™œ์šฉ ๋“ฑ์˜ ์ „๋žต์ด ํ•„์š”ํ•˜๋ฉฐ, ์ด๋ฅผ ์ž˜ ์ ์šฉํ•˜์—ฌ ์›ํ™œํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ ์šด์˜์„ ๋ชฉํ‘œ๋กœ ํ•จ.

2. ์„ ํƒ ์ด์œ 

  1. ๋Œ€์šฉ๋Ÿ‰ ์ด๋ฏธ์ง€ ์ €์žฅ ๊ฐ€๋Šฅ
  2. ๋น ๋ฅธ ์ด๋ฏธ์ง€ ๋กœ๋”ฉ ์†๋„
    • ์ „ ์„ธ๊ณ„ ์–ด๋””์—์„œ๋“  ๋น ๋ฅด๊ฒŒ ๋กœ๋”ฉ ๊ฐ€๋Šฅ
    • ๋ชจ๋ฐ”์ผ ๋ฐ ์ €์† ์ธํ„ฐ๋„ท ํ™˜๊ฒฝ์—์„œ๋„ ์›ํ™œํ•œ ์„œ๋น„์Šค ์ œ๊ณต
  3. ๋ฐ์ดํ„ฐ ์†์‹ค ์•ˆ์ „ ๋ฐ ๋ณด์•ˆ ๊ฐ•ํ™”
    • ์ž๋™ ๋ฐ์ดํ„ฐ ๋ณต์ œ: ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ ์„ผํ„ฐ์— ๋ณต์ œ ์ €์žฅํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์†์‹ค ๋ฐฉ์ง€
    • ์ ‘๊ทผ ์ œ์–ด ๊ฐ€๋Šฅ: ํผ๋ธ”๋ฆญ/ํ”„๋ผ์ด๋น— ์„ค์ •์„ ํ†ตํ•ด ํŠน์ • ์‚ฌ์šฉ์ž๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
  4. ๋น„์šฉ ์ ˆ๊ฐ ํšจ๊ณผ
    • ์‚ฌ์šฉ๋Ÿ‰ ๊ธฐ๋ฐ˜ ๊ณผ๊ธˆ์œผ๋กœ ๋ถˆํ•„์š”ํ•œ ๋น„์šฉ ์ ˆ๊ฐ
  5. ๊ฒฐ๋ก 
    • S3๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋ฏธ์ง€ ์ €์žฅ์ด ํŽธ๋ฆฌํ•˜๊ณ , ๋กœ๋”ฉ ์†๋„๊ฐ€ ๋น ๋ฅด๋ฉฐ, ๋ฐ์ดํ„ฐ ์†์‹ค ์œ„ํ—˜์ด ๋‚ฎ๊ณ , ๋ณด์•ˆ์ด ๋›ฐ์–ด๋‚˜๋ฉฐ, ๋น„์šฉ ์ ˆ๊ฐ ๊ฐ€๋Šฅ
    • ํŠนํžˆ, ๋งŽ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œํŒ์— ์ ์ ˆํ•œ ์†”๋ฃจ์…˜

3. ๋Œ€์•ˆ ๋น„๊ต

๋Œ€์•ˆ ์žฅ์  ๋‹จ์ 
Azure Blob Storage - ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ ํ™˜๊ฒฝ๊ณผ ์—ฐ๊ณ„ ์šฉ์ด - AWS ๋Œ€๋น„ ํ™•์žฅ์„ฑ๊ณผ ๊ธ€๋กœ๋ฒŒ ์ปค๋ฒ„๋ฆฌ์ง€ ๋ถ€์กฑ
- ๊ด€๋ฆฌ ์ฝ˜์†”์ด ๋‹ค์†Œ ๋ณต์žก
Firebase Storage - ๋ชจ๋ฐ”์ผ ์•ฑ๊ณผ์˜ ์—ฐ๋™ ์ตœ์ ํ™” - ๋Œ€๋Ÿ‰ ์ด๋ฏธ์ง€ ์ €์žฅ๋ณด๋‹ค๋Š” ๋ชจ๋ฐ”์ผ ์•ฑ ์ค‘์‹ฌ
- ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์ด ์ œํ•œ์ 
SSE(Server-Sent Events) ๊ธฐ๋ฐ˜์˜ ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ์‹œ์Šคํ…œ

1. SSE ๋„์ž… ๋ฐฐ๊ฒฝ

  • ์ดˆ๊ธฐ ์•Œ๋ฆผ ๊ธฐ๋Šฅ์€ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ 5๋ถ„๋งˆ๋‹ค ๋ฏธํ™•์ธ๋œ ์•Œ๋ฆผ์„ ์ด๋ฉ”์ผ๋กœ ์ „์†กํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„๋จ.
  • ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์€ ์‹ค์‹œ๊ฐ„์„ฑ์ด ๋ถ€์กฑํ•˜์—ฌ ์ฆ‰๊ฐ์ ์ธ ์•Œ๋ฆผ ์ œ๊ณต์ด ๋ถˆ๊ฐ€๋Šฅํ–ˆ์Œ.
  • ์ด๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด SSE(Server-Sent Events) ๊ธฐ๋ฐ˜์˜ ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ์‹œ์Šคํ…œ์„ ๋„์ž…ํ•˜๊ฒŒ ๋จ.

2. SSE ์„ ํƒ ์ด์œ 

  • ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด Short Polling, Long Polling, SSE, WebSocket ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ์ˆ ์„ ๊ฒ€ํ† ํ•œ ๊ฒฐ๊ณผ, SSE๊ฐ€ ๊ฐ€์žฅ ์ ํ•ฉํ•˜๋‹ค๊ณ  ํŒ๋‹จ๋จ.
  • SSE(Server-Sent Events) ์žฅ์ 
    โœ… ๋‹จ๋ฐฉํ–ฅ(one-way) ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ์ „์†ก
    โœ… ๊ธฐ์กด HTTP ํ”„๋กœํ† ์ฝœ์„ ํ™œ์šฉํ•˜๋ฏ€๋กœ ์„ค์ •์ด ๊ฐ„ํŽธ
    โœ… WebSocket๊ณผ ๋‹ฌ๋ฆฌ ์žฌ์—ฐ๊ฒฐ(์ž๋™ ๋ณต๊ตฌ) ๊ธฐ๋Šฅ ๋‚ด์žฅ
    โœ… ์•Œ๋ฆผ๊ณผ ๊ฐ™์ด ๋‹จ๋ฐฉํ–ฅ ์ „์†ก์ด ์ฃผ๋ฅผ ์ด๋ฃจ๋Š” ์„œ๋น„์Šค์— ์ ํ•ฉ

3. ๋Œ€์•ˆ ๋น„๊ต

๊ธฐ์ˆ  ๋™์ž‘ ๋ฐฉ์‹ ์žฅ์  ๋‹จ์ 
Short Polling ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ผ์ • ์ฃผ๊ธฐ๋งˆ๋‹ค ์„œ๋ฒ„์— ์š”์ฒญ ๊ตฌํ˜„์ด ๊ฐ„๋‹จํ•จ ๋ถˆํ•„์š”ํ•œ ์š”์ฒญ ์ฆ๊ฐ€๋กœ ๋ฆฌ์†Œ์Šค ๋‚ญ๋น„
Long Polling ์„œ๋ฒ„๊ฐ€ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ๊นŒ์ง€ ์‘๋‹ต์„ ์ง€์—ฐ ์‹ค์‹œ๊ฐ„์„ฑ ๊ฐœ์„  ๋‹ค์ˆ˜์˜ ์—ฐ๊ฒฐ ์œ ์ง€ ์‹œ ์„œ๋ฒ„ ๋ถ€๋‹ด ์ฆ๊ฐ€
WebSocket ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๊ฐ„ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ฒฐ ์œ ์ง€ ์Œ๋ฐฉํ–ฅ ํ†ต์‹  ๊ฐ€๋Šฅ ์„ค์ •์ด ๋ณต์žกํ•˜๋ฉฐ, HTTP/2 ํ™˜๊ฒฝ์—์„œ ์˜ค๋ฒ„ํ—ค๋“œ ์ฆ๊ฐ€ ๊ฐ€๋Šฅ

4. ๊ฒฐ๋ก 

  • ์•Œ๋ฆผ ์„œ๋น„์Šค๋Š” ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ๋‹จ๋ฐฉํ–ฅ ๋ฉ”์‹œ์ง€ ์ „์†ก์ด ์ฃผ๋œ ์—ญํ• ์„ ํ•จ.
  • WebSocket์˜ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ฒฐ ๊ธฐ๋Šฅ์ด ๋ถˆํ•„์š”ํ•˜๋ฉฐ, ๊ตฌํ˜„์ด ๊ฐ„๋‹จํ•œ SSE๊ฐ€ ์ตœ์ ์˜ ์„ ํƒ์ด์—ˆ์Œ.
์•Œ๋ฆผ ์‹œ์Šคํ…œ์— Redis Stream ์ ์šฉ

๋ฉ”์‹œ์ง€ ์˜์†์„ฑ๊ณผ ์‹ ๋ขฐ์„ฑ ํ™•๋ณด

  • ๊ธฐ์กด SSE๋งŒ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๋„คํŠธ์›Œํฌ ๋ฌธ์ œ๋‚˜ ์„œ๋ฒ„ ์žฅ์•  ์‹œ ์•Œ๋ฆผ์ด ์œ ์‹ค๋  ์ˆ˜ ์žˆ์Œ
  • Redis Stream์€ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€๋ฅผ ์ผ์‹œ์ ์œผ๋กœ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•˜์—ฌ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ์˜ ์‹ ๋ขฐ์„ฑ์„ ๋†’์ž„

์žฅ์•  ์ƒํ™ฉ ๋Œ€์‘

  • ์‚ฌ์šฉ์ž์˜ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์ด ๋Š๊ธฐ๊ฑฐ๋‚˜ ์„œ๋ฒ„์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ๋„ Stream์— ๋ฉ”์‹œ์ง€๊ฐ€ ๋ณด๊ด€๋˜์–ด ์žˆ์–ด ์žฌ์ ‘์† ์‹œ ๋ฏธ์ „์†ก๋œ ์•Œ๋ฆผ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ

์‹œ์Šคํ…œ ํ™•์žฅ์„ฑ

  • ํ–ฅํ›„ ์‹œ์Šคํ…œ์ด ํ™•์žฅ๋˜์–ด ๋‹ค์ค‘ WAS ํ™˜๊ฒฝ์—์„œ ์•Œ๋ฆผ์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๊ฒฝ์šฐ Redis Stream์„ ํ†ตํ•ด ๋ฉ”์‹œ์ง€ ํ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์—์„œ๋„ ์•ˆ์ •์ ์ธ ์•Œ๋ฆผ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅ

๋Œ€์•ˆ ๋น„๊ต

๊ธฐ์ˆ  ๋™์ž‘ ๋ฐฉ์‹ ์žฅ์  ๋‹จ์ 
Redis Pub/Sub ๊ตฌ๋…์ž๊ฐ€ ์žˆ์œผ๋ฉด ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฉ”์‹œ์ง€ ์ „์†ก ๋น ๋ฅธ ์‹ค์‹œ๊ฐ„ ๋ฉ”์‹œ์ง• ๊ตฌ๋…์ž๊ฐ€ ์—†์œผ๋ฉด ๋ฉ”์‹œ์ง€ ์œ ์‹ค
Kafka ๋กœ๊ทธ ๊ธฐ๋ฐ˜ ์ŠคํŠธ๋ฆฌ๋ฐ ๊ฐ•๋ ฅํ•œ ๋ฉ”์‹œ์ง€ ๋ณด์žฅ, ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ ์„ค์ •์ด ๋ณต์žกํ•˜๊ณ  ์šด์˜ ๋น„์šฉ์ด ๋†’์Œ
Redis Stream ๋ฉ”์‹œ์ง€ ์ €์žฅ + ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฉ”์‹œ์ง€ ์œ ์‹ค ๋ฐฉ์ง€, ์†Œ๋น„์ž ๊ทธ๋ฃน ์ง€์› Pub/Sub๋ณด๋‹ค ์•ฝ๊ฐ„์˜ ์„ค์ • ํ•„์š”

๊ฒฐ๋ก 

์•Œ๋ฆผ ์„œ๋น„์Šค์—์„œ๋Š” ๋ฉ”์‹œ์ง€ ์œ ์‹ค ๋ฐฉ์ง€๊ฐ€ ์ค‘์š”ํ•˜๋ฏ€๋กœ, ๋‹จ์ˆœ Pub/Sub๋ณด๋‹ค Redis Stream์ด ์ ํ•ฉํ–ˆ์Šต๋‹ˆ๋‹ค. Kafka๋Š” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ์šด์˜ ๋ณต์žก์„ฑ๊ณผ ๋น„์šฉ ๋ฌธ์ œ ๋ฐ ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ํ˜„์žฌ ๋ ˆ๋ฒจ์—์„œ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋˜์–ด ์˜ค๋ฒ„ ์—”์ง€๋‹ˆ์–ด๋ง ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ด์œ ๋“ค๋กœ Redis Stream์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿšจ Trouble Shooting

๊ฒŒ์ž„์ถ”์ฒœ- ํ”„๋กฌํ”„ํŠธ ๊ด€๋ จ ๋ณด์•ˆ ์œ„ํ—˜

๋ฌธ์ œ์ธ์‹

๊ฒŒ์ž„ ์ถ”์ฒœ ๊ธฐ๋Šฅ์ค‘ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์‘๋‹ต ๋ฐ›๋Š” ์ค‘ SQL ์ธ์ ์…˜ ์œ„ํ—˜์ด ์˜ˆ์ƒ๋จ

  • ๋ณด์•ˆ ์œ„ํ—˜ ๋ถ„์„

    String prompt = String.format("...์ถ”๊ฐ€์ ์ธ ์š”์ฒญ์€ %s ์•ผ", 
    userGamePreference.getExtraRequest());
    • ๋ฌธ์ œ์ :ย **extraRequest**๊ฐ€ ํ”„๋กฌํ”„ํŠธ์— ์ง์ ‘ ์‚ฝ์ž…๋˜์–ด ์•…์„ฑ ์ฝ”๋“œ ์‹คํ–‰ ๊ฐ€๋Šฅ
    • ์œ„ํ—˜: ํ”„๋กฌํ”„ํŠธ ์กฐ์ž‘์„ ํ†ตํ•œ ์‹œ์Šคํ…œ ๋ช…๋ น์–ด ์ฃผ์ž…, ๋ฐ์ดํ„ฐ ์œ ์ถœ ๋“ฑ์˜ ๊ณต๊ฒฉ ๊ฐ€๋Šฅ์„ฑ
  • ๊ฐœ์„  ๋ฐฉ์•ˆ

    • OWASP ์ธ์ฝ”๋”ฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ ์šฉ

      import org.owasp.encoder.Encode;
      
      String safeExtraRequest = Encode.forJava(extraRequest);
      • ๊ธฐ๋Šฅ: ํŠน์ˆ˜ ๋ฌธ์ž ์ž๋™ ์ด์Šค์ผ€์ดํ”„
      • ์˜ˆ๋ฐฉ ๊ณต๊ฒฉ: XSS, ๋ช…๋ น์–ด ์ฃผ์ž…
    • Bean Validation ํ†ตํ•ฉ

      public class UserGamePreferenceRequestDto {
      
          @Size(max = 100, message = "์ถ”๊ฐ€ ์š”์ฒญ์€ 100์ž ์ด๋‚ด๋กœ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”")
          @Pattern(regexp = "^[a-zA-Z0-9\\s]+$", message = "ํŠน์ˆ˜ ๋ฌธ์ž๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค")
          private String extraRequest;
      }
      
      public class GameRecommendContorller {
       @PostMapping
          public ResponseEntity<UserGamePreferenceResponseDto> createUserGamePreference(
                  @Valid @RequestBody UserGamePreferenceRequestDto requestDto,
                  @AuthenticationPrincipal CustomUserDetails customUserDetails
          ) {
      • ์žฅ์ : ์„ ์–ธ์  ๊ฒ€์ฆ ๊ทœ์น™ ๊ด€๋ฆฌ
  • ๊ธฐ๋Œ€ ํšจ๊ณผ

    • ์ž…๋ ฅ ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ๊ณผ ์œ ํšจ์„ฑ์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋˜์–ด, ์•…์˜์ ์ธ ๋ฐ์ดํ„ฐ ์ฃผ์ž… ์‹œ๋„๋ฅผ ์‚ฌ์ „์— ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ์Œ
    • SQL Injection๊ณผ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ณต๊ฒฉ ์œ„ํ—˜์ด ํ˜„์ €ํžˆ ๊ฐ์†Œํ•˜์—ฌ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ณด์•ˆ์„ฑ์ด ํ–ฅ์ƒ
    • ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ์ธก๋ฉด์—์„œ๋„ ๊ฐœ์„ ์ด ์ด๋ฃจ์–ด์ ธ, ์œ ํšจํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ ์ž…๋ ฅ์— ๋Œ€ํ•œ ์ฆ‰๊ฐ์ ์ธ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•จ์œผ๋กœ์จ ์‚ฌ์šฉ์ž ์นœํ™”์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ
ํŠน์ • ์œ ์ €์˜ ํŒ”๋กœ์›Œ ์กฐํšŒ ์‹œ ์„ฑ๋Šฅ ์ตœ์ ํ™”

๐Ÿ” ๊ธฐ์กด ์ฝ”๋“œ ๋ฌธ์ œ์ 

public List<FollowFindResponseDto> findFollowers(String email) {
    User followee = userRepository.findByEmail(email)
        .orElseThrow(() -> new ApiException(ErrorCode.USER_NOT_FOUND));

    if (followee.getUserStatus() == UserStatus.WITHDRAW) {
        throw new ApiException(ErrorCode.IS_WITHDRAWN_USER);
    } // ํƒˆํ‡ดํ•œ ํšŒ์› ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

    List<Follow> followListByFollowee = followRepository.findByFollowee(followee);

    List<User> followersByFollowee = followListByFollowee.stream()
        .map(Follow::getFollower)
        .filter(follower -> follower.getUserStatus() != UserStatus.WITHDRAW)
        .toList();

    return followersByFollowee.stream()
        .map(FollowFindResponseDto::toDto)
        .toList();
}

์œ„ ์ฝ”๋“œ์˜ ๋ฌธ์ œ์ ์€ FetchType.LAZY๋กœ ์ธํ•ด N+1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • Follow ์—”ํ‹ฐํ‹ฐ์—์„œ getFollower()๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ, ๊ฐ ํŒ”๋กœ์›Œ์— ๋Œ€ํ•œ ๋ณ„๋„์˜ ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋จ
  • ๊ฒฐ๊ณผ์ ์œผ๋กœ ํŒ”๋กœ์›Œ๊ฐ€ 1,000๋ช…์ผ ๊ฒฝ์šฐ ์ด 1,002๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒ (1๊ฐœ์˜ ์‚ฌ์šฉ์ž ์กฐํšŒ + 1๊ฐœ์˜ ํŒ”๋กœ์šฐ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ + 1,000๊ฐœ์˜ ํŒ”๋กœ์›Œ ์กฐํšŒ)

๐Ÿ’ก ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•: JPQL์„ ํ™œ์šฉํ•œ ์„ฑ๋Šฅ ์ตœ์ ํ™”

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด JPQL์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•œ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋„๋ก ์ˆ˜์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

@Query("SELECT NEW com.example.gamemate.domain.follow.dto.FollowFindResponseDto(f.follower.id, f.follower.nickname) " +
       "FROM Follow f " +
       "JOIN f.follower " +
       "WHERE f.followee.email = :email " +
       "AND f.follower.userStatus != 'WITHDRAW'")
List<FollowFindResponseDto> findFollowersDtoByFolloweeEmail(@Param("email") String email);

โœ… ์ตœ์ ํ™”๋œ ์ฝ”๋“œ์˜ ์žฅ์ 

  • ๋‹จ 2๊ฐœ์˜ ์ฟผ๋ฆฌ๋งŒ ์‹คํ–‰๋จ โ†’ ๊ธฐ์กด 1,002๊ฐœ โ†’ 2๊ฐœ
  • N+1 ๋ฌธ์ œ ํ•ด๊ฒฐ โ†’ JOIN์„ ํ†ตํ•ด ํ•œ ๋ฒˆ์— ๋ฐ์ดํ„ฐ ์กฐํšŒ
  • DTO๋กœ ์ง์ ‘ ๋งคํ•‘ โ†’ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ DTO๋กœ ๋ณ€ํ™˜

๐Ÿ“Š ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

image (7)

ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ๊ธฐ์กด ์ฝ”๋“œ ์ตœ์ ํ™”๋œ ์ฝ”๋“œ ์„ฑ๋Šฅ ๊ฐœ์„ ์œจ
ํŒ”๋กœ์›Œ 1,000๋ช… ๊ธฐ์ค€ 752ms (1,002๊ฐœ ์ฟผ๋ฆฌ) 7ms (2๊ฐœ ์ฟผ๋ฆฌ) 99% ์„ฑ๋Šฅ ๊ฐœ์„  ๐Ÿš€

๐Ÿ”Ž ๊ฒฐ๋ก 

JPQL์„ ํ™œ์šฉํ•œ ์ตœ์ ํ™”๋ฅผ ํ†ตํ•ด:

  • N+1 ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์—ฌ ์‹คํ–‰ ์‹œ๊ฐ„์„ 752ms์—์„œ 7ms๋กœ 99% ๋‹จ์ถ•
  • ๋ถˆํ•„์š”ํ•œ ์ฟผ๋ฆฌ๋ฅผ ์ œ๊ฑฐํ•˜์—ฌ DB ๋ถ€ํ•˜๋ฅผ ๋Œ€ํญ ๊ฐ์†Œ (1,002๊ฐœ โ†’ 2๊ฐœ)
  • DTO ์ง์ ‘ ๋งคํ•‘์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ตœ์ ํ™”

์ด๋Ÿฌํ•œ ์„ฑ๋Šฅ ๊ฐœ์„ ์„ ํ†ตํ•ด ํŒ”๋กœ์›Œ๊ฐ€ ๋งŽ์€ ์‚ฌ์šฉ์ž์˜ ํ”„๋กœํ•„ ์กฐํšŒ์‹œ์—๋„ ๋น ๋ฅธ ์‘๋‹ต ์†๋„๋ฅผ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.



[๐Ÿ“‹ ERD Diagram]

๐Ÿ“‹ ERD Diagram


๐ŸŒ Architecture

image (8)

๐Ÿ“† ์ผ์ • ๊ด€๋ฆฌ (WBS)

image


๐Ÿ“ Technologies & Tools ๐Ÿ“

Java 17 | SpringBoot 3.4.1 | MySql 8.0 | QueryDSL 5.0





About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages