웹 프로그래밍 고급 주제들

3. AJAX와 플라스크

영바이트 2020. 12. 16. 15:04

 

AJAX(Asynchronous JavaScript and XML)는 자바스크립트JavaScript를 이용하여 서버와 클라이언트 사이에 비동기적으로 데이터를 교환하는 방식이다. 말이 어렵다. 조금 풀어서 이야기해보자.

 

서버와 클라이언트가 데이터를 주고받는 기본적인 방식은 페이지 단위로 주고받는 것이다(정확히는 클라이언트가 요청하면 서버가 페이지 단위로 준다).

 

기본동작 - 페이지 단위 전달

 

만약 페이지 내용이 몇 글자 밖에 바뀌지 않았다고 가정하자. 이러한 일이 자주 일어나면 매번 페이지를 새로 받는 것은 낭비라고 할 수 있다. 더불어 페이지가 바뀔 때(새로고침될 때) 웹 브라우저의 뷰(view)전체가 바뀌는 것도 사용자에게 좋은 경험을 주지는 못한다(화면이 깜빡거리고 웹 브라우저에서 딸깍하는 소리를 낸다).

 

AJAX를 이용하면 페이지 전체를 새로고침 하지않고 필요한 데이터만 주고 받을 수 있다. 그리고 자바스크립트를 이용하여 웹 페이지의 특정 부분만 새로고침 하게된다. 간단한 예제를 통해 AJAX를 통한 서버-클라이언트 동작을 살펴보자.

 

AJAX 데이터 단위 교환

 

※ AJAX 기능 구현에는 자바스크립트JavaScript 코드가 사용됩니다. 자바스크립트를 이미 알고 계신다고 생각하고 별도로 설명하지 않고 진행하겠습니다.

 

 


 

 

예제는 아래와 같이 서버가 초기 페이지(이름 및 나이 정보)를 보내오고 사용자가 'Send data'버튼을 클릭하면 AJAX 요청 및 응답 과정을 통해 상세 데이터(전공 정보)만 추가로 보내는 동작을 구현해 볼 것이다.

 

초기 페이지

 

전공 정보만 AJAX를 이용해 추가한 페이지

 

간단한 예제이지만 AJAX를 이용하는 방법과 흐름이 내용에 포함되어 있어서 더 복잡한 응용에도 적용될 수 있다.

 

 

 


 

 

AJAX 기능을 플라스크 웹 서버 환경에서 어떻게 구현하는지 그 방법을 예제를 진행하면서 살펴보자. 예제 진행을 위해 예제 프로젝트(여기서는 03_AJAX로 이름붙였다)를 생성하고 프로젝트 디렉토리 아래에 플라스크 웹 서버 객체가 포함될 appmain 디렉토리를 생성한다.

 

예제를 위한 디렉토리 생성

 

웹 서비스 구현을 위한 기본 순서인 모델/폼 → 뷰 → 로직 순서로 구현을 진행하자. 이번 예제에서는 특별히 사용자로부터 받을 입력은 없기 때문에 뷰부터 구현하였다. 아래와 같이 appmain 디렉토리 아래에 templates 디렉토리를 생성하고 이 templates 디렉토리 안에 AJAX 기능을 가진 웹 페이지를 생성한다.

 

뷰 파일 구현

 

▶appmain/templates/ajax.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>AJAX exercise</title>
</head>
<body>
    <div>
        <h2 id="name">Mike</h2>
    </div>
    <div>
        <h2 id="age">62</h2>
    </div>
    <div>
        <h2 id="major"></h2>
    </div>
    </div>
        <button id="sendDataButton">Send data</button>
    </div>
    <!-- AJAX를 위해 추가된 JavaScript -->
    <!-- HTML 파일은 클라이언트에서 수행되는 것임을 명심하자 -->
    <script>
        var sendDataButton = document.getElementById("sendDataButton");

        <!-- Send data 버튼을 클릭하면 실행될 내용을 event listener에 등록한다 -->
        sendDataButton.addEventListener("click", function(){
            
            <!-- 뷰(html 파일)에서 name, age, major 정보를 가져온다 -->
            var name = document.getElementById("name").innerHTML;
            var age = document.getElementById("age").innerHTML;
            var major = document.getElementById("major").innerHTML;

            <!-- name, age, major 정보를 JSON으로 만든다 -->
            var args = JSON.stringify({'name':name, 'age':age, 'major':major});

            <!-- AJAX에 쓰일 XMLHttpRequest 객체를 생성한다 -->
            var ajaxRequest = new XMLHttpRequest();
            
            <!-- POST 방식으로 서버에 정보(데이터 요청)를 전달한다 -->
            ajaxRequest.open('POST', '/ajax/request');
            
            <!-- onload 함수는 서버로부터 AJAX 응답이 오면 실행된다 -->
            <!-- onload 함수와 같이 어떤 사건이 일어나면 실행되는 함수를 콜백callback 함수라 부른다 -->
            ajaxRequest.onload = function(){
                <!-- 서버의 응답으로부터 major 데이터를 추출하고 페이지에 표시한다 -->
                var resData = JSON.parse(ajaxRequest.responseText);
                var major = document.getElementById("major");
                major.innerHTML = resData['major'];
            };
            
            <!-- 서버에 보낼 요청 형식을 지정한다 -->
            ajaxRequest.setRequestHeader('Content-type', 'application/json');
            
            <!-- JSON 형태로 생성한 데이터인 args를 서버로 전송한다 -->
            ajaxRequest.send(args);
        }, false);
    </script>
    <!-- AJAX를 위해 추가된 JavaScript -->
