프로젝트/프로젝트 관련

NGINX란 무엇인가? 왜 사용하는가?

Wonuk 2021. 12. 28. 17:55
반응형
본 포스팅은 테코톡 유튜브를 기반으로 작성되었습니다.
https://www.youtube.com/watch?v=Ps8HDIAyPD0

NGINX vs APACHE SERVER

설명 시작에 앞서 특정 상황에 대해 이야기 하겠습니다.

다른 개발자와 개발에대해 이야기 하고있는 상황에서

상대방이 엔진엑스가 무엇인지 질문을 합니다.

 

인터넷에 검색하면 간단하게 엔진엑스는 웹서버, 리버스 프록시, 로드 밸런서,

HTTP Cache로도 쓰일 수 있는 소프트웨어 라는것을 알 수 있습니다.

요청에 응답하기 위해 이벤트 기반 구조를 채택했고 덕분에

현재 웹서버 분야에서 1등을 하고 있습니다.

 

그렇다면 이벤트 기반 구조의 장점은 무엇이고

웹 서버에서 제일 잘나가는것이 Apache HTTP Server로 알고있는데

그것과 엔진엑스의 차이점은 무엇일까요?

 

단순히 엔진엑스가 벤치마크 테스트를 했을 때 가볍고 성능이 좋고

아파치 서버에 비해 최신기술이기 때문은 아닙니다.

아파치 서버는 1995년, 엔진엑스는 2002년에 출시하였고

엔진엑스 또한 오랜 역사를 가지고 있습니다.

 

1995 ~ 2002 당시의 인터넷 상황을보면 엔진엑스가 어떻게

이렇게 많은 역할을 현재 담당하고 있고 왜 1등을 하고있는지 알게됩니다.

 


1995년 - APACHER SERVER의 등장

우선 1995년 당시에는 유닉스 기반으로 만들어진 최초의 웹서버

NCSA HTTPd가 있었습니다. 하지만 이 프로그램은 버그가 굉장이 많았습니다.

그래서 몇몇 뛰어난 개발자들이 버그를 수정하기 시작하였고

구조를 변경하고 기능을 추가해서 만든것이 APACHE SERVER 입니다.

 

 

APACHE SERVER의 구조

요청이 들어오면 커넥션을 형성하기 위해 프로세스를 생성합니다.

그래서 새로운 클라이언트의 요청이 들어올 때 마다 새로운 프로세스를 만듭니다.

이는 유닉스계열 OS가 네트워크 커넥션을 형성하는 모델을 그대로 적용하는 것입니다.

 

그런데 프로세스를 만드는것이 시간이 오래걸리는 작업이다보니 

요청이 들어오기전에 프로세스를 미리 만들어놓는 PREPORK방식을 사용했습니다.

 

그래서 새로운 클라이언트로부터 요청이 들어오면

미리 만들어놓은 프로세스를 가져다 사용했습니다.

만약 만들어놓은 프로세스가 모두 할당되었다면 추가로 프로세스를 생성했습니다.

 

이러한 구조는 개발하기 쉽다는 장점이 있었습니다.

덕분에 개발자는 다양한 모듈을 만들어서 서버에 빠르게 기능을 추가할 수 있었습니다.

 

이런식으로 APACHE SERVER는 동적 컨텐트를 처리할 수 있게 되었습니다.

그리고 확장성이 좋다는 그 장점덕분에 요청을 받고 응답을 처리하는 과정을

하나의 서버에서 해결할 수 있게됩니다.

 

이것이 APACHE SERVER가 인기를 얻은 비결중 하나입니다.

출시된지 1년도 되지 않은 시점에 세계1위의 서버라는 타이틀을 거머쥡니다.


1999년 - C10K 문제

이 시기는 인터넷 트래픽이 지속적으로 증가하는 상황이였습니다.

이전에는 서버가 처리할 요청양이 그당시 기술로 감당할 수 있었지만

점점 컴퓨터가 많아지고 요청이 많아지면서 서버에 이상한

문제들이 생기기 시작합니다.

서버에 동시에 연결된 커넥션이 많아졌을 때 

더이상 커넥션을 생성하지 못하는 문제가 발생하게 됩니다.

이를 C10K문제 라고합니다.(커넥션 10000개의 문제라는 뜻)

 

