(썸네일은 처음 엔진엑스에 대해 어렴풋이 들었을 때 전혀 이해하지 못했던 것이 기억나서
그냥 엔진엑스로 걸었다.)
역할의 개념 : 같은 컴퓨터라도 서비스를 제공하면 Server, 서비스를 제공 받으면 Client
하드웨어(물리적인 기계)
결국 백엔드 개발자가 개발한다는 그 서버, 그것이 바로 웹 서버
하드웨어가 아닌 소프트웨어의 개념
대표적으로 Apache, NginX, IIS(window용)
'웹' 서버이므로 컴퓨터들 즉 서버들 중에서도 웹사이트를 제공하는 서버로 만들어주는 서비스
Apache vs. NginX
Apache가 보다 오래전부터 널리 사용되어 옴. NginX가 요즘 점유율이 부쩍 늘었음.
이 둘은 근본적으로 작동 방식에서부터 차이가 있다.Apache
다중 프로세스로 일을 처리 (비동기)
MPM (멀티 프로세스 모듈) 방식으로 일함
- MPM prefork : 때마다 프로세스 자체를 새로 생성
- MPM worker : 한 프로세스 안에서 때마다 스레드를 새로 생성
그나마 MPM worker 방식이 메모리를 덜 잡아먹겠으나, 어떤 방식을 택한다해도 컨텍스트 스위칭(프로세스나 스레드가 하나의 일을 처리하다 다른 일을 처리하는 것)과정에서 자원 소모가 상당.
(NginX 도래 이후 아파치도 이벤트 처리 방식을 도입하긴했음)
--> 단점이 있으나, 다양하고 검증된 기능을 필요로 할 경우에는 Apache를 선택NginX
이벤트로 일을 처리 (Event Driven)
즉, 이벤트 하나 치고 또 하나 치고 또 하나 치고 이런 식으로 순차처리 하는 것 (동기)
아파치보다 더 가벼울 수밖에 없음
--> 성능과 가벼움을 중시한다면 당연히 NginX를 선택
정적 웹
블로그 페이지, 회사 소개 페이지처럼 컨텐츠가 바뀔 일이 없는 웹 페이지.
고정된 HTML, CSS, JS 코드로 구현이 가능.
완제품들을 갖다놓은 편의점 진열대와 같은 페이지
정적웹을 띄우기 위해 필요한 것은
브라우저 (ex. 크롬)와
(서버가 보내주는) 해당 브라우저가 읽어올 수 있는 HTML, CSS, 자바 스크립트 파일 각종 이미지, 기타 여러 데이터들임
'서버가 보내주는 각종 이미지, 기타 여러 데이터들'
이 자원들은 서버측 컴퓨터에 저장되어 있음
서버의 특정 폴더, 디렉토리에 이것들을 넣어두고 외부에서 접근 가능하도록 개방
이후 서버에 지정된 웹사이트 주소로 접속하면 이것들을 받아갈 수 있도록 하는 것이 웹서버의 기본 역할 중 하나
결국
동적 웹
게시판과 같이 항상 같은 내용이 뜨는게 아닌 사이트
누군가 댓글이라도 달거나 새로운 게시글을 작성하는 경우, 더이상 고정된 HTML 파일을 진열해서 제공할 수 있지 않음. 사용자가 접속할 때마다 DB내의 데이터들을 그때그때 잘 처리하여 새로운 페이지 내용을 보내줘야 함.
요리사가 바로바로 음식을 만들어주는 식당 같은 페이지
Apache나 NginX의 모듈로 동적 웹 구현이 가능함
(하지만 웹 서버의 '고유' 역할 중 하나가 이런 동적 웹을 구현하는 것이라고 보기는 애매할 수 있음)
Apache, PHP, Mysql(APM)조합으로 동적인 PHP 웹사이트를 제공하는 방식이
동적웹을 그리는 가장 대표적인 방법
APM 작동 방식
정적웹의 경우에는 정말 완제품 코드를 그대로 보여주는 기능을
동적웹의 경우는 실제로 그자리에서 코드(PHP)와 DB(mysql)내의 데이터를 요리해서 보여주는 기능을
톰캣, Node.js, Django 내장 서버 등의 전문 서버(Web Application Server)들과 클라이언트를 연결해주는 기능을
수행한다.
(여기는 잠시 자바 이야기)
요즘은 스프링부트에 톰캣이 내장되기 때문에 직접 접하거나 볼 일은 잘 없지만
자바와 JSP로 만든 웹 또는 API 어플리케이션을 실행할 때에는
자바 Web Application Server (WAS)인 톰캣이 실행된다.
JAVA - Springboot
스프링 기반의 사용화가 가능한 애플리케이션을 쉽게 만들기 위해 단독 실행을 가능하게 해주는 프로젝트
스프링이 필요한 설정을 대부분 미리 세팅해둠
(비슷한 예로 python - Django의 페어링을 떠올릴 수 있음)Springboot의 특징
단독으로 실행이 가능한 스프링 애플리케이션 생성
Tomcat, Jetty, Undertow를 내장 (후술할 내용과 연관)
기본설정이 되어있는 starter 컴포넌트 제공
가능한 자동으로 설정
상용화에 필요한 통계, 상태 체크, 외부 설정 등을 제공
설정을 위한 XML 코드를 생성하거나 요구하지 않음reference: https://toastfactory.tistory.com/227 [이삭이의 토스트 공장]
JAVA - JSP
Java Server Pages
HTML 코드에 JAVA 코드를 넣어 동적 웹을 생성하는 웹 어플리케이션 도구
WAS는 말그대로 '웹'과 '서버' 사이에 '어플리케이션'이 들어가서 WAS
즉, 그냥 그대로 자원을 보내주고 갖다주기만 하는 것이 아니라 뭔가 프로그래밍적인 작업이 더 들어간다는 의미. 그게 뭐냐면, 동적 웹을 전문적으로 처리해주는 것.
웹 서버는 최고 앞단, WAS는 그 바로 뒷단에서 실제 작업을 처리.
실제 WAS는 작업을 처리하고 해당 작업물은 웹 서버가 클라이언트에게 전달한다고 볼 수도 있고
WAS가 작업 처리 및 전달까지 모두 한다고 볼 수도 있다.
웹 서버와 웹 컨테이너의 합 혹은 웹 서버와 CGI(파이썬의 경우 WSGI)의 합으로 WAS를 보기도 한다.
Apache나 NginX와 같은 웹 서버가 다룰 수 있는 것은 PHP 정도에 불과하며, 스프링 정도만 되어도 톰캣과 같은 WAS가 필요해진다.
(JAVA 바이트코드로 컴파일되는 언어들에 쓰이는 것은 대표적으로 톰캣, Jetty, Undertow 등)
톰캣 작동 방식
(너무나 자바 상식)
- 스프링으로 코딩한 웹앱을 war 파일로 빌드
- war 파일 안에는 .class 파일, jsp, 이미지, CSS, JS 파일 등이 압축되어 있음
- 톰캣을 다운받으면 여러 폴더 및 파일들이 들어있는 하나의 폴더로 되어있는데 이 중 특정 폴더에 war 파일을 넣고 명령어를 실행하면 스프링 서비스가 톰캣을 사용하여 돌게 되는 것
(톰캣에 war 파일을 넣어 실행 -> 스프링 서비스가 톰캣 위에서 돔)- 요즘은 스프링을 톰캣이 들어있는 jar 파일로 빌드하여 배포하곤 함
(스프링에 톰캣을(jar 파일) 올려 빌드 및 배포 -> 톰캣이 스프링 위에서 돔)
Apache, NginX는 Web Server, 톰캣은 WAS.
위 그림에서처럼 구니콘이 WAS의 역할을 담당하는 것처럼 보인다. 그러나 사실 구니콘은 엄밀히 WSGI이다. python 언어를 사용하는 프레임워크 django는 그 자체로는 프레임워크이나, runserver
를 통해 WAS의 역할을 할 수 있게 된다. django에 NginX를 웹서버로 설치한다고 치면, NginX는 Http request를 처리하는 앞단이 되고, 실제 요청 처리는 runserver로 구동한 WAS가 담당하는 것이다. (그러나 이 runserver
는 실제 프로덕션 환경에서 쓰지 않는 것이 좋다. 장고 공식문서에서도 runserver
명령으로 돌리는 서버는 검수용일뿐이며 실제 프로덕션 환경에 적합한 정도의 보안을 갖추지 못했음을 명시하고 있다.)
django에서 Nginx를 웹 서버로 사용할 경우, NginX는 파이썬 언어를 이해할 수 없기에 WSGI(ex. 구니콘)가 http request를 python으로 번역하고 django의 response는 nginX가 알아들을 수 있도록 변환해주는 역할을 수행한다.
WSGI는 웹 서버인 게이트웨이 사이드와 서버사이드를 연결하는 역할인데, 이 때 서버사이드는 어플리케이션을 실제 실행하면서 환경 정보를 제공하고 콜백 함수를 어플리케이션 사이드에 전달한다. 이후 어플리케이션은 받은 request을 실행한 후 전달받은 콜백함수를 통해 response를 서버사이드에 넘긴다.
(reference: https://itmining.tistory.com/135)
JS의 경우 Node.js에서처럼 어플리케이션이 WAS 역할까지 할 수도 있다.
정적 또는 가벼운 동적 리소스를 제공하는 역할 외에도 웹 서버는
의 역할도 하기 때문
(우선) Proxy
어떤 사이트에 접속할 때 유저가 본인의 IP를 숨기기 위해(==서버에 방문하는 손님들이 본인의 집 주소를 감추기 위해) 중간에 설정하는 것.
프록시는 서버에 방문한 (주소를 감추는) 손님들이 최종 목적지로 타고 오는 대절버스와도 같음.
그 프록시 서버에서 데이터를 주고 받는데 이 프록시는 엄밀히 forward proxy에 해당한다.
Reverse Proxy
웹 서버가 수행하는 기능으로 반대로 유저에게 서버의 정보를 감추는 것.
이미 유저는 서버의 IP를 다 알고 찾아왔지만, 보안상 실제 서버의 내부 구조
(ex. 정적 리소스는 어디에 있는지, WAS가 동적 요소를 어떤식으로 처리하는지, 실제 서비스는 몇 번 포트로 돌고 있는지 등)를 감춰야할 필요가 있을 때 사용.
실제 처리단(서버의 내부 구조)까지 유저가 들어가지 못하도록 그 앞단에서 웹 서버가 처리된 결과만 내어주는 것.
만일 한 서버에서 A, B, C의 서비스(어플리케이션)를 제공한다고 치면 유저가 A, B, C 중 어느 주소로 접속을 하든 앞단에서 웹 서버에서 유저가 A, B, C 중 어느 주소로 찾아왔는지를 판단하여 유저의 request에 대해 뒷단에서 was에 의해 작업된(아님 웹 서버가 직접 작업한) 적절한 response를 내어주는 것.
유저가 여럿 몰렸을 때, 여러 WAS에 적절히 그 부하를 분산해주는 것.
서버에서 하나의 서비스(어플리케이션)를 제공하면서 웹 서버를 여럿 둔다면 그 이유는 '지속성 유지'에 있다.
실제로 정적을 넘어 동적인 부분까지 서비스를 업데이트해야 할 때 실제 서비스를 종료하고 업데이트 후 다시 실행을 해야한다면 서비스의 중단이 발생함. 즉 무중단 업데이트 및 배포를 위해 웹 서버 여러개를 두는 것.
(-> 웹 서버를 순차적으로 차례차례 업데이트하여 하나가 재부팅되는 동안에는 다른 웹 서버가 다른 WAS로 일처리를 분산시켜주어 유저 입장에서 중단이 없도록)
다수의 인스턴스(==WAS로 이해해도 좋음)로 서비스를 돌리고, 이를 웹 서버에서 밸런싱.
웹서버의 캐싱은 reverse proxy의 캐시를 의미함
(forward proxy의 캐싱은 사용자 관점의 캐싱. 한번 받아온 이미지 등 정적 파일이 사용자와 서버 사이에 있는 프록시 서버라는 곳에 쌓였다가 다음번 동일한 요청 시 다시 서버까지 가지 않고 한 번 꺼내온 것들을 빠르게 불러올 수 있도록 하는 것.)
reverse proxy의 캐싱은 반대로 서버단에서의 캐싱
-> 서버로 찾아온 유저들이 자주, 반복적으로 찾을만한 리소스들을 웹 서버단에 쌓아두고 빠르게 꺼내줄 수 있도록 하는 것
공통 : forward proxy든 reverse proxy든 사용자 입장에서 캐싱 덕에 빨라지는 것은 같음
Web Server와 WAS는 기능상 겹치는 부분이 있으나 각자가 특화된 부분들을 활용하는 것이 좋음
웹 서버의 경우 위에서 언급한 보안과 운영(로드밸런싱, WAS 상태 체크)에 더욱 특화되어 있으므로
제작된 웹, API 앞단에 두어 유저를 처음 맞도록 하자.
reference:
https://www.youtube.com/watch?v=Zimhvf2B7Es
얄팍한 코딩사전 '아파치, NginX, 톰캣이 뭔가요? (+ 웹서버, WAS, 로드밸런싱, 프록시)'