본 포스팅에서는 현직 개발자에게도 생소하기 쉬운 쓰로틀링(Throttling)과 디바운싱(Debouncing) 테크닉에 대해 설명하고자 한다.


본래 Throttling 이란 주로 모바일 기기에서 많이 사용되는 용어로 성능을 위한 오버클럭(Overclock)이 디바이스에 무리를 주는 것을 방지하기 위해 고의로 성능을 낮추는 조절 방식을 말한다.


소프트웨어 적인 의미로도 Throttling 은 언급이 되곤 한다.


이 때에는 주로 트랜잭션을 처리하는 Middleware 나 네트워크 트래픽을 제어하는 ISP 에서 언급이 되며 UI 처리를 담당하는 프론트엔드(Frontend)에서도 사용된다.


프론트엔드(Frontend) 에서 쓰로틀링과 디바운싱은 어떤 경우에 사용될까?


가령 웹페이지를 구성하는데 해당 사이트는 다시 방문시 사용자가 읽던 포스트의 위치를 기억하고 그 페이지를 보여준다고 생각해보자.

페이지를 나눌 단위가 없으므로 스크롤 단위로 페이지 좌표를 서버에 기록하고자 한다면, 가장 단순한 방법은 Javascript 의 Scroll 이벤트를 이용해서 좌표를 저장하고 기록하는 방식이다.


이 경우 사용자의 스크롤링마다 이벤트를 발생시키면... 서버에도 클라이언트에도 매우 큰 부하가 발생되게 된다.

최악의 경우 페이지의 세로 좌표만큼 이벤트가 발생될 것이다.


예시는 최악의 구조와 최악의 경우를 가정한 것이지만, 중요한 점은 "이벤트의 오버클럭(Overclock)이 소프트웨어에 손상을 가져온다는 점" 이다.


이런 경우의 처리를 위해서도 쓰로틀링과 디바운싱 이라는 개념이 똑같이 적용되어 사용된다.


먼저 쓰로틀링(Throttling) 테크닉을 알아보자

쓰로틀링(Throttling) 을 이용하면 발생되는 이벤트 중간에 Delay 를 포함시킨다.


즉, Delay 이내로 연속적으로 발생된 이벤트에 대해서는 무시한다.


다음 코드를 보면 쉽게 이해될 것이다.




이런 종류의 테크닉은 특히 애니메이션을 구현하는 코드 등에서 많이 확인해볼 수 있다.


다음으로 디바운싱(Debouncing) 역시 쓰로틀링과 비슷하게 소프트웨어적인 오버클럭을 조절하는 테크닉이다.


하지만 쓰로틀링(Throttling) 과는 조금 다른 방법을 사용하는데, 쓰로틀링이 필터링(Filtering)의 방법을 사용한다면,


디바운싱(Debouncing)은 그루핑(Grouping)의 방법을 사용한다.


즉, 이벤트 핸들러가 주기적으로 여러 개의 발생한 이벤트를 하나로 묶어서 처리하는 방식이다.


이때, 먼저 발생한 이벤트가 처리를 대기하며, 대기하는 도중 새 이벤트가 발생하면 이전 이벤트의 대기를 취소(Cancel)하고, 해당 이벤트를 기준으로 다시 처리(Process)를 대기한다.

이렇게 특정 시간 동안 처리(Process)는 대기하게 되며 결과적으로는 일정한 시간 동안 연속적으로 발생한 이벤트는 마지막으로 발생한 이벤트 기준으로 처리된다.


여기서 Leading Edge 라는 디바운싱 테크닉을 이용하면 이 처리를 앞의 이벤트 기준으로 변경할 수 있으며 이 경우엔 쓰로틀링과 유사하게 동작하게 된다.

(나중에 발생하는 이벤트를 무시하는 방식은 같지만 첫 이벤트 처리가 딜레이 된다.)


다음 코드를 참조해보자.



쓰로틀링과 디바운싱은 생소하지만 알고보면 많은 이벤트 처리에 사용되고 있는 테크닉이다.

특히 UI를 처리하는 부분은 입력의 오버클럭을 감당하기 위해 없어서는 안되며 많은 라이브러리나 프레임워크에 이미 내장된 경우가 많으므로 잘 숙지해두는 것이 좋다.



좀 더 자세한 예시는 다음 링크가 가장 잘 되어 있는 듯 하다.

 : https://css-tricks.com/debouncing-throttling-explained-examples/


