Nginx의 등장 배경: Apache 의 문제점
Apache 웹 서버에 대해서 들어본적이 있는가? 아주 어렸을때부터 수차례...(게임에 관심이 많았던 건지) 아파치 톰캣 서버 어쩌고 저쩌고를 많이 본 기억이있다. Apache는 Nginx의 등장 전 까지 가장 널리 쓰이던 웹 서버다.
웹 서버는 World Wide Web에서 만들어진 클라이언트 요청을 서비스하기위해 HTTP나 그 이외의 프로토콜(HTTPS/SMTP/FTP...)을 사용하는 SW/HW다. 하드웨어로서의 웹 서버는 웹 서버가 설치되어있는 컴퓨터를 의미하며, 소프트웨어로서의 웹 서버는 앞서말한 기능을 제공하는 컴퓨터 프로그램을 말한다. Apache, Nginx, IIS 등이 있다. 대부분은 웹 페이지 컨텐츠를 제공하는 역할을 한다.
Nginx는 당시 대세 웹 서버였던 Apache가 가지고 있던 문제점을 보완하기 위해 등장하게 되었다. 그것은 바로 C10k 문제인데 Concurrent 10,000 clients/connections의 줄임말로 기존의 웹 서버를 통해 1만개의 동시 연결을 처리하기 어렵다는 것이었다.
Apache 웹 서버는 Process-Driven 방식이다. Apache의 MPM(Multi-Processing Module)은 클라이언트에 요청이 많을 경우 그때마다 Process 또는 Thread를 생성하여 처리한다. 이같은 방식은 동시 접속 요청이 10,000개라면 그에 해당하는 Thread 생성 비용이 발생하게 되고, 시스템 자원이 고갈된다는 문제점이 있다.
(하지만 왜 이같은 방식으로 개발 할 수 밖에 없었나에 대한 의문이든다...간섭이 적고 이해하기 쉽다는 이점이 있긴한데 주관적 의견이고 찾아봐도 잘 나오지 않넵)
Nginx의 구조 알아보기
반면 Nginx는 Event-Driven 방식을 사용한다. Node.js가 대표적으로 이 방식을 사용하고 있는데, 싱글 쓰레드의 Event Loop가 계속해서 돌아가면서 Event Queue에 요청이 들어오면 Thread Pool에 분배하여 넣어 비동기적으로 처리하도록 한다. 그렇기 때문에 많은 요청이 한꺼번에 오더라도 무리없이 서비스할 수 있다.
식당에 비유하자면...손님들에게 일단 당장 음식은 내오지 못하더라도 메뉴는 주방에 전달하고 손님을 앉히게해서 한꺼번에 많은 손님들을 받을 수 있는 그런 구조다.
Nginx는 설정을 읽거나 포트에 바인딩을 하는등 주요한 기능을하는 Master Process가 있고, 다수의 Worker들이 있으며, Helper Process가 그 아래에 존재한다. 실질적으로 모든 클라이언트 요청을 처리하는 일은 Worker Process가 담당하고 있는데, Worker process는 nginx 설정에서 개수를 정의할 수 있고, 기본적으로는 CPU의 코어 수에 맞게 할당된다. 클라이언트 요청이 늘어난다고 해서 Worker Process가 증식하지 않는다. 그 외에도 아래의 구조 그림에서 볼 수 있듯 Cache Helper 프로세스들이 존재한다.
4코어를 가지고있는 내 서버에서 따로 Worker process를 정의해주지 않고 실행했는데 이렇게 4개의 Worker process들이 있는 것을 볼 수 있었다.
Nginx 서버가 구동되면, 각각의 Worker Process가 Context-switching을 최소화하면서 비동기적으로 여러 커넥션을 처리한다. 각각의 Worker Process는 독립적인 싱글 쓰레드 프로세스이며 그 프로세스들은 공유 메모리(Shared memory)를 이용하여 cache data, session data 등등 공유자원에 접근할 수 있다.
Nginx의 활용: Reverse Proxy
동시에 많은 요청을 처리할 수 있다는 장점때문에 Nginx는 Reverse Proxy로도 널리 사용되고 있다.
Forward Proxy는 클라이언트가 서버로 직접 요청하지 않고 Proxy 서버를 이용해서 요청을 하는 방식이다. 이는 서버에게 클라이언트가 누군지 속일 수 있게되는데, 게임할때 VPN을 써서 해외서버로 우회접속을 해본 사람들이라면 단번에 이해할 것이다. 한국 유저이지만 한국유저가 아닌것처럼 속이는거다.
Reverse Proxy는 그 반대다. 클라이언트의 요청을 받아서 내부 서버로 전달해주는 방식이다. 호출한 IP를 알아낸다 하더라도 실제 어느 IP까지 통하는지 알 수 없기 때문에 이는 클라이언트로 부터 서버를 숨기는 역할을 하게 된다. 이렇게 보안성이 높아진다는 장점도 있지만, 클라이언트의 요청을 여러대의 서버로 나누어 처리한다면 Load Balancer 역할도 할 수 있다.
참고자료
https://serverguy.com/comparison/apache-vs-nginx/
https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/
https://icarus8050.tistory.com/57
'프로그래밍 > Network' 카테고리의 다른 글
HTTP Request/Response의 메세지 구조 뜯어보기 (0) | 2022.02.12 |
---|---|
MIME 타입 (0) | 2022.02.12 |
[Nginx] 리버스 프록시로 사용하기 (백업 서버 설정, 로드 밸런싱) (0) | 2021.11.05 |
[Nginx] Static 파일을 캐싱해서 웹 페이지 로딩 속도를 높이자 (0) | 2021.01.26 |
IP와 Subnet (0) | 2020.11.28 |