cors 모듈 직접 구현해보기

2023.02.06

이 포스트는 CORS 개념을 알고있다는 가정하에 작성되었으며 예제는 KoaJS 를 기준으로 합니다.


대부분의 nodejs(express,koa 등) 환경에서 cors 설정을 한다면 아마 express cors@koa/cors를 사용할것이다.
근데 이때까지 마냥 가져다 쓰기만했지 실제 내부적으론 어떻게 동작하는지 몰랐고 이 cors 모듈을 직접 작성해서 사람들도 있어서 한번 분석을 해보았다. 근데 사실 이미 만들어진 모듈 가져다 써도 아무 문제없고 본인이 시간이 많고 탐구에 관심이 많다면 재미로 한번 읽어보자.

아직 cors에 대해 자세히 모른다면 이걸 한번 읽어보자. 정리가 잘 되어있다. (사실 이 포스트의 내용도 전부 나와있음)


cors 모듈의 동작 방식

기본적인 cors 모듈의 역할은 브라우저와 서버가 주고받는 http 헤더에 값을 설정해서 브라우저에게 이 리소스를 써도 안전하다 라는것을 알려주는것이다.
이때 수정하는 주요 헤더의 값들 을 알아보자


Access-Control-Allow-Origin

cors를 허용할 요청의 오리진(도메인)을 설정한다. 이 블로그에서 요청한 오리진은 https://pizza7311.me 이고 서버쪽에서 이 오리진을 허용한다고 헤더에 적어서 브라우저에 알려줘야 브라우저는 cors 에러를 일으키지 않는다. 그니까 쉽게 말해서 Access-Control-Allow-Origin 라는 값에 cors를 허용할 도메인 주소를 문자열 형태로 적는다.

(ctx,next)=>{
    ctx.set('Access-Control-Allow-Origin','https://pizza7311.me')
    //...
}

Access-Control-Allow-Methods

허용하는 http 요청 메소드를 문자열 형태로 정의한다. 각 메소드는 , 로 구분한다.

(ctx,next)=>{
    ctx.set('Access-Control-Allow-Methods','GET,POST,PUT,PATCH')
    //...
}

Access-Control-Allow-Headers

프리플라이트 요청이 왔을때 실제 요청할때 사용할수 있는 헤더들을 정의한다.
이 문서를 보면 알수있는데 프리플라이트 요청은 먼저 브라우저가 실제 요청을할때 이런 헤더들을 쓸수 있냐고 물어보는데 이때 서버에서 사용 가능이라고 OK를 받으면(Access-Control-Allow-Headers 로 정한 값) 브라우저는 실제 요청을 보낸다.
그니까 서버에서 요청이 들어올때 허용하는 헤더 내용을 정의한다. 커스텀 헤더 정의도 할수있다.


(ctx,next)=>{
    //프리플라이트 요청은 무조건 OPTIONS 메소드로 한다. 프리플라이트 요청이 들어왔을때 이 헤더들을 허용한다고 브라우저에 알려준다.
    if(ctx.method === 'OPTIONS'){
        ctx.set('Access-Control-Allow-Headers','Content-Type, x-requested-with')
    }
    //...
}

(ctx,next)=>{
    //커스텀 헤더를 지원한다고 정의도 가능하다.
    if(ctx.method === 'OPTIONS'){
        ctx.set('Access-Control-Allow-Headers','Custom-Header')
    }
    //...
}

(ctx,next)=>{
    //또는 아래와 같이 프리플라이트 요청이 올때 사용할수 있냐고 물어보는 헤더를 전부 허용할수도 있다.
    if(ctx.method === 'OPTIONS'){
        allowHeaders = ctx.get('Access-Control-Request-Headers')
        ctx.set('Access-Control-Allow-Headers', allowHeaders)
    }
    //...
}

Access-Control-Allow-Credentials

요청의 자격증명 모드가 include 일때 응답을 할지 여부를 정한다. 주로 쿠키같은 인증 정보를 요청헤더에 담아야할때 fetch나 axios 에서 credentials 옵션과 함께 쓰인다. 값은 문자열 형태로 'true' 또는 'false' 로 정의한다.


직접구현 해보기

위의 목록들을 바탕으로 직접 cors 모듈을 작성한다면 대략 이렇게 될것이다.


const cors=(ctx,next)=>{
    ctx.set('Access-Control-Allow-Origin','https://허용할 주소.com')
    ctx.set('Access-Control-Allow-Credentials','true')    //대부분 쿠키를 쓰기때문에 사실상 기본으로 true다
    ctx.set('Access-Control-Allow-Methods','GET,POST,PUT,DELETE,PATCH')
    
    //프리플라이트 요청이 들어왔을때의 처리
    if(ctx.method==='OPTIONS'){
        ctx.set('Access-Control-Allow-Headers','허용하는 헤더 목록')
    }
    
    return next()
}

진짜 별거없다. 사실 Access-Control-Allow-Origin 만 지정해줘도 cors 에러는 안뜬다. 실제 @koa/cors 패키지와 express cors 패키지의 구현 코드와 비교해보자

Do you want something exciting?

© 2022. YSH All rights reserved.