Spring 서버를 어떻게 구현하는게 맞을까?(SpringMvc, RSocket, REST의 비교)

HEYDAY7·2022년 11월 12일
0

Learn Kotlin + Spring

목록 보기
23/25

시작하며

이번 글에선 Spring에서 서버를 구현하려 할 때 어떤 방식을 선택하게 될 지 정하기 위해 관련된 지식들을 비교 조사 해보려 한다. 이를 통해 이후 진행할 프로젝트에서 어떤 식으로 프로젝트 초기를 구성해 나갈지 정해질 것이다.

Rest, MVC, Socket

REST, RESTFul, REST Api

REST란

Representational State Transfer의 약자로 찾아보면 많이들 "자원을 특정 이름(대표)으로 주고 받는 모든 것"을 의미한다고들 쓰여있다. 이는 HTTP의 장점을 잘 활용하기 위해 '로이 필딩'이 발표한 방식이며, 번역을 해 오며 말 자체가 애매하게 표현되어 있다고 생각을 한다. 쉽게 말해 자원을 표현할 수 있는 키워드들을 이용해서 정보를 주고 받는다 라고 생각하면 된다.

조건 (from 나무위키)

REST의 조건으로는 아래와 같이 6가지가 있다고 알려져있다.(여러 글에 따라 조금씩 다르나, 그 핵심은 일치한다.)

  • Client-Server : 클라이언트와 서버로 분리되며, 의존성이 서로 없어야 한다.
  • Stateless(무상태성) : 상태 정보를 저장하지 않고, 누가 어디서 접근하던지 결과가 항상 동일해야 한다.
  • Cache : HTTP를 비롯한 네트워크 프로토콜에서 제공하는 캐싱 기능을 적용할 수 있어야 한다.
  • Uniform Interface : Request-Response Method, URL, 응답코드 등으로 Interface를 구축해 URL이 무분별하게 길어지는 걸 막고, 많은 표현을 담을 수 있도록 한다.
  • Layered System : 계층 구조로 분리되어 있어야 한다.
  • Self-descriptiveness : 별다른 설명 없이도 API와 그 결과물을 이해할 수 있어야 한다.

REST API

REST API의 경우 이러한 REST를 기반으로 만들어진 API를 의미한다. 또한 RESTFul이란 위의 조건들이 잘 지켜지는 API를 의미한다.

여기서 API의 의미를 먼저 집어보자.
Application Programming Interface로 애플리케이션 간의 프로그래밍을 위해 정의된 인터페이스이다~ 라고 말 그대로 해석하면 되며, 이를 통해 정보를 교환 가능하게 된다.

이런 REST API의 설계의 가장 큰 두 규칙이 있다.

  • URI는 정보의 자원을 표현해야 한다.
  • 자원에 대한 행위는 HTTP Method(Get, Put, Post, Delete)로 표현한다.

이를 고려하는 예시는 다음과 같다.

  • api/player/create (x) -> POST api/player : 이런 식으로 주소에 동사표현이나 method를 의미하는 표현이 들어가서는 안된다.

Data의 형태

일반적으로(또 내가 경험적으로 보았을 때) 100의 99개의 REST API는 JSON 형태로 데이터를 주고 받는다.(물론 xml도 있기는 하다)
Json은 "키 - 값" 쌍으로 이루어진 데이터 오브젝트를 주고받기 위한 하나의 포맷이며, 많은 HTTP 통신 에서 사용하고 있다. 언어나 플랫폼에 상관없이 사용할 수 있어 애용되고 있으며 데이터를 serialize, deserialize하는 과정을 통해 각 application에서 json을 해석하여 사용한다.

정리

여기까지가 간단한 REST와 그 관련 지식들이었다. 정리하자면

  • REST는 자원을 특정 이름들로 대표하여 주고받는 것들을 의미하며
  • REST API는 HTTP의 장점을 잘 활용하기 REST의 원칙들을 준수해 만든 API라고 할 수 있다.

Spring MVC

MVC란

