[N332] TIL 및 회고

Sea Panda·2022년 12월 27일
0

부트캠프 TIL

목록 보기
34/46

0. 학습목표

Level 1.

  • 웹 애플리케이션과 웹 프레임워크에 대해 설명할 수 있다.
  • Flask, JinJa, 라우팅, 블루프린터에 대해 설명할 수 있다.
  • Flask 예제를 활용하여 간단한 웹 애플리케이션을 제작할 수 있다.
  • Bootstrap을 통해 HTML을 꾸미는 예제 코드를 재현할 수 있다.
  • IP주소에 대해 설명할 수 있다.

Level 2.

  • 웹 애플리케이션을 제작하여 csv파일의 내용을 출력할 수 있다.
  • JinJa템플릿을 활용하여 웹 애플리케이션의 사용자가 입력한 데이터를 활용할 수 있다.
  • 웹 애플리케이션의 Endpoint마다 요구하는 기능을 구현할 수 있으며, HTTP 상태 코드를 전달할 수 있다.

Level 3.

  • Application Factory를 기반으로 웹 애플리케이션을 제작할 수 있다.
  • 제작한 웹 어플리케이션을 폴더와 라우팅에 따른 프레임워크 기반으로 설명할 수 있다.
  • Flask 기반 웹 어플리케이션에 데이터베이스를 연결하고 데이터를 읽고 쓰는 API를 제작할 수 있다.

Level 4.

  • Flask-SQLAlchemy를 활용하여 웹 애플리케이션과 데이터베이스를 연결하고 조작할 수 있다.
  • Flask에서의 리다이렉트 및 사용자 세션처리에 대해 설명할 수 있다.
  • 웹 3계층 시스템 아키텍처에 대해서 설명할 수 있다.

1. 주요개념

Flask

장고(Django)나 플라스크(Flask)에 대해서는 파이썬을 접하게 되면 한 번은 들어봤을 수도 있다. 이 두 개의 프레임워크는 파이썬을 사용해 웹 애플리케이션을 작성할 수 있도록 도와준다.

그 중에서 Flask에 대해서 배우게 될 것이다.

Flask는 마이크로 웹 프레임워크(Micro Web Framework)이다. 웹 프레임워크는 웹 애플리케이션을 개발할 수 있도록 웹 서비스(Web Service)나 웹 API(Web API)등을 제공하고 웹 개발과 배포를 할 수 있는 특정 방법을 제공한다. 즉, 뭔가를 만들어낼 수 있는 도구 모음을 제공한다고 보면 된다.

Flask는 웹 프레임워크이긴 하지만 마이크로가 앞에 붙는다.즉, 이러한 도구 모음들이 최소한의 크기로 줄여진 것이다. 예를 들어 일반적인 웹 프레임워크를 손톱깎이 세트로 비유하자면 손톱깎이를 비롯한 여러 가지가 들어 있는 것이다. Flask는 여기에서 정말 최소한의 도구들을 모아놓은 것이다.

기본적으로 프레임워크에 따라 패키지와 라이브러리 등 모듈들의 컬렉션이 있어 개발이 수월할 수 있도록 도와준다. Jinja, Werkzeug, Flask-SQLAlchemy 등 다양한 패키지들과 라이브러리들이 존재한다.

Flask 시작하기

1. Flask 시작
우선 파이썬 환경에 Flask를 먼저 설치해야 한다.

pip install flask

2. 폴더 생성하기
다음으로 Flask 애플리케이션을 저장할 폴더를 새로 만들어 준다. 이름은 통상적으로 애플리케이션 이름으로 지정해준다. 이번 예시에서는 flask_app을 사용하겠다.
그리고 폴더 안에 __init__.py이라는 파일을 하나 만들면 다음과 같은 구조가 된다.

flask_app
└── __init__.py

3. Flask 애플리케이션 생성하기
이번에는 __init__.py파일에 코드를 담아보겠다. 먼저 Flask를 사용해서 웹 애플리케이션을 만드는 방법은 다음과 같다.

# __init__.py
from flask import Flask

app = Flask(__name__)

코드를 보면 Flask(__name__)은 해당 애플리케이션의 이름을 지정해 주고 있다. 비록 아무 기능은 없지만 Flask 웹 애플리케이션을 생성한 것이다.

4. CLI로 실행하기
CLI 명령어로 실행할 때에는 프로젝트 폴더 상위 디렉토리에서 다음과 같이 실행해 주면 된다.

FLASK_APP = (폴더명) flask run

위에서는 프로젝트 폴더명을 flask_app으로 했기 때문에 폴더명 자리에 flask_app이 들어간다.
그러면 다음과 같은 화면이 나타난다.

