์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[์€ผ] ํ™”๋ฉด์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ”๋€Œ์–ด์•ผ ํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์„ ํ•ด๊ฒฐํ•ด๋ณด์ž (1) ๋ฐฑ์—”๋“œ : WebSocket ๊ตฌํ˜„

๋ณธ๋ฌธ

728x90
ํด๋ผ์ด์–ธํŠธ์˜ ํ™”๋ฉด์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ”๋€Œ๋Š” ์š”๊ตฌ์‚ฌํ•ญ

๋ถ€๋ถ€ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์—ฐ๊ฒฐํ•˜๊ธฐ, ์‹œ์ž‘ํ•˜๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋‹ค๋ฅธ ๋ฐฐ์šฐ์ž์˜ ํ™”๋ฉด์ด ๋ฐ”๋€Œ์–ด์•ผ ํ•œ๋‹ค

 

 


 

 

๋‹ค์–‘ํ•œ ๋ฐฉ์‹ ๋น„๊ต 
WebSocket ์„ ํƒํ•จ

 
WebSocket
์„œ๋ฒ„์™€์˜ ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. 
 
HTTP Polling
ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ฃผ๊ธฐ์ ์œผ๋กœ ์„œ๋ฒ„์—๊ฒŒ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์ด๋‹ค.
 
Server-Sent Events(SSE)
์„œ๋ฒ„์™€ ํ•œ ๋ฒˆ ์—ฐ๊ฒฐ์„ ๋งบ๊ณ  ๋‚˜๋ฉด ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ์„œ๋ฒ„์—์„œ ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†ก๋ฐ›๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ๋‹จ๋ฐฉํ–ฅ ํ†ต์‹ ์ด๋‹ค.

 

 

       
  WebSocket SSE HTTP Polling
ํ†ต์‹  ๋ฐฉํ–ฅ ์–‘๋ฐฉํ–ฅ ๋‹จ๋ฐฉํ–ฅ (์„œ๋ฒ„ → ํด) ๋‹จ๋ฐฉํ–ฅ (์„œ๋ฒ„ → ํด)
์—ฐ๊ฒฐ ์œ ์ง€ ๋ฐฉ์‹ ์ง€์† ์—ฐ๊ฒฐ ์ง€์† ์—ฐ๊ฒฐ ์—ฐ๊ฒฐ-์‘๋‹ต-์žฌ์—ฐ๊ฒฐ ๋ฐ˜๋ณต
๋ธŒ๋ผ์šฐ์ € ์ง€์› ๊ฑฐ์˜ ๋ชจ๋‘ ์ผ๋ถ€ IE ๋ฏธ์ง€์› ๊ฑฐ์˜ ๋ชจ๋‘
์„œ๋ฒ„ ๋ถ€ํ•˜ ๋‚ฎ์Œ ๋‚ฎ์Œ ๋†’์Œ
์ง€์—ฐ ์‹œ๊ฐ„ ๋งค์šฐ ๋‚ฎ์Œ ๋‚ฎ์Œ ์ค‘๊ฐ„~๋†’์Œ
๊ตฌํ˜„ ๋ณต์žก๋„ ์ค‘๊ฐ„ ์‰ฌ์›€ ์‰ฌ์›€

 

 

์ž‘๋™ ๋กœ์ง

 

1. ๋กœ๊ทธ์ธ ์™„๋ฃŒ ํ›„ ์ž„์‹œ ํŽ˜์ด์ง€
- ๋กœ๊ทธ์ธ๊ณผ ๋™์‹œ์— ์ƒํƒœ ๋ฆฌํ„ด

2. ์œ ์ €์ •๋ณด๋“ฑ๋ก ํŽ˜์ด์ง€
- ์‚ฌ์šฉ์ž๊ฐ€ ์œ ์ €์ •๋ณด ๋“ฑ๋ก์„ ์™„๋ฃŒํ•˜๋ฉด
์„œ๋ฒ„์—์„œ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์•Œ๋ฆฐ๋‹ค

3. ๋ถ€๋ถ€์ฝ”๋“œํ™•์ธ ํŽ˜์ด์ง€
- ์‚ฌ์šฉ์ž๊ฐ€ ๋ถ€๋ถ€ ์—ฐ๊ฒฐ์„ ์™„๋ฃŒํ•˜๋ฉด {์œ ์ผํ•œ ์ž„์‹œ ID๊ฐ’ : ์œ ์ €์•„์ด๋”” 2๊ฐœ ์ •๋ณด}๊ฐ€ ๋ ˆ๋””์Šค์— ์ €์žฅ๋œ๋‹ค.
- ์ด๋•Œ ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ธ์ฆํ•˜๋ฉด
๋ฐฐ์šฐ์ž๋„ ํ™”๋ฉด์ด ์ž๋™์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์•Œ๋ฆฐ๋‹ค.

4. ๋ถ€๋ถ€์ •๋ณด๋“ฑ๋ก ํŽ˜์ด์ง€
- ์‚ฌ์šฉ์ž๊ฐ€ ๋ถ€๋ถ€ ์ •๋ณด ๋“ฑ๋ก ๋ˆ„๋ฅด๋ฉด
์ด๋•Œ ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ธ์ฆํ•˜๋ฉด
๋ฐฐ์šฐ์ž๋„ ํ™”๋ฉด์ด ์ž๋™์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์•Œ๋ฆฐ๋‹ค.

