Flask Web Framework

실무 강의는 실제 연구/개발 과정에서 제가 적용하는 사례와 경험을 공유하는 차원에서 만들고 있습니다. 고로, 사용하는 문법과 라이브러리에 대한 세밀한 설명은 생략합니다.

Flask 라이브러리가 제공하는 web framework를 이용하여 간단한 웹 서버(Web Server)를 만들어 볼게요. 웹 서버에서 보여주는 웹 페이지도 HTML과 javascript로 함께 만들어 보지요.


강의들은 모두 무료입니다. 단, 저작권은 키클 코딩랩 에 있으며, 무단 복제 및 배포를 엄금합니다.
이를 어길 시, 본 사이트의 서버가 미국에 있으므로, 미국법에 의해 처벌될 수도 있습니다.




Flask 라이브러리

Flask는 빠르고 간단하게 웹(Web) 서버(Server)를 만들 수 있게 해주는 라이브러리예요. 저 같은 경우에는, 로봇과 사용자가 소통하는 UI(User Interface)를 웹 기반으로 만들 때 사용한 적이 있답니다. 즉, 로봇에 설치되어 있는 컴퓨터에 Flask를 이용하여 웹 서버를 돌리고, HTML과 Javascript를 이용하여 사용자에게 보여주는 웹 페이지를 만들었지요. 그리고, 사용자는 이 웹 페이지를 통해 로봇에 명령을 내리는 등 소통을 하는 것이랍니다.
하나 알려둘 점은, 이 강의는 웹 개발(e.g., GET/POST request, URL, HTML, Javascript, JSON 등)에 대한 배경 지식이 어느 정도 있어야 이해가 가능합니다.




Web server (웹 서버) 만들기

그럼, Flask 라이브러리를 이용하여 웹 서버를 만드는 코딩을 아래와 같이 해 볼까요? 폴더를 하나 생성한 후, 그 안에 "server.py"라는 파일을 만들었답니다.

server.py
from flask import Flask, jsonify, request, render_template

app = Flask(__name__)

@app.route("/")
def hello():
    return render_template("index.html")

@app.route("/sayhi", methods=['GET'])
def say_hi(): 
    data = {'msg':'Hi there~!'}
    return jsonify(data)

@app.route("/send_data", methods=['POST'])
def receive_data():
    client_data= request.form.get('mydata')
    print("Data from client:", client_data)
    return jsonify({})

#-------------------------------------------------------

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

줄1에서는, flask 라이브러리로부터 여러 가지 객체들을 import하고 있답니다. jsonify는 웹 페이지와 데이터를 주고 받을때 JSON 메세지 형태를 이용하기 위한 것이랍니다. 그리고, render_template은 사용자가 웹 서버에 처음 접속할 때 보여줄 "index.html" 웹 페이지 파일을 줄7에서와 같이 통째로 넘겨줄 때를 위해서 import하고 있답니다.
줄3에서는, 실질적인 웹 서버 역할을 하는 Flask 객체를 생성하여 "app"이라는 이름의 변수에 저장하고 있어요. 웹 서버의 작동 시작은 줄23에서 코딩을 하게 될 거예요.
줄5~줄7에서는, hello()라는 함수(Function)을 정의하고, 이 함수를 app.route()로 decorate를 하고 있는 것이랍니다. "@" 표시는 app.route()가 hello()를 decorate한다는 것을 알려주는 코드이지요. 줄5~줄7의 전체적인 의미는, 사용자가 웹 브라우저에서 root path("/")를 입력하면 "index.html" 파일을 사용자에게 보내준다는 것이랍니다. 그리고, "index.html"를 보내기 위해서 줄1에서 import했던 render_template() 함수를 사용했지요.
줄9~줄12에서는, say_hi()라는 함수를 정의하고 있어요. 이 함수에서는, 줄11과 같이 {'msg':'Hi there~!'} 라는 딕셔너리(Dictionary, 공부가 필요하면 여기로)를 만들고, 줄12에서와 같이 jsonify() 함수를 이용하여 JSON 메세지로 변환한 후 리턴하고 있답니다. 그리고, say_hi() 또한 app.route()에 의하여 decorate되고 있지요. 줄9를 살펴보면, say_hi() 함수는 사용자가 웹 브라우저에서 "/sayhi" path(경로)를 "GET" request(요청)으로 웹 서버에 접속할 때 호출된다는 것을 알 수 있지요.
줄14~줄18에서는, receive_data()라는 함수를 정의하고 있어요. 이 함수 또한 decorate되고 있는데요, 줄14을 보면, 이 함수는 "/send_data"라는 path에 "POST" request로 사용자가 접속할 때 호출된다는 것을 알 수 있어요. 사용자가 웹 브라우저를 통해서 보낸 "POST" request에는 "mydata"라는 정보가 있답니다(이것은 웹 페이지(Page) 만들기에서 코딩을 할 거랍니다). 이 "POST" request 정보는 줄1에서 import한 request 객체를 통해서 접근이 가능하고, 줄16에서 "mydata"가 담고 있는 것이 무엇인지 알아내어 client_data에 저장하고 있지요. 줄17에서는 사용자가 보내온 "mydata"의 내용을 출력하고 있어요. 줄18에서는, 사용자에게 비어 있는 JSON 메세지를 보내고 있답니다.
줄23에서는 앞서 생성해둔 Flask 서버 객체의 작동을 시작하고 있지요. 웹 서버를 저의 컴퓨터에서 돌릴 것이기 때문에, IP 주소로 '127.0.0.1'를 사용했고, 포트(Port)번호는 5000를 사용했답니다.




