NginX

younghyun·2022년 8월 22일
0

NginX

트래픽이 많은 웹사이트의 서버(WAS)를 도와주는 비동기 이벤트 기반구조의 경량화 웹 서버 프로그램

클라이언트로부터 요청을 받았을 때 요청에 맞는 정적 파일을 응답해주는 HTTP Web Server로 활용되기도 하고, 또는 Reverse Proxy Server로 활용하여 WAS의 부하를 줄일 수 있는 로드밸런서 역할을 하기도 함.

Nginx가 만들어진 배경

1995년 UNIX 기반으로 만들어진 NCSA HTTPd(CERN httpd 웹 서버가 먼저 나옴). 하지만 이 프로그램은 버그가 굉장히 많아서 개발자들이 사용할 때 불편함을 많이 느낌. 그래서 문제를 해결하기 위해서 만들어진 것이 바로 Apache Server. Apache 같은 경우 요청이 들어오면 connection을 생성. 그래서 새로운 클라이언트의 요청이 올 때마다 새로운 process를 생성.

그런데 프로세스를 생성하는 과정은 시간이 오래 걸리기 때문에 프로세스를 미리 만들어 놓는 PREFORK라는 방식을 이용. 그래서 새로운 클라이언트의 요청이 오면 미리 만들어놓은 프로세스를 할당. 만약 만들어놓은 프로세스가 없다면 추가로 프로세스를 생성.

이런 구조 덕분에 개발자는 다양한 모듈을 만들어서 서버에 빠르게 기능을 추가할 수 있었습니다. 즉, 확장성이 높았고, Apache Server는 동적 컨텐츠를 처리할 수 있게 됨. 확장성이 좋다는 장점은 결국 요청을 받고 응답을 처리하는 과정을 하나의 서버에서 해결하기 좋음.

하지만 1999년에 들어오면서 컴퓨터가 많이 보급됨에 따라 요청이 많아져서 서버에 동시에 연결된 connection이 많을 때 더 이상 새로운 connection을 생성하지 못하게 됨.

이를 C10K(connection 10000 problem)문제라고 하는데 connection 10000개의 문제라는 뜻 입니다. Apache Server는 구조적으로 아래와 같은 문제점이 있었음.

  1. 메모리 부족: connection이 연결될 때마다 프로세스를 생성
  2. 무거운 프로그램: 확장성이 좋다는건 곧 리소스가 않다는 걸 의미
  3. CPU 부하 증가: 많은 connection 요청이 들어오면 context switching을 많이 하기에 CPU 부하가 증가

즉, Apache Server는 현대로 올수록 사용하기 꺼려졌고, 이러한 구조적 문제점을 해결한 Nginx가 2004년에 나왔습니다.

초창기 Nginx는 Apache와 함께 사용하기 위해 만들어짐. 웹 서버이기는 하지만 아파치 서버를 완전히 대체할 목적은 아님. 아파치 서버가 지닌 구조적 한계를 Nginx를 사용하면서 극복하려고 함.

위 이미지와 같이 수많은 동시 connection을 Nginx가 유지하고, Nginx도 웹 서버이기에 정적 파일에 대한 요청은 스스로 처리하고, 클라이언트로부터 동적 파일의 요청을 받았을 때만 아파치 서버와 connection을 형성하여 아파치 서버의 부하를 줄임.

Nginx의 구조
그렇다면 Nginx는 어떠한 구조로 되어있길래 그 많은 동시 connection을 유지할 수 있을까?

  • Nginx는 설정파일을 읽고, 설정에 맞게 worker process를 생성하는 master process가 있음.
  • worker process는 실제로 일을 하는 프로세스이며 worker process가 만들어질 때 지정된 listen 소켓을 배정받음.
  • 그리고 그 소켓에 새로운 클라이언트의 요청이 들어오면 connection을 형성하고 처리함.
  • connection은 정해진 Keep-Alive 시간만큼 유지. 하지만 connection이 형성되었다고 해서 worker process가 해당 connection 하나만 담당하지는 않음.
  • 형성된 connection으로부터 아무런 요청이 없다면 새로운 connection을 형성하거나 이미 만들어진 다른 connection으로부터 들어온 요청을 처리함.