</body>
</html>

 

AJAX는 자바스크립트의 XMLHttpRequest객체를 이용해서 구현된다. 뷰 파일의 내용 중 Script 부분을 보면 'Send data' 버튼을 클릭하면 XMLHttpRequest 객체를 생성하고 현재 뷰에 표시되어 있는 정보들(name,age,major)을 서버로 전송하도록 구현되어 있다.

 

서버로부터 응답이 도착하면 XMLHttpRequest객체의 onload 함수에 설정한 내용이 실행된다. 이처럼 특정 사건이 발생하면 호출되는 함수를 콜백callback함수라고 한다. 설정한 콜백 함수의 내용은 서버로부터 받은 데이터에서 major 정보를 추출하고 이를 웹 페이지에 자바스크립트를 이용하여 나타내는 것이다.

 

서버는 AJAX 요청을 /ajax/request URL로 전달받는다. 요청을 받으면 수행할 내용을 플라스크 웹 서버가 구현되어 있는  패키지인 appmain 패키지의 routes.py 파일에 구현한다.

 

클라이언트 요청 처리로직 구현

 

▶ appmain/routes.py

from flask import render_template, request, Blueprint

main = Blueprint('main', __name__)

@main.route("/ajax")
def home():
    return render_template("ajax.html")

@main.route("/ajax/request", methods=['POST'])
def respondAjax():
    #### 클라이언트가 보내온 요청을 가져온다.
    data = request.json
    
    #### 요청 내용 중 'major' 항목에 데이터를 입력한다.
    data['major'] = 'Physics'
    
    #### 수정된 요청 데이터를 플라스크 웹 서버를 통해 클라이언트에 전달한다.
    return data

 

AJAX방식으로 데이터를 요청하기 위해 뷰 파일(ajax.html, 클라이언트에서 실행)에서는 약속한 URL 주소로 요청을 보낸다. 이 주소가 ajax.html의 ajaxRequest.open('POST', '/ajax/request')와 같이 XMLHttpRequest 객체에 설정되어 있다. 로직 파일(서버에서 실행)은 이 주소로 AJAX 방식의 요청이 들어오면 처리하는 로직을 구현하여야한다. 그리고 이 처리 로직이 routes.py 파일의 respondAjax() 함수로 구현되어 있다.

 

이제 appmain 패키지에서 플라스크 웹 서버를 생성하고 구현한 로직을 등록한다.

 

appmain 패키지 초기화

 

▶ appmain/__init__.py

from flask import Flask

app = Flask(__name__)

from appmain.routes import main

app.register_blueprint(main)

 

마지막으로 프로젝트 실행 파일을 프로젝트 디렉토리 바로 아래에 작성한다.

 

프로젝트 실행 스크립트

 

▶ run.py

from appmain import app

if __name__ == "__main__":
    app.run("127.0.0.1", 5000)

 

 


 

 

프로젝트 실행 스크립트 run.py 파일을 실행하여 웹 서버를 실행시킨 후 웹 브라우저의 주소창에  http://127.0.0.1:5000/ajax을 입력하면 아래와 같이 웹 서비스에서 보내온 페이지를 볼 수 있다.

 

초기 페이지

 

Send data 버튼을 누르면 페이지 새로 고침 없이 서버가 보내온 데이터가 표시되는 것을 확인할 수 있다.

 

AJAX 방식으로 데이터가 추가된 페이지

 

이번 절을 통해 AJAX 방식으로 데이터를 요청하고 받아서 페이지에 해당 데이터를 추가하는 과정을 살펴보았다. 그 과정을 더 잘 살펴볼 수 있도록 JQuery와 같은 라이브러리를 사용하지 않고 순수한 자바스크립트 코드를 이용해서 예제를 구성하였다. 이번 절의 내용을 기반으로 플라스크 웹 서비스에 AJAX 기능을 추가할 수 있을 것이다.