티스토리 뷰

면접대비

Ajax에 대해

빵파레2 2019. 9. 14. 20:44

Ajax란?


  • Ajax란 Asynchronous JavaScript and XML (비동기식 자바스크립트와 xml)의 약자이다.
  • 브라우저가 가지고 있는 XMLHttpRequest 객체를 이용해 비동기식으로 서버와 통신하는 기술이다.
  • 즉, JavaScript를 사용한 비동기 통신이며 클라이언트와 서버간에 JSON, XML 등의 데이터를 주고받을 수 있는 기술이다.
Q) 비동기식 (Asynchronous)?
비동기식이란 여러가지 일이 동시적으로 발생한다는 뜻으로, 서버와 통신하는 동안 다른 작업을 할 수 있다는 의미를 지닌다.

 

Ajax의 장점?


  • 웹 페이지 전체를 다시 로딩하지 않고도, 웹 페이지의 일부분만을 갱신할 수 있다. (기본적으로 HTTP는 Connectionless 한 성질을 갖는다. 즉, 일반적으로 화면의 내용을 갱신하기 위해서는 다시 request, response의 과정을 거쳐 페이지 전체를 로드해야 한다.)
  • ajax를 사용하지 않고 페이지 전체를 다시 로드하려면 자원과 시간낭비를 초래할 것이다.
  • ajax는 JSON이나 XML 형태로 필요한 데이터만 받아 갱신할 수 있기 때문에 자원과 시간을 아낄 수 있는 좋은 방법이다.

 

Ajax의 한계


  • Ajax는 클라이언트가 서버에 데이터를 요청하는 클라이언트 풀링 방식을 사용하므로, 서버 푸시 방식의 실시간 서비스는 만들 수 없다.
  • Ajax 스크립트가 포함된 서버가 아닌 다른 서버로 Ajax 요청을 보낼 수 없다. (SOP(Same-Origin Policy) 때문)
Q) 클라이언트 풀링 (Client Pooling) 방식
사용자가 직접 원하는 정보를 서버에게 요청하여 얻는 방식을 의미한다.
이에 반해 서버 푸시(server push) 방식이란 사용자가 요청하지 않아도 서버가 알아서 자동으로 특정 정보를 제공하는 것을 의미한다.
요즘 많이 사용하는 스마트 폰에서 각종 앱이 보내는 푸시 알림이 서버 푸시 방식의 대표적인 예이다.

 

SOP (Same-Origin Policy) 란?


  • 동일 출처 정책의 약자로 한 출처(Origin)에서 로드된 문서나 스크립트가 다른 출처 자원과 상호작용하지 못하도록 제약하는 것이다.
  • 동일 출처라는 것은 Protocol, Host, Port가 같다는 것을 의미하고 이 중 하나라도 다르면 동일 출처(Same-Origin)가 아니다.
  • 자바스크립트의 API에 대한 호출은 SOP의 제약을 받는다. (ajax 또한 SOP의 제약을 받음)
  • 쉽게 말해, 웹 페이지의 스크립트는 그 페이지와 같은 서버에 있는 주소로만 ajax 요청을 할 수 있다.

 

CORS (Cross-Origin Resource Sharing)란?


  • CORS란, 웹 서버 도메인간 액세스 제어 기능을 제공하여 보안 도메인간 데이터 전송을 가능하게 해주는 정책이다.
  • SOP 정책이 초기에는 웹 사이트의 보안을 위한 좋은 방법으로 생각되었으나 요즘은 여러 도메인에 걸쳐서 구성되는 대규모 웹 프로젝트가 늘어나고, REST API 등을 이용한 외부 호출이 많은 상황에서는 거추장스러운 기술이 되기도 한다.
  • 그래서 만들어진 추가 정책이 바로 CORS 이다.
  • CORS를 사용하면 외부 서버의 주소로 Ajax요청이 가능하다.

 

CORS의 작동 방식


  • 요청하려는 URL이 외부 도메인일 경우 웹 브라우저는 preflight request(사전 요청)을 먼저 보낸다.
  • preflight요청은 실제로 요청하려는 경로와 같은 URL에 대해 OPTIONS 메서드로 요청을 미리 날려보고 요청 할 수 있는 권한이 있는지 확인한다.
  • CORS요청을 편법없이 처리하기 위해서는 클라이언트 처리만으로는 어렵고 서버측에서 preflight요청을 처리하는 기능이 필요하다.

 

SOP를 방지하는 방법


1. JSONP 방식으로 요청

  • 웹 브라우저에서 css나 js 같은 리소스 파일들은 SOP에 영향을 받지 않고 로딩이 가능하다. 이런 점을 응용해서 외부 서버에서 읽어온 js 파일을 json으로 바꿔주는 일종의 편법이다.
  • CORS 구현이 안되어 있는 서버로 ajax 요청을 해야 하지만 서버 쪽 컨트롤이 불가능할 경우 시도해 볼 수 있는 방법이다. (ex. open API 서버에 ajax 요청을 하고자 할 경우)
  • 단점은 리소스 파일을 GET 메서드로 읽어오기 때문에 GET 방식의 API만 요청이 가능하다.
$.ajax({ 
    type: 'GET', 
    url: url, 
    dataType: 'jsonp', //cross-domain 이슈를 회피하기 위해 jsonp요청을 한다. 
    success: callback
})

 

2. 서버에서 CORS 요청 핸들링하기

  • Ajax 요청을 해야 하는 다른 도메인의 서버를 클라이언트와 같이 개발하거나 서버 개발 쪽 컨트롤이 가능할 경우 시도해 볼 수 있는 방법
  • 스프링 같은 경우에는 @CrossOrigin 어노테이션을 제공하여 크로스도메인 이슈를 쉽게 처리할 수 있다.
@CrossOrigin(origins = “허용주소:포트”)

 

  • ex1) WebMvcConfigurer를 통해 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) {
      // 모든 uri에 대해 http://localhost:18080, http://localhost:8180 도메인은 접근을 허용한다.
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:18080","http://localhost:8180");

    }
}

 

  • ex2) @CrossOrigin 어노테이션을 통해 적용하는 방식.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
//해당 컨트롤러의 모든 요청에 대한 접근 허용(아래 도메인 두개에 대해서만..)
@CrossOrigin(origins = {"http://localhost:18080", "http://localhost:8180" }) 
@RestController
public class CorssampleApplication {
 
	//아래와 같이 특정 메소드에만 적용할수도 있다.
    //@CrossOrigin(origins = {"http://localhost:18080", "http://localhost:8180" })
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
	
	@GetMapping("/my")
    public String my() {
        return "my";
    }
	
 
    public static void main(String[] args) {
        SpringApplication.run(CorssampleApplication.class, args);
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script
           src="https://code.jquery.com/jquery-3.3.1.js"
            integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
            crossorigin="anonymous"></script>
    <script>
       // alert(1);
        $(function() {
			  // 만약 이 코드가 실행되는 웹서버의 도메인이 http://localhost:18080과 http://localhost:8080이 아닐경우 fail이 발생한다.
            $.ajax("http://localhost:8180/hello")
                .done(function(msg) {
                    alert(msg);
                }).fail(function() {
                    alert("fail");
                });
        });
    </script>
</head>
<body>

</body>
</html>

 

3. proxy 서버를 이용하는 방법

  • Same-Origin Policy의 문제는 API 서버와 Javascript가 호스팅 되는 서버의 URL이 다르기 때문에 발생하는 문제이므로 앞단에 Reverse Proxy를 구축해서, 전체 URL을 같게 만들어 주면 된다.

  • 위와 같은 구조에서는 javascript 가 로딩된 사이트도 mysite.com이 되고, javascript에서 호출하고자 하는 api URL도 mysite.com이 되기 때문에, Same Origin Policy에 위배되지 않는다.
  • 위의 방식은 자사의 웹사이트를 서비스 하는 경우에만 가능하다. (타사의 사이트를 Reverse Proxy뒤에 놓기는 쉽지 않다.) 그래서 자사의 서비스용 API를 만드는데는 괜찮지만, 파트너사나 일반 개발자에게 자바스크립트용 REST API를 오픈하는 경우에는 적절하지 않다.

 

참고자료


https://brunch.co.kr/@adrenalinee31/1

https://brocess.tistory.com/168

https://bcho.tistory.com/tag/Same%20origin%20policy

'면접대비' 카테고리의 다른 글

TDD와 Junit에 대해  (0) 2019.11.01
프록시 서버에 대해  (0) 2019.09.18
TCP와 UDP에 대해  (0) 2019.09.11
프로세스와 스레드에 대해  (0) 2019.09.10
싱클톤 패턴에 대해  (0) 2019.09.09