웹 서버

seongmin·2022년 12월 9일
1

Cloud

목록 보기
3/4
post-thumbnail

Tomcat

Tomcat은 Apache사에서 개발한 서블릿 컨테이너만 있는 오픈소스 웹 애플리케이션 서버다. Spring Boot의 내장 서버이기 때문에 별도의 설치 과정 없이 자연스럽게 Tomcat을 사용할 수 있다. Tomcat은 다음과 같은 특징을 가지고 있다.

  • 자바 애플리케이션을 위한 대표적인 오픈소스 WAS(Web Application Server)
  • 오픈소스이기 때문에 라이선스 비용 부담 없이 사용할 수 있다.
  • 독립적으로도 사용 가능하며 Apache 같은 다른 웹 서버와 연동하여 함께 사용할 수 있다.
  • Tomcat은 자바 서블릿 컨테이너에 대한 공식 구현체로, Spring Boot에 내장되어있어 별도의 설치 과정이 필요 하지 않다.

spring-boot-starter-web 모듈의 토글을 열어보면, 해당 모듈이 포함하고 있는 다른 모듈을 확인할 수 있다. 웹 서버를 구성하는 모듈 속엔 spring-boot-starter-tomcat 모듈도 포함하고 있다. 따라서 우리는 Tomcat을 설치하는 과정이 없어도 Spring Boot를 실행할 때 내장되어있는 Tomcat을 통해 실행됨을 알 수 있다.

Jetty

Jetty는 이클립스 재단의 HTTP 서버이자 자바 서블릿 컨테이너다. Jetty도 Tomcat과 같이 자바 서블릿 컨테이너이자 서버로 사용할 수 있기 때문에 개발자는 원하는 서버를 선택하여 프로젝트를 구성할 수 있다. Jetty의 특징은 다음과 같다.

  • 2009년 이클립스 재단으로 이전하며 오픈소스 프로젝트로 개발되었다.
  • Jetty는 타 웹 애플리케이션 대비 적은 메모리를 사용하여 가볍고 빠르다.
  • 애플리케이션에 내장 가능하다.
  • 경량 웹 애플리케이션으로 소형 장비, 소규모 프로그램에 더 적합하다.

Spring Boot 서버 Jetty로 변경하기

아무런 설정을 해주지 않는다면 Spring Boot의 기본 내장 서버인 Tomcat으로 실행된다.

build.gradle 파일에서 spring-boot-starter-web 의존성이 추가되어있는 부분을 확인한다. 이 의존성 모듈 내에 포함되어있는 Tomcat을 제외시킨다. 제외 시킨 후 프로젝트를 재 빌드하면 의존성이 제거 되었음을 확인할 수 있다.

implementation ('org.springframework.boot:spring-boot-starter-web') {
		exclude module: 'spring-boot-starter-tomcat'
	}

Tomcat을 제외했다면 대체할 서버로 Jetty 의존성을 추가한다. 추가한 후 프로젝트를 재 빌드하면 Jetty에 대한 의존성이 추가되었음을 확인할 수 있다.

implementation ('org.springframework.boot:spring-boot-starter-jetty')

Jetty로 변경하여 실행되는 모습을 확인할 수 있다.

Nginx - Proxy Server

Nginx는 가볍고 높은 성능을 보이는 오픈소스 웹 서버 소프트웨어다. Tomcat과 Jetty는 자바 서블릿 컨테이너 혹은 웹 애플리케이션 서버였다면, Nginx는 클라이언트에게 정적 리소스를 빠르게 응답하기 위한 웹 서버로 사용할 수 있다. Nginx는 다음과 같은 특징을 가지고 있다.

  • Nginx는 트래픽이 많은 웹 사이트의 확장성을 위해 개발된 고성능 웹 서버다.
  • 비동기 이벤트 기반으로 적은 자원으로 높은 성능과, 높은 동시성을 위해 개발되었다.
  • 다수의 클라이언트 연결을 효율적으로 처리할 수 있다.
  • 클라이언트와 서버 사이에 존재하는 리버스 프록시 서버로 사용할 수 있다.
  • Nginx를 클라이언트와 서버 사이에 배치하여 무중단 배포를 할 수 있다.

Spring Boot와 Nginx 연동하기

기존의 구조에서 스프링부트 앞에 Nginx로 리버스 프록시 서버를 구축하여, 아래 그림처럼 클라이언트와 서버가 Nginx를 통해서 소통할 수 있도록 만들기

1. Nginx 설치

