read

Python, Flask


flask

간단한 포스팅이다 얼마전부터 Python과 Flask를 공부하고 있었고, 거기에 대해 이번에 만들고 싶은게 한가지 있어, 어떻게 공부했는지 부터 적어두려고 하던 찰나, iOnic과 함께 적용했으면 하던게 있어 만들게 되었다.

간단히 Flask를 어떻게 공부했는지 보면, 이곳에 다 정리해 두었다.

참고 사이트도 있는데, 특히 이곳 을 따라 했고, 약간의 버젼 문제들만 개인적으로 해결해주면서 나가면 쉽게 마무리 지을 수 있다.

Flask와 Django가 대표적인 파이썬 웹 프레임워크인데, 비교를 하면서 알아보면 참 좋다. 각자의 목적이 다르기 때문이다.

동영상이 하나 있는데, PyCon APAC 2016에서 한 고등학생 친구가 멋진 발표를 한 영상이다. 한번 참고하면 좋을 것이다.

Flask는 Micro 가 아마 가장 큰 특징일 것이다. 매우 가볍고 심플하다. 즉, 하고싶은 것에 있어서 자유도가 상당히 높다. 그러므로 만들고 싶은 게 있을 때, 라이브러리를 자유롭게 import할 수 있고, 만드는 방향이 가지각색이다. 같은 일을 처리하는 함수를 만들더라도 개발자에 따라 매우매우 달라진다. 정형화된 것이 거의 없다.

이번에 간단히 만들어 볼 것은 Daum postcode API를 하이브리드 앱에서 사용하려는 데, 프로토콜상 어플 내에서 띄울 수 없게 되어 있어, 간단히 flask로 서버를 올리고 실행한 후 보이게 하려고 한다.


준비


준비해야 할 게 있다고 하면, Heroku를 사용할 것이기 때문에 가입정도는 해두는 것이 좋다. 물론 가격정책상 무료에 해당하는 부분까지 사용할 것이므로 편하게 쓸 수 있다. 당연히 파이썬3는 설치되어 있다는게 가정이다.

여기서는 파이썬 3.6.0을 사용하였다.

그럼 파일을 만들어 보자.

원하는 디렉토리를 만든 후, 폴더 내에서 git init 혹은 소스트리나 기타등등 git을 이용할 수 있는 상태를 만들어 주자. heroku는 git으로 코드를 관리한다.

그 다음은 pyvenv env 라는 명령어로 파이썬 가상환경을 설정한다.

그리고 source env/bin/activate 를 실행하면 가상환경이 실행되어 터미널에 (env)가 뜨는 것을 볼 수 있다.

그 상태에서 touch app.py .gitignore README.md requirements.txt 와 같이 입력을 하여 가장 기본적인 파일들을 만든다. 특히 app.py와 requirements 파일은 필수다.

pip install Flask requests render_template을 터미널에 입력하여 Flask와 기타 필요사항들을 설치해 주자.

pip freeze > requirements.txt 추가로 다음 코드를 입력하면, requirements에 등록이 되며, 설치한 목록, 라이브러리를 저장하여 관리할 수 있게 한다.

requests는 통신, render_template는 템플릿과의 연결을 해주는 용도이다.

이제 전체 환경설정은 벌써 끝났고 코딩만이 남았다.


코딩 시작하자마자 끝


app.py부터 보도록 하자. 코드는 다음과 같다.


import requests
from flask import Flask, render_template, request
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.run()


바로 실행하면 당연히 실행이 안된다. index.html이 없기 때문이다. 다만, 여기서 app.py가 얼마나 간단한지 보인다면 Flask 의 매력에 빠지기 시작하는 것이다.

그럼 index.html을 만들어보자.

먼저 폴더를 만들어야 한다. 위치는 아까만든 폴더(가상환경도 깔고 실행시켰을 것이다)에 바로 만들어주면 된다. 폴더 이름은 templates로 하고 그 내부에 index.html을 만들면 된다.

그리고 index.html 내부를 한번 만들어 보자.