추가로 본 포스팅에선 이해를 돕기 위해 간단한 파이썬 코드로 예시를 작성했지만 실제 Javascript 에서 사용되는 코드의 예시는 다음을 참조해보자.

 : https://codeburst.io/throttling-and-debouncing-in-javascript-646d076d0a44



 

 

HTTP/1.0 은 가장 기초적인 형태의 웹 프로토콜을 제시하였고, 이는 일전 포스팅에도 정리되어 있듯이 TCP 프로토콜 위에 HTTP Spec 을 이용한 HTTP 프로토콜을 충실히 따른다.


이 방식은 웹이라는 새로운 환경에서 TCP에 비해 나은 성질의 프로토콜이었으나, 웹의 규모가 거대해지면서 몇가지 이슈들이 발생하였다.

 

특히 Network Latency 이슈가 주된 문제였는데, HTTP/1.1 은 이 문제를 해결하기 위해 특징적인 2가지 개념을 도입한다.

 

(1) HTTP Pipelining (HTTP 파이프라이닝)

 

 

 

HTTP Pipelining 이란 HTTP1.1 로 스펙이 업그레이드 되면서 클라이언트와 서버간 요청과 응답의 효율성을 개선하기 위해 만들어진 개념이다.

 

HTTP Request 들은 연속적으로 발생하며, 순차적으로 동작한다.


HTTP/1.0 에서 HTTP Request 는 소켓에 write 한뒤, 서버의 Response 를 받아 다음 Request 를 보내는 방식으로 웹이 동작한다. 

여러 요청에 대해 여러 응답을 받고, 각 처리가 대기되는 것은 Network Latency 에 있어서 큰 비용을 요구한다.

게다게 HTTP/1.0 에서 HTTP 요청들은 연결의 맺고 끊음을 반복하기 때문에 서버 리소스 적으로도 비용을 요구한다.


HTTP/1.1 에서는 다수의 HTTP Request 들이 각각의 서버 소켓에 Write 된 후, Browser 는 각 Request 들에 대한 Response 들을 순차적으로 기다리는 문제를 해결하기 위해 여러 요청들에 대한 응답 처리를 뒤로 미루는 방법을 사용한다.

 

즉, HTTP/1.1 에서 클라이언트는 각 요청에 대한 응답을 기다리지 않고, 여러개의 HTTP Request 를 하나의 TCP/IP Packet 으로 연속적으로 Packing 해서 요청을 보낸다.


파이프라이닝이 적용되면, 하나의 Connection 으로 다수의 Request 와 Response 를 처리할 수 있게끔 Network Latency 를 줄일 수 있다.


하지만 위의 기법 설명에서 언급하듯이, 결국 완전한 멀티플렉싱이 아닌 응답처리를 미루는 방식이므로 각 응답의 처리는 순차적으로 처리되며, 결국 후순위의 응답은 지연될 수 밖에 없다.


<이미지 출처 : https://www.popit.kr/%EB%82%98%EB%A7%8C-%EB%AA%A8%EB%A5%B4%EA%B3%A0-%EC%9E%88%EB%8D%98-http2/>



이는 HTTP의 Head Of Line Blocking 이라 부르며 Pipelining 의 큰 문제점이다.


따라서 HTTP/1.1 의 웹서버는 서버측에 Multiplexing 을 통한 요청의 처리를 요구하며, 각 Connection 당 요청과 응답의 순서가 보장되는 통신을 한다.

 

HTTP 파이프라이닝은 HTTP/2 가 등장하면서 멀티플렉싱 알고리즘으로 대체되었고, 모던 브라우저들에서도 기본적으로는 활성화하지 않고 있다.

 

 

(2) Persistent Connection

 

 

HTTP 1.0 초기의 HTTP 연결은 요청시 TCP 의 3-way handshake 방식으로 연결이 이루어졌었다.

즉, 웹클라이언트와 서버간의 연결 성립 이후 SYN, SYN-ACK, ACK 핸드셰이킹이 발생하고 이를 바탕으로 통신을 구성한 뒤 연결을 끊는 순서가 필요했다..

웹의 초창기에는 컨텐츠의 수가 많지 않았기 때문에 이런 TCP 연결은 부담되지 않았지만, 웹을 통한 멀티미디어 컨텐츠의 발달로 인해, TCP Connection 의 재사용이 요구되게 되었다.

 