Nginx에서는 이러한 connection 형성과 제거, 그리고 새로운 요청을 처리하는 것을 이벤트(event)라고 함.

그리고 이 이벤트들은 os커널이 queue형식으로 worker process에게 전달. 이 이벤트들은 queue에 담긴 상태에서 비동기 상태로 대기. 그리고 worker process는 하나의 스레드로 이벤트를 꺼내서 처리해 나감. 이런 방식은 worker process가 쉬지 않고 일을 하기에, 요청이 없을 때 프로세스를 방치시키는 Apache Server보다 훨씬 효율적으로 자원을 사용할 수 있음.

위 이미지를 보면 알 수 있듯이 Apache 방식인 스레드 기반은 하나의 커넥션 당 하나의 스레드를 잡아먹지만 이벤트 기반 방식은 여러 개의 connection을 전부 Event Handler를 통해 비동기 방식으로 처리해 먼저 처리되는 것부터 로직이 진행.

이러한 이벤트 기반 구조가 바로 Nginx의 핵심.

Nginx의 장단점
Nginx 단점

  • 동적 컨텐츠를 기본적으로 처리 할 수 없음
  • 동적 콘텐츠에 대한 PHP 및 기타 요청을 처리하려면 NGINX가이를 실행하기 위해 외부 프로세서로 전달하고 렌더링 된 콘텐츠가 다시 전송 될 때까지 기다려야함(프로세스 속도 저하).
  • 즉, 동적 웹 페이지 컨텐츠를 가진 모든 요청을 위해 외부 자원과 연계(php-fpm)

Nginx 장점

  • 이벤트 중심 접근 방식을 사용하여 클라이언트 요청 제공
  • 제한된 하드웨어 리소스로도 여러 클라이언트 요청을 동시에 효율적으로 처리
  • 단일 스레드를 통해 여러 연결을 처리 가능
  • 최소한의 리소스로 웹 서버의 아키텍처를 개선하기 위해 독립형 HTTP 서버로 배치 가능

성능 비교

위 이미지는 동시 connection 수 당 메모리 사용률을 나타냄. Apache Server에 비해 Nginx는 동시 connection 수가 늘어나도 메모리 사용률이 낮고 일정한 사실을 알 수 있음.

동시 connection 수가 많아졌을 때 처리하는 초당 요청 수는 Nginx가 Apache에 비해 압도적으로 높은 모습을 보여줌.

정리
Apache의 한계
클라이언트 접속마다 Process 혹은 Thread 를 생성하는 구조. 1만 클라이언트로부터 동시접속 요청이 들어온다면 CPU 와 메모리 사용이 증가하고 추가적인 Process/Tread 생성비용이 드는 등 대용량 요청에서 한계를 보. 또한, Apache 서버의 프로세스가 blocking 될 때 요청을 처리하지 못하고 처리가 완료될 때까지 대기상태에 있음. 이는 Keep Alive(접속대기) 로 해결이 가능하지만, 효율이 떨어짐.

Nginx 의 정리
Nginx 는 위에서 언급했듯이 Event-Driven 방식으로 동작. 즉, 프로그램 흐름이 이벤트에 의해 결정 됨. 한 개 또는 고정된 프로세스만 생성하고, 그 내부에서 비동기로 효율적인 방식으로 task 를 처리. Apache 와 달리 동시접속자 수가 많아져도 추가적인 생성비용이 들지 않음.

  • 비동기 이벤트 기반으로 요청하여 적은양의 스레드가 사용되기 때문에 CPU소모가 적음.
  • Apache 와 달리 CPU 와 관계없이 I/O 들을 전부 Event Listener로 미루기 때문에 흐름이 끊이지 않음.
  • context switching 비용이 적음.
  • 다수의 클라이언트 연결을 효율적으로 처리 가능.
  • Apache에 비해 모듈이 다소 적음.
  • 복잡한 처리가 필요한 요청의 경우 시스템 큐에 쌓이게 되어 성능이 저하될 수 있음.

설치
node.js도 웹 서비스 구동이 가능하지만 보안요소와 여러 기능이 안정되고 검증된 NginX를 AWS에서 제공하는 EC2(컴퓨터 한대 빌림)안에 설치해서 사용. (내 컴퓨터에 서버를 24시간 켜 놓기도 힘들고, 고장 날 수도 있음.)

