01 Flask 시작하기
웹 서버의 동작 과정 이해하기
웹 서버의 동작 과정

요청과 응답은 어떻게 할까?
- 미리 약속한 규칙을 통해서 요청하면
정해진 형태의 데이터로 응답을 한다.
웹 서버 동작 예시
창구가 API 역할을 하는 것
정해진 형식, 데이터의 통로 API
- url 주소를 작성하고 Enter키를 크롬창에서 치는 것이 클라이언트가 정해진 형식대로 서버에 데이터를 요청하는 행위
- 서버가 클라이언트의 요청에 응답해 네이버 페이지를 돌려줌
- 네이버와 구글의 각각 페이지 접속 주소는 미리 약속된 주소(API 주소)라고 할 수 있다.
- 미리 약속된 방법으로 요청한 후 해당 페이지를 보게 되는 것이다.
- 정해진 방식으로 데이터의 통로 역할을 하는것이 바로 API라고 할 수 있다.
Flask Framework란?
Framework
- 하나의 결과물을 만들기 위해서 제공하는 '틀'
미리 작성되어 있는 함수 (라이브러리) 이상의 기능을 제공
Flask Framework
- Flask는 Python을 사용해서 웹 서버를 만들 수 있게 도와주는 Web Framework
- 다양한 기능을 미리 제공하는 Django와는 다르게 기본적인 기능만 제공하지만 개발이 자유롭다.
- 나만의 서버를 쉽게 작성할 수 있고, 간단한 코드로 빠르게 실행할 수 있으며 원하는 기능을 유연하게 확장하기 편리하다.
Flask 웹 서버 만들기
Flask Simple Web Server 만들기

- __name__은 이 파일이 다른 파일에 의해 실행 되었는지, 직접 실행 되었는지 알려주는 것
- 위의 두 줄은 어떤 Flask 서버를 실행해도 꼭 들어있는 코드
- @app.route()는 Flask의 기능과 파이썬의 함수가 합쳐져 하나의 API 역할을 함
route는 데이터가 이동하는 길을 정해준다. (url/api 주소를 만들어줌)
URL을 연결하고 데이터를 화면에 나타내기
어떻게 URL을 연결할까?
- @app.route()는 url을 만들어 준다.
- @app.route()와 연결되어 있는 함수를 이용해 HTML, JSON 형식의 데이터를 전달할 수 있다.
JSON 형식의 데이터 나타내기

- Flask 패키지에서 jsonify를 import
- jsonify 함수는 jsonify() 안에 있는 내용을 화면에 전달한다.
- def elice_json() 함수는 app.route()의 url에서 실행할 함수이고, {"name" : "elice"} 라는 데이터를 화면에 전달해준다.
HTML 형식의 데이터 나타내기
파일 준비하기
- html을 화면에 전달하기 위해서는 html 파일이 필요하다.
- html 파일을 templates라는 폴더 아래에 넣어준다.
- templates 폴더에 html 파일을 넣어놓으면 Flask가 자동으로 찾아서 연결해준다.
app.py

- render_template을 import
- render_template 함수는 templates라는 폴더 안의 html 파일을 불러와 주는 역할을 한다.
- templates 폴더 내의 파일 이름과 함수 안의 이름이 같아야 화면에 잘 전달할 수 있다.
여러가지 url 연결하기
@app.route("URL주소")
- "URL주소"라고 되어있는 부분은 우리가 만들어 줄 수 있는 url의 주소
- 1개의 @app.route는 1개의 함수와 연결될 수 있다.(가정)
@app.route(url1)
@app.route(url2)
def abc():
=> 함수 abc가 url1과 url2 둘 다 매핑됨(1에서도 함수를 실행시킬 수 있고, 2에서도 함수를 실행시킬 수 있음)
- @app.route에 연결된 함수의 이름은 중복될 수 없다