여기서 제일 마지막에 적혀있는 문구를 살펴보겠다.

Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

실행한 웹 애플리케이션을 시작했는데 이 애플리케이션에 접속할 수 있는 주소를 알려주고 있다. 바로 http://127.0.0.1:5000/이다. 127.0.0.1localhost이고 5000번 포트에서 작동하고 있다는 뜻이다.

웹 브라우저를 키고 접속하면 애플리케이션에 접근할 수 있지만 아무 설정도 없기 때문에 404(Not Found)페이지가 보일 것이다.

어플리케이션을 종료하기 위해서는 Press CTRL+C to quit이 명령대로 해주면 된다. 만일 이 방법으로 종료하지 않으면 프로세스를 따로 찾아서 종료를 해줘야 한다. 터미널만 종료한다고 꺼지는 것이 아니다. 명심하자.

5. 라우트 추가하기
이제 애플리케이션에 접속하면 "Hello World!"가 나타나도록 코드를 수정해보겠다.
기존 파일에 다음과 같은 작업을 추가한다.

# __init__.py

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World!'

이제 코드를 하나씩 뜯어서 살펴보자.

  • @app.route('/')
    애플리케이션의 루트 주소 ('/')에 접속했을 때에 실행하라는 뜻이다. URL에 따라 실행하게 될 함수를 지정하는 역할이다. 즉, 엔드 포인트(endpoint)를 설정하게 되는데, 이때 엔드 포인트란 주소가 어떻게 끝나는지를 말하고 있는 것이다.

    기본적으로 기본 URL 뒤에는 슬래시(/)가 붙어야 하기 때문에 만일 '/'없이 그저 @app.route('about')와 같은 설정을 하게 되면 Flask를 실행할 때에 에러를 일으킨다.

  • def index()
    루트 주소로 접속했을 때 실행되는 함수로 "Hello World!"라는 문자열을 반환한다.

이제 이 코드를 실행해보면 이전과 달리 index()함수가 실행되면서 "Hello World"라는 문구를 볼 수 있다.

❗️ 만약 동일한 라우트가 여러개라면?
라우트(Route) 자체는 경로, 서로 다른 네트워크 간 데이터를 전송하고 전송한 데이터를 받는 경로를 의미한다. 즉, 위의 @app.route('/')기본경로 URL + /라는 경로를 통해서 데이터를 전송하고 받는다는 것을 의미한다는 것이다.

그런데 만약 동일한 라우트가 여러 개가 있다면 Flask에서는 HTTP Request를 받고 처리할 때에 가장 먼저 엔드 포인트 조건이 맞는 라우트를 사용한다.

6. 라우트 기능들
Flask에서는 라우트를 다양하게 설정할 수 있다. 앞서 했던 것처럼 기본적으로 엔드 포인트를 지정할 때도 있지만 URL 내에서 변수를 받을 상황도 있을 수 있다. 그리고 시각적인 부분 없이 접속이 되는 라우트들도 있을 수 있다. 이러한 기능들을 여기에서 다 다루지는 않지만 몇 가지만 살펴보겠다.

  • HTTP Request 메서드

기본적으로 Flask의 라우트 데코레이터를 사용하게 되면 3가지 HTTP Request메서드를 허용한다. 바로 GET, HEAD, OPTIONS이다. 하지만 이외에 POST, PUT, PATCH, DELETE등 다른 메서드들을 통과하다록 설정하기 위해서는 데코레이터 함수에 methods라는 인자를 추가하면 된다.

예를 들어 @app.route('/')에 POST메서드를 추가하려면 다음과 같이 할 수 있다.

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

이제는 GET과 POST라는 메서드가 통과된다. 그리고 HEAD와 OPTIONS라는 메서드들은 이제 사용이 불가하다.

  • 세부 엔드 포인트

URL을 보다 보면 슬래시(/)로 이어진 긴 엔드 포인트들이 있다. 예를 들어 유어클래스에서 코스 카드를 하나 선택하면 다음과 같은 URL이 하나 뜨게 된다.

https://urclass.codestates.com/course/37/curriculum

여기에서 course 뒤에 37이라는 숫자가 보이고 curriculum이라는 단어가 잇따라 온다. 이처럼 URL을 세부적으로 지정하고 주소에서 값을 전달할 수 있다.

index의 번호에 따라 해당 번호가 포함된 Welcome to Index {번호}를 리턴하도록 Flask애플리케이션에 index라우트를 만들어보겠다.