여러 디자인 패턴 중 하나로 Model - View - Controller로 구성된 패턴을 의미한다. 각각의 자신의 역할을 분리하여 맡고 있고, 이를 통해 로직의 분리를 이끌어 낸다. 이는 유지 보수, 확장 등에 있어 큰 이점을 가지고 온다.

하나의 예시를 살펴보자. 화면에 숫자 0과 + 버튼이 있다고 상상해보자. + 버튼을 누르면 숫자가 올라가게 된다. 해당 버튼을 눌렀을 때의 처리 과정이 다음과 같다.
1. + 버튼이 눌렸다는 사실을 Controller로 전달(View -> Controller)
2. 해당 event에 연결된 plus method가 동작(Controller)
3. Model 측에 count 데이터의 값을 1 올리라고 지시(Controller -> Model)
4. Model 측에서 처리 count = 0 -> count = 1 ( Model)
5. count 값을 받아 그리던 View에서 0이 1로 바뀜(Model -> View)

  • 마지막 동작의 경우 Model -> Controller -> View로 일어날 수도 있음.

Spring MVC란

기존의 MVC 패턴을 따라가며 Front Controller Pattern에 기초한 프레임워크라고 할 수 있다. 기본적인 Model, View, Controller를 명확한 클래스로 분할하여 작업하게 된다.

DispatcherServlet

앞서 언급한 Front Controller의 역할을 하는 것이 바로 이 DispatcherServlet이며, SpringMVC에서 가장 중요한 역할이라고 볼 수 있다. 사실 SpringMVC는 많은 기본 연결을 제공하기에 유저가 직접 작업해야할 파트는 View, Model, Controller(Handler) 정도이며, DispatcherServlet을 직접 작성하게 될 필요는 없을 것이다. 다만 그 동작은 이해해 두는 것이 좋다.

그래서 이게 무엇인가... 한 문장으로 요약하면

클라이언트로부터 오는 모든 Request를 접수하고, 각 상황에 맞게 알맞는 Handler(Controller)로 요청을 뿌려주는, 일종의 Gate의 역할을 한다.

DispatcherServlet이 요청을 전달해주는 것으로는 3가지가 있다.

  • HandlerMapping : 해당 request를 처리할 Controller가 누구인지 DispatcherServlet에 알려준다.
  • HandlerAdapter : 그 Controller를 호출하여 결과를 받아온다. 또한 보여줄 View의 이름이 필요하다면 이 때 Dispatcher Servlet으로 그 이름이 전달된다.
  • ViewResolver : 해당 View를 호출하여 돌려준다.

이런 과정을 거치면 결국 Dispatcher Servlet이 View를 통해 클라이언트가 볼 화면을 제공하게 된다.
이렇듯 Spring MVC에서 DispatcherServlet이 중앙 관제의 역할을 앞단에서 한다고 보면 된다.

정리

이렇듯 Spring MVC는 MVC 패턴을 기반을 하여 Spring에서 좀 더 편하게 해당 구조를 만들 수 있도록 도와주는 구조라고 볼 수 있다. Annotation을 이용하여 작성하므로 코드 작성 또한 그렇게까지 어렵지 않다.

RSocket

RSocket 이란

RSocket이란 TCP와 같은 프로토콜의 한 종류이며, 다중화 양방향 소통을 위하여 넷플릭스에서 만든 어플리케이션 프로토콜 이다. 우리가 일반적으로 생각하는 API와는 구조가 좀 다르며, HTTP를 사용하지 않고, 또한 Rsocket의 R이 Reactive를 지칭하여 Reactive한 기술이라고 볼 수 있다.

큰 특징으로는 한번 연결이 되면 클라이언트와 서버의 구분이 사라지고, 양쪽 다 동일하게 통신을 시작할 수 있으며, 따라서 통신에 참여하는 주체들을 "Requester"와 "Responder"라 부른다.

RSocket의 통신 모델