5. ํ™ˆ ํŽ˜์ด์ง€
 
 
 
 
 


WebSocket ํ”„๋กœํ† ์ฝœ

 

ํ”„๋กœํ† ์ฝœ ๋‹จ๊ณ„

1. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— WebSocket ์—ฐ๊ฒฐ์„ ์š”์ฒญํ•˜๋Š” ๋‹จ๊ณ„

2. ์—ฐ๊ฒฐ์ด ์„ค์ •๋œ ํ›„์— ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ตํ™˜๋˜๋Š” ๋‹จ๊ณ„

 

1. ์˜คํ”„๋‹ ํ•ธ๋“œ์…ฐ์ดํฌ

HTTP ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹œ์ž‘๋˜์ง€๋งŒ, ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ WebSocket ์—ฐ๊ฒฐ๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋ ค๋Š” ์˜๋„๋ฅผ ๋ช…ํ™•ํžˆ ํ•ด์•ผ ํ•œ๋‹ค.

 

- ํด๋ผ์ด์–ธํŠธ ์ธก : ์—ฐ๊ฒฐ  ์š”์ฒญ ํ—ค๋” 

  • 1) Upgrade : websocket
    • ์„œ๋ฒ„๊ฐ€ WebSocket ์—ฐ๊ฒฐ์„  ํ—ˆ์šฉํ•˜๋„๋ก ์œ ๋„
  • 2) Connection : Upgrade   
    • ํŠน์ •ํ•œ ์—ฐ๊ฒฐ ๊ด€๋ จ ํ—ค๋”๋ฅผ ์ง€์ •ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋จ
  • 3) Sec-WebSocket-Key
    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ด๋Š”  ์ž„์˜์˜ Base64 ์ธ์ฝ”๋”ฉ๋œ ๊ฐ’
    • ์„œ๋ฒ„๊ฐ€ ์‘๋‹ตํ•  ๋•Œ, ,Sec-WebSocket-Accept ํ—ค๋”์— ํฌํ•จ๋œ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋จ
  • 4) Sec-WebSocket-Version
    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ง€์›ํ•˜๋Š” WebSocket ํ”„๋กœํ† ์ฝœ์˜ ๋ฒ„์ „์„  ์ง€์ •ํ•˜๋Š” ํ—ค๋” 
  • 5) Origin
    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฐ๊ฒฐ์„  ์‹œ๋„ํ•˜๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ถœ์ฒ˜๋ฅผ ๋ช…์‹œ 

 

- ์„œ๋ฒ„ : ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์„ ๋ฐ›์•„๋“ค์ด๊ณ , 101 Switching Protocols ์ƒํƒœ ์ฝ”๋“œ๋กœ ์‘๋‹ตํ•˜์—ฌ ์—ฐ๊ฒฐ์„ WebSocket ํ”„๋กœํ† ์ฝœ๋กœ ์—…๊ทธ๋ ˆ์ด๋“œ

 

  • HTTP/1.1 101 Switching Protocols
    • ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์˜ WebSocket ์š”์ฒญ์„ ์ˆ˜๋ฝํ•˜๊ณ  ์—ฐ๊ฒฐ์„ ์—…๊ทธ๋ ˆ์ด๋“œํ•œ๋‹ค๋Š” ์‘๋‹ต ์ƒํƒœ ์ฝ”๋“œ
  • Upgrade: websocket
    • ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ˆ˜๋ฝํ•˜๊ณ , HTTP ์—ฐ๊ฒฐ์„ WebSocket ํ”„๋กœํ† ์ฝœ๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ–ˆ์Œ์„ ๋ช…์‹œ
  • Connection: Upgrade
    • ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์— ๋”ฐ๋ผ ์—ฐ๊ฒฐ์„ ์—…๊ทธ๋ ˆ์ด๋“œํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋ƒ„ 
  • Sec-WebSocket-Accept
    • ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์˜ Sec-WebSocket-Key์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ๊ณ„์‚ฐํ•œ ์‘๋‹ต ๊ฐ’
    • ํด๋ผ์ด์–ธํŠธ๋Š” ์ด ๊ฐ’์„ ํ†ตํ•ด ์„œ๋ฒ„๊ฐ€ ์ •์ƒ์ ์œผ๋กœ WebSocket ์—ฐ๊ฒฐ์„ ์ค€๋น„ํ–ˆ์Œ์„ ํ™•์ธํ•จ. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ „์†กํ•œ Sec-WebSocket-Key์— ํŠน์ •ํ•œ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋จ

 

 

๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹ 

- ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ : UTF-8 ์ธ์ฝ”๋”ฉ ๋ฌธ์ž์—ด

- ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ : ์ด๋ฏธ์ง€ & ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ 

 

2. ํด๋กœ์ง• ํ•ธ๋“œ์…ฐ์ดํฌ  

