티스토리 뷰

우선 이 글은 Nginx에 대한 기본 글이 아닌 조건을 두고 proxy 설정하기에 대한 글이니 nginx에 대한 설명은 간단하게 하겠다.

 

 

Nginx 란?

Nginx란 일종의 웹 서버이다. 하지만 resource에 직접 접근하는 기능 및 특정 서버로 전달해주는 proxy 기능도 할 수 있어 웹 서버 뿐만 아니라 다양한 기능을 할 수 있는 웹 서버이다.

윈도우 환경 및 리눅스 환경에서 모두 사용할 수 있는 웹 서버이다.

 

 

 

Nginx의 proxy란?

Nginx에 설정해놓은 경로로 요청이 들어왔을 때 해당 요청을 다른 곳으로 전달해주는 곳이다.

보통은 전달해주는 곳을 숨기기 위해서 사용하기도 하고 나의 경우는 frontend의 https backend 요청을 http로 구동되고 있는 backend로 전달해주기 위해서 사용했다.

 

 

https frontend 즉 https웹에서 http backend로 요청을 하면 CROS(Cross-origin resource sharing) 일명 Cross Origin 에러가 발생해 request를 보낼 수 없다. 즉, backend 또한 SSL 설정을 해줘야 하는데 내가 이번에 맡은 프로젝트에서는 backend를 frontend와 따로 물리적으로 분리하지 않고 같은 서버 내에서 실행중이고, 오직 font에서만 사용할 것이며 굳이 SSL 설정을 backend에 해주지 않아도 Nginx에서 proxy를 통해 front의 https request를 http backend로 전달해주기만 하면 될 것으로 판단 되었다.

 

 

Nginx proxy 설정

Nginx에서 proxy 설정은 매우 간단했다.

Ubuntu(데비안 계열)에서의 nginx 설정 파일의 위치는 '/usr/local/nginx/conf'이고,

CentOs(레드헷 계열)에서의 nginx 설정 파일의 위치는 '/etx/nginx/conf.d'이다.

Windows에서는 nginx를 설치하고 생성된 파일의 conf 폴더 안에서 nginx 설정 파일을 찾을 수 있다.

 

각각 운영체제에 맞는 위치에서 nginx의 설정 파일을 찾아서 ssl이 적용된 server 블록 안에 아래와 같이 코드를 삽입한다.

location /test {
	proxy_pass http://localhost:8080/;
}

 

ssl이 적용된 server에 '/test'라는 서브 도메인으로 요청이 들어올 경우 로컬에서 실행 중인 8080(여기서는 백엔드 서버)으로 해당 요청을 전달하겠다는 뜻이다.

이렇게 하면 ssl이 적용되어 있어 https로 nginx 서버에 요청이 'https://${server_name}/test' 형식으로 요청이 들어올 경우 로컬로 실행 중인 백엔드 서버로 해당 요청이 전달된다. 그러면 간단하게 https => http 요청에서 CORS 에러가 발생하는 것을 해결할 수 있다.

 

 

특정 도메인 또는 IP에서 요청이 들어왔을 때만 해당 전달하기

위와 같이 설정을 해놓고 개발을 열심히 하던 중 점점 서비스 날짜가 다가왔다. 클라우드의 auto scailling이나 DB 이중화나 등등 생각하기 전에 위와 같이 nginx에서 proxy_pass를 통해 프론트와 백엔드의 https에서 http를 요청하는 문제를 해결한 것에 문제가 있다는 것을 확인했다. 바로 프론트에서 뿐만 아니라 어디서든 백엔드로 요청을 할 수 있다는 것이다.

애초에 백엔드에서는 데이터를 가공해서 프론트에 넘겨주는 것 뿐이고 실제 row 데이터나 외부에서 접근하지 말아야할 데이터에 접근할 만한 API는 없었지만 그래도 뭔가 프론트 말고 외부에서 백엔드에 요청하는 것을 막고 싶었다.

 

그래서 nginx의 proxy_pass에 따로 if문과 같은 조건을 걸 수는 없는지 찾아봤다.

그 결과 nginx 설정에 if문을 사용할 수는 있지만 proxy_pass는 if문 안에 존재할 수 없다는 것을 테스트해 에러를 발생시키며 확인했다.

 

어떻게 할까 여러 가지 삽질은 한 끝에 아래와 같이 특정 도메인 또는 IP에서 요청이 들어왔을 때만 백엔드 서버로 해당 요청을 전달하게 설정할 수 있었다.

location /test {
	if($http_referer !~ ^(https|http)://(front-test.co.kr|127.0.0.1:5500|localhost:5500) {
    		return 404;
    	}
    	proxy_pass http://localhost:8080/;
 }

 

Google Maps API나 Kakao API 등 API들을 사용해본 사람들은 해당 API Key에 http 레퍼러 설정을 해본 경험이 있을 것이다.

nginx에서도 마찬가지로 http_referer라는 변수를 가져오면 요청이 들어온 곳의 도메인을 넘겨준다. (그 외에 다른 여러 가지 값들을 nginx에서는 활용할 수 있다.)

또한 nginx에서는 정규식을 사용할 수 있다. 정규식은 다른 코드들에서 사용하는 정규식과 차이가 없어서 아마 개발하면서 정규식을 사용해본 사람은 익숙할 것이다.

위 코드에서 사용한 것들에 대한 설명은 아래와 같다.

 

 

  • !~ : 해당 정규식과 일치하지 않을 경우
  • ^: 문자열의 시작
  • (문자1|문자2): 문자1 또는 문자2인 경우

 

더보기

정규식을 작성하다가 막히면 아래 사이트에서 정규식을 작성하면서 실시간으로 테스트를 해볼 수 있다.

https://regexr.com/

 

 

즉, https, http 프로토콜 상관 없이 웹을 배포한 도메인인 'front-test.co.kr' 또는 개발을 위해 로컬에서 웹을 돌리는 도메인인 '127.0.0.1:5500', 'localhost:5500'에서 들어온 요청이 아닐 경우 무조건 404에러 페이지를 반환하겠다는 뜻이다.

만일 위의 그러한 외부 도메인의 경우는 if문에 걸려서 404페이지를 반환 받게 되고 그렇지 않을 경우에는 해당 프론트에서 또는 개발하면서 사용했다는 것이므로 백엔드인 'http://localhost:8080/'으로 해당 요청을 반환해준다.

 

 

참고로 '127.0.0.1:5500'만 등록하고 'localhost:5500'을 등록하지 않을 경우 무조건 개발할 때 프론트를 'localhost:5500'이 아닌 '127.0.0.1:5500'으로 동작 시켜야한다. 안 그러면 마찬가지로 404 에러 페이지를 반환한다.

또한 '127.0.0.1'이나 'localhost'는 개발 기간에만 등록해놓거나 아니면 local주소가 아닌 회사 내부 네트워크 ip를 등록하지 않으면 누군가 로컬에서 프론트를 구동시킬 때의 port를 알아내면 마찬가지로 백엔드에 request를 날릴 수 있다.

 

 

 

 

나는 nginx 사용법을 누구한테 배운 것도 아니고 구글링하면서 설정해서 이번에 도메인을 특정하는 것도 구글링하면서 삽질을 엄청 많이 했다. 이게 다 nginx 설정 파일에서 사용할 수 있는 값과 여러가지 설정 옵션들을 모르기 때문... 나중에 nginx의 여러가지 설정 옵션들에 대해서도 공부해봐야겠다.

 

 

 

 

반응형

'Server' 카테고리의 다른 글

CDN이란?  (0) 2024.03.31
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함