[Server] Ngnix 왜 사용할까?

조예진·2022년 6월 6일
7
post-thumbnail

🔎 들어가기 전..

이번 포스팅은 Nginx 사용법보다는 Nginx를 사용하는 이유에 대해 중점적으로 다뤄보려고 한다.

ngnix 서버 올리는 방법, 포트 포워딩 하는 방법, redirect하는 방법 등 과 같은 사용법에 대해서는 구글링만 하면 코드를 그대로 갖다 쓸 수 있을 정도로 잘 정리된 포스팅이 많다.

그렇기 때문에 nginx를 굳이 왜 써야하는지, nginx를 왜 만들었는지에 대한 이해를 바탕으로 쓴다면 위에 말한 포스트들을 내가 필요한 순간에 잘 활용할 수 있을 것 같았다.

웹서버에 대해 듣게 된다면 꼭 빠지지 않는 Ngnix! 왜 만들게 된 걸까?

✏️ 기존 Apache의 한계

먼저 웹의 역사와 긴밀한 관련이 있다.

초기 웹 상황

웹 브라우저에 정보를 표현할 수 있게 해주는 마크업 언어 HTML이 제일 먼저 개발 되었다. 이 언어는 기존에 작성된 화면을 보여주기 때문에 초기 웹 사이트들은 모두 정적(static)인 웹사이트였다.

따라서, 단순히 브라우저에 정보를 표현해주는게 전부라 서버가 데이터를 처리할 부담이 없었다.

자바스크립트 & SPA 등장

하지만 이후 스크립트 등장으로 동적인 데이터를 다루고,
SPA라는 개념이 등장하면서 서버에서 처리해야할 양이 방대해졌다.

SPA(Single Page Application)는 기존의 웹페이지와는 달리 기본적인 정적인 정보는 한번에 다운받아 이후 페이지 갱신 시 필요한 데이터만을 전달받아 갱신하는 방식으로 개발되었다.

이때, 사용자마다 필요한 데이터들이 다를 수 밖에 없었고, 이로써 이전보다 복잡한 로직이 필요해졌다.

하지만 정적인 페이지와 동적인 데이터 모두 한 서버에서 담당하게 되어
서버는 부담이 커지고, 수행 속도도 느려짐에 따라 사이트가 느려지게 되었다.

그래서 이에 대한 해결책으로
정적인 페이지는 정적인 페이지대로,
동적인 페이지는 동적인 페이지대로,
각각 다른 서버에서 처리를 하면 어떨까? 라는 생각이 나왔고,

웹 서버 등장

그리하여
정적인 페이지는 ws(web server)
동적인 페이지는 was(web application server)로 분리되어 처리하게 되었다.

즉, ws(web server)는 클라이언트의 요청을 처리하는 기능을 담당하고,
was(web application server)는 db조회나 다양한 로직을 처리하는 기능을 담당하는 서버로 분리되었다.

그래서 Unix기반으로 만들어진 최초의 웹서버 NCSA HTTd를 사용했다.
그런데 개발자들이 사용하다보니 버그가 너무 많아 불편함을 겪었다.

이것을 보완하여 개발한 웹서버 부동의 1위였던 Apache가 생겨나게 되었다.

apache 구조

1995년에 apache는 기존의 웹서버의 버그, 구조 등을 보완하며 탄생했다.

Apache의 구조는 다음과 같다.
요청이 들어오면 커넥션을 형성하기 위해 프로세스를 생성하는데,
요청이 들어올 때마다 프로세스가 생성된다.

그런데 프로세스를 만드는 작업이 시간이 소요되는 작업이다 보니
요청이 들어오기 전에 프로세스를 미리 만들어 놓는 PREFORK 방법을 사용했다.

그래서 새로운 클라이언트의 요청이 들어오면 미리 만들어 놓은 프로세스를 가져다 사용했다.

만약 만들어놓은 프로세스를 다 사용했다면, 추가로 프로세스를 할당하는 방식이었다.

이 구조의 장점은
1. 개발하기 쉽다
덕분에 다양한 모듈을 만들어 서버에 빠르게 추가할 수 있다.
동적인 컨텐츠를 다룰 수 있게 됨
2. 확장성이 좋다
요청을 받고 응답하는 과정을 하나의 서버에서 처리할 수 있다.

이렇게 apache는 웹 서버 1위를 차지하게 되었다.

apache의 위기

2000년 초반, 컴퓨터 보급이 점점 증가하던 시기였다.

따라서 이전보다 수많은 클라이언트들이 수많은 요청을 생성했고, 당연히 서버는 기존보다 처리해야할 양이 더 많아지게 되었다.

