Skip to content

ASPILGI/devlog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

63 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Devlog โ€“ JWT ๊ธฐ๋ฐ˜ ์ธ์ฆ/๊ถŒํ•œ ๋ธ”๋กœ๊ทธ ๋ฐฑ์—”๋“œ API

Java / Spring Boot ๊ธฐ๋ฐ˜์œผ๋กœ JWT ์ธ์ฆยท์ธ๊ฐ€, ๊ถŒํ•œ ๋ถ„๊ธฐ, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ, ๊ทธ๋ฆฌ๊ณ  Docker ๊ธฐ๋ฐ˜ CI/CD ๋ฐฐํฌ๊นŒ์ง€ ์‹ค๋ฌด ๊ธฐ์ค€์œผ๋กœ ์„ค๊ณ„ยท๊ตฌํ˜„ํ•œ ๋ฐฑ์—”๋“œ ์ค‘์‹ฌ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ

๐Ÿ”น Overview (ํ•œ๋ˆˆ ์š”์•ฝ)

  • JWT Access / Refresh Token ์ธ์ฆ ๊ตฌ์กฐ ์ง์ ‘ ์„ค๊ณ„
  • Spring Security ํ•„ํ„ฐ โ†” Service ๊ณ„์ธต ์ฑ…์ž„ ๋ถ„๋ฆฌ
  • ์ธ์ฆ ๊ถŒํ•œ๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๊ถŒํ•œ ๋ถ„๋ฆฌ ์„ค๊ณ„
  • ์‹ค๋ฌด ๊ธฐ์ค€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ยท ํŠธ๋žœ์žญ์…˜ ํŒจํ„ด ์ ์šฉ
  • Docker + GitHub Actions ๊ธฐ๋ฐ˜ ์ž๋™ ๋ฐฐํฌ ํ™˜๊ฒฝ ๊ตฌ์ถ•
  • ์ตœ์†Œ UI๋ฅผ ํ†ตํ•œ ์ธ์ฆยท๊ถŒํ•œ ์ •์ฑ… ์‹ค์ œ ๋™์ž‘ ๊ฒ€์ฆ

๐Ÿ‘‰ UI ๊ตฌํ˜„์ด ์•„๋‹Œ ๋ฐฑ์—”๋“œ ์„ค๊ณ„์™€ ์šด์˜ ํ™˜๊ฒฝ ๊ฒ€์ฆ์— ์ดˆ์ ์„ ๋‘” ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค.


๐ŸŒ Devlog (AWS ๊ธฐ๋ฐ˜ ์šด์˜ ์ค‘)

๐Ÿ‘‰ https://aspilgi.com

  • EC2 + Nginx + HTTPS ์ ์šฉ
  • ์‹ค์ œ ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ ์ธ์ฆ ํ๋ฆ„ ํ™•์ธ ๊ฐ€๋Šฅ

๊ธฐ์ˆ  ์Šคํƒ

Backend

  • Java 17
  • Spring Boot 3.x
  • Spring Security
  • JPA (Hibernate)
  • MariaDB, Flyway
  • JWT (Access / Refresh Token)

Infra / DevOps

  • AWS EC2 (Ubuntu)
  • Docker / Docker Compose
  • Nginx (Reverse Proxy)
  • GitHub Actions
  • GitHub Container Registry (GHCR)
  • Self-hosted GitHub Actions Runner

Test / Validation

  • IntelliJ HTTP Client (auth.http)
  • React (Minimal UI, ๊ฒ€์ฆ ๋ชฉ์ )

์•„ํ‚คํ…์ฒ˜ ๊ฐœ์š”

Client
  โ†“
Nginx (Reverse Proxy)
  โ†“
Spring Boot API (Docker)
  โ†“
MariaDB (Docker)

Controller โ†’ Service โ†’ Repository  
  • Service ๊ณ„์ธต:
    • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง
    • ๊ถŒํ•œ ๊ฒ€์‚ฌ
    • ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ๋‹ด๋‹น
  • Controller ๊ณ„์ธต:
    • ์š”์ฒญ/์‘๋‹ต ์—ญํ• ์— ์ง‘์ค‘