사실 과거의 역사를 살펴본 진짜 이유는 이 C10K문제에 있습니다.

이제 앞으로 나아가기 전에 알아두어야 할 내용이 있습니다.

 

동시에 연결된 커넥션과 초당 요청 처리 수는 다릅니다.

초당 요청 처리 수는 말 그대로 서버가 얼마나 빨리 요청을 처리할 수 있는지 나타내는 지표입니다.

동시에 연결된 커넥션 수란 요청을 처리하기 위해 서버가 한 시점에 얼마나 많은 클라이언트와 커넥션을

형성하고 있는지를 나타냅니다.

 

한 클라이언트는 하나의 커넥션을 이용하여 여러 요청을 보낼 수 있습니다.

그리고 커넥션을 긴 시간동안 유지될 수 있기 때문에 두 지표는 같다고 볼 수 없습니다.

이렇게 커넥션이 길게 유지되는 이유는 커넥션을 형성하는데 여러 절차들이 있기 때문입니다.(TCP 3-way handshake)

그래서 이 당시에는 각 요청마다 매번 커넥션을 만들기엔 비효율적이고 속도 또한 느렸습니다.

 

그래서 사람들은 요청을 보낼 때 이미 만들어진 커넥션이 있다면 그것을 재활용하자는 생각을 합니다.

HTTP header에 보면 Keep-Alive 헤더가 있는데 그곳에 적힌 시간만큼 클라이언트와 서버는

한번 형성한 커넥션을 유지합니다.

 

그런데 클라이언트 수가 많아지면 그만큼 동시에 연결되어 있는 커넥션 수는 많아지게되고

그 단위가 10000이 넘어가는 순간 서버는 더이상 커넥션을 형성하지 못합니다.

그래서 C10K 문제는 하드웨어적인 문제가 아니였습니다.

 

문제는 APACHE SERVER의 구조에 있습니다. 그외 대다수 서버도 마찬가지 였습니다.

APACHE SERVER는 구조상 커넥션이 형성될 때마다 프로세스를 할당합니다.

그렇기 때문에 동시에 처리하고 있는 커넥션이 많아지면 그만큼 형성되는 프로세스가

많다는 뜻이고 이는 곧 메모리 부족 현상으로 이어집니다.

 

설상가상으로 APACHE SERVER의 확장성은 프로세스가 차지하는 리소스의 양을 늘렸습니다.

그리고 많은 커넥션에서 요청이 들어오면 CPU 코어는 계속해서 프로세스를 바꿔가며 일하기 때문에

컨텍스트 스위칭을 많이하여 부하가 발생됩니다.

 

쉽게 말해서 수많은 동시 커넥션을 감당하기엔 APACHE SERVER는 부적합합니다.

이같은 문제를 해결하기 위해서 많은 시도를 하며 성능개선이 지금까지도 이루어지고 있습니다.

그리고 새로 만들어진 서버들의 경우는 다른 구조를 채택하기도 했습니다.

 


2004년 - 엔진엑스의 등장

시간이 흐르고 새로운 구조를 채택하면서 APACHER SERVER를 보완한 소프트웨어가 출시됩니다.

이것이 바로 NGINX입니다.

초창기 NGINX는 APACHE SERVER와 함께 사용하기 위해 만들어 졌습니다.

 

웹서버이기는 하지만 APACHE SERVER를 완전히 대체할 목적은 아니였습니다.

APACHE SERVER가 지닌 구조적 한계를 NGINX를 사용함으로써 극복하고자 했습니다.

 

사용된 방식을 보면 간단합니다. APACHE SERVER 앞단에 NGINX를 둡니다.

이렇게 하면 수많은 동시 커넥션을 엔진엑스가 대신하여 유지할 수 있습니다.

구조적으로 많은 동시 커넥션을 유지하지 못하는 아파치 서버를 엔진엑스를 이용하여 크게 줄일 수 있습니다.

 

그리고 엔진엑스는 그 자체로 웹서버 입니다.

그래서 정적파일에 대한 요청은 스스로 처리할 수 있습니다.(웹서버 vs WAS 서버의 차이)

 

엔진엑스는 클라이언트로부터 동적 파일요청을 받았을 경우에만 

아파치 서버와 커넥션을 형성합니다.

 

