외부에 노출되어야 하는 네 개의 모듈 즉 네 개의 서로 다른 웹사이트가 존재하는데, 외부로 나갈 수 있는 포트는 하나 뿐이니 하나의 포트 안에서 네 개의 모듈을 모두 서빙하라는 요구사항이었다.
처음에는 "이게 무슨 헛소리지..."하면서 당황했었다. 그렇다고 을의 입장에서 "헛소리 하지 말고 포트 네 개 열어주십쇼." 라고 말하기도 뭐했다. 그래서 이를 해결하기 위해 같이 프로젝트를 진행하는 다른 회사의 개발자와 이야기를 하던 중 리버스 프록시로 해결할 수 있을 것 같다는 이야기를 들었다.
그 말을 듣고 옛날에 포트 하나로 두 개의 모듈을 서빙할 때 과장님께서 "리버스 프록시를 활용하라"고 알려주셨던 게 기억이 났다. 때마침 서버 안에 static 파일 서빙을 위한 아파치 서버가 설치되어 있었고, 이를 통해 해당 요구사항을 충족시킬 수 있었다.
과장님께서 가르쳐 주셨던 내용을 적어놓았다면, 위 요구사항을 들었을 때 바로 해결할 수 있었겠지만 이번에는 그러지 못했다. 만약 타 회사 개발자가 리버스 프록시라는 키워드를 언급하지 않았다면 네 개의 포트를 열어달라고 고객에게 요구했을 지도 모른다. 그래서 다음부터는 까먹지 않고 유사한 요구사항 발생 시 곧바로 해결할 수 있도록 해당 작업 내용을 적어놓을까 한다.
Reverse Proxy
리버스 프록시는 인터넷과 서버 사이에 위치해서 클라이언트의 요청을 대신 전달하는 서버이다. 즉 클라이언트의 요청을 받아 적절한 백엔드 서버로 요청을 전달하고, 백엔드 서버의 응답을 다시 클라이언트에게 전달한다.
리버스 프록시를 사용함으로 얻을 수 있는 이점은 아래와 같다.
- 로드 밸런싱 : 여러 서버 간 트래픽을 균등하게 분배해 성능을 향상시킨다.
- 캐싱 : 주로 사용되는 웹 컨텐츠를 캐시해 응답 시간을 줄인다.
- 암호화 : 클라이언트와의 통신을 SSL 암호화를 통해 보안을 강화할 수 있다.
- 글로벌 서버 로드 밸런싱 : 지리적으로 여러 위치에 분산된 서버 중 가장 가까운 위치의 서버로 라우팅할 수 있다.
그리고 단점은 아래와 같다.
- 복잡성 증가 : 클라이언트와 서버 사이에 리버스 프록시가 들어가기에 구성과 관리가 복잡해질 수 있다.
- 비용 증가 : 추가 하드웨어나 소프트웨어가 필요하므로 비용이 증가할 수 있다.
- 지연 증가 : 올바르게 구성하지 않을 경우 네트워크 지연이 발생할 수 있다.
위 내용을 적던 중 갑자기 궁금한 점이 생겼다.
프록시와 리버스 프록시의 차이점이 뭘까? 하는 점이다.
궁금증 해결을 위해 검색을 할 결과 둘 사이의 차이점은 위치, 역할, 용도 정도로 설명할 수 있을 것 같다.
프록시 | 리버스 프록시 | |
위치 | 클라이언트와 인터넷 사이 | 인터넷과 서버 사이 |
역할 | 클라이언트의 요청을 인터넷으로 전달 | 인터넷의 요청을 서버로 전달 |
용도 | 사용자의 인터넷 사용 관리 및 제어 | 서버의 부하 분산, 보안 및 성능 최적화 |
Apache Server를 이용한 도메인 기반 리버스 프록시
리버스 프록시는 Nginx, HAProxy, Apache Server 등 여러 SW들이 존재하지만, 앞서 언급했듯 서버에는 apache server가 설치되어 있기에 해당 모듈을 이용해 설명을 하고자 한다.
우선 시작하기 전에 리버스 프록시를 하는 방법에는 대표적인 방법 두 가지가 있다. 첫 번째는 URL을 이용한 리버스 프록시, 두 번째는 도메인을 이용한 리버스 프록시이다.
우선 URL을 이용한 리버스 프록시는, 경로 패턴을 기반으로 요청을 다른 서버로 라우팅한다.