호스팅(Hosting)
서버 컴퓨터의 전체 또는 일정 공간을 이용할 수 있도록 임대해 주는 서비스

AWS 홈페이지 접속 -> 회원가입 -> Region(서비스할 지역과 가까운 지역(통신 속도 증대 위해) : 대한민국 ) -> EC2서비스 설정(운영체제만 설치된 빈 컴퓨터) ->




서버명은 web server

운영체제는 ubuntu 또는 CentOS

Ubuntu Server 20.04.LTS (HVM) 550 volumne Type
( 20버전 설치, '프리티어' 사용 시 무료 )


키 페어 설정. 원격 접속 시 키 페어 필요함. ( 로그인 시 패스워드 역할 )

aws-webserver .pem파일 (윈도우 쓰면 .ppk 내보내기 하고 불러다가 써야 함.)
키 페어 파일은 패스워드역할 잘 보관.

패스워드 선택 후

SSH는 원격 붙을 때 사용하는 통신 방법 (http 프로토콜 처럼 하나의 방식)
http는 80번 서비스 이용. SSH는 22번 서비스 오픈 하겠다는 말
이게 오픈이 되있어야 해 빌린 컴퓨터에 접근 가능. 그 다음에 NginX 설치하는 것은 웹 서비스 제공하겠다
방화벽 쪽에 HTTP 기본값이 막혀있음

허용하면 HTTP 트래픽 허용됨.
HTTPs는 사용안하지만 체크는 함.

인스턴스 시작

unbuntu20 nginX설치 검색


sudo apt update -> sudo apt upgrade -> sudo apt install nginx

public Ip 주소에 접근 해야 함
SSH가지고 어떻게 접근하는가?
mac aws ssh 접근


ssh -i pem경로 ubuntu@public ip4 주소 또는 ip4 주소

ssh -i ~/Desktop/aws-webserver.pem ubuntu@52.78.77.77 


내 컴퓨터 Terminal이 아님.
서울 데이터 센터에 있는 컴퓨터에 원격 붙어서 사용하고 있는 것
그래픽 환경이 아님.
그럼 여기서 아까 본 명령어 하나 하나 입력 해서 실행함.
sudo apt update
sudo apt upgrade
sudo apt install nginx
nginx 화면까지 보이게 하는 게 목표

sudo systemctl enable nginx

public ip주소 입력

실행됨. nginx 서버가 가진 html파일 줌.


nginx 기본 경로가 etc에 있음.

nginx config 파일 수정 시


우리가 중요하게 볼 파일은


default파일이 /etc/nginx/sites-available과 연결이 되어있음.
vi default하면 뭔가 나옴

중요하게 볼게 var/www/html이게 html파일 모아놓은 기본 경로.


vi index.nginx-debian.html

서버는 Html파일 있음. 단순히 회사 소개 페이지 만들거면 Node.js가지고 만들 필요 없이
Nginx만 설치해서 회사소개 내용 꾸며 줌
Sudo vi index.nginx-debian.html ( 관리자 모드로 해야 수정 가능 )

nginx가 html 파일 준비 해놓고 준비한 파일을 클라이언트에게 제공.

이전 파일 다시 봄.
/etc/nginx/sites-available/default


index.html index.htm index.nginx-debian.html
이거는 server_name에 index.html -> index.htm -> index.nginx-debian.html
차례대로 보여줌.

ip 주소 입력했을 때 마지막 파일명만 보여줌. index.html만어떤 파일 먼저 보여줄지 결정하는 부분
index.html생성해봄
sudo vi index.html

다시 ip주소 호출 시

index.html 파일이 먼저 나옴.
mkdir board라는 폴더를 만듦.

board 폴더에 아무 파일도 없음.
그래서 ip주소/board 해도 아무것도 안 나옴.

sudo vi index.html
test 저장 시

var/www/html뒤로는 board부터는 이 url과 매칭 됨.

당연히 들어가짐. 시드니 컴퓨터가 제공하는 것. 어떤 디바이스에서 접근해도 사이트 접근 가능
그럼 간단히 NginX 설치 까지 진행 해봄. 만든 소스 코드 그냥 여기다 넣어주면 됨.

