๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
โญ Personal_Study/Spring

์›น์†Œ์ผ“์„ ํ™œ์šฉํ•ด ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ตฌํ˜„ํ•˜๊ธฐ - Spring

by ํฌ์ŠคํŠธ์‰์ดํฌ 2023. 4. 23.

์›น์†Œ์ผ“์„ ํ™œ์šฉํ•ด ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ตฌํ˜„ํ•˜๊ธฐ - Spring

์›น์†Œ์ผ“์„ ํ™œ์šฉํ•ด ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ตฌํ˜„ํ•˜๊ธฐ - Springboot
์›น์†Œ์ผ“์„ ํ™œ์šฉํ•ด ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ตฌํ˜„ํ•˜๊ธฐ - React

์›น์†Œ์ผ“์ด๋ž€

โœ” WebSocket์€ ์‹ค์‹œ๊ฐ„ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ์œ„ํ•œ ํ”„๋กœํ† ์ฝœ์˜ ์ผ์ข…์ด๋‹ค.

WebSocket์€ ๊ธฐ๋ณธ์ ์œผ๋กœ TCP ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ํ•ธ๋“œ์‰์ดํฌ ๊ณผ์ •์„ ํ†ตํ•ด ์—ฐ๊ฒฐ์„ ์ˆ˜๋ฆฝํ•œ ํ›„, ์ง€์†์ ์ธ ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋œ๋‹ค.

์ฃผ๋กœ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…, ๊ฒŒ์ž„ ๋“ฑ์— ๋งŽ์ด ์“ฐ์ธ๋‹ค

์›น์†Œ์ผ“์˜ ์žฅ์  ๋ฐ ํŠน์ง• (vs HTTP)

โœ” ์›น์†Œ์ผ“์˜ ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ๋Š” ์ง€์†์ ์ธ ์—ฐ๊ฒฐ์ด๋‹ค.

์›น์†Œ์ผ“์˜ ์žฅ์ ๊ณผ ํŠน์ง•์€ HTTP์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ ๋ช…ํ™•ํ•ด์ง„๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” HTTP๋Š” stateless, connectionless๋ผ๋Š” ํŠน์ง•์œผ๋กœ ์ธํ•ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ๋งบ๊ณ ์žํ•  ๋•Œ WebSocket์ด ํ›จ์”ฌ ์œ ๋ฆฌํ•˜๋‹ค.

์›น์†Œ์ผ“์˜ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ์ œ์ธ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…์„ HTTP๋กœ ๊ตฌํ˜„ํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž.
polling์ด๋ž€ ๊ธฐ๋ฒ•์„ ํ™œ์šฉํ•ด์•ผ๋˜๋Š”๋ฐ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์ด ์˜ฌ ๋•Œ๊นŒ์ง€ ๊ณ„์†ํ•ด์„œ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์ด๋ผ ๋‹น์—ฐํžˆ ๋น„์šฉ์ด ์—„์ฒญ ํฌ๋‹ค

HTTP์—์„œ Polling์œผ๋กœ ๊ตฌํ˜„ํ•œ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…

๋‚˜ -> ์„œ๋ฒ„: ์•ˆ๋…•!

๋‚˜ -> ์„œ๋ฒ„: ๋Œ€๋‹ต (์š”์ฒญ1)
๋‚˜ -> ์„œ๋ฒ„: ๋Œ€๋‹ต (์š”์ฒญ2)
๋‚˜ -> ์„œ๋ฒ„: ๋Œ€๋‹ต (์š”์ฒญ3)
...
๋‚˜ -> ์„œ๋ฒ„: ๋Œ€๋‹ต (์š”์ฒญN)

์„œ๋ฒ„ -> ๋‚˜: ์•ˆ๋…•~ (๋Œ€๋‹ต ์ˆ˜์‹ )

๋”ฑ๋ด๋„ ๋น„ํšจ์œจ์ ์ด๋‹ค...

long polling์ด๋ž€ ๋ฐฉ๋ฒ•๋„ ์žˆ๋Š”๋ฐ ๊ธฐ๋ณธ์ ์œผ๋กœ HTTP ์ž์ฒด๊ฐ€ ์‹ค์‹œ๊ฐ„ ํ†ต์‹ ์„ ์œ„ํ•ด ์„ค๊ณ„๋œ ํ”„๋กœํ† ์ฝœ์€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์›น์†Œ์ผ“์— ๋น„ํ•  ๋ฐ”๋Š” ๋ชป๋œ๋‹ค.

STOMP

โœ” STOMP(Simple Text Oriented Messaging Protocol)๋Š” ๊ฐ„๋‹จํ•œ ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ๋ฉ”์‹œ์ง• ํ”„๋กœํ† ์ฝœ๋กœ ๋ฉ”์„ธ์ง€์˜ ํ˜•์‹ ๋“ฑ์„ ์ •์˜ํ•˜๋ฉฐ sub/pub๋กœ ๋ฉ”์„ธ์ง€์˜ ์†ก์ˆ˜์‹ ์„ ๊ด€๋ฆฌํ•œ๋‹ค.

์ฃผ๋กœ WebSocket์—์„œ ์‚ฌ์šฉ๋˜๋Š”๋ฐ ์‚ฌ์‹ค์„ ๋ณ„๊ฐœ์˜ ํ”„๋กœํ† ์ฝœ์ด๋‹ˆ ํ—ท๊ฐˆ๋ ค์„  ์•ˆ๋  ๊ฒƒ์ด๋‹ค.

Spring ์ฝ”๋“œ

Spring์€ Stomp ์„œ๋ฒ„๋กœ์„œ ์—ญํ• ์„ ํ•˜๊ฒŒ ๋œ๋‹ค