그런데 요청이 많아지면서 갑자기 문제가 생겼다.
동시 커넥션이 많아졌을 경우 더이상 커넥션을 형성하지 못하는 상황이 생겼다.
이를 C10K 문제라고 한다.

C10K (connection 10,000): 10,000개의 연결 을 동시에 처리하기 위한 숫자

한 클라이언트는 여러개의 커넥션을 형성할 수 있었다.
그래서 개발자들은 이미 한 클리언트가 기존에 만든 커넥션이 있다면 그걸 재활용하자는 생각을 하고
header정보의 keep-alive에 적힌 시간만큼 클라이언트와 서버는 한 커넥션을 길게 유지할 수 있게 되었다.

그럼에도 불구하고 클라이언트의 수가 현저히 많아져서 동시 커넥션 수가 10,000단위를 넘어가니
커넥션이 형성되지 못하는 상황이 생겼다.

두가지 관점에서 문제를 바라보았다.

  1. 하드웨어
  2. 소프트웨어

일단 하드웨어에서는 문제가 없다고 판단했다.
왜냐하면 이미 하드웨어는 발전 속도가 어마어마했고, 현 기준 웹페이지를 다루기에 하드웨어의 성능은 충분히 좋았기 때문이다.

문제는 그 당시, 원탑이었던 웹서버 소프트웨어 Apache의 구조였다.

Apache 구조의 문제점

기존 apache의 구조는 요청이 들어올 때마다 프로세스를 할당하는 구조였다.
즉, 이용자가 많아지면서 그만큼 프로세스도 비례하여 증가하고, 메모리 부족을 야기하게 되었다.

Apache의 장점이었던 확장성 덕분에, 다양한 모듈을 추가할 수 있었고
프로세스가 차지하는 리소스의 양도 증가한 상황이었다.

또한, 많은 요청이 들어옴에 따라 cpu 코어는 계속해서 프로세스를 바꿔가며 일을 해야했다. 이를 context-switching이라고 하는데, cpu가 감당해야하는 작업이 증가한 상황이었다.

따라서, 수많은 클라이언트 즉, 대용량의 트래픽을 감당하기에는 Apache 서버의 구조가 적합하지 않았다.

Nginx의 탄생

위에 말한 Apache 서버의 구조를 보완하기 위해 새로운 구조인 웹서버가 나오게 되는데, 현재 웹서버 1위인 Nginx이다.

Nginx의 구조는 다음과 같다.
Master process와 worker process로 이루어져 있다.

Master process
설정 파일을 읽고, 설정 파일에 맞게 worker process생성하는 작업을 한다.

Worker process
실제로 요청을 처리하는 작업을 한다.
master process에서 배정받은 listen socket을 통해 클라이언트와 커넥션을 형성하고, 해당 커넥션은 keep-alive 시간만큼 유지된다.

worker process는 커넥션 하나만 담당할까? 아니!
형성된 커넥션에 아무런 요청이 없을 경우
1. 새로운 커넥션을 형성하거나
2. 이미 만들어진 기존의 커넥션에 요청이 들어온다면 해당 요청을 처리한다.
이런 커넥션 형성, 제거, 새로운 요청 처리 작업들을 이벤트라고 한다.

이 이벤트들은 OS커널이 큐 형식으로 worker process에게 전달해준다.
큐에 담긴 상태에서 worker process가 처리할 때까지 비동기 방식으로 대기한다.

worker process는 하나의 쓰레드로 이벤트들을 꺼내서 처리해나간다.

이 구조의 장점은
worker process가 쉬지 않고 작업을 할 수 있다.
즉, apache구조와 비교 시, 요청이 없을 시 방치되던 프로세스와 컴퓨터 자원을 훨씬 효율적으로 쓸 수 있다.

그렇다면, 만약 이 요청 중 하나가 시간이 오래 걸리는 작업이라면?
그래서 Nginx는 시간이 오래 걸리는 요청들을 따로 수행하는 쓰레드 풀을 만들었다.

그래서 worker process는 특정 작업이 오래 걸릴 경우 쓰레드 풀에 그 작업을 위임하고 그 시간에 다른 요청들을 처리한다.

worker process는 보통 cpu의 코어 갯수만큼 생성되는데
이러면 코어가 담당하는 프로세스를 바꾸는 횟수를 줄일 수 있다.
즉, cpu가 그런 부가적인 작업을 하지 않아도 되니 cpu의 context-switching 사용을 줄일 수 있다.

이러한 구조를 이벤트 기반의 구조(event-driven model)라고 한다.

Nginx 단점

개발자가 기능 추가를 시도 했을 시 돌아가고 있던 worker process를 종료하는 상황이 생길 수도 있다.

