API를 사용하다보면 CORS(Cross-Origin Resource Sharing) 오류를 자주 경험하게 된다. 예를 들어, OpenAPI와 같이 무료 API를 사용할 수 있다고 해서 요청을 보냈는데, CORS 정책으로 인해 막히는 경우가 발생할 수 있다.
API 요청을 보냈지만 브라우저에서 CORS 오류로 차단되었다면, 'API를 사용할 수 있는 것인지 아닌지' 혼란스럽게 느껴질 수 있다. 무료 API라서 쉽게 사용할 수 있을 거라고 기대했는데, 서버측의 제한으로 인해 막히는 상황이 난감하기 때문이다.
그러나 결론적으로, 이러한 무료 API는 CORS 문제를 해결한 뒤 정상적으로 사용할 수 있다. 지금부터 CORS에 대해 알아보고, 어떻게 요청을 해야 CORS 문제를 우회할 수 있는지 살펴보자.
SOP
CORS에 대해서 알아보자고 했는데, 갑자기 'SOP'라는 용어가 나와 당황했을 수 있다. SOP(Same Origin Policy), 즉 "같은 출발지 정책"이라고 불리는 개념을 먼저 이해해야 CORS를 제대로 이해할 수 있다.
초기 웹에서는 브라우저와 백엔드가 같은 서버에 있을 때만 요청을 주고 받을 수 있었다. 이는 보안을 위한 정책이었는데,
예를 들어, 네이버 브라우저에서 네이버 백엔드로만 요청을 보낼 수 있었고, 다른 서버(예: 다음)로는 요청을 보낼 수 없었다. 이렇게 제한을 둔 이유는, 다른 출처로부터 악의적인 스크립트가 데이터를 탈취하는 것을 방지하기 위함이었다.
하지만, OpenAPI와 같은 다양한 서버로부터 데이터를 주고받는 현재 웹 환경에서는 이런 제한이 상당이 불편해졌다.
네이버 브라우저가 다음 백엔드로 요청을 보낼 수 없다면, 검색 결과에서 얻을 수 있는 정보가 제한적일 것이다.
이러한 불편함을 해결하기 위해, 보안 정책을 조금 완화한 방식이 바로 CORS다. SOP는 여전히 유지되지만, 서버가 명지적으로 허용하는 경우에는 다른 출처의 요청을 허용해서 받을 수 있다.
CORS
CORS(Cross Origin Resource Sharing)는 API 요청을 귀찮게 만드는 요소로 생각되기도 하지만, 사실은 우리를 보호하는 중요한 보안 정책이다. 이 정책은 SOP로 부터 시작되었고, 다른 출처의 서버에 요청을 보낼 수 있게 해주는 역할을 한다.
하지만, 다른 서버로의 요청을 무조건 허용하는 것은 보안상 큰 문제가 될 수 있다. 따라서 요청을 허용하려면 반드시 CORS 규칙을 따라야 한다. 이를 통해 보안을 유지하면서도 외부 서버로부터 안전하게 데이털르 주고받을 수 있다.
CORS 요청 과정을 네이버 브라우저가 다음 백엔드에 글쓰기 요청을 보내는 예시로 살펴보자.
먼저 다음 백엔드에서 글쓰기 API가 존재하고 네이버 브라우저는 이 API를 사용해서 글쓰기 기능을 활용하려고 한다.
다음 백엔드의 개발자는 CORS를 허용할지 말지를 먼저 결정해야 한다. 만약 CORS 요청을 허용하지 않는다면, 외부에서 들어오는 모든 요청이 차단된다. 반면, 허용할 때는 특정 서버만 허용할 수 있고, true로 설정하여 모든 서버의 요청을 허용하거나 , false로 전체 차단할 수 있다.
이 예시에서는 다음 백엔드가 모든 요청을 허용했다고 가정해보자.
CORS를 전체 허용을 해줬다고 네이버 브라우저에서 바로 다음 백엔드 서버로 요청을 보낼 수 있는 것은 아니다.
네이버에서 다음 백엔드로 요청을 보내려면, 먼저 Preflight 요청을 보낸다. 이는 브라우저가 실제 API 요청 전에, 이 서버가 해당 요청을 허용하는지 확인하는 과정이다. Preflight 요청은 OPTION 메서드로 보내지며, 다음 백엔드에서 요청에 응답하여 CORS 정책에 따라 어떤 요청이 허용되는지 알려준다.
이 과정을 마친 후에야, 네이버 브라우저는 실제 다음 백엔드에 API 요청을 보낼 수 있다.
정리하면, 네이버 브라우저가 다음 백엔드에 CreateBoard라는 API 요청을 보내려 할 때, 바로 요청을 보내는 것이 아니라 먼저 Preflight Request를 보내서 CORS 허용 여부를 확인한다. 응답을 받은 후에야 비로소 실제 API 요청을 전송하게 된다.
이 때문에 API 요청을 보낼 때 네트워크 탭에 요청이 두 번 나타나는 것을 확인할 수 있다.
여기까지는 CORS 정책을 허용했을 때의 상황을 다루었다. 그렇다면, CORS 정책을 거부했을 때는 어떻게 될까?
동일하게 네이버 브라우저가 다음 백엔드에 CreateBoard 요청을 보내기 전에 Preflight 요청을 보내게 된다. 하지만 이번에는 다음 백엔드에서 CORS를 허용하지 않는다는 응답을 보내게 된다.
이렇게 되면, API 요청을 다음 백엔드에서 막는 것이 아니라, 네이버 브라우저가 요청을 차단하게 된다. 즉, 브라우저 자체가 보안 정책에 따라 요청을 보내지 않도록 막는 것이다.
그렇다면 우리는 어떻게 해야할까?
OpenAPI를 사용하고 있는데, 다음 백엔드에서 CORS 정책을 거부하는 경우가 있을 수 있다. 물론, 우리가 다음 회사에 찾아가서 CORS 설정을 변경해 달라고 요청할 수는 없다. 그렇다면 API를 사용하는 우리는 어떤 대안을 찾을 수 있을까?
여기서 중요한 점은, CORS가 브라우저에서의 요청을 차단하는 보안 정책이라는 것이다. 네이버 브라우저 개발자가 네이버 백엔드 개발자에게 다음 백엔드로의 CreateBoard 요청을 대신 처리해 달라고 할 수 있다. 이렇게 하면, 네이버 백엔드가 다음 백엔드로 직접 요청을 보내게 되므로, CORS 문제는 더 이상 발생하지 않는다. CORS는 브라우저에서만 적용되기 때문이다.
이처럼, 브라우저의 CORS 문제를 해결하기 위해 프록시 서버(Proxy Server)를 사용할 수 있다. 프록시 서버는 네이버 백엔드처럼 중간에서 요청을 대신 처리해주는 서버다. CORS가 차단된 경우, 프록시 서버를 통해 API 요청을 보내고 받을 수 있게 되는 것이다.
근데 이런 CORS 정책은 Proxy Server를 통해서 우회할 수 있는데 CORS 정책이 존재하는 이유는 뭘까?
CORS 존재 이유
CORS 정책은 브라우저에서 차단을 목적으로 하는 보안 정책이다. 그렇다면, CORS가 브라우저를 어떻게 보호하는 걸까?
예를 들어, 사용자가 다음 브라우저에서 다음 백엔드로 로그인을 하면, 백엔드는 해당 사용자가 로그인이 완료되었다는 로그인 증표(예: Access Token)를 반환한다. 이 증표는 쿠키에 저장될 수 있으며, 이후 사용자가 브라우저에서 백엔드로 API 요청을 보낼 때 쿠키에 저장된 로그인 증표가 자동으로 포함되어 전송된다. 이로 인해 백엔드는 해당 요청이 누구로부터 왔는지, 로그인 상태인지 등을 확인할 수 있다.
이 과정은 개발자가 특별히 신경 써서 구현하는 것이 아니라, 브라우저의 내장된 기능에 의해 자동으로 처리된다.
하지만, 문제가 생길 수 있는 상황을 가정해보자. 사용자가 다음 브라우저에서 로그인을 마친 후, 우연히 해커가 만든 '다은'(가칭)이라는 사이트에 접속하게 되었다고 하자. 만약 이 해킹 사이트에서 다음 백엔드로 API 요청을 보낸다면 어떻게 될까? 로그인 증표가 이미 브라우저 쿠키에 저장되어 있기 때문에, 브라우저는 이 요청에도 자동으로 로그인 증표를 포함하게 된다. 결과적으로, 해커의 요청이 사용자의 인증 정보를 가지고 있는 것처럼 백엔드에 전송될 수 있다.
이런 상황에서 CORS 정책이 없다면, 해커는 사용자의 인증 정보를 도용해 사용자 대신 요청을 보낼 수 있게 된다. 즉, 유명 인물의 로그인 세션이 해킹되어 해커가 게시물을 작성하거나 정보를 탈취하는 등의 일이 발생할 수 있다.
하지만, CORS 정책이 적용되어 있다면, 다음 브라우저에서만 다음 백엔드로의 요청이 허용되기 때문에, 해커가 만든 사이트는 CORS 차단으로 인해 요청을 보낼 수 없게 된다. 이로써 브라우저는 보안 위협으로부터 보호받게 되는 것이다.
또한, 해커가 프록시 서버를 통해 요청을 시도한다고 해도, 브라우저 쿠키에 저장된 로그인 증표는 프록시 서버의 도메인과 일치하지 않기 때문에, 다음 백엔드에서는 로그인이 필요하다는 응답을 보내게 된다. 따라서, 해커는 악의적인 행위를 할 수 없게 된다.
'Web' 카테고리의 다른 글
iPad 클론코딩 (3) | 2024.11.23 |
---|---|
Critical Rendering Path (4) | 2024.11.13 |
단방향 암호화와 양방향 암호화 (1) | 2024.10.05 |
웹사이트 로그인의 역사 (1) | 2024.10.02 |
3D 애니메이션 심화 (2) | 2024.09.08 |