위 그림을 예시로 들면, URL이 http://{ip}/A/service/download 같이 입력하면 A server로 request가 라우팅되고, http://{ip}/B/service/download 같이 입력하면 B server로 request가 라우팅되는 형식이다.

하지만 이 기술은 API를 서빙할 때는 사용할 만 하지만, 웹 포탈을 서빙할 때는 사용하기 부적합했다.
예를들어 아래와 같은 메커니즘으로 동작하는 서버가 있다고 보자.
- /main 진입
- 웹 포탈이 자동으로 /dashboard url로 redirect
그런데 /A/main url로 진입 시 자동으로 /dashboard로 redirect될 때, 리버스 프록시 서버는 /dashboard를 알지 못한다. 만약 리버스 프록시가 알게 하려면 /A/dashboard로 redirect uri를 수정해야 하는데, 그러러면 프로그램 자체를 수정해야 한다.
* 애초에 css, js 같은 정적 파일도 못불러온다.
그리고 지금의 목적은 웹 포탈을 라우팅하는 것이기에, URL을 이용한 리버스 프록시 말고, 도메인을 이용한 리버스 프록시를 사용하려고 한다.
도메인을 이용한 리버스 프록시는 아래와 같이 동작한다.

URL이 패턴에 의한 검사였다면, 도메인 기반 리버스 프록시는 도메인 또는 서브 도메인을 기반으로 클라이언트 요청을 라우팅한다.
예를 들어 CLIENT가 http://b.com/main URL을 입력했을 때 리버스 프록시는 b.com 도메인에 대한 서버인 B server로 라우팅을 수행한다.

실습 준비
우선 실습 전에 아래와 같은 간단한 웹 포탈 두 개를 만들어주었다.
- /main 진입 시 A서버 라는 문구가 출력되는 웹 포탈 (8881 포트)
- /main 진입 시 B서버 라는 문구가 출력되는 웹 포탈 (8882 포트)

이제 http://a.com/main 으로 들어오는 request는 8881포트로, http://b.com/main로 들어오는 request는 8882포트로 라우팅해 줄 것이다.
실습 (CentOS 7.9)

우선 apache server를 설치한다.
yum install -y httpd
*추가로 java-11-openjdk-devel, vim, net-tools 가 설치된 상태이다.
이제 /etc/httpd 폴더로 이동 후 다음 세팅을 추가한다.
## 실서버가 아닌 테스트용이므로 방화벽 끄기
systemctl stop firewalld
## 리버스 프로시 설정
## 파일명은 맨 뒤에 .conf만 유지하면 어떻게 설정해도 무방함.
cd /etc/httpd
vim conf.d/default-site.conf
## 아래 내용 입력
<VirtualHost *:80>
ServerName a.com
ErrorLog /var/log/httpd/a_error.log
CustomLog /var/log/httpd/a_access.log combined
ProxyRequests Off
<Proxy>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://192.168.0.12:8881/
ProxyPassReverse / http://192.168.0.12:8881/
</VirtualHost>
<VirtualHost *:80>
ServerName b.com
ErrorLog /var/log/httpd/b_error.log
CustomLog /var/log/httpd/b_access.log combined
ProxyRequests Off
<Proxy>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://192.168.0.12:8882/
ProxyPassReverse / http://192.168.0.12:8882/
</VirtualHost>
## 저장 후 apache 재실행
systemctl restart httpd
- ServerName : 도메인명 지정
- ErrorLog : 에러 로그 저장 위치 지정
- CustomLog : 액세스 로그 저장 위치 지정
- ProxyRequests : on일 경우 Forward Proxy, off일 경우 Reverse Proxy
- ProxyPass : request 변환
- ProxyPassReverse : 내부에서 리다이렉트가 일어났을 시 response의 ip를 다시 도메인으로 변환
다음으로 위에서 설정한 도메인은 public 도메인이 아니므로 윈도우의 다음 파일을 수정해준다.
- 메모장 관리자 권한으로 실행
- C:\Windows\System32\drivers\etc\hosts 열기
- 아래 내용 추가 (ip는 환경에 따라 다르게 설정)
- 192.168.0.12 a.com
192.168.0.12 b.com - hosts 파일은 보안 관련 파일이기에 사용중인 보안 프로그램에 따라 수정이 불가할 수 있으니, 반드시 보안 프로그램을 해제하고 진행할 것. (알약의 경우 설정 > 검사 > 실시간 감시 > 호스트 파일 보호 > off)
- 192.168.0.12 a.com