그래서 Nginx는 개발자가 직접 모듈을 만들기가 어렵다.

Nginx 장점

  1. 가볍고 빠르다
    기존보다 동시 커넥션 수가 최소 10배가 증가했고, 생성되는 프로세스 수도 적다보니 가볍다는 장점이 있다.
    동일한 커넥션 수일 때 속도가 2배 향상된다.
  2. 동적으로 설정 파일 변경 가능
    master process는 동적으로 변경된 설정파일을 읽고 해당 설정에 맞게
    worker process를 생성한다.
    기존 worker process의 커넥션 형성을 막고, 처리하던 이벤트들이 모두 완료되면 해당 worker process를 종료한다.

동적 파일 설정은 언제쓰는걸까?
서버가 추가될 시 사용된다.
동시 커넥션을 담당하고 있다면, 설정파일을 변경하기 위해 Nginx를 종료하는게 힘들다.

그런데 동적으로 파일 설정을 변경할 수 있다면?
기존 요청은 요청대로 처리할 수 있고,
뒤에서 새로운 서버를 추가할 수 있다.

Nginx는 이런 설정을 초당 수십번을 변경해도 무리없이 커넥션을 관리할 수 있다.
이러한 작업을 할 수 있는 것이 이벤트 기반의 구조라서 가능하다.

Nginx가 주목받게 된 계기

사실 Nginx 생기고 초창기 시절에는 웹서버 순위권에도 들지 못했을 정도로 관심을 받지 못했다.

그러던 중 2008년 이후로 Apache서버의 점유율이 낮아지고 Nginx의 점유율이 확 상승했다.

왜 그럴까?
2008년 즈음에 스마트폰이 등장했다.
따라서, 트래픽이 증가했고, 그에 따라 동시 커넥션 수도 폭발적으로 증가했다.

예를 들어, 싸이월드에서 일촌평 실시간 알림을 받는다던지 다양한 정보를 실시간으로 제공받기를 원했다.

그래서 기존보다 폭발적으로 증가한 동시 커넥션 수를 감당하기 위해 많은 회사들이 Nginx를 도입했고, 이 중 대용량 트래픽이 발생하는 회사에서 큰 빛을 발하게 되며 점차 점유율이 상승했다.

(이때쯤, Apache도 MPMs라는 모듈을 도입하여 성능을 개선했다)

동시 커넥션 수가 많을 경우 메모리를 차지하는 비율을 비교한 사진 넣기


Nginx 기능

리버스 프록시
Nginx와 Apache를 함께 사용할 수 있다.
Apache 앞에 nginx를 이용하면 리버스 프록시의 장점을 활용할 수 있다.

로드밸런싱
nginx에 여러대의 서버가 연결되었을 시
한 서버에 부하가 걸리지 않도록 균등하게 요청을 분배하는 역할을 한다.

SSL 터미네이션
Nginx가 클라이언트와 https 통신을 함
server와는 http통신을 한다.

  • 이 과정을 통해 서버가 복호화 과정을 담당하지 않도록 해준다.
  • 비즈니스 로직에 비중을 둘 수 있도록 부하를 줄여준다.
  • 보통 Nginx와 서버는 같은 네트워크 상에 있기 때문에 http통신을 해도 보안 이슈가 비교적 적다.

캐싱
위와 반대로 Nginx를 클라이언트 쪽과 가깝게 배치?
한번 서버로부터 받은 응답을 보관하고 클라이언트에게 응답한다.


그럼에도 불구하고 Apache를 왜 여전히 많이 사용할까?

Apache는 안정적이다.
Apache가 탄생하게 된 계기는 기존 웹서버의 버그를 보완하기 위해서였기 때문에 오랜기간 업데이트를 통해 서버자체의 호환성이 높다.

반면, Nginx는 윈도우에서는 제대로 된 성능을 못 보여주는 등 호환성이 그리 높지 않다.

Apache는 확장성이 좋다
Apache로 만들어진 오래된 서비스라고 해도 현재 이상이 없고,
다양한 모듈을 자유롭게 추가할 수 있기 때문에 모듈의 종류가 훨씬 많은 Apache를 두고 굳이 다른 서버로 변경할 필요가 없다.


동시 커넥션 수

요청을 처리하기 위해 한 시점에 서버가 얼마나 많은 클라이언트와 커넥션을 형성하는지 나타내는 지표

초당 요청 처리 수

초당 얼마나 빨리 클라이언트의 요청을 처리할 수 있는지를 나타내는 지표

profile
블로그 이전 중 -> https://devjooj.tistory.com/

0개의 댓글