- /student/<name> name 부분을 변수로 받아올 수 있다.
(/student/elice라고 치면 name이라는 변수에 elice가 들어감)
REST API란?
REST API의 개념
- HTTP URL을 통해 데이터의 자원을 표현하고
HTTP Method를 통해서 데이터를 다루는 방법을 의미한다.
Database, 이미지, 텍스트 등의 다양한 데이터에 적용 할 수 있다.
- HTTP URI를 통해 자원을 명시하고, HTTP Method를 통해 해당 자원에 대한 CRUD를 적용하는 것

HTTP Method 사용하기
HTTP Method의 개념 - GET/POST
- GET과 POST는 HTTP Method 중 하나
- GET은 데이터를 URL 뒤에 ?와 함께 사용한다.
url~~~?name=elice & lecture=python : GET 방식으로 서버에 data를 전송하는 방법 중 하나(보안에 취약하기 때문에 로그인 같은 기능을 만들 때 선호하지 않음)
- POST는 특정 양식(form)에 데이터를 넣어 전송하는 방법이다.
데이터를 전송할 때 HTTP Body에 데이터를 넣어 전송하는 방식(보안에 좋고 데이터 길이 제한이 없음)
GET/POST 예시
-
GET 방식 예시

-
POST 방식 예시

app.route()에 method 옵션 사용하기

- POST 방식으로 url1에 접근하면 에러
- 이렇게 방식을 나누면 url1번과 url2번이 같아도 상관이 없음(method가 다르기 때문)
GET 요청만 사용하기

- request.args.get['name']은 url~~~?name = elice라고 되어 있을 때 ? 뒤에 있는 변수의 이름을 []안에 적어주면 그 값을 가져올 수 있다. (url?lecture=pyton일 때 request.args.get['lecture']면 python을 가져옴)
POST 요청만 사용하기 - templates/index.html 만들기

- elice/1234 데이터가 form이라는 형식에 묶여 서버에 전송된다.
- 서버에서는 id:elice pwd:1234 이렇게 저장이 됨
여러가지 url 연결하기

02 서비스 다루기
Blueprint와 Jinja Template
Blueprint란?
- API들을 분류/관리
- Flask의 기능이 늘어날수록, 코드의 양이 증가한다.
- 이 때, Blueprint를 사용해서 길어진 코드를 모듈화해주어 수정 개발과 유지보수에 용이하게 코드를 관리할 수 있다.
Blueprint를 사용하지 않았을 때

- @app.route가 api의 개수(여기선 api가 많다)
- 만약 게시판 기능 중 글을 수정하는 API를 찾아야하는데 API의 수가 많다보니 찾기가 힘듦
Blueprint를 사용하였을 때

- app.py는 오로지 서버 실행에만 집중할 수 있다.
- API들을 따로 모아서 파이썬 파일을 만들고 사용
Jinja2란?
- Jinja2는 Python에서 가장 많이 사용되는 템플릿이다.
- 서버에서 받아온 데이터를 효과적으로 보여주고
비교적 간략한 표현으로 데이터를 가공할 수 있다.(HTML 내에서 Python 문법처럼 데이터를 불러오고 출력할 수 있음)
Jinja2 Template에서 데이터 넘겨주기 - 단일변수

- return render_tempate 안에 선언해준 변수 이름으로 데이터가 전송된다.
Jinja2 Template에서 데이터 넘겨주기 - list

- {% %}를 사용하면 저 안에서 python 문법을 사용할 수 있다.
- endfor는 for문이 끝났다고 알려주는 거 같은 느낌(if문에서도 endif써줌)
Jinja2 Template에서 데이터 넘겨주기 - dictionary

- 딕셔너리 값을 가져올 때는 key값을 기준으로 가져온다.
게시판을 위한 CRUD 설계 및 제작
CRUD

Authentication이란?
Authentication vs Authorization
- 인증 : 로그인(2FA, OTP, SMS, PIN 등)
- 권한 : 이 서버에서 어떠한 역할/기능을 하고 사용할 수 있는지
Authentication
- 사용자가 누구인지 확인하는 절차(회원가입하고 로그인하는 과정)
로그인 기능 구현
쿠키
- 클라이언트에 저장되는 키/값이 들어있는 데이터
- 사용자가 따로 요청하지 않아도 Request 시에 자동으로 서버에 전송한다.
세션
- 쿠키를 기반으로 하지만 서버 측에서 관리하는 데이터
- 클라이언트에 고유 ID를 부여하고 클라이언트에 알맞은 서비스를 제공한다.
- 서버에서 관리하기 때문에 보안이 쿠키보다 우수하다.
로그인 예제

