본문 바로가기
Frontend

왜 api 베이스에 서버 IP주소를 그대로 넣으면 안되는가

by 잘먹는 개발자 에단 2025. 6. 27.

왜 리액트에서 서버 연결 정보 넣을 때 ip 주소를 바로 넣으면 안될까?

 

[ 보안의 측면에서 ]

가장 큰 문제는 내부 시스템 정보노출이다.

1. 누구나 볼 수 있다. 

- React 코드는 최종적으로 사용자의 웹 브라우저에서 실행된다. 악의적인 사용자를 포함한 그 누구라도 브라우저의 개발자 도구를 열어서 네트워크 요청이나, js 소스코드를 살펴보는 것만으로 서버 b의 내부 ip주소와 포트주소를 알아낼 수 있다.

 

2. 공격자에게 지도를 주는 셈이다.

- 공격자는 이제 우리 시스템이 최소한 서버 a( 웹서버 ) 서버b ( api 서버 ) 라는 두개의 서버로 구성되어 있다는 내부 구조를 알게 된다.

- 더 중요한 것은, 공격 대상이 될 수 있는 서버 b의 정확한 주소를 확보하게 된다.

- 만약 다른 경로 ( 피싱, 내부자 위협, 다른 서버의 취약점 등 )을 통해 어떻게든 우리 회사 내부망에 발을 들인다면, 그 공격자는 어디를 공격해야할지 이미 알고있는 상태에서 시작하게 되고, 헤매지 않고 곧바로 서버 b를 향해서 공격을 시도하게 된다.

 

그래서 보통 오픈된 서버에 리버스 프록시를 설정하는 방식으로 이러한 정보노출 문제를 원천적으로 차단한다. 이러면 다음과 같은 보안적 이점을 누릴 수 있다.

1. 내부 ip 및 포트 은닉

- 사용자의 브라우저는 오직 서버 a의 주소하고만 통신한다. 서버 b의 존재 자체를 알지 못하며, 당연히 ip주소나 포트번호도 알 수 없다. 내부 시스템의 구조는 완벽하게 숨겨진다.

 

2. 공격 표면이 감소한다.

- 외부 인터넷에서 직접 접근할 수 있는 지점은 오직 서버 a하나로 줄어든다. 서버b는 내부망에만 존재하며 방화벽으로 보호되므로, 공격자는 서버 b를 직접 공격할 방법이 없다. 서버 a라는 단단한 문을 먼저 뚫어야 하는 셈이다. 

 

3. 중앙화된 보안관리

- 모든 요청은 반드시 서버 a를 거쳐야만 한다. 이는 서버 a에서 모든 트래픽에 대한 로그기록, 비정상 트래픽 감지, 디도스 공격방어, 웹 방화벽 적용 등 보안 정책을 중앙 집중적으로 관리할 수 있다는 의미이다. 보안을 강화하기 매우 용이한 구조이다.

 

4. HTTPS ( SSL/TLS ) 적용의 용이성

- 웹 사이트 전체에 HTTPS 암호화를 적용할 때, 외부와 맞닿아 있는 서버 A에만 SSL 인증서를 설치하고 관리하면 된다. 서버 A와 서버 B간의 내부 통신은 암호화되지 않는 HTTP를 사용하더라도, 가장 중요한 사용자 브라우저와 우리 서버 간의 통신은 안전하게 암호화된다. 

 

 

[ 개발 및 배포, 운영의 측면에서 ]

1. 유지보수 및 유연성의 저하이다.

- 서버 정보는 언제든 바뀔 수 있다. 서버 이전, 인프라 확장, 포트 변경, 보안정책 변경 등 다양한 이유로 IP 주소나 포트번호는 영원하지 않다.

- 변경의 어려움. 만약 IP주소가 코드 한 곳이 아니라 여러 파일에 흩어져 있다면 어떨까. 바꿀 때마다 모든 소스 코드를 뒤져서 수정해야한다. 이 과정에서 실수가 발생할 확률이 매우 높다.

- 매번 다시 빌드해야한다. 리액트 코드를 수정했기 때문에 이 사소한 주소변경 하나 때문에 프로젝트 전체를 다시 빌드하고 빌드된 결과물을 서버에 다시 배포해야한다. 간단한 설정변경이 아니라, 코드 수정과 배포라는 무거운 작업이 되어버린다.

 

2. 환경별 설정의 어려움

- 실제 프로젝트는 다음과 같이 해야한다.

- 로컬 개발환경 : 실제 개발하는 환경

- 개발 서버환경 : 여러 개발자들이 함께 테스트 하는 공유 서버 환경

    ㄴ api 서버 주소는 http://dev.api.server.com 과 같이 한다.

- 스테이징(qa) 환경 : 실제 출시 전에 최종 테스트를 하는 실제 환경과 거의 동일한 서버.

    ㄴ api 서버 주소는 http://staging.api.server.com 과 같이 한다.

- 프로덕션(실서비스) 환경 : 실제 사용자들이 사용하는 최종 서버이다.

 

3. 그럼 어떻게 해야할까?

리액트 프로젝트의 루트 폴더에 .env 파일을 만들어서 거기에 설정 값을 저장한다.

1. .env 파일 생성

- 프로젝트 최상단 폴더에 목적에 맞는 .env 파일을 만든다.

- .env.development : npm start로 개발 서버를 실행할 때 적용된다.

- .env.production : npm run build로 프로덕션용 빌드를 할 때 적용된다.

- .env : 모든 환경의 기본값이 된다.

 

2. 환경 변수 정의

- .env 파일 안에는 REACT_APP_ 접두사를 붙여서 변수를 정의한다. ( Create React App )의 규칙이다.

 

.env.development

# 개발 환경에서는 테스트 서버 B의 IP를 직접 바라봄
REACT_APP_API_URL=http://<서버B_IP>:<포트>

 

 

.env.production

# 프로덕션(실서버) 환경에서는 지난번에 설정한 리버스 프록시를 사용
# 따라서 절대 주소가 아닌 상대 주소를 사용
REACT_APP_API_URL=/api

 

 

 

3. 코드에서 환경변수 사용

- 이제 axios 인스턴스를 만들 때, 하드코딩된 ip 주소대신 process.env 객체를 통해 환경 변수를 불러온다.

import axios from 'axios';

const apiClient = axios.create({
  baseURL: process.env.REACT_APP_API_URL,
  // 기타 다른 설정들...
});

export default apiClient;