반응형

 

#. 크로스 도메인(Cross Domain)의 정의


크로스 도메인의 정의는 '서로 다른 도메인(Domain) 간의 호출'입니다.

만약, 제가 개발한 웹 사이트에서만 사용하기 위해서 API 서버를 구축하였는데, 다른 웹 서비스에서 이 API 서버에 마음대로 접근하여 API를 호출하여 사용한다면 보안상 큰 문제가 되어 이를 차단합니다. 그래서 Javascript는 Same Origin Policy(동일한 출처 정책)을 두어 다른 도메인 서버에 요청(Request) 하는 것을 차단합니다. 다시 말해 Javascript는 동일한 도메인 내에서만 서버 요청을 허용한다는 것입니다.

이러한 크로스 도메인 이슈는 아래와 같이 A, B 페이지 간에 통신을 하려고 할 때 발생할 수 있습니다. 예를 들어 설명을 하겠습니다.

1. 아래와 같이 도메인이 다른 경우

A : 네이버(www.naver.com) / B : 구글(www.google.com)

2. 아래와 같이 메인 도메인은 같지만 서브 도메인이 다른 경우

A : 네이버 카페(cafe.naver.com) / 네이버 블로그(blog.naver.com)

3. 아래와 같이 포트 번호가 서로 다른 경우

A : 네이버(www.naver.com:8080) / B : 네이버(www.naver.com:8088)

4. 아래와 같이 프로토콜이 상이한 경우