리액트로 소스코드 만들었어. 그럼 리액트 가지고 빌드 하는 과정이 있음.

빌드 한 폴더

여기다 넣으면 누가 가장 메인? index.html이 가장 메인. index.html 파일 여기다 메인 가지고 두고
여기 접근하면 만든 리액트 소스코드 index.html 받아와서 js 소스코드 받아와서 동작.

NginX에서 대표적으로 제공하는 다양한 기능이 있음
첫 번째. 설정을 안했지만 뭐가 뜨고 있는가 주의 요함

https가 아니어서
지금 우리는 http만 사용 중. 웬만한 웹 사이트는 Https 사용해야 크롬에서 이동도 잘되고 경고창도 안 뜸. 적용해야함.
그럼 이걸 알고 있어야 해. http 통신은 80번 사용. https는 443포트 번호 사용
그럼 우리는 어떻게 해야 하냐. 사용자가 https를 붙이지 않고 웹 사이트에 접근 하면

52.63.252.30에 접근했어. 그럼 이거는 지금 80 번 포트 가지고 접근
그럼 NginX에서 무슨 짓을 할 수 잇는가. 포트 포워딩 이라는 것을 할 수 있음.
개념은 맞음. 포트를 바꿔주는 거니까
NginX에서 80번 가지고 서비스가 들어오면

board파일 보여줘 가지고 설정할 수 있지만 80번으로 요청 들어오면 443페이지로 이동해줘 라고도 설정 가능
그래서 저희가 이 설정을 NginX에서 설정 가능.
저희는 지금 HttpS가 없어서 이동을 해도 이동이 안됨.
443이 없어서

둘 째. node.js 가지고 웹 서비스 개발 했다고 해봄
node.js에서 8000번 포트 가지고 구동 되고 있음
NginX에서 80번 포트가지고 접근을 하는데 80/board/list라고 요청을 보내면, 여기 있는 80번 포트를 8000가지고 바꿔서 board/list하고 요청을 보내줘

Node.js에 API가 board/list하고 구현이 되어잇으면 그럼
8000번 한테 요청을 보낼 수 있음.
그럼 또 무슨 짓을 할 수 있는가.
만약에 나중에 개발하실 때 Node.js에서 8000번 포트가지고 서비스가 구성이 되어있는데
여기에 만약에 express내에
/board/list
/board/write
/board/edit
이렇게 있는데 개발이 너무 되서 하나 하나 바꾸기는 그렇고
개발 다 해놓고 앞에 api 붙이고 싶음.
하나하나 바꾸면 버그가 발생할 수도 있음.

그럼 어떻게 할 수 있냐. 우리가 이걸 Proxy 설정이라고 함.
NginX 에서 사용자가 /api/board/list이렇게 요청을 하면
내가 NginX 가 알아서 8000 포트에 /board/list 요청을 보내게 해줄게 할 수 있음.
그러면 저희는 클라이언트에서 api 붙여서 요청 보내면

NginX가 api를 제거 하고 알아서 8000번 포트에 /board/list요청을 보내줌
이걸 저희가 프록시 설정이라고 함.

리눅스 명령어
sudo : 하나의 명령에 대해 일시적으로 root권한을 빌리는 것 ( root : 리눅스, macOS와 같은 유닉스 계열의 운영체제에서 모든 권한을 가지고 있는 최고 관리자가 사용하는 ID )
chmod : 파일 권한 변경
ls : 현재 위치에 있는 내용(디렉토리, 허가권, 소유권, 파일 등)을 확인
ls -l: 파일에 대한 정보를 길게 출력

vim 편집기 명령어
vi [파일명] : 파일 열기, 작성

unbuntu 명령어
apt : ubuntu계열에서 외부 기능 설치할 때 사용

웹 서버(Web Server), 웹 어플리케이션 서버(Web Application Server)

정적 페이지(static pages)와 동적 페이지(dynamic pages)

우리가 보는 웹페이지는 위의 이미지처럼 웹 서버는 주소(url)를 가지고 통신 규칙(http)에 맞게 요청하면, 알맞은 내용(html)을 응답받음.
그러나 이처럼 단순한 클라이언트(웹 브라우저)와 웹 서버로는 정적(static)인 페이지밖에 처리하지 못한다는 한계를 가짐. 이러한 html의 태생적인 한계를 극복하기 위해 application을 활용한 것이 Web Application.
따라서 정적인 html의 한계를 극복하고 동적인 페이지를 제공하고자 하는 목적, 더 나아가 보안 강화와 장애 극복을 가능하게 만드는 것이 WAS