다음과 같이 라우트를 설정할 때 엔드포인트에 꺽쇠(<>)모양으로 어떠한 변수를 설정할 수 있다. 그리고 꺽쇠 안에는 변수의 이름을 지정해주고 함수에서는 변수를 그대로 받아 사용할 수 있다.

@app.route('/index/<num>')
def index_number(num):
	return 'Welcome to Index %i' % int(num)

한 번 살펴보자.

  • < num >
    num이라는 이름의 변수를 만들어 받게 하도록 한다. 따라서 사용자가 입력하는 값과 상관없이 변수로 받게된다. 만약에 index/hello를 넘겨주면 hello가 값이 된다. 따라서 변수의 타입을 신경 써야 하기도 한다.

  • int(num)
    들어오는 변숫값의 타입을 변환해 준다. 그 이유는 기본적으로 URL을 통해 들어오게 되는 값은 문자열 타입이기 때문이다. 따라서 숫자로 표현하기 위해서는 변환해 주는 작업이 필요하다.

만약에 숫자를 넘겨주지 않으면 어떻게 될까요? 예를 들어 숫자가 안 주어지면 0을 기본으로 설정해 주는 방법은 다음과 같다.

@app.route('/index/', defaults={ 'num' : 0 })
@app.route('/index/<num>')
def index_number(num):
    return 'Welcome to Index %i' % int(num)
  • 블루프린트 사용하기

기능이 많아질수록 라우트도 많아진다. 그렇기 때문에 이러한 라우트들을 하나의 파일로 모아서 사용하지 않고 기능별로 나눠서 블루프린트 기능을 사용한다. 블루프린트는 Flask에서 여러 개의 라우트를 한 곳에 묶어둘 수 있는 기능이 있다.

사용하는 방법은 다음과 같다.

그리고 routes라는 폴더를 만들어 그 안에 user_routes.py라는 파이썬 파일을 생성한다. 이제 프로젝트 구조는 다음과 같다.

flask_app
├── __init__.py
└── routes
    └── user_routes.py

그리고 user_routes.py파일에는 다음과 같이 코드를 작성한다.

# user_routes.py

from flask import Blueprint

bp = Blueprint('user', __name__, url_prefix='/user')

@bp.route('/')
def index():
    return 'User index page'

위에서 Blueprint의 인수로 들어가는 것은 다음과 같다.

  • user:블루프린터의 이름
  • __ name__:블루프린트의 import이름
  • url_prefix='/user': URL 접두어 설정(해당 블루프린트의 라우트는 URL 앞에 /uesr가 자동으로 붙게 된다.)

그리고 __init__.py파일에서 해당 파일을 불러와서 사용할 수 있다.

# __init__.py

from flask import Flask
from flask_app.routes import user_routes

app = Flask(__name__)
app.register_blueprint(user_routes.bp)

@app.route('/')
def index():
    return 'Hello World!'

이제 위 코드를 실행하여 http://127.0.0.1:5000/user/로 접속하면 다음과 같은 문구가 보이게 된다.

Application Factory

Flask를 통해서 애플리케이션을 만드는 방법을 살펴봤다. 하지만 추후에 프로젝트가 커지고 파일들이 많아지면 import를 사용할 일이 많아진다. 이때 파이썬에서 circular import(순환참조)를 피하기 위해서 Flask에서는 애플리케이션 팩토리 패턴을 추천하고 있다.

말 그대로 애플리케이션을 만드는 "공장"을 세우는 것이다. 여태까지는 글로벌한 컨텍스트에서 app을 선언하고 사용했다. 하지만 이렇게 되면 여러 개의 애플리케이션을 동시에 사용하거나 app이 선언되어 있는 파일의 일부분만 필요할 때에도 문제가 발생할 수 있다.

이러한 잠재적인 문제점들을 피하기 위해 사용되는 방법이 함수를 따로 만드는 것이다. 기본적인 패턴은 다음과 같다.

__init__.py파일에서 다음과 같은 코드가 들어가게 된다.

from flask import Flask

def create_app():
    app = Flask(__name__)

    from yourapplication.views.admin import admin
    from yourapplication.views.frontend import frontend
    app.register_blueprint(admin)
    app.register_blueprint(frontend)

    return app

if __name__ == "__main__":
  app = create_app()
  app.run()

보시는 것처럼 함수 안에 애플리케이션을 생성해 준다면 해당 함수를 실행하기만 하면 원하는 애플리케이션이 하나 만들어진다. 이제는 다른 파일에서 import를 해도 문제가 될 일도 줄어든다.

블루프린트도 함수 내에서 import를 해온 뒤에 애플리케이션에 추가해 준다.

앞으로 작성하는 Flask 애플리케이션은 이 패턴으로 작성하면 좋다.

0개의 댓글