개발 지식

[개발 지식] Cors 해결 방법 (React + TypeScript, Spring Boot)

hminor 2024. 8. 30. 22:26
반응형

React

1.1 프록시 서버 사용

개발 환경에서 CORS 문제를 가장 쉽게 해결할 수 있는 방법은 프록시 서버를 사용하는 것입니다.
React 애플리케이션에서 프록시를 설정하면 API 요청이 동일한 도메인에서 이루어지는 것처럼 보이도록 할 수 있습니다.

  • 설정 방법: package.json 파일에 프록시 설정 추가
// package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "dependencies": {
    // ...
  },
  "proxy": "http://localhost:8080" // Spring Boot 백엔드 주소
}

설명: 이 설정은 React 앱이 http://localhost:3000에서 실행 중일 때, API 요청을 http://localhost:8080으로 프록시합니다.              이를 통해 개발 중 CORS 문제를 우회할 수 있습니다.

1.2 Fetch 또는 Axios에서 CORS 설정

API 요청 시 CORS 문제를 해결하기 위해 credentials 옵션을 사용하여 쿠키나 인증 정보를 함께 전송할 수 있습니다.

  • Fetch API 사용 예시:
fetch('http://localhost:8080/api/data', {
  method: 'GET',
  credentials: 'include' // 쿠키를 함께 전송
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));
  • Axios 사용 예시:
import axios from 'axios';

axios.get('http://localhost:8080/api/data', { withCredentials: true })
  .then(response => console.log(response.data))
  .catch(error => console.error('Error:', error));
  • 설명: credentials 또는 withCredentials 옵션을 사용하여 인증된 요청을 보낼 수 있습니다.
             이는 쿠키 기반의 인증을 사용하는 경우에 유용합니다.

1.3 Fetch Base Query 설정에서 CORS 처리 (RTK-Query)

RTK-Query에서 가장 기본적인 데이터 페칭 방법은 fetchBaseQuery를 사용하는 것입니다.
fetchBaseQuery에서 credentials 옵션을 설정하여 CORS 문제를 해결할 수 있습니다.

  • 설정 방법: RTK-Query의 fetchBaseQuery 설정
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const api = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({
    baseUrl: 'http://localhost:8080/api',
    credentials: 'include', // CORS 문제 해결을 위한 설정
  }),
  endpoints: (builder) => ({
    getData: builder.query<DataType, void>({
      query: () => '/data',
    }),
  }),
});

export const { useGetDataQuery } = api;

설명: credentials: 'include' 옵션을 추가하면, 브라우저가 쿠키를 포함한 인증 정보를 API 요청에 자동으로 포함시킵니다.
         이를 통해 CORS 문제를 해결할 수 있습니다.

1.4 RTK-Query와 프록시 서버 설정 (RTK-Query)

개발 중에는 fetchBaseQuery 설정 외에도 프록시 서버를 활용할 수 있습니다.
이 방법은 특히 로컬 개발 환경에서 CORS 문제를 우회할 수 있는 간단한 방법입니다.

  • 설정 방법: package.json 파일에 프록시 설정 추가
// package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "dependencies": {
    // ...
  },
  "proxy": "http://localhost:8080" // Spring Boot 백엔드 주소
}

설명: 프록시 설정을 사용하면, RTK-Query에서 사용하는 모든 API 요청이 동일한
         도메인으로 전송되는 것처럼 보이게 할 수 있습니다.
         이를 통해 CORS 문제를 쉽게 우회할 수 있습니다.

1.5 RTK-Query의 Custom Fetch 사용 (RTK-Query)

기본 fetchBaseQuery 대신, 커스텀 fetch 함수를 정의하여 CORS 문제를 해결할 수도 있습니다.
이 방법은 보다 세밀한 제어가 필요할 때 유용합니다.

  • 설정 방법: 커스텀 Fetch 함수 정의
import { createApi } from '@reduxjs/toolkit/query/react';
import { FetchArgs } from '@reduxjs/toolkit/dist/query/fetchBaseQuery';

const customFetchBaseQuery = async (args: string | FetchArgs) => {
  const response = await fetch(args.url, {
    ...args,
    credentials: 'include', // CORS 문제 해결을 위한 설정
  });

  if (!response.ok) {
    throw new Error('Network response was not ok');
  }

  return response.json();
};

const api = createApi({
  reducerPath: 'api',
  baseQuery: customFetchBaseQuery,
  endpoints: (builder) => ({
    getData: builder.query<DataType, void>({
      query: () => '/data',
    }),
  }),
});

export const { useGetDataQuery } = api;