<!DOCTYPE html>
<html>
  <head>
    <title>Daum postcode API</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

  </head>
  <body>
    <div id="wrap" style="display:none;border:1px solid;width:100%;height:300px;margin:5px 0;position:relative">
    </div>

    <script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script>
    <script>
    // 우편번호 찾기 찾기 화면을 넣을 element
    var element_wrap = document.getElementById('wrap');

    function foldDaumPostcode() {
        // iframe을 넣은 element를 안보이게 한다.
        element_wrap.style.display = 'none';
    }

        // 현재 scroll 위치를 저장해놓는다.
        var currentScroll = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
        new daum.Postcode({
            oncomplete: function(data) {
                // 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.

                // 각 주소의 노출 규칙에 따라 주소를 조합한다.
                // 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
                var fullAddr = data.address; // 최종 주소 변수
                var extraAddr = ''; // 조합형 주소 변수

                // 기본 주소가 도로명 타입일때 조합한다.
                if(data.addressType === 'R'){
                    //법정동명이 있을 경우 추가한다.
                    if(data.bname !== ''){
                        extraAddr += data.bname;
                    }
                    // 건물명이 있을 경우 추가한다.
                    if(data.buildingName !== ''){
                        extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
                    }
                    // 조합형주소의 유무에 따라 양쪽에 괄호를 추가하여 최종 주소를 만든다.
                    fullAddr += (extraAddr !== '' ? ' ('+ extraAddr +')' : '');
                }
                localStorage.setItem('address', fullAddr);
                console.log(fullAddr);

                // // 우편번호와 주소 정보를 해당 필드에 넣는다.
                // document.getElementById('sample3_postcode').value = data.zonecode; //5자리 새우편번호 사용
                // document.getElementById('sample3_address').value = fullAddr;

                // iframe을 넣은 element를 안보이게 한다.
                // (autoClose:false 기능을 이용한다면, 아래 코드를 제거해야 화면에서 사라지지 않는다.)
                //element_wrap.style.display = 'none';

                // 우편번호 찾기 화면이 보이기 이전으로 scroll 위치를 되돌린다.
                document.body.scrollTop = currentScroll;
            },
            // 우편번호 찾기 화면 크기가 조정되었을때 실행할 코드를 작성하는 부분. iframe을 넣은 element의 높이값을 조정한다.
            onresize : function(size) {
                element_wrap.style.height = size.height+'px';
            },
            width : '100%',
            height : '100%'
        }).embed(element_wrap);
        // iframe을 넣은 element를 보이게 한다.
        element_wrap.style.display = 'block';

    </script>
  </body>
</html>


Daum postcode API 에 예시로 있는 것에 몇가지를 손본 것이다. 물론 원한다면 하고싶은데로 커스텀해서 넣어주어도 된다.

한번 python app.py 로 실행해보고 성공적으로 진행 되는 지 확인해보자.

성공적으로 실행됨을 확인 했다면, heroku와 연결해서 실행을 해볼 것이다.

먼저, 해당 폴더에 touch Procfile로 파일을 만들자. 이것에 대한 정보는 heroku 홈페이지 내에서 알아 볼 수 있다.

내부에 web: gunicorn app:app와 같이 적어두고 저장을 하자. 그럼 이제 gunicorn 이란 것이 새롭게 나왔는데, pip install gunicorn 설치를 해주자. 이것에 대한 설명은 이곳에서 참고 하도록 하자.

그럼 설치가 되었으니 pip freeze > requirements.txt를 실행해 입력해두자.

또한, 한가지 더 저장해 두어야 할 것이 있는게 runtime.txt라는 파일이 필요하다. 그 역시 이곳에서 확인이 가능하다. 간단히 보면 specify an arbitrary version of Python to be used to run your application. 이다.

그럼 runtime.txt내에 현재 파이썬 정보를 저장하자. 나의 경우는 python-3.6.0라고 적어주었다.

그 이후는 이제 heroku를 만들어 갈 것인데, create시 두개의 instance를 만들어 개발과정 때 사용할 것과 퍼블리싱 과정에서 사용할 것을 나누어 적용해도 된다. 그에 대한 방법은 위에 말한 것중 참고를 했다는 사이트를 보면 제대로 알 수 있다.

먼저 로그인을 하려면 heroku login을 실행해 아이디와 비밀번호를 입력한다. 이후

heroku create 이름 으로 instance 내에 해당 이름으로 만들어 줄것인데, 이름은 유니크한 이름을 가져야 하므로 잘 설정해 주도록 하자.

이후, git에서 지금 상태에서 git push heroku master를 한다면 바로 적용이 될 것이지만, 혹시나 위 참고 사이트처럼 따로 remote 를 설정해 주는 방향으로 했다면 자유롭게 하면 될 것이다.

이로써 서버설정은 모두 마무리 지었다. 간단히 Flask 를 사용해 서버를 만들어 보았다. 구체적인 서버 코딩은 크게 없었지만 단순히 뷰만 이용하더라도 iOnic과 연결 지을 수 있다. 그리고 어떻게 데이터를 연결 지을 수 있는지 확인해 보도록 하자.

물론, 서버와의 통신으로 연결해주어도 되지만 간단한 데이터라면 굳이 그렇게 하지 않아도 되기 때문에 그 부분에 대해서 포스팅 할 생각이다.

iOnic에 대한 부분은 다음 포스팅에서 마무리 하도록 하겠다.

Blog Logo

구찌


Published

Image

구찌의 나도한번 해블로그

구찌의 개발 블로그 입니다.

Back to Overview