A : HTTP 네이버(http://www.naver.com) / HTTPS 네이버(https://www.naver.com) 

 

동일한 도메인 내에서만 통신을 할 수는 없는 노릇이고 개발을 진행하다 보면 분명 다른 도메인과 통신이 필요한 경우가 생기게 되고 이를 해결하기 위해 크로스 도메인을 허용해야 경우가 있습니다.

 

#. 크로스 도메인을 허용해야 하는 이유


 

 

예를 들어, 하나의 웹 사이트에서 효율성이나 성능 등의 이유로 각 기능별로 여러 서버를 두는 경우가 많습니다. (API 서버, WAS 서버, 파일 서버 등) 그런데 이 서버들은 물리적으로 분리된 서버이고, 다른 용도로 구축된 서버이기 때문에 당연히 각각 다른 도메인을 가진 서버들입니다. 그래서 크로스 도메인 이슈(다른 도메인의 서버의 URL을 호출하여 데이터를 가져올 수 없다.)가 발생하기 때문에 서로 간의 AJAX 통신을 할 수가 없습니다. 그래서 크로스 도메인(서로 다른 도메인 간의 호출)을 허용해야 하는 경우가 생깁니다.

그래서 고안된 게 크로스 도메인을 허용하는 방법입니다. 크로스 도메인을 활성화시키는 방법은 약 3가지가 있으며 방법은 아래와 같습니다.

 

첫 번째 방법은 Javascript의 document.domain을 이용하는 것입니다. 참고로 이는 서브 도메인 간의 크로스 도메인 문제 해결에만 사용될 수 있는 방법입니다.

예를 들어 http://cafe.naver.com/test.html에서 http://blog.naver.com/test.html에에 접근한다고 하면 각 소스의 Javascript 부분에 아래와 같이 명시해서 도메인 값을 맞춰줍니다.

<script type="text/javascript">
     document.domain = 'naver.com';
</script>

 

두 번째 방법은 jsonp를 이용하는 것입니다. 이 방법은 서브 도메인 외에도 사용할 수 있는데 아래 두 가지 특성을 이용한 일종의 편법적인 방법입니다.

  - HTML의 scipt 요소로부터 요청되는 호출에는 Same Origin Policy(동일 출처 정책) 정책이 적용되지 않음

  - script 요소는 src를 호출한 결과를 javascript를 불러와서 포함시키는 것이 아니고 실행시키는 태그임

<script src="http://code.jquery.com/jquery-latest.js"></script>

예를 들어 위 코드는 jquery를 링크하는데 code.jquery.com에서 항상 최신 버전을 받아오도록 하는 코드입니다.

제가 개발하는 도메인과 다른데도 전혀 문제가 되지 않습니다. Same Origin Policy(동일 출처 정책) 정책이 적용되지 않기 때문입니다.

클라이언트 측은 jquery를 이용해서 아래와 같이 간단하게 구현할 수 있습니다.

$.ajax ( {
    url : "http://cafe.naver.com/useSearch",
    data : "id=user";
    dataType : "jsonp",
    jsonCallback : "callbackOfJsonp",
    success : function(response) {
            /* data는 JSON 객체임 */
            console.log(response);
    }
} )

서버 측에서도 별도의 작업이 필요합니다.

"script 요소는 src를 호출한 결과를 javascript를 불러서 포함시키는 것이 아니고 실행시키는 태그이다."라는 특성을 이용해 실행될 함수 자체를 문자열로 완성해서 리턴해주어야 하는데 위 AJAX Jsonp 처리를 위해서는 결국 서버의 Controller에서 아래와 같은 문자영을 리턴해주어야 합니다.

"callbackOfJsonp ("name", "test", "ageL28")

이렇게 되면 $.ajax 에서는 jsonpCallback 요소로 지정된 함수명과 일치하는 함수 문자열을 success 요소에 바인딩해서 처리되도록 해줍니다.

이를 위해서 데이터는 Json 문자열 포맷으로 하고 그것을 다시 특정 함수로 감싸줘야 합니다.

일반적으로 Jackson 라이브러리와 @RestController를 많이 사용하기 때문에 Json 포맷을 리턴하는 것은 문제가 되지 않지만 위와 같이 함수명을 감싸려면 아래와 같이 @ControllerActive를 만들어놔야 합니다.

@ControllerActive
public class JsonAdviceController extends AbstractJsonResponseBodyAdvice {
       public JsonAdviceController () {
               super ("callback");
      }
}

 

세 번째 방법은 CORS를 이용하여 핸들링하는 것입니다.

CORS (Cross-Origin Resources Sharing)의 약자로써 HTML5에서 스펙이 정의되었으며, IE8이상의 모든 브라우저에서 구현되어 있습니다. CORS는  서버와 클라이언트가 정해진 헤더를 통해서 서로 요청이나 응답에 반응할지 결정하는 방식으로써 웹 페이지의 제한된 자원을 외부 도메인에서의 접근 및 요청을 허용해 주는 것입니다. CORS를 이용하여 특정 도메인에서 접근하는 것이 가능하도록 허용해 줌으로써 서로 다른 도메인 간의 호출이 가능하게 됩니다.

동작 방식은 아래와 같습니다.

이처럼 요청하는 URL이 외부 도메인일 경우 웹 브라우저는 OPTION으로 preflight 요청을 먼저 날려고 요청할 수 있는 권한이 있는지 확인합니다. 서버 단에서는 이렇게 날아온 preflight 요청을 처리하여 웹 브라우저에서 실제 요청을 날릴 수 있도록 해주면 됩니다.

일반적으로 filter나 interceptor로 처리하여 Spring에서 filter 기준 아래와 같이 구현합니다.

public class CORSFilter extends OncePerRequestFilter {

    @override
    protected void doFilterInternal (HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
    throws ServletException {
          response.addHeader ("Accept-Control-Allow-Origin", "*");
          response.addHeader ("Accept-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE");
          response.addHeader ("Accept-Control-Max-Age", "3600");
          response.addHeader ("Accept-Control-Allow-Headers", "X-Requested-With");

          filterChain.doFilter (request, response);

    }
}

Reference

1. [JavaScript] 크로스 도메인(Cross Domain) : 네이버 블로그 (naver.com)

2. 크로스 도메인(cross-domain) 이슈 : 네이버 블로그 (naver.com)

반응형

'Development > Web' 카테고리의 다른 글

[Web] Spring Framework vs Spring Boot  (0) 2022.09.24
[Web] Spring Framework의 특징  (0) 2022.09.24
[Web] 뷰 컴포넌트 통신  (0) 2022.09.19
[Web] 뷰 컴포넌트  (0) 2022.09.18
[Web] 뷰 인스턴스 라이프 사이클  (0) 2022.09.18

+ Recent posts