๊ณตํ†ต ์„ค๊ณ„

  • ์ธ์ฆ/์ธ๊ฐ€: JWT + Spring Security
  • ๋น„์ฆˆ๋‹ˆ์Šค ์˜ˆ์™ธ: BusinessException + ErrorCode
  • ์‘๋‹ต ํฌ๋งท: ApiResponse
  • ์ „์—ญ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ: GlobalExceptionHandler

์ธ์ฆ / ๊ถŒํ•œ ์„ค๊ณ„

JWT๋ฅผ ์„ ํƒํ•œ ์ด์œ 

  • Stateless ๊ตฌ์กฐ๋กœ ์„œ๋ฒ„ ํ™•์žฅ์„ฑ ํ™•๋ณด
  • API ์ค‘์‹ฌ ์„œ๋น„์Šค ๊ตฌ์กฐ์— ์ ํ•ฉ
  • ํ”„๋ก ํŠธ์—”๋“œ / ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ๊ณผ ํ˜ธํ™˜์„ฑ ์šฐ์ˆ˜

Access / Refresh Token ๋ถ„๋ฆฌ ์ด์œ 

  • Access Token: ์งง์€ ์ˆ˜๋ช… โ†’ ํƒˆ์ทจ ํ”ผํ•ด ์ตœ์†Œํ™”
  • Refresh Token:
    • DB์— ์ €์žฅ
    • ๊ฐ•์ œ ๋กœ๊ทธ์•„์›ƒ ๋ฐ ์žฌ๋ฐœ๊ธ‰ ์ œ์–ด ๊ฐ€๋Šฅ

์„ธ์…˜ ๊ธฐ๋ฐ˜ ์ธ์ฆ ๋ฐฉ์‹๋„ ๊ฒ€ํ† ํ–ˆ์œผ๋‚˜, ์„œ๋ฒ„ ์ˆ˜ํ‰ ํ™•์žฅ ์‹œ ์„ธ์…˜ ๊ณต์œ  ๋น„์šฉ์„ ์ค„์ด๊ธฐ ์œ„ํ•ด JWT ๋ฐฉ์‹์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.


์ธ์ฆ ํ๋ฆ„ ์ƒ์„ธ

๋กœ๊ทธ์ธ

  • POST /api/v1/users/login
  • AccessToken + RefreshToken ๋ฐœ๊ธ‰
  • RefreshToken์€ DB ์ €์žฅ (์œ ์ €๋‹น 1๊ฐœ)

AccessToken ์‚ฌ์šฉ

  • Authorization: Bearer {accessToken}
  • JwtAuthenticationFilter์—์„œ ๊ฒ€์ฆ ํ›„ SecurityContext์— ์‚ฌ์šฉ์ž ์ •๋ณด ์ €์žฅ

ํ† ํฐ ์žฌ๋ฐœ๊ธ‰

  • POST /api/v1/users/reissue
  • RefreshToken ๊ฒ€์ฆ ํ›„ AccessToken๋งŒ ์žฌ๋ฐœ๊ธ‰
  • Refresh Token์ด ์œ ํšจํ•˜์ง€ ์•Š์œผ๋ฉด ์žฌ๋กœ๊ทธ์ธ ์œ ๋„

๋กœ๊ทธ์•„์›ƒ

  • POST /api/v1/users/logout
  • RefreshToken DB ์‚ญ์ œ
  • ๊ธฐ์กด AccessToken์€ ๋งŒ๋ฃŒ ์‹œ๊นŒ์ง€ ์œ ํšจ (Stateless)

๊ถŒํ•œ ์ฒ˜๋ฆฌ ์ „๋žต

์ธ์ฆ ์—ฌ๋ถ€

  • Spring Security ํ•„ํ„ฐ ๋‹จ๊ณ„์—์„œ ์ฒ˜๋ฆฌ
  • ์ธ์ฆ ์‹คํŒจ ์‹œ 401 ๋ฐ˜ํ™˜