설명: 이 방법을 사용하면, API 요청 시 필요한 설정을 더욱 세밀하게 조정할 수 있습니다.
특히, credentials: 'include' 설정을 통해 CORS 문제를 해결할 수 있습니다.

1.6 CORS 확장 프로그램 사용

개발 중에만 사용하는 방법으로, 브라우저에서 CORS 확장 프로그램을 설치하여 CORS 정책을 무시할 수 있습니다.

  • 추천 확장 프로그램: CORS Unblock, Allow CORS 등
  • 설명: 이 방법은 개발 환경에서만 임시로 사용하는 것이 좋습니다.
    실제 배포 환경에서는 보안상 위험이 있으므로 사용하지 않는 것이 좋습니다.

2. 백엔드 (Spring Boot)에서 CORS 에러 해결 방법

Java 기반의 Spring Boot 백엔드에서는 CORS 설정을 통해 클라이언트 요청을 허용할 수 있습니다.
아래에서 Spring Boot에서 CORS 문제를 해결할 수 있는 몇 가지 방법을 살펴보겠습니다.

2.1 @CrossOrigin 애노테이션 사용

Spring Boot에서 가장 간단하게 CORS 문제를 해결하는 방법은 @CrossOrigin 애노테이션을 사용하는 것입니다.
이 애노테이션을 컨트롤러나 특정 엔드포인트에 추가하여 특정 도메인에서의 요청을 허용할 수 있습니다.

  • 설정 방법: 컨트롤러에 @CrossOrigin 추가
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(origins = "http://localhost:3000") // React 앱 도메인 허용
public class MyController {

    @GetMapping("/api/data")
    public String getData() {
        return "Hello from Spring Boot!";
    }
}
  • 설명: @CrossOrigin 애노테이션을 사용하면 특정 도메인에서의 요청을 허용할 수 있습니다.
    이 방법은 특정 엔드포인트에만 적용할 수 있어 간편하게 사용할 수 있습니다.

2.2 전역 CORS 설정 (Spring Security 사용 시)

Spring Security를 사용하는 경우, 애플리케이션 전역에서 CORS 설정을 관리할 수 있습니다.
이 방법은 모든 엔드포인트에 대해 일괄적으로 CORS 정책을 적용할 때 유용합니다.

  • 설정 방법: 전역 CORS 설정
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // 쿠키 허용
        config.addAllowedOrigin("http://localhost:3000"); // React 앱 도메인
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}
  • 설명: 이 설정은 Spring Boot 애플리케이션의 모든 엔드포인트에 대해 CORS 요청을 허용하도록 합니다.
    CorsConfiguration 객체를 통해 허용할 도메인, 헤더, 메서드를 정의할 수 있습니다.

2.3 Spring Security에서 CORS 설정

Spring Security를 사용하고 있다면, 보안 설정과 함께 CORS 정책을 설정할 수 있습니다.
이 방법은 보안 요구사항과 CORS 설정을 동시에 관리할 수 있어 유용합니다.

  • 설정 방법: Spring Security와 함께 CORS 설정
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors() // CORS 설정 활성화
            .and()
            .csrf().disable() // 필요한 경우 CSRF 비활성화
            .authorizeRequests()
            .anyRequest().authenticated(); // 요청 인증 설정

        return http.build();
    }
}
  • 설명: 이 설정은 Spring Security와 함께 CORS를 활성화하며, 필요한 경우 CSRF 보호를 비활성화할 수 있습니다.
    이는 보안 요구사항과 CORS 설정을 동시에 관리할 수 있다는 장점이 있습니다.

3. CORS Preflight 요청 처리

CORS 정책에 따라, 브라우저는 실제 요청 전에 Preflight 요청(OPTIONS 메서드)을 서버로 전송할 수 있습니다.
이를 처리하려면 서버에서 OPTIONS 요청에 대해 올바른 응답을 반환해야 합니다.

  • 설정 방법: Preflight 요청 처리
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(origins = "http://localhost:3000", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS})
public class MyController {

    @RequestMapping(value = "/api/data", method = RequestMethod.OPTIONS)
    public void preflight() {
        // Preflight 요청에 대한 응답
    }

    @GetMapping("/api/data")
    public String getData() {
        return "Hello from Spring Boot!";
    }
}

설명: @RequestMapping을 사용하여 OPTIONS 메서드를 처리함으로써 Preflight 요청에 대한
         응답을 제공할 수 있습니다.
         이 방법은 브라우저가 보내는 Preflight 요청에 적절한 응답을 제공하는 데 유용합니다.