통신에 참여하는 주체들이 아래 모델들 중 하나의 방식으로 서로 통신을 하게 된다.

  • Request-Response : 메시지 하나를 전송하고 하나를 돌려받는다.
  • Request-Stream : 메시지 하나를 전송하고 메시지 스트림을 돌려받는다.
  • Channel : 양방향 메시지 스트림을 전송한다.
  • Fire-and-Forgett : 메시지를 한 번 "전송"만 한다.

정리

RSocket의 경우 WebSocket에서 reactive한 성격이 가미되었다고 보면 편하다. 물론 WebSocket 또한 많이 사용해본 것은 아니라 잘은 알지 못하나, 실시간으로 양방향 소통이 가능하다! 정도를 핵심으로 기억해두면 비교가 어렵지는 않을 것이다.

비교

이번 기회에 세가지를 얕게 나마 찾아보며 알게된 것들이 많다. 비교를 해보며 정리해본다.

REST API vs Spring MVC

우선 이 둘은 동일한 선상에서의 비교가 아니다. RestAPI는 API를 설계하는 방식으로 Spring MVC를 통해서 REST API를 구현할 수 있다. 따라서 이 둘은 일종의 교집합이 있다, 혹은 관점에 따라 포함관계가 될 수 있다. 따라서 하나의 선택지로 보아도 무방할 것 같다.

(REST API + Spring MVC) vs RSocket

이 비교는 스프링 가이드에서 짧게 나왔던 키워드들의 비교인데, 느낀 바로는 서비스에 따라 달리 적용될 것 같다. 내가 제공하고자 하는 서비스가 좀 더 즉각적이여야 하며 쌍방향의 소통이 필요하다 하면 RSocket을 쓰는 것이고, 아니라 하면 Rest형식을 사용하는 것이다. 또한 RSocket의 경우 Spring에서도 공식문서를 잘 제공하고 있어 해당 방식을 채택해야 하는 경우에 더 파보면 될 것 같다는 생각이 들었다.

vs WebFlux

이 글을 쓰고 나니 오히려 WebFlux와의 비교가 필요했던 것 같다는 생각이 들었다. Spring MVC는 동기적으로 동작하는 Blocking 방식이며, 이는 요청이 들어오면 thread를 생성해서 처리하게 된다. 이는 사용자의 요청이 대량으로 쏟아지기 시작하면 그 한계에 다다르게 되는데 이를 해결해 줄 수 있는 것이 WebFlux로 보인다. 이는 비동기적으로 동작하는 non-Blocking 방식으로 이벤트 루프가 있어 요청을 핸들러에 위임하고, 처리가 완료되면 callback을 통해 응답해주게 된다.

비교 정리

결국 이 비교는 MVC vs WebFlux vs RSocket이 되었어야 했을 것 같으며, 현재의 선택은 MVC와 WebFlux 둘 중 하나가 되겠지만, 아마 MVC가 될 것 같다. 그 이유는 내가 진행할 수준의 프로젝트의 경우 MVC로도 우선 충분할것이다. 물론 결국 후의 입사를 해서 어마어마한 트래픽을 다뤄야하는 시점이 오면 결국 비동기지식을 더 익히는 것이 좋다고 보이긴 한다. 다만 MVC로 처리할 수 있는 코드를 굳이 비동기로 작성해볼 이유를 아직까지는 모르겠는 상황이며, 이 필요를 느낄 때 공부를 해도 늦지 않을 것 같다는 생각이 든다.
따라서 이후 진행할 프로젝트에서는 MVC를 통해 동기로 프로젝트를 구현해보려하며, WebFlux 자체의 경우 시간이 남는다면 추가로 사용해보려 한다.

여러 자료

https://hunp.tistory.com/32
https://goodteacher.tistory.com/254
https://junseokdev.tistory.com/m/57
https://www.baeldung.com/rest-vs-websockets
https://godekdls.github.io/Reactive%20Spring/rsocket/
https://rsocket.io/
https://godekdls.github.io/Reactive%20Spring/springwebflux/

profile
(전) Junior Android Developer (현) Backend 이직 준비생

0개의 댓글