nginx 란 ? (필요성, 구조, 동작원리)

박규범·2023년 3월 12일
1
post-thumbnail

보통 시스템 아키텍쳐를 구성할 때에 Front | WS(nginx / apach)->WAS(node.js / java)->DB 구조로 이루어지는 경우가 많다.
Web Server를 제공하는 nginx는 전 세계 상위 100만 사이트 중 web site 중 점유율이 21.23%나 차지했다. (서베이 자료 참조)
우리는 서버를 구성할 때 node.jsjava를 통해 구현했는데 또 앞단에 WS를 두어야 하는 이유는 무엇일까 ?
그리고 nginx는 어떤 차별화된 서비스를 제공하기에 점유율이 세계 1등인 서비스가 될 수 있는지 알아보도록 하자 📖

Web Server의 필요성

node.js로 http 통신을 열고, 어떤 URL 이냐에 따라서 우리는 각 기능에 맞는 로직을 구성해서 결과를 전달할 수 있다.
웹에서 발생될 수 있는 일들은 WAS 에서 핸들링이 다 되는데 웹 서버는 왜 필요한 것일까?

  • 정적 파일의 캐싱 역할 (부하 방지)
    WAS는 DB에서 데이터를 조회하는 기능과 같이 동적인 요청을 처리하는게 목적인 서버이다.
    사용자가 많아질수록 부하가 많아질텐데, 정적인 파일까지 처리를 한다면 과부하가 걸릴 수 도 있다.
    하지만, 웹 서버와 병행해서 사용한다면, 처음 요청할 때는 WAS에서 받아오지만 한 번 받은 전달된 파일을 웹 서버에서 저장해놓고 다음 요청이 들어오면
    WAS까지 가지 않아도 웹 서버에서 전달이 가능하다. 이러한 기능을 cahcing이라고 한다. 사용자에게 좀 더 빠른 리스폰스를 해줄 수 있다

  • 리버스 프록시 역할(보안 강화)
    프록시란, 대리의 의미로, 인터넷과 관련해서 쓰이는 경우 특정 주소로 접속했을 때 다른 주소로 이동시켜주는 역할을 한다.
    웹 서버가 앞 단에 존재한다면 클라이언트에서 80포트로 요청을 해도 내가 설정한 포트에 도착할 수 있게 길을 변형 시켜준다. 이러한 프록시 기능을 사용하게 된다면 보안적으로 강화된다는 장점이 있다. 실제 서비스하는 서버의 주소를 숨길 수 있기 때문에 공격을 어느정도 보호할 수 있다.
    프록시에는 forward froxyreverse froxy 종류로 나뉘게 된다.

  • 로드밸런싱 역할(트래픽 분산)
    서비스를 사용하는 유저의 수가 100명이 아니라 수백만명이 되고 동시 접속하는 수가 몇만명이 될 경우, 서버 한대로는 커버할 수 가 없다.
    이러한 경우 서버의 사양을 높혀 어느정도는 방어를 할 수는 없지만 해결하고자 무한히 스펙을 올릴 수 없다.
    때문에 같은 기능을 하는 서버를 여러 개 두어, 과부하가 걸리지 않게 분산하여 운영할 수 있다.
    로드밸런서는 위와 같이 여러 서버를 운영할 때 앞단에서 트래픽을 분산시켜주는 역할을 한다. 그리고 이러한 기능을 제공하는 웹 서버가 있다.

nginx를 왜쓰는가 ?

단순히 정적인 파일을 내려주는것 뿐만 아니라 WAS와 함께 사용한다면 이점이 상당히 많이 존재하는 걸 알 수 있었다.
그럼, 이제 nginx는 어떻게 전 세계 사용률 1위라는 업적을 달성할 수 있었는지 확인해보겠다.

배경