웹에서의 커넥션 재사용을 Keep-alive 또는 Connection reuse 라 하며, HTTP/1.0 에서는 클라이언트가 서버에게 요청하는 Request Header에 다음과 같은 값을 통해 연결을 유지하였다.

 

Connection: keep-alive


HTTP/1.1 에서는 이 헤더를 사용하지 않더라도 모든 요청/응답이 Connection을 재사용하도록 설계되어 있으며, 필요없는 경우에만 TCP 연결을 종료하는 방식으로 변경되었다.

 

Connection: close

 

해제 시에 위와 같은 명시적 Connection 헤더를 이용하며, 그렇지 않은 경우 무조건 연결은 재사용되게 되어 있다.

 

이러한 이슈는 HTTP/2 로 웹이 한단계 더 발전하면서 해결되었다.

자세한 건 다음 링크를 참조

(https://jins-dev.tistory.com/entry/HTTP2-%ED%8A%B9%EC%A7%95%EB%93%A4%EC%97%90-%EB%8C%80%ED%95%9C-%EC%A0%95%EB%A6%AC)

 


현재 웹 표준으로는 HTTP/2 가 개발중이며 이미 공개가 되어있다. HTTP/2 에서는 구글이 프로토타입으로 제시한 SPDY 등의 프로토콜을 기반으로 한 웹 기술의 발전이 예상되는 만큼 위의 기술들 또한 보다 더 나은 방향으로 진화될 것이라 생각한다.


Software 를 다루는데 있어서 Proxy 는 흔히 접할 수 있는 단어이다.

많은 IT에 대해 잘 알지 못하는 사람들도 "우회" 를 목적으로 운영되는 프록시 서버에 대해 알고 있으며, Software 공학에 있어서 Proxy 는 상식처럼 알아두어야할 개념 중 하나이다. 

크게 많이 사용되는 Proxy 용어의 의미는 Proxy 서버, Proxy Design Pattern 등 다양하지만, 본 포스팅에서는 프록시 서버에 대해 다룬다.


Proxy 란 대리 혹은 중계 Agent 로써의 의미를 지니며 프록시 서버란 대리자 역할을 하는 서버를 말한다.


즉, 웹브라우저에서 Request를 보냈을 때 내 IP가 아닌 Proxy 서버의 IP로 웹서버에 접근하여 요청과 응답을 처리한 후 Proxy 서버에서 나에게 응답을 해주게 된다.


이렇게 프록시 서버를 사용하는 목적은 3가지 정도가 있다.


목적에 따른 분류


(1) 익명성과 우회접근


 : 서비스형태로 제공하는 Proxy 가 주로 이 범주에 속하며, IP를 숨기는 것이 주 목적이다. 요청을 대신 수행해주는 프록시 서버를 통해 우회하여 서버에 접근이 가능하다. 

IP 를 숨긴 채 모든 사용자가 접근가능하도록 허용하는 Open Proxy 형태가 있다.



(2) 서버의 부하를 줄여주기 위한 Filter 이자 Cache


 : Proxy 를 도구로써 사용하는 가장 대표적인 예시이다. 프록시 서버가 서비스 서버에 작업하는 위치와 네트워크 구성에 따라서 Forward Proxy / Reverse Proxy 로 구분된다.


 - Forward Proxy : 일반적인 프록시 서버를 말하며, 요청하는 Client 와 Service Server 사이에 위치하여 중간에서 요청을 중계한다. 가령 서버에 요청이 들어왔을 때, 요청은 Proxy를 거쳐 서버에 전달되며 이 과정에서 별도 작업을 처리해서 Service Server로 전달하거나, Cache 로써의 역할을 한다.


 - Reverse Proxy : 마찬가지로 Client 의 요청이 실제 Service Server의 도메인으로 이루어지는 것이 아닌 프록시 서버로 이동한다. 

Forward Proxy 와는 다르게, Service Server 들이 대게 내부망으로 구성되며 프록시에서만 연결을 허용하게 만들어 서비스를 위한 보안 채널을 구축하는 역할을 한다. 

이런 경우 Client 가 Service Server 에 직접 접근이 불가능하므로 Reverse Proxy 에서 요청을 좀 더 적극적으로 중계하는 Load Balancing 의 역할을 수행하기도 한다.


 : 이렇게 서버 측에 위치한 Cache 를 위한 Proxy 외에도 클라이언트 네트워크 쪽에서 프록시와 캐싱을 함께 수행하는 서버가 따로 존재한다. (Squid와 같은 서버가 예이다.) 

 : 이 때 캐싱 시에는 HTTP 헤더에 Cache-control : no-cache 옵션이 주로 작용하며 주로 포털 사이트에서 해당 헤더를 사용하는 경우를 볼 수 있다.

(Cache-control 옵션에 대해 얘기하자면, no-cache로 지정할 경우 캐싱을 사용하지 않고 실 서버까지 도달한다. 

그렇기 때문에 사용하려면 max-age=3600, must-revalidate 와 같이 지정해야 한다.)



(3) 서버 접근 작업 자체를 담당하는 서버


 : 다소 특수한 케이스로 주로 모니터링 및 데이터 분석을 위해 요청 자체를 기록하고 다루는 형태의 서버 엔진이 있다. 보안, ACL(Access Control List), Log / Audit 등을 위해 사용된다.



웹서비스를 구현하는 데 있어서 보통 사용되는 프록시 서버의 형태는 (1)번과 (2)번으로 Reverse Cache 의 형태가 가장 보편적이라고 할 수 있다.




 실무에서 REST API 설계를 처음 다뤄보았을 때, 부족한 점들이 많이 있었다. 

많이 혼나고 나서 너무나도 좋은 글을 찾아 정리해두었다.


원본 출처는 다음과 같으며, 아래 내용은 한글로 알아보기 쉽게 정리해 놓은 부분이다.

(https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/)



 RESTful Service API 의 설계 업무를 하던 중 처음에 칭찬받아서 대충 설계하다가 다시 공부하게 된 내용.

일반적으로 커뮤니케이션과 개발에 원활한 설계를 하기 위한 10가지의 방법이 존재하며 다음과 같이 서술된다.


(1) Use nouns but no verbs (동사가 아닌 명사를 통한 API 설계를 할것.)


- 가장 초보적인 실수가 CRUD 에 대한 기능을 Path에 명시하는 것이다.

 예를들어 /getAllCars, /createNewCar, /deleteAllCars 와 같은 방식인데, REST 디자인을 위해서는 CRUD 를 Method 를 이용하며 표현하기 때문에 그 외의 것은 전부 entity를 명시하는 명사로 표기한다.


 따라서 예시는 다음과 같이 HttpRequest Method를 통해서 기능이 구분되어야 한다.




 이 원칙은 표준 웹의 REST API 대부분에서 따르는 원칙이며, GET / POST / PUT / DELETE 외의 Method 들, 가령 HEAD 나 TRACE 등, 의 경우 별도의 원칙을 갖고있지 않다.



(2) GET method and query parameters should not alter the state


 역시 위에 명시한 바와 마찬가지로 모든 Functioning 은 Method로 하고 query parameter 역시 state change 등의 기능으로 사용하지 않는다.

(ex) GET /users/811?activate or GET /users/811/activate ---         (X)



(3) Use plural nouns


 path는 entity 항목을 나타내므로 복수형을 쓰고 특정하게 지정하고 싶다면 다음 Path에서 {항목} 으로 지정해준다.

(ex) GET /cars/{carName}            -- cars 와 같이 path 는 복수형. 뒤에 {carName} 으로 단수 객체 모델을 가져온다.



(4) Use sub-resources for relations


 리소스는 관계에 따른 계층형 구조를 유지한다.


(ex) GET /cars/811/drivers/ > 차811 의 드라이버 리스트를 반환한다.

(ex) GET /cars/811/drivers/4 > 차 811의 4번 드라이버 정보를 반환.



(5) Use HTTP headers for serialization formats


 서버와 클라이언트 간 커뮤니케이션에 있어서 Header Serialization format을 이용한다.



(6) Use HATEOAS


 HATEOAS 란 Hypermedia As The Engine Of Application State 의 약자로, 하이퍼텍스트 링크를 데이터 내에 명시할 경우 API를 통해 갈 수 있는 navigator 형태로 표기해준다.


<HATEOAS 의 예시. links 하위의 href 를 주목하자>


 위의 예시에서 drivers.links.href 항목은 주소를 저장함으로써, 외부주소에 저장된 리소스 자체를 가리키고 있다.

REST API 는 이런식으로 실제 리소스를 담는 것이 아닌 경로를 담아서 HyperMedia 컨텐츠를 기록한다.


 이렇게하면 네트워크 비용도 절감되고, 성능면에서도 많은 이점을 갖는다. 물론, 해당 주소로 다시 접근하여 실제 리소스를 받아와야 하는 점이 있지만, 오히려 리소스를 CDN 등을 이용한 static 저장소에 두고 가져온다면 네트워크 비용 측면에서도 훨씬 저렴하고 뛰어난 성능으로 핸들링할 수 있다.



(7) Provide filtering, sorting, field selection and paging for collections


 Filtering 은 특수한 query parameter 를 조건으로 주었을 때 해당 기능을 제공할 수 있게끔 하는 것이다.

(ex) GET /cars?color=red


 Sorting 은 오름차순, 내림차순의 정렬을 multiple field 에 대해 허용하는 것이다. 

(ex) GET /cars?sort=-name, +price > -(ascending) +(descending)


 Field selection 은 select 조건문과 같이 필드만 추출해서 보여줄 수 있도록 하는것으로, 네트워크 트래픽 관리에 효과적이다. 

(ex) GET /cars?fields=name, price


 Paging 은 Offset과 Limit 을 지정할 수 있는 조건으로 DB 조회에 필수적인 기능이다. (ex) GET /cars?offset=10&limit=5



(8) Version your API


 REST API는 Version 을 명기한다. (ex) /blog/api/v1



(9) Handle Errors with HTTP status codes


 에러는 별도의 로직으로 처리한다기 보다 HTTP 상태 코드와 메시지를 통해 처리하는 것이 좋다. 다음은 서버에서 반환하는 표준 HTTP 응답 코드를 설명한다.



에러에 따른 Payload 도 다음과 같이 명시한다.




(10) Allow overriding HTTP method


 몇몇 프록시 서버의 경우 POST와 GET 만을 지원하는 경우가 있다.

이러한 한계점을 지원하기 위해 API 단에서 override HTTP method 를 지원해줄 필요가 있다. X-HTTP-Method-Override 와 같은 Custom HTTP 헤더를 만들어 method 방식을 지원하자.






HTTP는 현재 세계에서 가장 널리 쓰이는 프로토콜 중 하나이다. 우리가 보통 사용하는 인터넷을 위한 기본 프로토콜이기도 하며, 최근래에는 다루는 기술도 비약적으로 발전하여, 예전에 웹의 영역이 아니라고 불렸던 게임 영역, 실시간 대용량 처리, 대용량 메시지 처리 등에서도 HTTP 기반의 웹 스택을 사용하는 경우를 흔히 몰 수 있다.


HTTP TCP 계층의 위에 HTTP 프로토콜 스택을 쌓아올린 Network Layer로 현재 가장 널리 사용되고 있는 Stateless / Connectless 형식의 프로토콜이다.


 여기서 Stateless 란, TCP와 다르게 상호간의 연결된 소켓이 연결을 유지하지 않는다는 의미이다.

 즉, 서로 요청과 응답만 처리하고 "상태" 는 기록하지 않는다. 서로 간에 지속적인 "연결" 이 유지되지 않기때문에 지속적이면서 연속적인 통신에는 적합하지 않다. 일반적으로 채팅 서비스를 구현할때 HTTP가 고려되지 않는 이유이기도 하다.


 대신에 단순한 정보 전달에 있어서는 가장 효율적인 프로토콜이라고 봐도 무방하다. 요청한대로 응답만 보내주면 되기 때문에, 서버 입장에서도 연결 관리에 대한 부담이 덜어지고, 클라이언트 측면에서도 원하는 정보만 얻을 수 있으므로 효율적이다.


 HTTP 역시 네트워크 프로그래밍이기 때문에 당연히 소켓을 이용하여 통신을 하게 되며, HTTP를 서비스하는 웹서버는 특유의 성질을 구현하기 위하여 일반적인 TCP 서버 등과는 다른 HTTP 프로토콜에 특화된 형태를 취하게 된다.


소켓을 이용하여 RAW한 방식으로 HTTP 웹서버를 구축할 때는 연결이 시작된 이후에(Accept) 바로 해당 소켓의 연결이 요청(Request)을 받고, 응답(Response)한 후에 연결이 끊어지게 만드는 것을 잊지 않아야 한다.


 HTTP URI Method 등을 기반으로 작동하게 된다.

 HTTP 프로토콜은 별다른 것이 있는 것이 아니라 말그대로 Socket 의 통신 버퍼에 특유의 프로토콜 스택을 쌓아올리는 것을 말한다. 다음은 요청과 응답에 따른 프로토콜 형태이다.

 

<HTTP Request Header>


 위의 요청 포맷에서 첫번째 라인은 Request Line이라고 해서 요청에 대한 포맷 정보를 명시하는 필수 요소이다. 해당 라인은 3가지의 필드로 이루어져 있으며 각 필드는 다음을 명시한다.


(1)  요청 메서드 : GET, POST, OPTIONS(UPDATE, DELETE), PUSH 등의 요청 방식이 온다.


(2)  요청 URI : 요청하는 자원의 위치를 명시한다.


(3)  HTTP 프로토콜 버전 : 프로토콜의 버전으로 1.0 1.1이 있다.



그 아래로 요청 헤더의 내용이 CRLF Delimeter로 하여 열거된다.

General Header : Cache-Control, Connection, Date, Pragma, Trailer, Transfer-Enco, Upgrade, Via, Warning

Request Header : Accept, Accept-Charset, Accept-Encoding, Accept-Language, Authorization, Expect, From, Host, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Max-Forwards, Proxy-Authorization, Range, Referer, TE, User-Agent

Entity Header : Allow, Content-Encoding, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range, Content-Type, Expires, Last-Modified, extension-header

요청 헤더의 내용이 전부 명시가 된 이후에는 Message Body두 개의 CRLF 아래에 명시된다. 두개의 CRLF 뒤에는 Request Body 가 포함되게 되며, 이부분은 HTTP 스펙에 따라서 해석의 여부가 나뉜다. (이부분은 REST API 소개 및 HTTP Method 분석 포스팅에서 자세히 다루겠다.)


 다음은 응답 헤더의 모습이다.


<HTTP Response Header>

 

첫번째 라인은 요청헤더의 Request Line 처럼 Response Header에서는 Status Line 이라 불리며 필수 정보를 포함한다.


(1)  응답 프로토콜과 버전 : HTTP/1.0, HTTP/1.1, HTTP/2.0 이 현재 버전으로 존재한다.


(2)  응답 코드 : 1xx, 2xx, 3xx, 4xx, 5xx 등의 번호가 응답 코드로 사용된다.


(3)  응답 메시지 : OK, Not Found, Internal Server Error 등의 메시지를 출력한다.


 역시 해당 라인 아래에 응답 헤더의 내용들이 포함되는데, Accept-Range, Age, Etag, Location, Proxy-Authenticate, Retry-After, Server, Vary, WWW-Authenticate 등의 정보가 포함된다. 이후에 두 개의 CRLF 라인 다음에 Message Body 가 첨부된다.

 


 복잡해보이지만 내부 구성원리는 간단하다. 

일반적인 TCP 서버를 구성하고, 프로토콜을 만드는데, 클라이언트로부터 요청을 받아서 해석하는 부분에 Request Parser를, 서버쪽에서 처리를 마치고 클라이언트에 응답을 내려줄 부분에 Response Builder 를 메시지의 머리에 붙여주면 된다.


 그렇게만 하면 웹서버가 HTTP Speculation 상에 약속한대로 메시지를 해석한다. 그렇다면 웹서버 작동의 기본 로직을 정리해보자.


(1) TCP 소켓을 열어 클라이언트의 접속을 받는다. (Accept)


(2) 커넥션을 관리할 수 있는 객체를 만들어, 쓰레드에 할당한다.


(3) 쓰레드가 해당 커넥션에 대해 HTTP Request 를 분석한다. Method 에 따라 서버 내에서 url Handler 를 라우팅해주고, 해당 라우터 메서드에서 요청에 대한 로직을 구현한다.


(4) 로직에 따라 구현한 HTTP Response 를 클라이언트에 반환하고, 접속을 끊는다. (Stateless)



좀 더 내부 동작 원리가 궁금하다면 자세한 예제는 다음 소스를 확인하면 도움이 될 것이다. 오래전에 작성한 소스라 허접하지만 웹서버 구현에 있어 기본에 충실한 좋은 예제라고 생각한다.

(https://github.com/ParkJinSang/Jinseng-Server)



+ Recent posts