| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 | 31 |
- 커뮤니티서버
- 이벤트핸들러this
- TDD
- 공통기술
- MVC요청플로우
- Ajax
- 냄새라도
- JDBC
- OOP
- 설정세팅
- 디스크i/o
- 문제선택근거
- Transaction
- AOP
- model
- SEQUENCE
- 공통규약
- 전전긍긍
- JPA
- 단위테스트
- 클린아키텍처
- 로그백
- 사면초가
- 이벤트핸들러등록
- DDD
- index
- MVC
- string
- SpringLegacy
- springsecurity
- Today
- Total
개발이군고구마
모바일 HTTP 이미지 요청과 /runtime/exception 추적 정리 본문
모바일 HTTP 이미지 요청과 /runtime/exception 원인 정리
목차
1. 문제 배경
운영 중인 사이트의 상품 상세 페이지에서 이미지는 아래와 같은 형태로 로드된다.
<img src="https://aromacomall.imghost.cafe24.com/ac/ac_cactus.jpg">
제니퍼에서는 지속적으로 /runtime/exception 호출 예외가 보였고, 추적해보니 일부 모바일 요청에서 이미지 URL이 HTTP로 시작하는 케이스가 있었다. 브라우저 콘솔에서는 이 요청이 301 또는 302로 HTTPS로 전환되는 것도 확인했다.
2. 이번에 확인된 구조
Cloudgateway는 추상적인 개념이 아니라 실제로 존재하는 프록시 서버이며, Web ALB 뒤의 Target Group 중 하나로 붙어 있다. Web ALB는 경로에 따라 Cloudgateway 또는 이미지 정적 경로 또는 WAS 쪽으로 요청을 분기한다.
- 사실Cloudgateway는 외부 인터넷으로 나가는 프록시 역할을 수행한다.
- 사실흐름은 대체로 Cloudgateway → NAT 고정 IP → 외부 인터넷 서버 형태다.
- 사실Cloudgateway는 Web ALB 뒤의 Target Group으로 존재한다.
- 사실Web ALB는 path 등에 따라 Cloudgateway / 이미지 정적 경로 / WAS로 요청을 보낸다.
3. 문제와 원인
3-1. 현재 발생하고 있는 흐름
문제의 핵심은 브라우저가 직접 외부 404를 받는 구조가 아니라, 내부 경로가 Cloudgateway를 통해 외부 서버를 호출하고 그 404 응답을 내부 코드가 받는다는 점이다.
3-2. 원인 요약
HTML 안의 HTTP 이미지 URL이 출발점이 되었고, 그 요청은 HTTPS로 전환된 뒤 Web ALB의 규칙에 의해 Cloudgateway Target Group으로 분기되었다. Cloudgateway는 외부 이미지 서버를 호출했고, 외부 서버는 404를 반환했다. 이후 그 404 응답을 받은 내부 코드가 예외로 처리하면서
/runtime/exception 로그가 적재된 것으로 보는 설명이 가장 자연스럽다.4. 리다이렉트가 일어나는 지점
브라우저 단계에서 HTTP 이미지 URL을 발견하고 HTTPS로 리다이렉트되는 흐름은 분명하다. 여기서 중요한 점은 리다이렉트는 브라우저가 먼저 경험하는 프론트 요청 흐름이고, 그 뒤 내부에서 Cloudgateway 경로를 타는 것은 서버사이드 처리 흐름일 수 있다는 점이다.
4-1. 브라우저가 보는 리다이렉트 흐름
4-2. 코드 관점의 리다이렉트 예시
리다이렉트는 여러 레이어에서 걸 수 있다. 다만 지금 구조에서는 브라우저에서 301, 302를 확인했기 때문에, 아래와 같은 프론트 레이어 설정이 있을 가능성이 높다.
# Nginx 예시
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
# Spring MVC 예시
@GetMapping("/image")
public String redirectToHttps() {
return "redirect:https://example.com/image";
}
# CDN rule 개념 예시
if (scheme == "http") {
redirect(301, "https://" + host + request_uri);
}
5. 핵심 원리: 요청한 쪽이 응답도 받는다
가장 중요한 포인트는 TCP 소켓은 요청한 쪽이 응답도 받는다는 것이다. 즉 WAS가 먼저 외부로 TCP 연결을 열었다면, 외부에서 오는 404 응답은 새로운 인바운드 요청이 아니라 기존 아웃바운드 세션의 응답 패킷이다.
5-1. TCP 소켓 관점의 흐름
WAS (PRD VPC 내부)
1) 외부로 TCP 연결 시작
-> NAT Gateway 또는 공인 IP를 통해 외부로 나감
외부 이미지 서버
2) 404 응답 반환
-> 새 요청처럼 보이지만, 실제로는 1)에서 열린 TCP 세션의 응답
WAS
3) 동일 소켓으로 404 응답 수신
-> 내부 예외 처리
6. 보안 그룹, NACL, NAT 관점
외부 응답이 VPC 안으로 들어오는 것이 가능하냐는 질문에 대한 답은 가능하다. 단, 새로운 인바운드가 아니라 Return Traffic이기 때문이다.
6-1. 보안/네트워크 관점 다이어그램
| 구분 | 동작 방식 | 외부 응답 허용 여부 |
|---|---|---|
| Security Group | Stateful. Outbound 허용 시 해당 세션의 응답은 자동 허용 | 자동 허용 |
| NACL | Stateless. Inbound와 Outbound를 각각 고려해야 함 | Ephemeral Port 범위 허용 시 통과 |
| NAT Gateway | 세션 테이블로 Outbound 연결을 추적하고 응답을 자동 매핑 | 자동 처리 |
WAS가 먼저 연결을 열었기 때문에, 외부에서 오는 404 응답은 새로운 인바운드 요청이 아니라 기존 아웃바운드 연결의 응답 패킷이다. 그래서 Imperva를 다시 거치지 않고 WAS까지 돌아올 수 있다.
7. 실제 패킷 흐름
7-1. 실제 패킷 흐름 다이어그램
[WAS 서버] 1) connect(외부IP:443) -> TCP SYN 전송 출발지: WAS 사설IP:ephemeral_port [NAT Gateway] 2) SNAT 처리 사설IP:포트 -> 공인IP:포트 세션 테이블 매핑 기록 [외부 이미지 서버] 3) 요청 처리 후 404 응답 목적지: 공인IP:포트 [NAT Gateway] 4) DNAT 처리 공인IP:포트 -> 사설IP:포트 복원 [WAS 서버] 5) 동일 소켓으로 404 응답 수신 -> HttpClientErrorException(404) 가능 -> /runtime/exception 로그 적재 가능
8. 코드 레벨에서 예외가 나는 이유
404 자체는 정상적인 HTTP 응답이지만, 서버사이드 코드가 이를 어떻게 처리하느냐에 따라 예외가 날 수 있다. 이미지에서 정리된 시나리오 A는 WAS가 서버사이드에서 직접 이미지를 fetch 하는 경우로 볼 수 있다.
8-1. 서버사이드 fetch 흐름
WAS (JSP or Spring) 내부 코드 -> 이미지 URL을 서버사이드에서 직접 HTTP 호출 -> 해당 호출이 Cloudgateway TG를 통해 외부로 나감 -> 외부 서버가 404 응답 -> WAS 코드가 404를 받아 Exception 처리 -> /runtime/exception 로그 발생
8-2. 예외가 발생할 수 있는 코드 예시
// RestTemplate 예시
try {
ResponseEntity<byte[]> res =
restTemplate.getForEntity(imageUrl, byte[].class);
} catch (HttpClientErrorException e) {
log.error("image fetch failed", e);
throw e;
}</byte[]>
// HttpURLConnection 예시
HttpURLConnection conn = (HttpURLConnection) new URL(imageUrl).openConnection();
int code = conn.getResponseCode();
if (code >= 400) {
throw new RuntimeException("image fetch error: " + code);
}
// WebClient 예시
webClient.get()
.uri(imageUrl)
.retrieve()
.bodyToMono(byte[].class)
.block();
이 경우 클라이언트 브라우저가 외부 이미지 서버를 다시 직접 호출하는 구조가 아니라, WAS가 먼저 외부 이미지를 요청했고 그 응답을 WAS가 동일한 소켓으로 받았기 때문에 WAS 로그에 예외가 찍힐 수 있다.
9. 최종 정리
/runtime/exception 로그가 적재될 수 있다.즉 이번 이슈의 핵심은 리다이렉트 자체보다도, ALB 분기 규칙, Cloudgateway를 통한 외부 호출, NAT의 세션 복원, 그리고 WAS의 404 처리 방식이 연결된 결과라고 보는 것이 가장 자연스럽다.
'SERVER > Architecture' 카테고리의 다른 글
| 프록시·NAT·네트워크 계층 기초 정리 (0) | 2026.07.03 |
|---|---|
| 서버 디스크가 100% — 로그 파이프라인 (0) | 2026.06.27 |
| 특정 환경/IP 차단 이슈 - 네트워크 경로 (0) | 2026.03.11 |
| 프록시 서버 (0) | 2026.03.11 |
| Strangler Fig Pattern : 테스트 하지 않는 환경에서 TDD 흐름 만들기 (0) | 2026.01.02 |