Nginx 다운로드 사이트에서 Stable 버전을 다운로드한다.

2. Nginx 실행

  • 명령어로 실행하기
$ sudo /etc/init.d/nginx start

실행 확인

3. Nginx 설정 파일 수정

Nginx 실행파일이 있던 폴더(압축 해제한 폴더)에 설정파일이 모여있는 conf 폴더가 있다. conf 폴더 내의 nginx.conf 파일을 수정한다. 우클릭 후 IntelliJ에서 수정하거나 터미널에서 nano 에디터로 수정할 수 있다.

Nginx 실행 파일이 있는 폴더(압축 해제한 폴더)로 이동하여 다음 명령어를 실행한다.

$ nginx -s reload

Nginx 재시작 후 localhost (80번 포트는 생략 가능)에 접속하면 아래와 같은 문구가 나타난다. 80번 포트로 수정한 Nginx에는 접속이 되지만, 아직 8080번 포트를 사용하지 않기 때문에 나타나는 문구다. Spring Boot(8080번 포트)를 실행한다.

Nginx는 다음의 명령어로 종료할 수 있다.

$ nginx -s stop
$ .\nginx -s stop

NginX - Load Balancer

1. 두 개의 스프링부트 서버 실행

  • 프로젝트 파일이 위치한 폴더 내로 이동한다.

  • 프로젝트를 빌드한다.
$ ./gradlew build

  • 빌드 파일을 실행한다. (포트를 변경하지 않은 경우 8080번 포트에서 실행된다.)
java -jar sample-0.0.1-SNAPSHOT.jar

  • 실행 결과

빌드 파일을 실행하면 현재 실행을 위해 사용한 프로세스의 ID가 화면에 출력된다.

8080번 포트에서 205번의 PID를 통해 실행되었음을 알 수 있다.

  • 빌드 파일을 이용하여 새 터미널에 다른 포트(8081번 포트)에서 실행한다.
java -Dserver.port=8081 -jar sample-0.0.1-SNAPSHOT.jar

  • 실행 결과

8080번 포트로 실행했을 때 PID가 205였던 것과 달리 8081번 포트에서는 PID가 441인 것을 알 수 있다.

즉, 두 프로젝트는 서로 별개의 프로세스를 가지며 각각 실행되었다. 어느 하나를 멈춘다고 해도 다른 포트로 열린 프로젝트에 영향이 가지 않는다.

2. NGINX 설정파일 수정

  • 이전에 작성한 내용은 주석처리하거나 삭제 후 진행한다.
http {
	upstream backend {
		server localhost:8080;
		server localhost:8081;
	}
	location / {
		proxy_pass http://backend;
	}
}

위의 코드는 backend라는 서버 그룹을 만든 뒤 그룹 자체로 전달을 하는 구조다. 서버 그룹의 이름은 다른 이름으로 변경 가능하다.

이 때 그룹에 속한 각 서버의 값은 위에서 실행한 두 개의 스프링부트 프로젝트 접속 URL을 작성한다. 로컬환경에서 8080번 포트와 8081번 포트로 실행했기 때문에 각각 포트 번호까지 함께 작성한다.

서버 그룹을 모두 작성했다면 location의 proxy_pass 값으로 해당 서버 그룹을 설정한다. NGINX의 포트는 80번으로 설정되어있기 때문에 포트를 생략한 localhost 로 접속시 8080번 포트와 8081번 포트가 번갈아 연결된다.

3. 로드밸런싱 결과

NGINX는 localhost (80번 포트 생략가능) 로 실행된다. 스프링부트 실행파일과 연결되었음을 알 수 있다.

여기서 새로고침을 하면 PID가 1367, 1446으로 두 프로세스가 번갈아 나오는 것을 확인할 수 있다.

Nginx 명령어

// 설치
$ sudo apt-get install nginx

// 버전확인
$ nginx -v

// 시작
$ sudo service nginx start
$ sudo systemctl start nginx
$ sudo /etc/init.d/nginx start

// 재시작
$ sudo service nginx restart
$ sudo systemctl restart nginx
$ sudo /etc/init.d/nginx restart

// 중지
$ sudo service nginx stop
$ sudo systemctl stop nginx
$ sudo /etc/init.d/nginx stop

// 상태
$ sudo service nginx status
$ sudo systemctl status nginx

// 설정 reload
$ sudo service nginx reload
$ sudo systemctl reload nginx
$ sudo nginx -s reload

// configuration file syntax check
$ sudo nginx -t

0개의 댓글