개발기초

CORS는 서버를 보호하는 장치가 아니라 사용자를 보호하는 장치다

hyriver(강화영) 2026. 8. 14. 14:26

 

 

상황

프론트가 떠있는 주소는 http://localhost:3000 (또는 http://192.168.x.x:3000)이고

요청보내는 주소는 http://server.test.co.kr 이다

 

이렇게 요청보내는 주소와 요청하는 주소가 다르면 먼저 서버에서 preflight를 보낸다

이게 바로 http의 option인데

의미는 "나 로컬호스트 3000인데 너한테 요청 보내도 됨?"

 

여기서 서버가 된다고 하면 실제 요청(ex. get - restful/mypage)을 보낼 수 있다

 

그런데 CORS라면 그 옵션에 대한 응답이 500으로 떨어진다!

 

 

근데 왜 500이 나죠?

서버의 CORS 설정에 허용 origin 목록이 있는데

이 목록에 로컬 개발 주소가 없으면 콜백에 new Error('Not allowed by CORS')를 던진다

이 에러는 서버 예외로 처리되어 500으로 터진다

 

 

 

내가 몰랐던 사실

두둥

CORS는 브라우저가 하는 검사이다

같은 api를 postman으로 호출하면 잘 된다. Node 스크립트로 해도 잘 된다. 브라우저의 js로 호출할 때만 막힌다.

cors는 http 표준이 아니라 브라우저 내의 규칙이다.

그래서 "서버가 나를 막았다"가 아니라 "내 브라우저가 나를 막았다"가 정확한 표현

 

어떤 위험으로부터?

브라우저는 특정 도메인의 쿠키를 그 도메인으로 요청할 때 자동으로 붙인다(ambient credential)
개발자가 코드를 안붙여도 알아서 붙여짐

 

그래서 아래와 같은게 가능해진다

// evil.com 페이지에 심어놓은 코드
fetch('https://bank.com/api/transfer', {
  method: 'POST',
  credentials: 'include',
  body: JSON.stringify({ to: '공격자', amount: 1000000 })
})

 

사용자가 evil.com을 열어봄 -> (bank.com에 로그인해 있으면)세션 쿠키가 자동으로 같이 딸려감

이때 브라우저가 개입 "이거 eveil.com에서 온건데 bank.com이 이걸 허락한적 있니?"

 

이전에 로그인 했었다면 "ㅇㅇ 허락했음" 하겠지 근데 왜 위험하냐

일부에게는 아무것도 클릭하지 않았는데 요청이 가는것 자체가 문제다!

 

 

postman과 브라우저의 차이

"누가 이 코드를 실행시켰냐"

포스트맨에서는 본인이 직접 url을 치고 send를 눌렀다.

본인이 의도한 요청이고 요청 내용도 본인이 다 안다.

 

하지만 브라우저는 다르다. 사이트에 접속하면 그 사이트가 넣어둔 js가 자동으로 실행된다.

사용자가 허락한 적도 없고, 무슨 코드인지 보지 않았는데 ;;;

즉 브라우저는 내가 통제하지 않은 코드를 자동으로 실행시키는 환경이다

 

 

cors는 서버를 보호하는 장치가 아니라 사용자를 보호하는 장치다

1) 브라우저는 origin(요청을 보낸 페이지의 주소)을 올려주고

2) 서버의 allowedOrigins(서버에 등록된 허용 주소)과 origin을 비교한다

3) 비교의 결과물이 Access-Control-Allow-Origin로 내려온다

4) 브라우저가 이 둘을 대조함

5) Access-Control-Allow-Origin가 없거나 안맞으면 응답을 JS에게 안넘겨줌

 

그래서 응답 결과를 서버엔서 확인해보면 200으로 찍히는데 프론트에서는 CORS에러가 난다