아파치 서버의 리소스를 커넥션 유지에 사용하기 않고, 개발자가 원하는

로직처리에 사용되도록 도와주는 것입니다.

 

그렇다면 엔진엑스는 어떤 구조로 되어있길래 그 많은 동시커넥션을 유지할 수 있을까요?

비결은 만들어지는 프로세스 수에 있습니다.

master process - 설정 파일을 읽고 설정에 맞게 worker process를 형성하는 프로세스

worker process - 실제로 일을하는 프로세스

 

이 worker process가 만들어질 때 각자 배정된 리슨소켓을 배정받습니다.

그리고 그 소켓에 새로운 클라이언트로 부터 요청이 들어오면

커넥션을 형성하고 그 요청을 처리합니다.

그리고 나면 해당 커넥션은 정해진 Keep-Alive 시간만큼 유지됩니다.

 

그런데 커넥션이 형성되어있다고 해서 worker process가

해당 커넥션 하나만 한정적으로 담당하지는 않습니다.

 

형성된 커넥션에 아무런 요청이 없다면 새로운 커넥션을 형성하거나

이미 만들어진 다른 커넥션으로부터 요청을 처리합니다.

 

엔진엑스에서는 이런 커넥션 형성, 제거, 새로운 요청 처리를 하는것을

이벤트라고 부릅니다.

그리고 이 이벤트들은 OS커널이 큐 형식으로 worker process에게 전달해줍니다.(멀티플렉싱, epoll)

 

이 이벤트는 큐에담긴 상태에서 worker process가 처리할 때 까지 비동기 방식으로 대기합니다.

worker process는 하나의 스레드로 이벤트를 꺼내서 처리 해나갑니다.

네모칸들이 큐이며 커넥션을 생성하거나 요청을 처리하는 이벤트로 채워져 있습니다.

이렇게되면 worker process가 쉬지않고 일을 한다는 장점이 생깁니다.

아파치 서버의 구조와 비교를 했을때 요청이 없으면 방치되는 프로세스보다

서버 자원을 훨씬 효율적으로 사용하게 됩니다.

 

그런데 여기서 이런 질문이 생길 수 있습니다.

만약 이 요청중 하나가 시간이 오래걸리는 작업이라면? 

 

예를 들어 디스크를 읽고쓰는 작업이라면 그 뒤에있는 이벤트는

요청을 처리하는동안 블러킹됩니다.

 

이를위해 오래걸리는 작업을 수행하기 위해 Thread Pool을 만들어 놓습니다.

그리고 worker process는 지금 처리할 요청이 시간이 오래걸릴것 같다면

해당 스레드풀에게 요청을 위임하고 큐 안에있는 다른 이벤트를 처리합니다.

 

이러한 worker process는 cpu 코어 개수만큼 생성합니다.

이렇게되면 코어가 담당하는 프로세스를 바꾸는 횟수를 대폭 줄일 수 있습니다.

즉, CPU가 부가적인 일을 하지 않아도 됩니다.

이로써 CPU의 컨텍스트 스위칭 사용을 줄이는 것입니다.

 

이것이 바로 엔진엑스가 채택한 이벤트 드리븐 모델, 즉 이벤트 기반 구조이고

아파치 서버와 가장 큰 차이점입니다.

 

엔진엑스의 이런 구조는 단점도 있습니다.

개발자가 기능추가를 시도했다가 돌아가고 있는 worker process를 종료하게 되는 상황이 발생합니다.

이렇게되면 해당 worker process가 관리하고 있는 커넥션과 관련된 요청을

더이상 처리할 수 없게됩니다.

그래서 엔진엑스는 직접 모듈을 만들기가 까다롭습니다.

 

하지만 단점에 비해 장점이 너무 좋았습니다.

 

엔진엑스의 장점

수많은 동시 커넥션을 빠르게 처리하는데 프로세스를 적게 만들다보니 가볍기까지 했습니다.

그리고 프로세스를 적게 만드는 이 구조는 엔진엑스의 설정을 동적으로 바꾸는것을 가능하게 했습니다.

 

개발자가 설정 파일을 변경하고 엔진엑스에 해당 설정을 적용하면

마스터 프로세스는 그 설정에 맞는 워커 프로세스를 따로 생성합니다.

