Skip to content

Tak002/Spring-Chat-Backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

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

Repository files navigation

๐Ÿš€ Spring WebSocket Chat Server

STOMP + Redis Pub/Sub ๊ธฐ๋ฐ˜์˜ ์‹ค์‹œ๊ฐ„ ๋ฉ€ํ‹ฐ๋ฃธ ์ฑ„ํŒ… ์„œ๋ฒ„

Build Status Latest Release


๐Ÿ–ผ๏ธ Demo

์ฑ„ํŒ…๋ฐฉ ํ™”๋ฉด
์ฑ„ํŒ…๋ฐฉ ํ™”๋ฉด
ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด
ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด
๋กœ๊ทธ์ธ ํ™”๋ฉด
๋กœ๊ทธ์ธ ํ™”๋ฉด
ํ† ํฐ ๊ฒ€์ฆ ํ™”๋ฉด
ํ† ํฐ ๊ฒ€์ฆ ํ™”๋ฉด

โœจ Features

  • STOMP ๊ธฐ๋ฐ˜ ๋ฉ€ํ‹ฐ๋ฃธ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…
  • Redis Pub/Sub์„ ํ†ตํ•œ ์„œ๋ฒ„ ๊ฐ„ ๋ฉ”์‹œ์ง€ ๋™๊ธฐํ™”
  • Docker + GitHub Actions ๊ธฐ๋ฐ˜ ์ž๋™ ๋ฐฐํฌ
  • ์ฑ„ํŒ… ๊ธฐ๋ก ์ €์žฅ ๋ฐ ์กฐํšŒ API ์ œ๊ณต

๐Ÿ”ฎ Planned Features

  • Image, PDF ๊ฐ™์€ ํŒŒ์ผ๋„ ์†ก์ˆ˜์‹  ๊ฐ€๋Šฅ
  • JWT ์ธ์ฆ ๋ฐ WebSocket ์ธ์ฆ ์™„์„ฑ
  • ๋Œ€๊ทœ๋ชจ ํŠธ๋ž˜ํ”ฝ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ๋ฐ ์ตœ์ ํ™”
  • ํ…Œ์ŠคํŠธ ์ž๋™ํ™” (๋‹จ์œ„ / ํ†ตํ•ฉ / E2E)
  • ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ๋กœ๊น… ๊ฐœ์„ 
  • kubernetes ๋„์ž…์„ ํ†ตํ•œ ์›น์†Œ์ผ“ ๋ชจ๋“ˆ์˜ HPA

๐Ÿ“ฆ ๋ชจ๋“ˆ ๊ตฌ์กฐ

๐Ÿ”น chat-ws โ€“ ์‹ค์‹œ๊ฐ„ ๋ฉ”์‹œ์ง€ ์†ก์ˆ˜์‹ 

  • WebSocket ๊ธฐ๋ฐ˜ STOMP ๋ฉ”์‹œ์ง•
  • ๋ฉ€ํ‹ฐ ์ธ์Šคํ„ด์Šค ๊ฐ„ Redis Pub/Sub ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ
  • ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ๊ด€๋ฆฌ (์ž…์žฅ/ํ‡ด์žฅ, Heartbeat ๋“ฑ)

๐Ÿ”น chat-history โ€“ ๋Œ€ํ™” ๋‚ด์—ญ ์ €์žฅ ๋ฐ ์กฐํšŒ

  • ๋ฉ”์‹œ์ง€ ์ €์žฅ ๋ฐ ์กฐํšŒ API
  • PostgreSQL ๊ธฐ๋ฐ˜ ์˜์†์„ฑ ๊ด€๋ฆฌ
  • ๋ฐฉ ๋‹จ์œ„ ๋Œ€ํ™” ๋‚ด์—ญ ํŽ˜์ด์ง• ์กฐํšŒ
  • ๊ฒ€์ƒ‰ / ํ•„ํ„ฐ๋ง / ์‚ญ์ œ ๊ธฐ๋Šฅ ํ™•์žฅ ์˜ˆ์ •

๐Ÿ”น app-auth โ€“ ์ธ์ฆ ๋ฐ ํ† ํฐ ๊ด€๋ฆฌ

  • ํšŒ์›๊ฐ€์ž… ๋ฐ ๋กœ๊ทธ์ธ
  • JWT ํ† ํฐ ๋ฐœ๊ธ‰ / ๊ฒ€์ฆ
  • ํ–ฅํ›„ OAuth2, ์†Œ์…œ ๋กœ๊ทธ์ธ ํ™•์žฅ ์˜ˆ์ •

๐Ÿ”น app-service โ€“ ์„œ๋น„์Šค์˜ ์ฑ„ํŒ… ์™ธ ๊ธฐ๋Šฅ ๋ชจ์Œ

  • ๋ชจ์ž„ ์ƒ์„ฑ ๋ฐ ๊ด€๋ฆฌ ๋“ฑ์˜ ๊ธฐ๋Šฅ ์ˆ˜ํ–‰