๋น„์ฆˆ๋‹ˆ์Šค ๊ถŒํ•œ (์ž‘์„ฑ์ž ์ฒดํฌ)

  • Service ๊ณ„์ธต์—์„œ ์ง์ ‘ ๊ฒ€์‚ฌ
  • ์ž‘์„ฑ์ž ๋ถˆ์ผ์น˜ ์‹œ AccessDeniedException ๋ฐœ์ƒ
  • GlobalExceptionHandler์—์„œ 403์œผ๋กœ ์‘๋‹ต

์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ „๋žต

๋น„์ฆˆ๋‹ˆ์Šค ์˜ˆ์™ธ

  • Service ๊ณ„์ธต์—์„œ BusinessException

๊ฒ€์ฆ ์˜ค๋ฅ˜

  • @Valid ์‹คํŒจ ์‹œ MethodArgumentNotValidException

๊ถŒํ•œ ์˜ค๋ฅ˜

  • Service ๊ณ„์ธต: AccessDeniedException
  • Security ํ•„ํ„ฐ ๋‹จ๊ณ„:
    • AuthenticationEntryPoint
    • AccessDeniedHandler

Security ํ•„ํ„ฐ ๋‹จ๊ณ„ ์˜ˆ์™ธ์™€ ์„œ๋น„์Šค ๊ณ„์ธต ์˜ˆ์™ธ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ์˜ˆ์™ธ ํ๋ฆ„์„ ๋ช…ํ™•ํžˆ ํ–ˆ์Šต๋‹ˆ๋‹ค.


HTTP ์ƒํƒœ ์ฝ”๋“œ ์ •์ฑ…

์ƒํƒœ ์ฝ”๋“œ ์˜๋ฏธ
400 ์ž˜๋ชป๋œ ์š”์ฒญ
401 ์ธ์ฆ ์‹คํŒจ
403 ๊ถŒํ•œ ์—†์Œ
404 ๋ฆฌ์†Œ์Šค ์—†์Œ
409 ์ค‘๋ณต ๋ฐ์ดํ„ฐ
500 ์„œ๋ฒ„ ์˜ค๋ฅ˜

ํŠธ๋žœ์žญ์…˜ ์„ค๊ณ„

  • ํŠธ๋žœ์žญ์…˜์€ Service ๊ณ„์ธต์—์„œ ๊ด€๋ฆฌ
  • ์กฐํšŒ ๋กœ์ง์€ @Transactional(readOnly = true) ์ ์šฉ
  • ์“ฐ๊ธฐ / ์ฝ๊ธฐ ์ฑ…์ž„ ๋ถ„๋ฆฌ

์„ค๊ณ„ ์ด์œ 

  • ๋ถˆํ•„์š”ํ•œ ๋ณ€๊ฒฝ ๊ฐ์ง€ ๋น„์šฉ ๊ฐ์†Œ
  • ์‹ค๋ฌด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„ ๊ธฐ์ค€ ์ ์šฉ

API ๋ชฉ๋ก

User

  • POST /api/v1/users/signup
  • POST /api/v1/users/login
  • GET /api/v1/users/me
  • POST /api/v1/users/reissue
  • POST /api/v1/users/logout

Post

  • POST /api/v1/posts
  • GET /api/v1/posts/{id}
  • GET /api/v1/posts?page=0&size=10
  • PUT /api/v1/posts/{id}
  • DELETE /api/v1/posts/{id}

Comment

  • POST /api/v1/posts/{postId}/comments
  • GET /api/v1/posts/{postId}/comments
  • PUT /api/v1/posts/{postId}/comments/{commentId}
  • DELETE /api/v1/posts/{postId}/comments/{commentId}

CI/CD & Deployment

๋ชฉํ‘œ

SSH ์—†์ด, main ๋ธŒ๋žœ์น˜ push๋งŒ์œผ๋กœ๋„ ์ž๋™ ๋ฐฐํฌ

๋ฐฐํฌ ๊ตฌ์กฐ

