Facts
✅ 프론트엔드 아키텍처와 백엔드 아키텍처 연결
✅ CORS 에러 fix
✅ API 통신 확인
Findings
SOP (Same Origin Policy)
Same Origin Policy의 약자로, 웹 브라우저의 브라우저 보안을 위해
Same-Origin(프로토콜, 호스트, 포트가 같은) 서버로만 리소스를 주고 받을 수 있도록 하는 정책이다.
왜 다른 출처의 리소스를 사용하는 것을 제한할까?
SOP를 이용해 악의적인 리소스를 분리해서 공격의 경로를 줄일 수 있기 위함이다.
하지만, 클라이언트와 서버를 분리하여 개발하는 경우가 많기에,
다른 도메인간에 API 통신을 허용을 위해서 CORS가 등장했다.
CORS (Cross Origin Resource Sharing)
CORS는 Cross-Origin Resource Sharing 약어로,
쉽게 설명하면, 다른 도메인간에 API 통신을 허용한다는 뜻이다.
지금 하고 있는 TDP 프로젝트는 프론트엔드와 백엔드가 분리되어있다.
프론트엔드와 백엔드 간의 도메인이 다르기 때문에 API 통신을 하려면 CORS를 허용해 주어야 한다.
Spring에서 CORS 에러 해결하기 위한 방법
Spring에서 CORS 에러를 해결하기 위한 방법을 찾아본 결과, 크게 3가지가 있었다.
- Servlet Filter를 사용하여 커스텀한 CORS 설정하는 방법
- Controller 클래스에 @Crossorigin 어노테이션을 통해 해결하는 방법
- WebMvcConfiguer를 구현한 Configuration 클래스를 만들어서
addCorsMappings()를 재정의 하는 방법
1️⃣ Servlet Filter를 사용하여 커스텀한 CORS 설정하는 방법
서버의 응답을 보내기 전에 Access-Control-Allow-Origin 헤더를 싣는 필터를 작성하는 방법이다.
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:5500");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods","*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization");
if("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
}else {
chain.doFilter(req, res);
}
}
@Override
public void destroy() {
}
}
이 방법은 실제로 응답 헤더에 실릴 값들을 모두 설정해준다.
복잡한 설정이 필요한 경우에 사용하면 좋을 것 같다.
2️⃣ Controller 클래스에 @Crossorigin 어노테이션을 활용하는 방법
Controller 클래스 상단이나 Controller Mapping 메소드 상단에
CrossOrigin(origins="도메인 url")을 어노테이션으로 작성하는 방법이다.
@CrossOrigin(origins = "http://127.0.0.1:5500/") // 컨트롤러 클래스의 상단
@RequiredArgsConstructor
@RestController
public class ArticleRestController {
public final ArticleRepository articleRepository;
public final ArticleService articleService;
public final LocationDistance location;
@CrossOrigin(origins = "http://127.0.0.1:5500/") // 컨트롤러 맵핑 메소드 상단
@GetMapping("/api/articles/{query}")
public ResponseEntity<List<Article>> getArticles (@PathVariable("query") String query) {
List<Article> articles = articleRepository.findAllByTitleContains(query);
return ResponseEntity.ok().body(articles);
}
}
1번 방법에 비해, 코드가 간결하고, 어노테이션 형태라 사용할 곳에 붙여 쓰면 되어 편리하다.
3️⃣ WebMvcConfig를 구현한 Configuration 클래스를 만드는 방법
WebMvcConfig 클래스를 활용하는 방법이다.
WebMvcConfiguer를 implement한 클래스를 만들고,
@Configuration 어노테이션으로 어플리케이션에 연결하는 방법이다.
allowedOrigins, allowedMethods 메서드를 통해 cors를 설정해줄 수 있다.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:5500", "http://127.0.0.1:5500")
.allowedMethods("POST", "PUT", "GET", "HEAD", "OPTIONS", "DELETE");
}
}
간단한 코드로 전체 범위의 CORS를 설정해줄 수 있어서 3번 방법을 선택!
이렇게 하면, 애플리케이션 단위에서 CORS를 허용해줄 수 있다.
참고 자료
'Project > TIL, WIL' 카테고리의 다른 글
TIL(51) JPA 관련 에러 고치기 (0) | 2021.12.27 |
---|---|
TIL(50) S3를 이용한 사진 업로드 기능 속도 개선하기 (0) | 2021.12.27 |
TIL(48) 21-12-08: API 문서 자동화와 테스트 코드 작성하기 (Using RestDoc) (0) | 2021.12.27 |
TIL(47) 21-12-07: ElasticBeanstalk으로 백엔드 아키텍처 구성하고 GithubAction으로 프로젝트 배포 (0) | 2021.12.27 |
TIL(46) 21-12-06: S3와 CloudFront로 프론트엔드 인프라 구성하기 (0) | 2021.12.27 |