웹 페이지(Page) 만들기

이제, 사용자가 Flask 웹 서버에 접속하면 사용자의 웹 브라우저에 보여질 웹 페이지를 만들어 보지요. 앞에서 만든 "server.py"를 담고 있는 폴더 안에 "templates"라는 하위폴더를 생성한 후, 그 안에 "index.html"이라는 파일을 만들고 아래와 같이 코딩해 보세요. HTML과 Javascript를 이용하여 코딩을 했는데요, 자세한 설명은 생략하고 중요한 몇 부분만 짚어보지요.

index.html
<!DOCTYPE html>
<html>

  <head>
    <title> Client </title>
    
    <style>
      html, body {
        background: #f6f6f8;
        height: 100%;
        position: relative;
        z-index: -2;
      }

      div#prompt {
        background-color: #fff;
        color: #002;
        display: block;
        font-size: 6vh;
        margin: auto;
        text-align: center;
        width: 50%;
        position: relative;
        top: 20%;
      }

      div#home {
        position: relative;
        margin: auto;
        top: 50%;
        text-align: center;
      }
      div#home button {
        top: 0%;
        /* color: #000; */
        display: inline-block;
        font-size: 5vh;
        text-align: center;
        height: 10vh;
        margin: auto;
        width: 50vh;
      }
    </style>
  </head>

  <body>
    <div id="prompt">
      Message from server is displayed here.
    </div>

    <div id="home">
      <button id="say_hi">Say Hi To Server</button>
      <button id="send_data">Send Data To Server</button>
    </div>

    <script>
      var IP = "http://localhost:5000/";

      prompt = document.getElementById('prompt');
      say_hi = document.getElementById('say_hi');
      send_data = document.getElementById('send_data');

      say_hi.addEventListener('click', function(event) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', IP + "sayhi", true);
        xhr.send();

        xhr.onreadystatechange = function() {
          if (xhr.readyState == 4 && xhr.status == 200) {
            var response = JSON.parse(xhr.response);
            prompt.textContent = response.msg;
          }
        }; 
      });

      send_data.addEventListener('click', function(event) {
        var xhr = new XMLHttpRequest();
        xhr.open('Post', IP + "send_data", true);
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        xhr.send("mydata=134");

        xhr.onreadystatechange = function() {
          if (xhr.readyState == 4 && xhr.status == 200) {
            prompt.textContent = "Server received the data";
          }
        }; 
      });
    </script>
  </body>

</html>