정적 페이지와 동적 페이지는 말 그대로 페이지가 바뀌느냐 바뀌지 않느냐의 차이

1) Static Pages

  • Web Server는 파일 경로 이름을 받아 경로와 일치하는 file contents를 반환
  • 항상 동일한 페이지 반환
  • html, css, js, images 파일과 같이 컴퓨터에 저장되어 있는 파일

2) Dynamic Pages

  • 인자의 내용에 맞게 동적인 Contents를 반환
  • 즉, 웹 서버에 의해서 실행되는 프로그램을 통해서 만들어진 결과물
  • 아래 이미지에서 개발자는 Servlet에 doGet()을 구현

Web Server와 WAS차이
1) Web Server
클라이언트로부터 HTTP 요청을 받아 HTML 문서나 각종 리소스(Resource)를 전달하는 컴퓨터

요청에 따라 아래의 두 가지 기능 중 적절하게 선택하여 수행.

기능 1

  • 정적인 컨텐츠를 제공
  • WAS를 거치지 않고 바로 자원을 제공

기능 2

  • 동적인 컨텐츠 제공을 위한 요청을 전달
  • 클라이언트의 요청(Request)을 WAS에 보내고, WAS가 처리한 결과를 클라이언트에게 전달(응답, Response)
  • 클라이언트는 일반적으로 웹 브라우저를 의미

Web Server에는 Apache Server와 NginX가 있는데 각각의 특성은 아래와 같음.

  • Apache Server: BSD, Linux 등 Unix계열뿐 아니라 Windows와 같은 기종에서도 운용 가능.
  • NginX: 가벼움과 높은 성능을 목표로 함, 웹 서버, 리퍼스 프록시 및 메일 프록시 기능을 가짐.

Apache Tomcat이라고 하는 이유
웹서버는 Apache, WAS는 Tomcat
2008년에 릴리즈된 Tomcat 5.5 부터 정적 컨텐츠 처리기능 추가
-> 순수 Apache를 사용하는것에 비해 성능 차이 없음
-> Tomcat이 Apache의 기능을 포함하므로 Apache Tomcat이라고함

2) Web Application Server, WAS
WAS는 웹 애플리케이션과 서버 환경을 만들어 동작시키는 기능을 제공하는 소프트웨어 미들웨어 프레임워크

위 이미지와 같이 WAS는 Web Server와 Web Container(JSP, Servlet)으로 이루어져 있음.
Web Server와의 차이점은 Web Container를 가진다는 점이며 WAS는 HTML 같은 정적인 페이지에서 처리할 수 없는 비즈니스 로직이나 DB 조회 같은 동적인 콘텐츠를 제공.

그런데 대규모 프로젝트를 보면 아래와 같이 WAS와 Web Server를 분리한 형태를 볼 수 있습니다. 분리를 하면 생기는 장점이 무엇일까요?

  1. 기능을 분리해 서버 부하 방지 가능
  • WAS는 DB 조회 등 페이지를 만들기 위한 다양한 로직을 처리하는데, 단순한 정적 콘텐츠를 WAS에서 제공한다면 다른 작업에 사용하는 리소스들로 인해 지연이 생겨날 수 있음.
  1. 물리적 분리하여 보안 강화
  • SSL에 대한 암복호화 처리에 Web Server를 사용
  • 공격에 대해 Web Server를 앞단에 두어 중요한 정보가 담긴 DB나 로직까지(WAS까지) 전파되지 못하게 함.
  1. 여러 대 WAS를 연결이 가능
  • Load Balancing(부하의 균등화) 가능 -> 한 서버가 다운되더라도 서비스를 이어갈 수 있다는 장점이 있음.
  • fail over(장애 극복), fail back 가능.
  • 대용량 웹 애플리케이션의 경우(여러 개의 서버 사용) Wev Server와 WAS를 분리하여 무중단 운영을 위한 장애 극복에 쉽게 대응할 수 있음.
  1. 다른 종류 WAS로 서비스 가능