์‚ฌ์‹ค์ƒ ์›น์†Œ์ผ“ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐ์„ ๋งบ๋Š” ๊ฑด ํ”„๋ก ํŠธ์—์„œ ํ•˜๊ฒŒ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฑ์—”๋“œ ์ฝ”๋“œ๋Š” ๋งค์šฐ ๋‹จ์ˆœํ•˜๋‹ค.

sub/pub๋ฅผ ์„ค์ •ํ•ด์ฃผ๊ณ , ์ปจํŠธ๋กค๋Ÿฌ์— ์›น์†Œ์ผ“ ํ†ต์‹  ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ์„ค์ •ํ•ด๋‘” ์ฃผ์†Œ๋กœ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒŒ ์ „๋ถ€์ด๋‹ค.

WebSocketConfig.java

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

  @Override
  public void configureMessageBroker(MessageBrokerRegistry config){
    config.enableSimpleBroker("/sub"); // ๊ตฌ๋… ์ฃผ์†Œ
    config.setApplicationDestinationPrefixes("/pub"); // ๋ฐœํ–‰ ์ฃผ์†Œ
  }

  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/ws") // ์›น์†Œ์ผ“ ์ฃผ์†Œ
        .setAllowedOriginPatterns("*"); // ํ—ˆ์šฉ ๋„๋ฉ”์ธ 
//        .withSockJS();
  }
}

โœ” SockJS๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ์›น์†Œ์ผ“์ด ์ง€์› ์•ˆ ๋  ๊ฒฝ์šฐ sockjs๋กœ ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜๋Š” ๊ฑด๋ฐ ํ”„๋ก ํŠธ์—์„œ ์ถ”๊ฐ€์ ์ธ ์„ค์ •์ด ํ•„์š”ํ•˜๊ณ , sockjs ์„ค์ •์„ ํ•  ๊ฒฝ์šฐ ์•„๋ž˜ ํ…Œ์ŠคํŠธ๊ฐ€ ์•ˆ๋˜๋ฏ€๋กœ ๊ทธ๋ƒฅ ์•ˆ ํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค. ๋ฌด์—‡๋ณด๋‹ค ์š”์ฆ˜์€ ๋Œ€๋ถ€๋ถ„ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์›น์†Œ์ผ“ ์ง€์›์ด ๋œ๋‹ค.

chatController.java

  private final SimpMessageSendingOperations sendingOperations;

  @MessageMapping("/send")
  public void sendChat(@RequestBody ChatInsertRequestDto requestDto) throws ClassNotFoundException, NotFoundException {

    String writerName = userService.getWriterName(requestDto.getWriterId());

    chatService.insertChat(requestDto, writerName);

    sendingOperations.convertAndSend("/sub/chat/" + requestDto.getGameId() + requestDto.getChatRoomId(), requestDto.toEntity(writerName));
  }

โœ” @MessageMapping์€ @GetMapping์ด๋‚˜ @PostMapping๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค. ์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๋•Œ ๋งคํ•‘ํ•  ์ฃผ์†Œ๋ฅผ ์ ์–ด์ค€๋‹ค.

  • ๋ฉ”์„ธ์ง€ ์ „์†ก ์š”์ฒญ์ด ๋“ค์–ด์˜จ๋‹ค๋Š” ๊ฑด ๋ฐœํ–‰ ์š”์ฒญ์ธ๋ฐ config์—์„œ ์„ค์ •ํ•œ ๋ฐœํ–‰ ์ฃผ์†Œ์ธ 'pub'๋Š” ์•Œ์•„์„œ ์ธ์‹ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— pub ๋’ค์— ์˜ฌ ์ฃผ์†Œ๋ฅผ ์ ์–ด์ฃผ๋ฉด ๋œ๋‹ค
  • ์ „์ฒด์ฃผ์†Œ: ws://{๋„๋ฉ”์ธ:ํฌํŠธ๋ฒˆํ˜ธ}/pub/{MessageMapping์ฃผ์†Œ}

โœ” simpMessageSendingOperation์„ ์ฃผ์ž… ๋ฐ›์•„์„œ ๋ณด๋‚ผ ์ฃผ์†Œ (sub/{ํ•˜์œ„ ์ฃผ์†Œ})์™€ ๋ณด๋‚ผ ๋‚ด์šฉ์„ ์ธ์ž๋กœ ๋„ฃ์–ด์„œ ๋ณด๋‚ด์ฃผ๋ฉด ๋

ํ…Œ์ŠคํŠธํ•ด๋ณด๊ธฐ

์›น์†Œ์ผ“์€ ํ”„๋ก ํŠธ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์žˆ์–ด์•ผํ•ด์„œ ํ…Œ์ŠคํŠธ๊ฐ€ ๋งค์šฐ ์–ด๋ ค์šด ํŽธ์ด๋‹ค.

๋ฉ”์„ธ์ง€ํ๋ฅผ ๊ตฌํ˜„ํ•ด ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์ง€๋งŒ ๋ณ„๋„์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ๊ผญ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์–ด๋ ค์›Œ์„œ ๊ถŒ์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค.

ํฌ๋กฌ ์ต์Šคํ…์…˜ APIC๋ฅผ ์ด์šฉํ•˜๋ฉด Stomp์™€ ์›น์†Œ์ผ“์„ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

https://chrome.google.com/webstore/detail/apic-complete-api-solutio/ggnhohnkfcpcanfekomdkjffnfcjnjam?hl=ko 

 

Apic - Complete API solution

The only tool you will ever need for all you API Design, Documentation and Testing needs.

chrome.google.com

 

๋Œ“๊ธ€