- user_id : 화면으로부터 입력받은 데이터
- user['user_id] : 서버가 가지고 있는 데이터
- user.id : 유저의 고유한 id(세션에 유저의 정보를 모두 넣으면 위험할 수도 있으므로 고유한 id 같은 거만 넣음)
로그아웃 예제

로깅
로깅이란?
- 로깅은 프로그램이 작동할 때 발생하는 이벤트(프로그램의 기능)를 추적하는 행위를 말한다.
- 프로그램의 문제들을 파악하고 유지보수 하는 데 사용되며, 로깅을 통해 발생한 에러를 추적할 수 있다.
로깅 - level
- DEBUG < INFO < WARNING < ERROR < CRITICAL
기본 로거 레벨 세팅은 WARNING이기 때문에 설정 없이 INFO, DEBUG를 출력할 수 없다.
높은 레벨은 아래 레벨을 신경쓰지 않는다.


- 기본은 WARNING이기 때문에 info는 출력하지 않는다.

- logging.getLogger() : 어떤 것으로 로깅을 할 것인지
- setlevel(logging.DEBUG) : DEBUG로 세팅
- DEBUG로 세팅하였기 때문에 info 출력된다.
Flask에서 로깅
- 에러가 발생했을 때 Flask의 logger를 사용하여 에러를 확인할 수 있다.
- import logging 안해줘도 된다.

03 RDB로 리소스 관리 및 저장하기
관계형 데이터베이스
데이터베이스
- 데이터를 저장하는 공간으로서, 서비스를 개발하는 곳에서는 빠질 수 없는 중요한 요소입니다.
관계형 데이터베이스(RDb)
- 키(key)와 값(value)들의 간단한 관계를 테이블 화 시킨 데이터베이스
- 특징 : 정형화 된 Data, DML을 사용해 데이터 간 결합, 제약조건 등의 설정을 통해 데이터를 추출할 수 있다.
RDB의 형태

RDB와 Flask의 상호작용
RDB와 Flask
- 파이썬은 오픈 소스와 상용 DB에 대한 대부분의 DB엔진을 위한 패키지를 가지고 있다.
- Flask에서 입력받은 내용을 DB에 저장할 수 있다.
->효율적인 데이터 관리 가능

간단한 게시판 만들기
구현 사항
- 사용자 검색
- 사용자 추가(중복 사용자는 방지)
- 게시판 내용 생성, 조회, 수정, 삭제
게시판 등록

- Ex) Create => cur.execute("INSERT INTO Board (name, context) values(?,?)", (name, context))
- con = sqlite3.connect(db정보) => DB에 연결
- cur = con.cursor() => sql문을 다룰 수 있게 도와주는 커서라는 객체
- cur.execute(~~~)
Flask JWT
JWT(JSON Web Token)란?
- 웹 표준으로서 두 개체에서 JSON 객체를 사용하여 통신합니다.(JSON Web Token은 하나의 인증 매개체)
JWT 생김새

- Header에는 토큰의 타입과 알고리즘을 저장한다.
- Payload에는 토큰에 담을 정보를 넣는다.
- Signature에는 헤더와 정보의 인코딩 값들과 관련된 비밀키가 들어있다.
JWT 구조
- JWT는 HEader ,Payload, Signature 3가지로 이뤄지며, JSON 형태인 각 부분은 Base64로 인코딩되어 표현된다.
- 각각의 부분을 이어주기 위해 . 구분자를 사용한다.

Payload