Forward Proxy, Reverse Proxy

프록시(Proxy)
프록시의 사전적 의미는 '대리', '대신'. 보안상의 문제로 직접 통신을 주고받을 수 없는 두 PC 사이에서 통신을 할 때 직접 하지 않고 중간에서 대리로 중계를 하는 개념.

이렇게 중계 기능을 하는 것을 '프록시 서버'

Forward Proxy
클라이언트에서 서버로 리소스를 요청할 때 직접 요청하지 않고 프록시 서버를 거쳐서 요청함. 이 경우 서버에서 받는 IP는 클라이언트의 IP가 아닌 프록시 서버의 IP이기 때문에 서버는 클라이언트가 누구인지 알 수 없음. 따라서 서버에게 클라이언트가 누구인지 감춰주는 역할.

예를 들어 사용자가 google.com 에 연결하려고 하면 사용자 PC 가 직접 연결하는게 아니라 포워드 프록시 서버가 요청을 받아서 google.com 에 연결하여 그 결과를 클라이언트에 전달(forward).

포워드 프록시는 대개 캐싱 기능이 있으므로 자주 사용되는 컨텐츠라면 월등한 성능 향상을 가져올 수 있으며 정해진 사이트만 연결하게 설정하는 등 웹 사용 환경을 제한할수 있으므로 보안이 매우 중요한 기업 환경등에서 많이 사용.

  • 클라이언트가 서버에게 요청할 때 직접 서버에 접근하지 않고 포워드 프록시 서버에게 요청하면 포워드 프록시 서버가 해당 서버에게 접근하여 요청을 전달하고 결과를 클라이언트에게 전달해주는 방식.
  • 포워드 프록시는 캐시 기능을 사용하기 때문에 캐시 서버로 활용하여 성능을 향상할 수 있음.
  • 자주 사용되는 자원을 캐시에 저장해놓기 때문에 해당 자원 요청이 온다면 서버에게 갈 필요 없이 프록시 서버 자체에서 처리가 가능.
  • 클라이언트가 서버를 직접 접근하지 못하기 때문에 접근 가능한 사이트를 제한할 수 있으므로 보안을 향상할 수 있음.
  • 즉, 클라이언트는 서버를 알지만, 서버는 프록시를 통해 요청이 오기 때문에 클라이언트를 알지 못함.

Reverse Proxy
리버스 프록시는 포워드 프록시와 반대 개념. 애플리케이션 서버의 앞에 위치하며 클라이언트가 서버를 요청할 때 리버스 프록시를 호출하고 리버스 프록시가 서버로부터 응답을 전달받아 다시 클라이언트에게 전송하는 역할.

이 경우, 클라이언트는 애플리케이션 서버를 직접 호출하는 것이 아니라 서버를 통해 호출하기 때문에 리버스 프록시는 애플리케이션 서버를 감추는 역할을 하게 됨.

예를 들어 리버스 프락시로 웹 서버를 설정할 경우 사용자가 example.com 웹 서비스에 데이타를 요청하면 Reverse Proxy 는 이 요청을 받아서 내부 서버(보통 WAS 입니다)에서 데이터를 받은후에 이 데이터를 사용자에게 다시 전달하게 됨.

  • 클라이언트가 서버에게 요청할 때 직접 서버에 접근하지 않고 리버스 프록시 서버가 이 요청들을 받아서 내부 서버에 접근하여 요청을 전달하고 결과를 클라이언트에게 전달해주는 방식.
  • 마찬가지로 클라이언트는 내부 서버를 접근하지 못하기 때문에 보안과 성능을 향상할 수 있음.
  • 여러 개의 내부 서버를 둘 수 있기 때문에 로드 밸런싱이나 서버 확장을 통해 트래픽을 분산시킬 수 있음.
  • 포워드 프록시 서버와는 반대로 내부 서버는 클라이언트를 알지만, 클라이언트는 프록시를 통해 내부 서버를 접근하기 때문에 내부 서버를 알지 못함.

참고
https://kanoos-stu.tistory.com/entry/Nginx
https://dkswnkk.tistory.com/513
https://blog.slashuniverse.com/m/13

profile
선명한 기억보다 흐릿한 메모

0개의 댓글