위의 설정까지 완료된 후 http://a.com/main, http://b.com/main으로 들어가보자.
만약 503 에러가 발생하고, /var/log/httpd/a_error.log에 아래와 같은 에러가 발생한다면 아래 명령어를 입력한다.
[Thu Sep 28 15:16:33.170190 2023] [proxy_http:error] [pid 2066] [client 192.168.0.5:54880] AH01114: HTTP: failed to make connection to backend: 192.168.0.12
[Thu Sep 28 15:16:33.185008 2023] [proxy:error] [pid 2067] AH00940: HTTP: disabled connection for (192.168.0.12)
setsebool -P httpd_can_network_connect on
systemctl restart httpd
그리고 다시 접속을 해본다면 리버스 프록시가 잘 설정되었음을 확인할 수 있다.

실습 (Ubuntu 20.04.6)

우선 apache server를 설치한다.
apt-get install -y apache2
* 마찬가지로 openjdk-11-jdk, vim, net-tools가 설치된 상태이다.
이제 /etc/apache2에 들어가 설정을 수행한다.
## 아파치 설정
cd /etc/apache2
vim sites-available/000-default.conf
## 아래 내용 추가
<VirtualHost *:80>
ServerName a.com
ErrorLog ${APACHE_LOG_DIR}/a_error.log
CustomLog ${APACHE_LOG_DIR}/a_access.log combined
ProxyRequests Off
<Proxy>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://192.168.0.13:8881/
ProxyPassReverse / http://192.168.0.13:8881/
</VirtualHost>
<VirtualHost *:80>
ServerName b.com
ErrorLog ${APACHE_LOG_DIR}/b_error.log
CustomLog ${APACHE_LOG_DIR}/b_access.log combined
ProxyRequests Off
<Proxy>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://192.168.0.13:8882/
ProxyPassReverse / http://192.168.0.13:8882/
</VirtualHost>
## 저장 후 proxy 설정 허용 및 apache2 재실행
a2enmod proxy
a2enmod proxy_http
systemctl restart apache2
*AH01144: No protocol handler was valid for the URL /main (scheme 'http'). If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule. 에러 발생 시 a2enmod proxy_http가 설정되지 않은 것이다.
설정이 완료되었다면 마찬가지로 hosts 파일을 수정한다.

그러면 마찬가지로 아래와 같이 정상 작동함을 확인할 수 있다.

'[WEB&WAS]' 카테고리의 다른 글
[참고] IFrame (Inline Frame) 설명!! (3) | 2025.01.08 |
---|---|
[참고][Jeus,WebtoB] Jeus,WebtoB를 연동 해야하는 이유 !! (60) | 2023.12.05 |
[참고][Jeus] Jeus에 대하여 !! (57) | 2023.12.05 |
[참고][Web] 정적 컨텐츠와 동적 컨텐츠란? (36) | 2023.12.05 |
[참고][Web] 웹 서비스 동작 원리!! (60) | 2023.12.05 |
댓글