- 클레임은 3가지로 나누어져 있다.(register, public, private)
- 등록된 클레임(registered) : 토큰 정보를 표현하기 위해 이미 정해진 종류의 데이터(토큰 발급자(issuer), 토큰 제목(subject), 대상자(audience), exp(만료시간), iat(토큰이 발급된 시간), jti(고유식별자))이다.
- 공개 클레임(public) : 충돌이 방지된 이름을 가지고 있어야 한다. 충돌을 방지하기 위해 클레임 이름을 URI 형식으로 짓는다.(공개 클레임 예제 =>{https://elice.io: true})
- 비공개 클레임(private) : 등록과 공개를 제외한 클레임이자 사용자 정의 클레임으로 서버와 클라이언트 협의로 사용되는 클레임이다. 서버와 클라이언트 사이에 임의로 지정한 정보를 저장한다. 이 클레임은 공개 클레임과 달리 이름이 중복되어 충돌될 수 있으니 유의해아 한다.(비공개 클레임 예제 => {"student_name": "elice"}
Signature

JWT 예시

04 SQL Alchemy
SQL Alchemy와 ORM
ORM이란?
- 데이터베이스에 객체를 통해 접근하는 방법을 ORM(Object Relational Mapping, 객체 관계 매핑)이라고 한다.
- ORM은 SQL 질의어가 없어도 데이터베이스를 다룰 수 있도록 도와준다.
- Python의 Class(객체로 봄)를 사용해 DB에 접근
SQL 쿼리 vs ORM

- Member()는 Class
- member1.name, member1.age에 값을 넣어 클래스 안의 각각의 요소들에 데이터를 저장
ORM 장점
- DB를 코드로 다룰 수 있다.
- 테이블 구조가 변경될 때, ORM 모델만 수정하면 된다.
- 코드로 작성하기 때문에 쿼리를 직관적으로 이해할 수 있다.
SQL Alchemy란?
- 파이썬 ORM 라이브러리
-> 파이썬 코드에서 Database와 연결하기 위해 사용할 수 있는 라이브러리
DB와 Model
DB와 Model

- 첫 번째 줄이 앞에서 봤던 member1 = Member()
member1.name = ~~
member1.age=~~와 같은 의미
ORM Model

- db = SQLAlchemy()
이렇게 하면 db에 SQLAlchemy의 모든 기능을 사용할 수 있음
- id, name, age는 직접 넣어주지는 않지만 어떤 데이터가 들어갈 것이라고 명시해주는 것
- members = Members()라고 해주면 members라는 변수 이름으로 데이터베이스에 접근할 수 있음

- db.session.query(Members) = Members.query : Members테이블에 ORM 쿼리 사용 할거라는 뜻
- .filter(Members.name ==name) : Members 테이블의 name이 내가 가진 name과 같은 것만 가져오겠다는 뜻
Query
CRUD 예제 - Create: 데이터 저장

- Create 할 때는 db.session.add(내가 만든 클래스 안에 있는 변수들을 테이블 안에 넣을 것이다) 생각하기
CRUD 예제 - Read: 데이터 읽기

- Members 테이블에 ORM 쿼리 사용
- .all() : list형태로 데이터가 반환
- db.session.query(Members).first() : 젤 처음 데이터 하나만 가져옴(Model 객체 반환)
CRUD 예제 - Update: 데이터 수정

- Read를 먼저 해주고 Update
- members[0].name => 이렇게 해야함
CRUD 예제 - Delete: 데이터 삭제

- Read 먼저 해주고 Delete
- 얘는 .first()이므로 [0]이 없어도 됨
Query 사용법 - equal

Query 사용법 - not equal

Query 사용법 - like

- Member.name.like('%Elice%')와 같음
Query 사용법 - in

Query 사용법 - not in

Query 사용법 - is null

Query 사용법 - is not null

Query 사용법 - and

- db.session.query(Member).filter((A조건) & (B조건) & (C조건)) : and조건이랑 같음
Query 사용법 - or

Query 사용법 - order by

Query 사용법 - limit

Query 사용법 - offset

limit과 offset 같이 사용 가능
member_list = Member.query.order_by(Member.age.desc()).limit(limit_num).offset(offset_num)
Query 사용법 - count

이미지 출처 - Elice