본문 바로가기
개발/Finance-Seven 프로젝트

[Finance-Seven 프로젝트] Spring Boot 프로젝트 CORS 해결하기

by 코코의 주인 2023. 2. 24.

1.  Cross-Origin resource sharing(교차 출처 리소스 공유)

 CORS(Cross-Origin resource sharing)는 한 오리진에서 다른 오리진의 리소스에 접근할 수 있도록 하는 규약을 말한다. 

1) Origin(오리진)

Origin은 Domain에서 통신 규약과 포트 번호를 합친 것을 말한다. naver를 예로 들자면 아래와 같다.

도메인 : naver.com
오리진 : https://www.naver.com:443

http://www.example.com:80https://www.example.com:443은 같은 도메인을 사용하지만 서로 다른 오리진이다.

2) CORS로 인해 벌어지는 일

 만약 당신이 이 사실을 모르고 API 서버 배포를 했다면 10분쯤 뒤에 프론트엔드에게 "OO님 이거 안돼요"라는 슬랙 메시지를 받게 될 것이다.

"분명히 포스트맨에서 정상적으로 동작하는 걸 분명히 확인하고 배포했는데 뭐가 문제라는 겁니까?" 라는 백엔드와, "되는 게 없는데 뭐가 됐다는 겁니까?" 라는 프론트엔드가 감정이 격해질 무렵  프론트에서 배포한 리액트 서버와 API 서버의 오리진이 다르기 때문에 발생한 CORS 에러라는 것을 깨닫게 된다. 실제로 내가 그랬다.

 포스트맨에서 CORS 에러가 발생하지 않는 이유는 서버에서 서버로의 요청은 CORS 에러가 발생하지 않기 때문이다.

3) CORS 테스트 하는 법

 CORS를 테스트 하는 방법은 쉽다. 다른 오리진을 하나 만들어서 API 서버로 요청을 보내보면 된다. 나는 이걸 쉽게 테스트할 수 있는 nicks-cors-test 툴을 사용했다.

 

https://github.com/njgibbon/nicks-cors-test

 

GitHub - njgibbon/nicks-cors-test: Simple HTML & JS Tool to quickly test CORS locally.

Simple HTML & JS Tool to quickly test CORS locally. - GitHub - njgibbon/nicks-cors-test: Simple HTML & JS Tool to quickly test CORS locally.

github.com

해당 툴을 사용해보면 요청이 서버에 도착해서 로그가 찍히는 것은 보이지만 브라우저의 개발자 도구로 보면 CORS 에러가 발생한 것을 확인할 수 있다. 이렇게 보면 백엔드의 잘못도 프론트엔드의 잘못도 아니기 때문에 서로 억울할만 하다.


2. Spring Security Filter를 활용해서 CORS 해결하는 법

컨트롤러 위에 @CrossOrigin 어노테이션을 붙이는 방법도 있지만 나는 Spring Security의 SecurityConfig.java 파일에 설정을 추가하는 방식을 사용해서 해결했다.

 

@Configuration
@RequiredArgsConstructor
public class SecurityConfig {

    private final JwtFilter jwtFilter;
    private final JwtExceptionFilter jwtExceptionFilter;
    
    .
    .
    .

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();

        configuration.setAllowedOriginPatterns(Collections.singletonList("*")); // 모든 Origin에서의 요청을 허용
        configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")); // 해당 Http Methods를 사용하는 요청을 허용
        configuration.setAllowedHeaders(List.of("authorization", "content-type", "x-auth-token")); // 해당 헤더를 사용하는 요청을 허용
        configuration.setExposedHeaders(Collections.singletonList("x-auth-token")); // 헤더에 CSRF 토큰이 있는 요청에 대해 모든 응답 헤더를 노출
        configuration.setAllowCredentials(true); // 사용자 자격 증명(쿠키, 인증키) 사용을 허용할 것

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration); // 모든 URL에 대해 위의 설정을 사용해 CORS 처리를 할 것
        return source;
    }
}

참고

OpenJDK 11.0.15, Spring Boot 2.7.8  버전을 사용했습니다.

 

댓글