그리고 기존에 있는 워커 프로세스가 더이상 커넥션을 형성하지 않도록 합니다.

시간이 지나 기존 워커 프로세스가 담당하던 이벤트 처리가 모두 끝나면

해당 프로세스를 종료합니다.

 

그런데 이런 동적 설정변경을 언제 사용할까요?(리버스 프록시)

대표적인 경우로 엔진엑스가 여러 동시 커넥션을 관리하는 도중에

뒷단에 서버가 추가되는 상황이 있습니다.

 

이때는 엔진엑스가 로드밸런서의 역할을 담당하게 됩니다.

로드 밸런서는 요청을 여러 서버로 분산하는 작업을 수행하니다.

엔진엑스 뒤에 새로운 서버를 추가하여야 하는데 수많은 동시 커넥션을 담당하고 있다면

설정을 바꾸기위해 엔진엑스를 종료하여야 하는 상황이 생기게됩니다.

 

그런데 동적으로 설정을 변경할 수 있다면 어떨까요?

동시 커넥션을 유지한 채 기존 요청을 계속해서 처리하면서 뒷단에 서버를 추가할 수 있습니다.

엔진 엑스는 이런 설정 변경을 초당 수십번을 하여도 무리없이 처리가능 합니다.

이 모든것이 이벤트기반 구조이기 때문입니다.

 

그런데 신기하게도 처음 엔진엑스가 출시될 당시 사용자가 많지 않았습니다.


2008년 - 엔진엑스의 시대

점점 아파치 서버의 사용률이 줄어들고

엔진엑스의 사용률이 빠르게 증가하기 시작합니다.

도대체 2008년에 무슨일이 있던걸까요?

2008년에는 스마트폰이 인터넷 환경을 바꾸기 시작했습니다.

 

스마트폰은 사람들이 인터넷을 더 많이 사용하게 만들었습니다.

즉, 동시 커넥션을 훨씬 더 많이 생성하게 되는 계기가 됩니다.

사람들은 유튜브 등의 다양한 정보를 실시간으로 받고싶어 했습니다.

 

그리고 웹에 담기는 컨텐츠가 다양해지고 그 용량이 커지면서 브라우저도

리소스를 빨리 가져오기 위해 여러 TCP 커넥션을 동시에 형성하기 시작했습니다.

그리고 각각의 커넥션이 Keep-Alive 설정으로 유지되었습니다.

 

결국 동시커넥션으로 처리해야할 서버가 날이 갈수록 많아졌습니다.

회사들은 빠르게 엔진엑스라는 대체제에 눈을 돌리기 시작합니다.

 

특히 엔진엑스대규모 서비스를 운용하고 있는 큰 회사들이 좋아할만한 솔루션입니다.

덕분에 엔진엑스가 인터넷 트래픽에 관여하는 비중은 끊임없이 증가합니다.

 

 

 

이런 시대의 맞게 아파치 진영에서도 MPM이란 모듈을 추가하여 성능 개선을 시도합니다.

MPM이란 Multi Processing Module의 약자로 

아파치 서버를 어떤 방식으로 운영할지 선택할 수 있게 만들어주는 모듈이었습니다.

 

안정성이나 하위호환이 필요하다면, 기존의 PREFORK 방식을 사용하고

성능향상을 원한다면 WORKER라고 불리는 스레드를 만들어서 

워커가 요청을 처리하도록 했습니다.

 

개발자들은 이러한 구조적인 한계를 줄이기위한 시도를 지속적으로 하고있습니다.

하지만 성능테스트 결과를 보면

아직까지 동시커넥션 관련지표에서는 엔진엑스가 아파치를 크게 앞서고 있습니다.

 

이 지표는 동시커넥션 수당 메모리 사용률이며

엔진엑스는 동시 커넥션이 많아져도 메모리 사용률이 낮고 일정하게 나오는 반면

아파치 서버는 굉장히 많이 사용하게 됩니다.

 

처리하는 초당 요청의 수

동시 커넥션 수가 많아졌을 때 처리하는 초당 요청의 수는 오히려 엔진엑스가 훨씬 많고

아파치가 낮다는것을 확인할 수 있습니다.

 

이는 엔진엑스가 커넥션 관리를 얼마나 잘하는지 알려줍니다.

 

 