๐Ÿ”น app-media โ€“ ๋ฉ€ํ‹ฐ๋ฏธ๋””์–ด ํŒŒ์ผ ์—…๋กœ๋“œ

  • ๋ฉ€ํ‹ฐ๋ฏธ๋””์–ด ์—…๋กœ๋“œ ๋ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
  • S3์— ์—…๋กœ๋“œ ํ›„, ์ž„์‹œ url๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๊ฐ€๋Šฅ

๐ŸŒฟ ๋ธŒ๋žœ์น˜ ์ „๋žต

๐Ÿ”ง ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ

  • ๋ธŒ๋žœ์น˜๋ช…: feat/๊ธฐ๋Šฅ๋ช…
  • ๊ฐ ๊ธฐ๋Šฅ์€ feat/๊ธฐ๋Šฅ๋ช… ๋ธŒ๋žœ์น˜์—์„œ ๊ฐœ๋ฐœ
  • ์™„๋ฃŒ ํ›„ main ๋ธŒ๋žœ์น˜๋กœ PR ์ƒ์„ฑ

๐Ÿงฉ ์ฝ”๋“œ ๋ฆฌ๋ทฐ ๋ฐ ํ†ตํ•ฉ

  • ๋Œ€์ƒ ๋ธŒ๋žœ์น˜: main
  • ๋ชจ๋“  PR์€ main์„ ๊ธฐ์ค€์œผ๋กœ ์ƒ์„ฑ
  • ์ฝ”๋“œ ๋ฆฌ๋ทฐ ๋ฐ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ ํ›„ ๋จธ์ง€

๐Ÿš€ ๋ฐฐํฌ ๋ฐ ์‹คํ™˜๊ฒฝ ํ…Œ์ŠคํŠธ

  • ๋ฐฐํฌ์šฉ ๋ธŒ๋žœ์น˜: production
  • main โ†’ production์œผ๋กœ ๋จธ์ง€ ์‹œ ๋ฐฐํฌ ์ง„ํ–‰
  • ํ™˜๊ฒฝ ์„ค์ •์ด๋‚˜ ๊ธด๊ธ‰ ์ˆ˜์ •์€ production์—์„œ ์ง์ ‘ ๊ฐ€๋Šฅ
  • ๋‹จ, production ๋ณ€๊ฒฝ์‚ฌํ•ญ์€ ๋ฐ˜๋“œ์‹œ main์œผ๋กœ PR ๋ฐ˜์˜

๐Ÿ” ๋ธŒ๋žœ์น˜ ํ๋ฆ„ ์˜ˆ์‹œ

1๏ธโƒฃ feat/๊ธฐ๋Šฅ๋ช… โ”€โ–ถ main           # ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ ํ›„ PR ๋ฐ ๋จธ์ง€
2๏ธโƒฃ main โ”€โ–ถ production            # ๋ฐฐํฌ ๋ฐ ์‹คํ™˜๊ฒฝ ํ…Œ์ŠคํŠธ
3๏ธโƒฃ production โ”€โ–ถ main            # ๋ฐฐํฌ ๊ด€๋ จ ์ˆ˜์ •์‚ฌํ•ญ ๋ฐ˜์˜
4๏ธโƒฃ production                    # ๋ฐฐํฌ ์‹คํ–‰

โš™๏ธ ๋ฐฐํฌ ๋ฐฉ์‹ (CI/CD)

๐Ÿงฑ ์ž๋™ํ™” ๋„๊ตฌ

  • GitHub Actions ๊ธฐ๋ฐ˜
  • main ๋˜๋Š” production ํ‘ธ์‹œ ์‹œ ์ž๋™ ๋นŒ๋“œ & ๋ฐฐํฌ

๐Ÿ”จ ๋นŒ๋“œ ๋‹จ๊ณ„

  • Gradle๋กœ chat-ws, chat-history JAR ์ƒ์„ฑ
  • Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ ํ›„ GitHub Container Registry๋กœ ํ‘ธ์‹œ (ํƒœ๊ทธ: latest, commit SHA)

๐Ÿš€ ๋ฐฐํฌ ๋‹จ๊ณ„

  • ์šด์˜ ์„œ๋ฒ„์— SSH ์ ‘์†
  • Docker Compose(base + prod)๋กœ ์„œ๋น„์Šค ๋ฌด์ค‘๋‹จ ์—…๋ฐ์ดํŠธ
  • Postgres, Redis ๋“ฑ ์ƒํƒœ ์„œ๋น„์Šค๋Š” ์œ ์ง€๋จ

๐Ÿ” ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๊ด€๋ฆฌ

  • GitHub Secrets์„ ํ†ตํ•ด ๋‹ค์Œ ์ •๋ณด ์ž๋™ ์ฃผ์ž…

    • API ๊ฒฝ๋กœ
    • ์ธ์ฆ ํ† ํฐ
    • CORS ํ—ˆ์šฉ ๋„๋ฉ”์ธ ๋“ฑ