아파치는 서버에 요청이 들어오게 되면 커넥션을 형성하기 위해 프로세스를 생성한다.
새로운 요청이 들어오게 되면 프로세스를 다시 생성하게 되고 이러한 방식이 반복된다.
프로세스 생성은 시간도 오래거릴고 자원을 많이 쓰기 때문에 요청이 들어오기 전 미리 생성하는 prefork방식으로 대응했다.
이러한 구조는 확장성이 유리하기 때문에 개발하기 쉽다는 장점에 많은 사용자들이 apach를 사용하여 웹서버를 구축했었다.
문제는 1999년 이후부터 서버의 트래픽 용량이 높아져 서버에 동시에 접속하는 커넥션을 대응하지 못하는 문제가 생기는데 이를 C10k Problems라고 한다.
또한 다음과 같은 단점이 생겼다.

  • 커넥션마다 프로세스를 할당하기에 메모리 부족으로 이어진다.
  • 확장성이라는 장점이 프로세스의 리소스 양을 늘려 무거운 프로그램이 되었다.
  • 많은 커넥션에서 요청이 몰리면 CPU 부하가 높아진다.

이러한 문제를 개선하기 위해 nginx가 탄생했다.

구조

nginx는 단일의 마스터 프로세스와 여러 워커 프로세스, 캐시로더캐시관리자로 구성되어 있다.
각 모듈 별 역할을 알아보자

  • 마스터 프로세스
    • 구성 읽기 및 유효성 검사
    • 소켓 생성 / 바인딩 / 닫기
    • 워커 프로세스 시작 종료 및 관리
    • 로그 파일 열기
  • 워커 프로세스
    클라이언트의 연결을 수락 처리하고 리버스 프록스 및 필터링 기능을 제공한다.
    즉 실제로 웹서버의 기능을 수행하는 모듈이며, 여러개가 생성될 수 있다.
  • 캐시로더
    온디스크 캐시 항목을 확인하고 nginx의 메모리 내 데이터베이스를 캐시 메타데이터로 채우는 역할을 한다.
  • 캐시 관리자
    주로 캐시 만료 및 무효를 담당한다.
    장애가 발생하면 마스터 프로세스에 의해 다시 시작된다.

프로세스

nginx가 실행되면 마스터 프로세스가 생성되고, 설정 파일을 읽어 워커 프로세스를 생성한다.
워커프로세스가 생성 될 때 내부에 listen 소켓을 배정받게 된다.
클라이언트로 요청이 들어오면 소켓에 커넥션을 형성하고 처리하게 된다.
커넥션은 여러개가 구성될 수 있으며, 정해진 keep alive time만큼 유지된다.
그리고 서버에서 처리해야할 작업 또는 상황을 event라고 한다.
이벤트는 큐에 담긴 상태에서 워커 프로세스가 처리할 때까지 비동기 방식으로 대기하게 된다.
그리고 워커 프로세스는 하나의 스레드로 이벤트를 꺼내서 처리해 나간다.
만약 큐에 담긴 요청중 하나가 시간이 오래 걸린면 스레드 풀(Thread Pool)을 만들어 그 요청은 따로 수행하게 된다.
워커 프로세스는 처리할 요청이 시간이 오래 걸릴 것 같으면 스레드 풀에 이벤트를 위임하고 다른 이벤트를 처리한다.
그래서 코어가 담당하는 프로세스를 바꾸는 횟수를 줄이기에 CPU의 컨텍스트 스위칭을 줄이게 된다.
이게 바로 nginx가 사용하는 Event-Driven Model(이벤트 기반 구조)이다.

성능

nginx는 커넥션이 발생했을 때 비동기적으로 처리하게 된다. 그리고 cpu 코어 수만큼의 워커 프로세스가 만들어지기 때문에, 메모리사용량이 적을수 밖에 없다.
또한 비동기처리를 기반으로 하기 때문에 동시접속 처리도 그만큼 빨라질 수 밖에 없다.
이 밖에도 로드밸런싱 기능, reverse froxy 기능과 같이 강력한 기능들이 많기 때문에 많이 사용하는 것 같다.

node.js의 최초개발자 Ryan Dahl은 다음과 같은 말을 했다.

"You just may be hacked when some yet-unknown buffer overflow is discovered. Not that that couldn't happen behind nginx, but somehow having a proxy in front makes me happy"
아직 알려지지 않은 버퍼 오버플로우가 발견되면 해킹 당할 수 있습니다. nginx가 완전히 막아주진 않지만, 프록시를 앞에 두는 것이 좋다고 생각합니다.

참조
내부프로세스
nginx란?

profile
즐겁게 코딩합시다 😀

0개의 댓글