[7/6 TIL] SPRING MVC(SPA, Origin, SOP, CORS)

yumyeonghan·2023년 7월 6일
0
post-custom-banner

🍃프로그래머스 백엔드 데브코스 4기 교육과정을 듣고 정리한 글입니다.🍃

SPA(Single-Page Application)

  • 사용자 요청에 의해 URL 변경 시 화면 전체의 로드 없이 일부반만 동적으로 렌더링
  • AJAX를 이용해서 대부분 리소스들(HTML, CSS, JS)은 어플리케이션 로드시 한번만 읽음
  • JSON같은 데이터만 어플리케이션 실행중에 읽어오고 관련된 화면을 동적으로 변경

서버사이드 라우팅 처리(JSP, Thymeleaf)

  • 서버는 클라이언트 요청을 받아 해당하는 데이터를 가져오거나 작업을 수행한 후, 클라이언트에 결과를 제공
  • 클라이언트가 새로운 URL을 요청하면, 서버는 해당 URL에 대한 페이지 전체를 다시 렌더링하고 클라이언트에 전달
  • 각 요청마다 서버에서 작업을 수행하기 때문에, 많은 요청이 동시에 발생하면 서버 부하가 증가

클라이언트 라우팅 처리(View.js, React.js)

  • 클라이언트는 초기 페이지를 로드한 후 서버로부터 데이터를 가져와 라우팅 처리를 수행
  • URL이 변경될 때, 클라이언트는 필요한 데이터만 서버로 요청하여 해당 데이터만 업데이트
  • 이미 로드된 페이지에서 필요한 데이터를 서버로부터 받아와 클라이언트 측에서 처리하므로 서버 부하가 감소
  • 웹 애플리케이션에서 동적으로 URL을 변경하고, 뒤로 가기/앞으로 가기 버튼과 같은 탐색 동작을 처리할 수 있HTML5 히스토리 API 사용

Origin(출처)

그림 출처

  • Protolcol 과 Host 그리고 Port 까지 모두 합친 URL을 의미

SOP(Same-Origin Policy)

  • 동일한 출처에서만 리소스를 공유할 수 있다라는 정책
  • 동일하지 않는 다른 출처의 악성 스크립트가 실행되지 않도록 브라우저에서 사전에 방지하기 위함

출처 구분

그림 출처

  • https://www.domain.com:3000 출처에 대한 여러 URL에 따른 동일 출처 비교
  • 같은 프로토콜, 호스트, 포트를 사용한다면, 그 뒤의 다른 요소는 다르더라도 같은 출처로 인정
  • 반대로 프로토콜, 호스트, 포트 중 하나라도 자신의 출처와 다를경우 브라우저는 SOP 정책상 차단(CORS 에러)
  • 이는 브라우저의 정책이기 때문에 브라우저를 통하지 않고 서버 간에 통신을 할때는 정책이 적용되지 않음
  • 즉, 클라이언트에서 API 요청을 하는게 아니라, 프록시 서버에서 다른 출처의 서버로 API 요청하면 CORS 에러 해결

CORS(Cross-Origin Resource Sharing)

웹페이지에서 다른 출처에 있는 리소스를 가져와 사용하는 일은 매우 흔한 일이기 때문에 이를 전부 차단할 수 없다. 그래서 나온 정책이 CORS

  • 다른 출처의 리소스 공유에 대한 허용/비허용 정책
  • SOP 정책을 위반해도 CORS 정책에 따르면 다른 출처의 리소스라도 허용함

CORS 3가지 동작 방식

Preflight Request

그림 참조

  • 브라우저가 요청을 한번에 보내지 않고 예비 요청과 본 요청으로 나눠 서버로 전송
  • 이때 예비요청을 preflight이라 함

Simple Request

그림 참조

  • 예비요청 없이 바로 본 요청을 보내고, 응답에 따라 CORS 정책 위반 여부를 검사
  • 단, simple request 시나리오를 위해선 특정 조건을 만족해야 함
    • HTTP method가 GET, HEAD, POST 중 하나여야 함
    • Accept, Accept-Language, Content-Language, Content-type, DPR, Downlink, Save-Data, Viewport-Width, Width 이외의 헤더를 사용하면 안됨
    • Content-Type 사용하는 경우 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용

Credentialed Request

  • 다른 출처 간 통신의 보안을 강화하고 싶을 때 사용
  • 클라이언트에서 인증 정보를 보내도록 credentials 옵션을 설정해야 함
    • same-origin(기본값): 같은 출처 간 요청에만 인증 정보를 담을 수 있음
    • include: 모든 요청에 인증 정보를 담을 수 있음
    • omit: 모든 요청에 인증 정보를 담지 않음
  • 서버에서 인증된 요청에 대한 응답 헤더의 Access-Control-Allow-Credentials 항목을 true로 설정해야 함

CORS 에러 해결 방법

클라이언트에서 프록시 사용

// React.js 프록시 설정 파일 (src/setupProxy.js 또는 src/setupProxy.js)

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:8080', // Spring 서버의 주소
      changeOrigin: true,
    })
  );
};
  • localhost에서 react와 spring 서버를 통신하는 상황이라면 프록시 서버를 spring 서버의 주소로 설정
  • OPEN API를 사용하는 경우 모든 출처를 허용한 프록시 서버를 사용

서버에서 Access-Control-Allow-Origin 헤더 세팅

@RestController
public class ExampleController {

    @CrossOrigin(origins = "http://localhost:3000", methods = RequestMethod.POST // React.js 애플리케이션의 주소
    @GetMapping("/api/data")
    public String getData() {
        // 데이터를 반환하는 로직
        return "Hello from Spring server!";
    }
}
  • 직접 spring 서버에서 HTTP 헤더 설정을 통해 출처를 허용하게 하는 방법
  • 특정 HTTP 메서드의 출처만 허용하게 적용 가능
profile
웹 개발에 관심 있습니다.
post-custom-banner

0개의 댓글