kjp0411 님의 블로그
내일배움캠프 단기심화 Java - 본 캠프 Day 67 본문
TIL - 2026.05.19
오늘 한 일
오늘은 티켓팅 MSA 프로젝트의 배포 환경에서 ALB 기반 이중 애플리케이션 서버 구성과 Gateway CORS 문제 해결을 진행했다.
기존에는 단일 EC2 애플리케이션 서버에 서비스들이 배포되어 있었기 때문에, 인프라 담당자가 실시간으로 서버 상태를 확인하고 직접 반영해야 하는 부담이 있었다. 이를 개선하기 위해 main 서버와 main 복제 서버를 구성하고, 두 서버를 ALB 뒤에 배치하여 외부 요청이 로드밸런서를 통해 분산되도록 구성했다.
또한 프론트엔드에서 Gateway API를 호출할 때 CORS preflight 요청이 401 Unauthorized로 응답되는 문제가 발생했고, Gateway 보안 설정과 CORS 허용 Origin을 수정하여 해결했다.
발생한 문제
1. Gateway CORS preflight 요청이 401로 응답됨
프론트엔드에서 API 요청을 보내기 전 브라우저가 OPTIONS preflight 요청을 보냈는데, Gateway가 이를 인증이 필요한 요청으로 처리하면서 401 Unauthorized가 발생했다.
확인 명령어는 다음과 같았다.
curl -i -X OPTIONS "http://localhost:10000/api/users" \
-H "Origin: http://localhost:5173" \
-H "Access-Control-Request-Method: GET"
응답 결과는 다음과 같았다.
HTTP/1.1 401 Unauthorized
즉, 실제 API 로직 문제가 아니라 Gateway 보안 필터에서 OPTIONS 요청을 먼저 차단하는 구조가 문제였다.
2. ALB 도메인이 CORS 허용 Origin에 누락됨
프론트엔드 또는 외부 접근 경로가 ALB 도메인을 기준으로 바뀌었는데, Gateway CORS 설정에는 해당 ALB 도메인이 포함되어 있지 않았다.
누락된 Origin은 다음과 같았다.
http://ticketing-alb-1966117378.ap-northeast-2.elb.amazonaws.com
CORS 설정은 단순히 백엔드 API만 열어둔다고 해결되는 것이 아니라, 실제 브라우저가 요청을 보내는 Origin 기준으로 허용해야 한다는 점을 다시 확인했다.
해결 방법
1. Gateway Security 설정에서 OPTIONS 요청 허용
Gateway의 Security 설정에서 OPTIONS 요청은 인증 없이 통과하도록 설정했다.
CORS preflight 요청은 실제 비즈니스 요청이 아니라 브라우저가 사전에 서버의 요청 허용 여부를 확인하는 요청이다. 따라서 JWT 인증 대상에서 제외해야 한다.
핵심 방향은 다음과 같다.
.pathMatchers(HttpMethod.OPTIONS, "/**").permitAll()
이를 통해 브라우저의 preflight 요청이 Gateway 인증 필터에서 막히지 않도록 처리했다.
2. ALB 도메인을 CORS allowedOrigins에 추가
프론트엔드가 접근하는 실제 Origin 기준으로 CORS 허용 목록을 수정했다.
허용 대상에는 로컬 개발 환경과 ALB 접근 주소를 함께 포함했다.
http://localhost:5173
http://ticketing-alb-1966117378.ap-northeast-2.elb.amazonaws.com
이후 Gateway를 재배포하고 다시 요청을 확인한 결과, CORS preflight 및 실제 API 요청 모두 정상적으로 200 OK 응답을 확인했다.
검증 결과
수정 후 OPTIONS 요청과 실제 API 요청을 다시 확인했다.
curl -i -X OPTIONS "http://localhost:10000/api/users" \
-H "Origin: http://localhost:5173" \
-H "Access-Control-Request-Method: GET"
이후 요청이 더 이상 401 Unauthorized로 막히지 않았고, 전체 API 요청도 정상적으로 200 OK 응답을 반환했다.
또한 ALB를 통해 main 서버와 main 복제 서버가 정상적으로 연결되는지도 함께 확인했다.
최종적으로 현재 배포 환경에서는 다음 구성이 정상 동작하는 상태가 되었다.
- Gateway 단일 진입점 구성
- main / main 복제 애플리케이션 서버 구성
- ALB 기반 외부 요청 분산
- Eureka 기반 서비스 등록 확인
- Gateway CORS 설정 반영
- 프론트엔드 Origin 및 ALB Origin 허용
- API 요청
200 OK확인
오늘 배운 점
이번 작업을 통해 CORS 문제는 단순히 백엔드 컨트롤러나 API 문제가 아니라, 브라우저 요청 흐름, Gateway 보안 필터, Origin 설정, 배포 접근 경로가 모두 맞아야 해결된다는 것을 다시 확인했다.
특히 OPTIONS 요청은 실제 API 요청과 다르게 인증 토큰을 포함하지 않는 경우가 많기 때문에, Gateway에서 이를 JWT 인증 대상으로 처리하면 정상적인 브라우저 요청도 차단될 수 있다.
또한 배포 환경에서 ALB를 추가하면 접근 주소가 바뀌기 때문에, CORS 설정도 함께 갱신해야 한다. 로컬에서는 정상 동작하더라도 실제 배포 도메인 또는 ALB 도메인이 허용 목록에 빠져 있으면 브라우저 요청은 실패할 수 있다.
느낀 점
오늘 작업은 단순히 코드를 수정하는 작업이라기보다, 실제 운영 환경에서 요청이 어떤 경로로 흐르는지 확인하는 과정에 가까웠다.
프론트엔드에서 Gateway로 요청이 들어오고, Gateway가 보안 필터를 거친 뒤 각 서비스로 라우팅하며, 서버는 ALB 뒤에서 동작하는 구조를 직접 구성하면서 MSA 배포 환경의 흐름을 더 구체적으로 이해할 수 있었다.
특히 문제가 발생했을 때 단순히 “CORS 오류다”라고 판단하는 것이 아니라, curl로 preflight 요청을 직접 재현하고, 응답 코드가 어디에서 발생하는지 확인한 뒤, Gateway 보안 설정과 CORS 설정을 분리해서 점검한 점이 의미 있었다.
다음에 할 일
다음 단계에서는 현재 구성한 ALB 기반 이중 애플리케이션 서버 구조를 기준으로, 각 서비스의 CI/CD 파일이 동일한 배포 방식으로 반영되도록 정리할 예정이다.
또한 현재는 모든 서비스가 public subnet 기반으로 운영되고 있으므로, 이후에는 인프라 구조를 문서화하면서 다음 항목들을 함께 정리할 계획이다.
- 전체 인프라 구성도 정리
- ALB, Gateway, Eureka, Config Server 흐름 정리
- main 서버와 main 복제 서버의 역할 정리
- 서비스별 배포 방식 통일
- 장애 발생 시 어떤 서버와 로그를 확인해야 하는지 정리
- 포트, 환경 변수, Origin 설정 문서화
오늘 작업을 통해 배포 환경에서의 문제 해결은 코드뿐만 아니라 네트워크, 보안 설정, 로드밸런서, 서비스 디스커버리까지 함께 봐야 한다는 것을 다시 체감했다.
'TIL' 카테고리의 다른 글
| 내일배움캠프 단기심화 Java - 본 캠프 Day 69 (0) | 2026.05.21 |
|---|---|
| 내일배움캠프 단기심화 Java - 본 캠프 Day 68 (0) | 2026.05.20 |
| 내일배움캠프 단기심화 Java - 본 캠프 Day 66 (0) | 2026.05.18 |
| 내일배움캠프 단기심화 Java - 본 캠프 Day 65 (0) | 2026.05.15 |
| 내일배움캠프 단기심화 Java - 본 캠프 Day 64 (0) | 2026.05.14 |