๐Ÿ—‚๏ธ ๊ด€๋ จ ํŒŒ์ผ

๋ชฉ์  ํŒŒ์ผ ๊ฒฝ๋กœ
CI/CD ์›Œํฌํ”Œ๋กœ์šฐ .github/workflows/deploy.yml
Docker Compose (๊ธฐ๋ณธ ์„ค์ •) infra/docker-compose.base.yml
Docker Compose (์šด์˜ ํ™˜๊ฒฝ) infra/docker-compose.prod.yml
sequenceDiagram
    autonumber
    
    participant Client as ํด๋ผ์ด์–ธํŠธ<br/>(์›น ๋ธŒ๋ผ์šฐ์ €)
    participant WS as chat-ws<br/>(WebSocket ์„œ๋ฒ„)
    participant Redis as Redis<br/>(Pub/Sub)
    participant History as chat-history<br/>(๋ฉ”์‹œ์ง€ ์ €์žฅ ์„œ๋ฒ„)
    participant DB as PostgreSQL<br/>(๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค)

    Note over Client,DB: 1๏ธโƒฃ ์ดˆ๊ธฐ ์—ฐ๊ฒฐ ๋ฐ ํžˆ์Šคํ† ๋ฆฌ ๋กœ๋“œ
    
    Client->>+WS: WebSocket ์—ฐ๊ฒฐ (SockJS/STOMP)
    WS-->>-Client: ์—ฐ๊ฒฐ ํ™•์ธ (SessionConnected)
    
    Client->>+WS: SUBSCRIBE /topic/{roomId}
    WS-->>-Client: ๊ตฌ๋… ํ™•์ธ
    
    Client->>+History: GET /{roomId}/messages
    History->>+DB: SELECT * FROM chat_message<br/>WHERE room_id = ? AND is_deleted = false
    DB-->>-History: ๊ณผ๊ฑฐ ๋ฉ”์‹œ์ง€ ๋ชฉ๋ก
    History-->>-Client: ChatMessagesReceiveDto<br/>(๊ณผ๊ฑฐ ๋Œ€ํ™” ๋‚ด์—ญ)

    Note over Client,DB: 2๏ธโƒฃ ๋ฉ”์‹œ์ง€ ์†ก์ˆ˜์‹  ํ”Œ๋กœ์šฐ

    Client->>+WS: SEND /app/chat<br/>ChatMessageSendDto {sender, content, roomId}
    
    WS->>+Redis: PUBLISH chat-message<br/>ChatMessagePubSubDto {tempId, sender, content, roomId}
    
    Note over Redis: Redis Pub/Sub์œผ๋กœ<br/>๋ชจ๋“  ์ธ์Šคํ„ด์Šค์— ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ
    
    Redis-->>WS: chat-message ์ด๋ฒคํŠธ
    WS->>Client: SEND /topic/{roomId}<br/>ChatMessageReceiveDto {id: tempId, createdAt: null}
    Note over Client: ์ž„์‹œ ID๋กœ ๋ฉ”์‹œ์ง€ ์ฆ‰์‹œ ํ‘œ์‹œ<br/>(๋‚™๊ด€์  UI ์—…๋ฐ์ดํŠธ)
    
    Redis-->>+History: chat-message ์ด๋ฒคํŠธ<br/>RedisChatMessageSubscriber
    
    History->>+DB: INSERT INTO chat_message<br/>(sender, content, room_id)
    DB-->>-History: ์ €์žฅ ์™„๋ฃŒ<br/>(id, created_at, edited_at ์ž๋™ ์ƒ์„ฑ)
    
    History->>+Redis: PUBLISH chat-timestamp<br/>ChatTimestampPubSubDto {id, tempId, createdAt, editedAt}
    
    Redis-->>WS: chat-timestamp ์ด๋ฒคํŠธ
    WS->>-Client: SEND /topic/{roomId}<br/>ChatTimestampReceiveDto {id, tempId, createdAt, editedAt}
    
    Note over Client: tempId๋ฅผ ์‹ค์ œ id๋กœ ๊ต์ฒด<br/>ํƒ€์ž„์Šคํƒฌํ”„ ์—…๋ฐ์ดํŠธ

    Note over Client,DB: 3๏ธโƒฃ ๋ฉ€ํ‹ฐ ์ธ์Šคํ„ด์Šค ๋™๊ธฐํ™”

    Redis-->>WS: chat-message ์ด๋ฒคํŠธ
    Note over WS: ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค์˜<br/>WebSocket ํด๋ผ์ด์–ธํŠธ๋“ค
    WS->>Client: SEND /topic/{roomId}<br/>๋™์ผํ•œ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ

    Note over Client,DB: 4๏ธโƒฃ ์—ฐ๊ฒฐ ์ข…๋ฃŒ

    Client->>WS: UNSUBSCRIBE /topic/{roomId}
    Client->>WS: DISCONNECT
    WS-->>Client: SessionDisconnect ์ด๋ฒคํŠธ
Loading

About

A practice project for building real-time chat features.

Resources

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •