Web/Javascript

[javascript / jQuery] 크로스 도메인

클리엘 2020. 7. 3. 03:32
728x90

웹브라우저는 보안을 위해 현재 도메인에서 다른 도메인으로의 요청을 원칙적으로 차단하고 있습니다. 따라서 다음과 같은 시도를 하게 되면

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
	<script>
		$(function () {
			$.ajax({
				url: 'https://www.naver.com/',
				success: function (data) {
					alert(data);
				}
			});
		});
	</script>
</head>
<body>
	<div>
	</div>
</body>
</html>

브라우저는 크로스 도메인 관련 오류를 내뿜게 됩니다.

 

위 문제를 해결하기 위한 방법으로는 대략 2가지 정도를 알아보고자 합니다.

 

1. JSONP

 

JSONP(JSON with Padding)는 다른 도메인에 요청을 보낼 때 callback매개변수를 보내면 응답을 보낼 때 JSON형태의 결과를 callback매개변수로 보낸 함수명으로 감싸 반환받는 형태를 의미합니다.

 

우선 예제작성을 위해 JSONP형태의 응답을 반환하는 서버를 만듭니다.

public class HomeController : Controller
{
    // GET: Home
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult JSONP(string callback)
    {
        var members = new List<Member>
        {
            new Member { Name = "홍길동", Age = 23, Address = "서울시" },
            new Member { Name = "홍길순", Age = 40, Address = "부산시" },
            new Member { Name = "홍길남", Age = 33, Address = "대구시" }
        };

        return Content(string.Format("{0}({1})", callback, JsonConvert.SerializeObject(members)));
    }
}

public class Member
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
}

예제는 ASP.NET으로 작성하였으며 callback매개변수로 전달해 오는 이름으로 특정 내용을 json으로 감싸 반환하게 됩니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
	<script type="text/javascript">
		function cb(data)
        {
			alert(data);
		}
	</script>
</head>
<body>
	<div>
	</div>
</body>
<script type="text/javascript" src="http://server2016.cliel.com/home/jsonp?callback=cb"></script>
</html>

요청은 위와같이 할 수 있습니다. callback매개변수로 cb라는 이름을 전달했고 따라서 응답이 올 때는 cb라는 함 수명 안에 json객체를 담아올 것입니다. 그렇게 되면 자연스럽게 cb함수가 실행할 수 있게 됩니다.

 

jQuery를 통해 요청하는 경우라면 다음과 같이 할 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
		<script>
		$(function () {
			$.ajax({
				url: 'http://server2016.cliel.com/home/jsonp',
				dataType: 'jsonp',
				success: function (data) {
					alert(JSON.stringify(data));
				}
			});
		});
	</script>
</head>
<body>
	<div>
	</div>
</body>
</html>

jQuery에서는 dataType을 jsonp로 지정하는 경우 알아서 callback을 전달하므로 별도로 callback을 지정하지 않습니다.

 

보시는 바와같이 JSONP를 사용하면 크로스 도메인 간 통신이 가능하지만 제대로 이용하려면 응답을 하는 서버 쪽에서도 JSONP형식의 응답을 해줘야 하며 json데이터만 전달할 수 있습니다.

 

2. 서버에서 가져오기

 

다루고자 하는 데이터 형식이 json이 아니거나 기타 이유로 JSONP를 이용할 수 없는 상태라면 서버단 backend에서 필요한 데이터를 요청하고 응답을 받아 처리하는 형식을 취해야 합니다.

public ActionResult GetHTML()
{
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.daum.net/");
    HttpWebResponse res = (HttpWebResponse)req.GetResponse();
    StreamReader reader = new StreamReader(res.GetResponseStream());

    return Content(reader.ReadToEnd());
}

위에서 작성환 ASP.NET코드에서 위 메서드를 추가합니다. 이 액션 메서드는 daum.net의 메인 페이지 HTML 소스를 긁어오는 동작을 수행합니다. 중요한 건 ASP.NET코드를 어떻게 작성하는가가 아니라 원하는 데이터를 가져오기 위해 서버에서 직접 요청을 하고 있다는 사실입니다.

 

서버를 통해 가져오는 경우라면 클라이언트에서는 타겟의 URL을 직접 호출하는 것이 아니라 서버의 URL을 통해 데이터를 가져올 수 있게 됩니다.

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/Scripts/jquery-3.4.1.min.js"></script>
    <script>
        $(function () {
            $.ajax({
                url: '/home/gethtml',
                success: function (data) {
                    alert(data);
                }
            });
        });
    </script>
</head>
<body>
    <div> 
    </div>
</body>
</html>

크로스 도메인은 어디까지나 웹브라우저 안에서만 제한되는 경우이므로 서버에서 직접 타 URL을 통해 원하는 데이터를 가져오는 우회적인 방법을 사용하는 것입니다.

 

728x90