동시 커넥션에 집중하여 본다면 엔진엑스가 훨씬 좋아보이지만

아파치가 아직 엔진엑스와 세계 1, 2위를 다투는 이유는

다 이유가 있습니다.

 

아파치서버 이전에 웹서버는 버그가 굉장히 많았습니다.

버그 수정을 계기로 시작된것이 아파치서버 이기에 그리고 지금까지 오랜기간

업데이트를 계속 해왔기 때문에 서버 자체가 다양한 OS에서 안정적이라는 장점이 있습니다.

 

엔진엑스는 그렇지 안하서 윈도우에서 제대로된 성능을 발휘하지 못합니다.

 

그리고 모듈을 추가해서 그 기능을 확장하기 쉽다는 장점 

아파치 서버로 만들어진 오래된 서비스라고 해도 현재 잘 돌아가고 있고

모듈로 기능을 계속해서 추가할 수 있다면 굳이 다른 서버로 옮길 이유가 없습니다.

 

그리고 모듈의 종류는 아파치 서버가 엔진엑스보다 훨씬 많습니다.

 

아파치서버 = 호환성, 안전성, 확장성

엔진엑스 = 동시커넥션 문제

로 간단하게 정리할 수 있습니다.

 


2021년 - 우리는 엔진엑스를 어떻게 사용해야 하는가?

 

앞서 우리는 엔진엑스의 웹서버로서의 기능, 로드밸런서 로서의 기능을 살펴보았습니다.

그런데 엔진엑스는 동시커넥션을 여러개 유지할 수 있고

그 자체가 가볍다는 이유로 이 이외에도 다양한 방법으로 웹서버 가속기 역할을 합니다.

 

먼저 엔진엑스는 SSL 터미네이션을 수행할 수 있습니다.

SSL 터미네이션 이란?

엔진엑스가 클라이언트와는 https통신을 하고 서버와는 http통신을 하는것을 말합니다.

이 구조를 만들어서 서버가 복호화 과정을 담당하지 않도록 할 수 있습니다.

비지니스 로직 처리에 리소스를 사용할 수 있도록 부하를 줄여줍니다.

 

보통 엔진엑스와 서버는 같은 네트워크 안에서 있는 경우가 많기 때문에

이 둘은 http 통신을 하여도 보안적인 위험이 비교적 적습니다.

 

다음으로 엔진엑스는 http 프로토콜을 사용하여 전달하는 컨텐트를 캐싱할 수 있습니다.

앞서 SSL 터미네이션을 할때는 서버와 엔진엑스가 같은 네트워크에 있다고 말했는데

 

캐싱을 활용할 때는 반대로 클라이언트 쪽에 가깝게 배치합니다.

그리고 한번 서버로부터 받은 응답을 스스로 보관하고 클라이언트에 전달합니다.

 

엔진엑스는 이외에도

  • HSTS (HTTP Strict Transport Security)
  • CORS 처리
  • TCP/UDP 커넥션 부하 분산
  • HTTP/2 지원

등 많은 방식으로 서버를 지원합니다.

 

그러니 엔진엑스를 아키텍처에 도입하고자 한다면 어떤 기능이 있는지 알아보고

적극적으로 적용해보면 됩니다.


현업 개발자들이 모은 엔진엑스 설정 템플릿 사이트

https://github.com/h5bp/server-configs-nginx

 

GitHub - h5bp/server-configs-nginx: Nginx HTTP server boilerplate configs

Nginx HTTP server boilerplate configs. Contribute to h5bp/server-configs-nginx development by creating an account on GitHub.

github.com

일반적인 상황에서는 이 템플릿을 사용하면 엔진엑스를 더 빠르고

강력하게 사용할 수 있습니다.

 

물론 제대로된 아키텍처를 구축하려고 한다면 템플릿이 아니라 실제로 튜닝하여 사용해야 합니다.

 

반응형

'프로젝트 > 프로젝트 관련' 카테고리의 다른 글

JUnit이란? 단위, 통합, 기능 테스트란?  (0) 2021.12.28
CI/CD 개념정리  (0) 2021.12.28
Docker 입문 下  (0) 2021.12.28
Docker 입문 上  (0) 2021.12.27
Docker란 무엇인가? 왜 쓰는가? 소개편  (0) 2021.12.25