줄63~줄74에서는, "say_hi"라는 ID를 갖는 버튼(줄52)을 클릭했을때, 웹 서버에 "/sayhi"라는 경로(Path)로 접속하는 "GET" 요청을 보내고 있답니다(줄65~줄66). 그리고, 서버에서 JSON 메세지 형태의 응답(Response)이 오면, 그 응답에 있는 내용을 "prompt" ID를 갖는 HTML 객체(줄47)에 출력하고 있답니다.
줄76~줄87에서는, "send_data"라는 ID를 갖는 버튼(줄53)을 클릭했을때, 웹 서버에 "/send_data"라는 경로(Path)로 접속하는 "POST" 요청을 보내고 있답니다(줄78~줄80). 요청을 보낼때, "mydata=134"라는 데이터도 함께 보내고 있지요(줄80). 그리고, 서버에서 응답이 오면, 서버가 사용자가 보낸 데이터를 잘 받았다는 메세지를 출력하고 있답니다(줄84).




실행하기

이제 웹 서버를 돌리고, 웹 브라우저를 통해서 접속해 볼까요?
먼저, "server.py"를 생성한 폴더의 내용을 살펴 보기 위해서 터미널 명령어 ls를 아래 줄1처럼 실행해 보지요. 줄2처럼, "server.py"파일과 "index.html"파일을 가지고 있는 "templates" 폴더가 보이지요?
이제 줄3처럼 우리가 코딩한 Flask 웹 서버를 실행해 보세요. 그럼, 줄4~줄9와 같이 메세지들이 출력이 된답니다. WARNING 문구도 있는데요, 내용은 동시에 많은 사람들이 접속하는 경우에는 Flask 대신 WSGI 라이브러리를 이용하여 웹 서버를 구축하라는 것이랍니다. 우리는 접속하는 사용자의 수가 적은 경우를 가정했기 때문에, Flask를 사용한 것이고, 고로, 이 경고 문구는 무시해도 된답니다.

Terminal
.../my_folder$ ls
server.py  templates
.../my_folder$ python3 server.py
 * Serving Flask app "server" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
.../my_folder$

이제 웹 브라우저 (Web Browser)를 여세요. 저는 크롬(Chrome)을 사용했어요. 그리고, 아래 그림의 빨간 상자 안에 보이는 것처럼, 주소창에 "127.0.0.1:5000" 혹은 "localhost:5000"를 입력하면, 자동으로 웹 서버의 root 경로("/")에 접속하게 된답니다. 그러면, 아래 그림의 중간에 보이듯, 웹 서버가 보내준 "index.html" 페이지가 보이게 된답니다.

버튼 "Say Hi To Server"를 클릭하면, 서버로 부터 "Hi there~!"라는 메세지를 받게 되고, 아래처럼 화면에 출력이 되지요.

"Send Data To Server" 버튼을 누르면, 서버를 실행한 터미널에 Flask 서버가 아래 줄11~줄12의 메세지들을 출력한답니다. 참고로, 줄8~줄9는 처음 root 경로에 접속했을 때, 줄10은 앞에서 "Say Hi To Server" 버튼을 눌렀을 때 출력된 메세지들이랍니다.
줄11을 보면, 우리가 "server.py"에 코딩한 대로, 사용자가 "Send Data To Server" 버튼을 클릭했을 때 보내진 "mydata"의 값인 "134"을 출력하고 있답니다. 그리고, 사용자의 웹 브라우저에는 "Server received the data"라는 메세지가 출력되지요.

Terminal
.../my_folder$ python3 server.py
 * Serving Flask app "server" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 127.0.0.1 - - [24/May/2020 10:49:38] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [24/May/2020 10:49:40] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [24/May/2020 11:08:25] "GET /sayhi HTTP/1.1" 200 -
Data from client: 134
127.0.0.1 - - [24/May/2020 11:12:10] "POST /send_data HTTP/1.1" 200 -
.../my_folder$





발자취

2019-09-11 "키클 코딩랩 - 미국 공학박사 아빠의 코딩 연구소"로 이름 변경
2019-06-28 코딩 교실 공개
2019-03-18 코딩 교실 제작 시작

바로가기
Python 배움터
C/C++ 배움터
About
Contact
Privacy Policy
강의목록
질문하기
처음으로