- ํด๋ผ์ด์–ธํŠธ ๋˜๋Š” ์„œ๋ฒ„ ์ธก: ์ข…๋ฃŒ ์š”์ฒญ (Close Request)

ํด๋ผ์ด์–ธํŠธ ๋˜๋Š” ์„œ๋ฒ„๊ฐ€ close ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋ƒ„

์ข…๋ฃŒ ๋ฉ”์‹œ์ง€๋Š” ํ”„๋ ˆ์ž„์œผ๋กœ ์ „๋‹ฌ๋˜๋ฉฐ, HTTP ํ—ค๋”๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Œ

  • Close Code: ์—ฐ๊ฒฐ์„ ์ข…๋ฃŒํ•˜๋Š” ์ด์œ ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” 2๋ฐ”์ดํŠธ ์ˆซ์ž ์ฝ”๋“œ
  • Reason (์„ ํƒ): ์—ฐ๊ฒฐ ์ข…๋ฃŒ์˜ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ํ…์ŠคํŠธ ๋ฌธ์ž์—ด 

- ์„œ๋ฒ„ ์ธก: ์ข…๋ฃŒ ์‘๋‹ต (Close Response)

์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์˜ ์ข…๋ฃŒ ์š”์ฒญ์„ ์ˆ˜๋ฝํ•˜๊ณ  ์‘๋‹ต์„ ๋ณด๋‚ผ ๋•Œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ close ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†ก

 

 

https://datatracker.ietf.org/doc/html/rfc6455

 

RFC 6455: The WebSocket Protocol

The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code. The security model used for this is the origin-based security mode

datatracker.ietf.org

 

 

WebSocket ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

 

1. WebSocket Upgrade, Connection ํ—ค๋” Nginx์—์„œ ํ—ˆ์šฉํ•˜๋„๋ก ์ฒ˜๋ฆฌ 

    # WebSocket ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์„ค์ •
    location /back/api/ws/ {
        proxy_pass http://127.0.0.1:8080;  # WebSocket ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ๋กœ์ปฌ ํฌํŠธ
        proxy_http_version 1.1;  # WebSocket ์—ฐ๊ฒฐ์— ํ•„์š”ํ•œ HTTP ๋ฒ„์ „
        proxy_set_header Upgrade $http_upgrade;  # WebSocket Upgrade ํ—ค๋” ์ฒ˜๋ฆฌ
        proxy_set_header Connection 'upgrade';  # WebSocket ์—ฐ๊ฒฐ์„ ์œ„ํ•œ Connection ํ—ค๋” ์ฒ˜๋ฆฌ
        proxy_set_header Host $host;  # ํ˜ธ์ŠคํŠธ ํ—ค๋” ์ „๋‹ฌ
        proxy_set_header X-Real-IP $remote_addr;  # ํด๋ผ์ด์–ธํŠธ IP ์ฃผ์†Œ ์ „๋‹ฌ
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # ํด๋ผ์ด์–ธํŠธ IP ์ „๋‹ฌ
        proxy_set_header X-Forwarded-Proto $scheme;  # ํ”„๋กœํ† ์ฝœ ์ „๋‹ฌ (http ๋˜๋Š” https)
    }

 

2. ๋ฐฑ์—”๋“œ ์ฝ”๋“œ  

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

	@Override
	public void configureMessageBroker(MessageBrokerRegistry registry) {
		registry.enableSimpleBroker("/topic");
		registry.setApplicationDestinationPrefixes("/app");
	}

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/ws").setAllowedOrigins("", "http://localhost:3000").withSockJS();
	}
}
@Component
@RequiredArgsConstructor

public class WebSocketEventListener {
	private final SimpMessagingTemplate messagingTemplate;
	private final LandingService landingService;

	@EventListener
	public void handleSubscriptionEvent(SessionSubscribeEvent event) {
		String destination = event.getMessage().getHeaders().get("simpDestination").toString();

		// ํŠน์ • ํ† ํ”ฝ ๊ตฌ๋… ์‹œ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์ „์†ก
		if (destination.startsWith("/topic/user/")) {
			String userId = destination.split("/")[3];
			LandingInfos landingInfos = landingService.getAllRelatedInfo(Long.parseLong(userId));
			LandingStatus stage = LandingStatus.from(landingInfos);
			String state = stage.toString().toLowerCase();
			messagingTemplate.convertAndSend("/topic/user/" + userId + "/married-status", state);

		}
	}
}

 

 

- ๋ถ€๋ถ€ ์ค‘ ํ•œ ์‚ฌ๋žŒ์ด๋ผ๋„ ์ •๋ณด๋ฅผ ์—ฐ๊ฒฐํ•˜๊ฑฐ๋‚˜ ๊ทธ๋Ÿฌ๋ฉด ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ์ƒํƒœ ์ „์†ก

 

- ์ด ํ›„์— ์—…๊ทธ๋ ˆ์ด๋“œ ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„

์‚ฌ์ง„, ๋‚ด์šฉ๋„ ์ „์†กํ•ด์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ์‚ฌ์ง„์ด๋‚˜ ๊ฒฐํ˜ผ ๊ธฐ๋…์ผ ๋‚ด์šฉ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ 

728x90

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