git push (main)
   โ†“
GitHub Actions
   - Docker Image Build
   - GHCR Push
   โ†“
Self-hosted Runner (EC2)
   - docker compose pull
   - docker compose up -d --force-recreate
   โ†“
Production ๋ฐ˜์˜

ํŠน์ง•

  • scp / ssh ๊ธฐ๋ฐ˜ ์ˆ˜๋™ ๋ฐฐํฌ ์ œ๊ฑฐ
  • ์ด๋ฏธ์ง€ ๋‹จ์œ„ ๋ฐฐํฌ๋กœ ์„œ๋ฒ„ ์ƒํƒœ ์ผ๊ด€์„ฑ ํ™•๋ณด
  • ์ปจํ…Œ์ด๋„ˆ ์žฌ์ƒ์„ฑ(--force-recreate)์œผ๋กœ ๋ฐฐํฌ ๋ฐ˜์˜ ๋ณด์žฅ
  • Spring Boot Actuator /actuator/health ๋กœ ๋ฐฐํฌ ์„ฑ๊ณต ์—ฌ๋ถ€ ๊ฒ€์ฆ
curl -I http://127.0.0.1:8080/actuator/health
# HTTP/1.1 200 OK

DB Migration (Flyway)

์šด์˜ ํ™˜๊ฒฝ์—์„œ ddl-auto=create/update๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ,
Flyway ๊ธฐ๋ฐ˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์œผ๋กœ DB ์Šคํ‚ค๋งˆ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • spring.jpa.hibernate.ddl-auto=validate ๊ณ ์ •
  • ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ์€ Flyway ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ๋กœ๋งŒ ์ˆ˜ํ–‰
  • Docker Compose ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋„ ์•ฑ ๊ธฐ๋™ ์‹œ ์ž๋™ migrate

ํ…Œ์ŠคํŠธ ๋ฐ ๊ฒ€์ฆ ๋ฐฉ์‹

  • IntelliJ HTTP Client(auth.http)๋กœ ์ธ์ฆยท๊ถŒํ•œยทCRUD ์‹œ๋‚˜๋ฆฌ์˜ค ๊ฒ€์ฆ
  • ์ธ์ฆ ์‹คํŒจ(401), ๊ถŒํ•œ ์‹คํŒจ(403) ์ผ€์ด์Šค ํฌํ•จ
  • ์š”์ฒญ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๊ด€๋ฆฌ

Minimal UI๋ฅผ ํ†ตํ•œ ๊ฒ€์ฆ

  • ๋ชฉ์ :
    • JWT ์ธ์ฆ ํ๋ฆ„ ๊ฒ€์ฆ
    • ๊ถŒํ•œ ์ œ์–ด ์ •์ฑ… ์‹ค์ œ ๋™์ž‘ ํ™•์ธ
  • ๋ชจ๋“  ๊ถŒํ•œ ํŒ๋‹จ์€ ๋ฐฑ์—”๋“œ์—์„œ ์ˆ˜ํ–‰
  • ํ”„๋ก ํŠธ์—”๋“œ๋Š” UX ๋ชฉ์ ์˜ ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง๋งŒ ๋‹ด๋‹น

ํ–ฅํ›„ ๊ฐœ์„  ์‚ฌํ•ญ

  • ์ข‹์•„์š” ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ๋ฐ ์‚ฌ์šฉ์ž ๋ฐ˜์‘ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ
  • ๊ฒ€์ƒ‰ ๋ฐ ํŽ˜์ด์ง• ๊ณ ๋„ํ™”
  • ์šด์˜ ํ™˜๊ฒฝ ๊ณ ๋„ํ™”
    • Refresh Token ์ €์žฅ์†Œ ํ™•์žฅ ์‹œ ์บ์‹œ ๋„์ž… ๊ฒ€ํ†  (ํŠธ๋ž˜ํ”ฝ ์ฆ๊ฐ€ ๋Œ€๋น„)
    • ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ๊ตฌ์กฐ(Blue/Green) ์ ์šฉ

About

No description or website provided.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors