서비스 개발을 하다보면, CORS문제는 정말 지겹도록 마주하는 문제 중 하나이다. 가장 흔히 발생하는 상황은 프론트 클라이언트 측에서 배포된 백엔드 서버로 요청을 보낼 때 발생하는 문제이다.
예를들어,
프론트 react.js 클라이언트에서 백엔드 Ec2에 배포된 SpringBoot로 요청을 보낼때 프론트의 서버가 백엔드 서버에 등록되어 있지 않다면 발생하게 된다. 이럴 경우 매우 쉽다.
총 두가지에서 CORS 허용 정책을 추가해야하는데 하나는 EC2의 인바운드 아웃바운드 규칙을 설정해줘야하고, SpringBoot 내에서도 SecurutyConfig를 통해 등록해줘야한다.
이렇게 두가지만 추가해주면 보통은 쉽게 해결이 된다.
하지만 최근에 내가 진행했던 프로젝트는 양상이 달랐다.
CORS 오류가 발생하는 지점이 우리가 배포한 백엔드 서버가 아닌, KOPIS라는 공연데이터 사이트에서 이미지를 다운 받는것에서 CORS가 막히는 것이었다. 이전과 달랐던 문제였다. 이전에는 직접 CORS를 열어주면 해결이 되었지만 지금 같은 경우에는 우리가 운영하는 서버가 아닌 외부 서버이었기에 CORS 설정을 해줄 수가 없었다. (당시 프론트는 리액트로 개발)
물론 직접 연락을 해서 특정 메서드에 한에, CORS를 열어달라고 할 수도 있었지만 시간 관계상 힘들었기에 다른 파훼법을 찾아 나섰다.
그래서 CORS의 원리부터 이해해보고자 했다.
CORS의 동작은 HTTP 요청과 응답의 헤더를 통해 이루어지고 단계별로 살펴보면 아래와 같다.
Same-Origin Policy (동일 출처 정책)
기본적으로 웹 브라우저는 다른 출처에서 리소스를 요청하는 것을 금지하고,
동일 출처란 다음이 모두 동일해야 한다는 뜻이다
- 프로토콜: (e.g., http:// vs https://)
- 호스트: (e.g., example.com vs api.example.com)
- 포트: (e.g., :80 vs :8080)
결국에는 CORS(Cross-Origin Resource Sharing) 에러가 발생하는 이유는, 웹 브라우저가 보안을 위해 다른 출처(origin)에서 리소스를 요청할 때 제한을 두기 때문이다.
보통 프론트 서버에서 CORS가 적용되는 이유는 프론트 서버가 하나의 웹브라우저 클라이언트로 인식이 되기 때문에 제한이 걸리는 것이다.
그렇다면 서버와 서버 사이에서는 CORS가 적용이 되지 않는다는 것이다.
예를들어 내장 Tomcat 서버를 사용하는 SpringBoot나 Python기반 서버 같은 경우에는 자체로 서버를 두기 때문에 어떠한 요청을 보내더라도 CORS의 영향을 받지 않을 것이라 생각하고 그대로 코드를 작성해보았다.
import requests
url = "http://www.kopis.or.kr/upload/pfmIntroImage/PF_PF253887_241118_1148450.jpg"
file_name = "downloaded_image.jpg"
try:
response = requests.get(url)
response.raise_for_status()
with open(file_name, 'wb') as file:
file.write(response.content)
print(f"이미지가 성공적으로 {file_name}으로 저장되었습니다.")
except requests.exceptions.RequestException as e:
print(f"이미지 다운로드 중 오류가 발생했습니다: {e}")
예상했던대로 해당 코드를 통해 이미지를 불러와 다운받을 수 있었다.
그렇다면 이제 이미지 다운을 클라이언트로 직접보내는 것이 아니라 위의 코드를 API형식으로 변경을 해서 클라이언트 대신, 서버에서 요청을 보내서 다운받을 수 있게 변경해주면 되는 것이었다.
즉 클라이언트와 KOPIS라는 외부 서버 사이에 백엔드 서버가 징검다리 역할을 해주는 것이다. 물론 효율적인 측면에서는 조금 떨어질 수 있기에 로직을 다음과 같이 구현하였다.
요청 플로우
1. 클라이언트에서 백엔드 API에 다운받고 싶은 이미지의 id 값 전달
2. 백엔드 서버에서 KOPIS로 다운 요청
3. 다운 받은 이미지 S3에 바로 저장후 S3 Object URL 프론트로 반환
4. 프론트에서는 받아온 S3 Object URL을 비동기로 다운 요청
당연히 클라이언트에서 바로 요청을 할때보다는 시간이 조금 더 걸리긴 했지만, 큰 차이 없이 해결할 수 있었다.
아무튼 이 계기를 통해 CORS의 정확한 동작 원리를 알 수 있었다!

'DevOps&Cloud' 카테고리의 다른 글
Serverless 아키텍쳐를 쓰면 좋은 이유(feat: Baas, Fass) (0) | 2025.03.13 |
---|---|
MSA: Micro Service Architecture 적용기(2) (1) | 2025.01.10 |
MSA: Micro Service Architecture 적용기(1) (3) | 2024.12.31 |
JWT: JWT와 Session (2) | 2024.12.26 |
GitActions: 환경변수 저장하기 (0) | 2024.12.22 |