치악산 복숭아
[엘리스 AI트랙] 07-04 Flask 기초 2 본문
1. 데이터베이스
- 데이터를 저장하는 공간
- 관계형 데이터베이스(RDB)와 NoSQL(Not Only SQL)로 나뉘어져 있음
관계형 데이터베이스(RDB)
- 키(key)와 값(value)들의 간단한 관계를 테이블화 시킨 데이터베이스
- DML을 사용해서 데이터 간 결합, 제약조건 등의 설정을 통해 데이터를 추출할 수 있음
- 테이블 간의 데이터 관계를 설정할 수 있음
- 각 컬럼마다 데이터의 형태가 동일, 정형화된 데이터를 가짐
- SQL 질의어(쿼리)를 사용
클라이언트와 서버 사이에서 일어나는 일
2. Flask와DB 연동하기
순서
1) SQL import 하기
2) 데이터베이스 연결하기 con = sqlite3.connect("database.db")
3) 데이터를 불러올 수 있는 cursor 객체 만들기 cur = con.cursor()
4) 실행할 쿼리 작성하기 cur.execute(f"SELECT * FROM Board WHERE name='{result}' or context='{result}'")
5) fetch all 함수 실행(레코드를 배열 형식으로 저장) rows = cur.fetchall()
6) 데이터베이스 연결 해제 con.close()
con = sqlite3.connect('database.db')
con.execute('쿼리문')
con.commit() #DB에 반영
con.close()
# 또는
with sqlite3.connect("database.db") as con:
con.execute("쿼리문")
con.commit()
3. JWT(JSON Web Token)
- 웹 표준으로써 두 개체에서 JSON 객체를 사용하여 통신
- JSON 포맷을 이용하여 사용자에 대한 속성을 저장하는 Web Token
- 토큰 자체를 정보로 사용하는 Self-Contained 방식으로 정보를 안정적으로 전달
- 서버와 클라이언트 간의 인증을 도와주는 도구 중 하나
JWT의 형태
- Header: 토큰의 타입과 알고리즘 저장
- Payload: 토큰에서 사용할 정보(클레임, Claim)를 넣음
- 토큰 발급자, 토큰 제목, 대상자, exp(만료 시간), iat(발급된 시간), jti(고유 식별자, 토큰의 중복성 방지) 등
- Signature: 헤더의 정보와 인코딩 값들과 관련된 비밀키가 들어 있음
- 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드
- JSON 형태인 각 부분은 Base64로 인코딩되어 표현됨
- 각각의 부분을 이어주기 위해 . 구분자 사용
예시
import jwt # PyJWT 모듈 import
data_to_encode = {"name": "elice"} # jwt로 암호화 할 데이터
encryption_secret = "secrete" # jwt 모듈이 사용되는 곳을 특정하기 위해 비밀키를 넣어줌
algorithm = "HS256" # 암호화 알고리즘
encoded = jwt.encode(data_to_encode, encryption_secret, algorithm=algorithm)
decoded = jwt.decode(encoded, encryption_secret, algorithm=[algorithm])
4. ORM(Object Relational Mapping, 객체 관계 매핑)
- 데이터베이스에 객체를 통해 접근하는 방법
- SQL 쿼리가 없어도 데이터베이스를 다룰 수 있도록 해줌
- 테이블 구조가 변경될 때 ORM 모델만 수정하면 됨
- 코드로 작성하기 때문에 쿼리를 직관적으로 이해 가능
# SQL 쿼리문
INSERT INTO 엘리스 (멤버, 나이) VALUES ('여왕', '18');
# ORM
class Members(db.Model): #db.Model은 SQLAlchemy 패키지 안에 들어가 있음
__tablename__ = 'my_user' # 데이터베이스 테이블을 명시
# 데이터베이스 테이블의 컬럼을 명시, `어떤 형태의 데이터를 저장할 것인가`
id = db.Column(db.Integer, primary_key=True, nullable=False)
name = db.Column(db.String(20), nullable=False)
age = db.Column(db.Integer, nullable=False)
member1 = Member() # DB의 테이블과 매핑되는 클래스를 모델이라고 함
member1.name = '여왕'
member1.age = '18'
# 또는 아래와 같이 한줄로 작성할 수 있음
member1 = Member(name='여왕', age='18')
db.session.add(member1)
db.session.commit()
- db.session.query(Members)와 Members.query는 같은 의미(전자가 더 명시적)
5. SQL Alchemy
- ORM을 쓸 수 있도록 도와주는 파이썬 라이브러리
- 파이썬 코드에서 Database와 연결하기 위해 사용할 수 있는 라이브러리
Query - CRUD 예제
- db.session.commit: 데이터베이스에 수정사항을 반영할 것
1) Create
- db.session.add: 내가 만든 변수들을 테이블 안에 넣어줄 것
2) Read
- Members 모델의 쿼리를 사용할 것
- all()을 붙이면 list 형태로 데이터가 반환됨, 한개여도 리스트
- first() 제일 처음거 하나, 반환되는 객체는 Model(class)
3) Update
- 해당하는 데이터를 먼저 가져온(Read) 뒤 수정함
4) Delete
- 해당하는 데이터를 먼저 가져온(Read) 뒤 삭제함
Query 사용법 예시
1) equal
@app.route('/')
def list():
member_list = Member.query.filter(Member.name == 'Elice')
return " ".join(i.name for i in member_list)
2) not equal
@app.route('/')
def list():
member_list = Member.query.filter(Member.name != 'Elice')
return " ".join(i.name for i in member_list)
3) like
@app.route('/')
def list():
member_list = Member.query.filter(Member.name.like('%Elice%'))
return " ".join(i.name for i in member_list)
4) in
@app.route('/')
def list():
member_list = Member.query.filter(Member.name.in_(['Elice', 'Dodo']))
return " ".join(i.name for i in member_list)
5) not in
@app.route('/')
def list():
member_list = Member.query.filter(~Member.name.in_(['Elice', 'Dodo']))
return " ".join(i.name for i in member_list)
6) is null
@app.route('/')
def list():
member_list = Member.query.filter(Member.name == None)
return " ".join(i.name for i in member_list)
- Null을 None으로 표현
7) is not null
@app.route('/')
def list():
member_list = Member.query.filter(Member.name != None)
return " ".join(i.name for i in member_list)
8)and
from sqlalchemy import and_
@app.route('/')
def list():
member_list = Member.query.filter(and_(Member.name == 'Elice',
Member.age == '15'))
return " ".join(i.name for i in member_list)
- db.session.query(Member).filter(A, B, C) 도 가능한 방법
9)or
from sqlalchemy import or_
@app.route('/')
def list():
member_list = Member.query.filter(or_(Member.name == 'Elice',
Member.age == '15'))
return " ".join(i.name for i in member_list)
10)order by
@app.route('/')
def list():
member_list = Member.query.order_by(Member.age.desc())
return " ".join(i.name for i in member_list)
11) limit
@app.route('/')
def list(limit_num = 5):
if limit_num is None:
limit_num = 5
# ⭐️괄호에 있는 숫자만큼만 반환⭐️
member_list = Member.query.order_by(Member.age.desc()).limit(limit_num)
return " ".join(i.name for i in member_list)
12) offset
@app.route('/')
def list(off_set = 5):
if off_set is None:
off_set = 5
# offset 크기만큼 앞에서부터 생력하고 반환
member_list = Member.query.order_by(Member.age.desc()).off_set(off_set)
return " ".join(i.name for i in member_list)
13) count
@app.route('/')
def list():
member_list = Member.query.order_by(Member.age.desc()).count()
return str(member_list)
- 쿼리문 실행결과로 반환된 tuple 수를 반환
6. REST API
- REST: 자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것
- 자원(resource)의 표현(representation)에 의한 상태 전달
REST의 구성
- 자원: URI에 표현이 되어야 함 ➡️ 무엇을 서버에 요청할 것인지
- 행위: HTTP Method ➡️ 어떻게(어떤 방법을) 요청할 것인지
- 표현: Representations ➡️ API만 보고 무엇을 요청할 것인지 알 수 있도록
* URL과 URI의 차이
URL: http://nyamnyamexample.com/index.html
URI: http://nyamnyamexample.com/index
URL은 실제로 서버 폴더 내에 파일이 있지만 URI는 그렇지 않음(실제로 파일 존재 X)
REST API 디자인 가이드
1) URI는 자원을 표현해야 함
2) 자원에 대한 행위는 HTTP Method로 나타내야 함(HTTP Method는 Rest API에서 동작을 표현하는 방법)
- GET: 리소스를 조회
- POST: 요청된 리소스를 생성
- PUT: 리소스를 업데이트
- DELETE: 리소스를 삭제
REST API 디자인 예시
- 리소스 요청은 주로 동사보다는 명사를 사용
- GET/members/insert/10 보다는 POST/members/10
- GET/members/delete/1 보다는 DELETE/members/1 등등
- 슬래시(/)는 계층 관계를 나타냄
- http://elice.example.co.kr/lecture/python
- 파일 확장자는 URI에 포함하지 않음
- 긴 URI에서는 밑줄(_)보다는 하이픈(-)을 사용
- http://elice.example.co.kr/board/free-talk
HTTP 응답 상태(HTTP status) 코드
상태 코드 | 내용 |
200 | 정상적으로 수행 |
201 | 성공적으로 리소스 생성 |
400 | 클라이언트의 요청이 부적절할 때 |
401 | 인증되지 않은 상태에서 리소스 요청 |
404 | 응답하고 싶지 않은 리소스, 혹은 없는 리소스를 요청 ex) Page Not Found |
500 | 서버에 문제가 생겼을 때 |
'elice > 토끼성장일지' 카테고리의 다른 글
[엘리스 AI트랙] 13-02-01 Numpy (0) | 2022.01.16 |
---|---|
[엘리스 AI트랙] 06-04 SQL 2 (0) | 2021.11.10 |
[엘리스 AI트랙] 07-02-01 ~ 07-02-02 Flask 기초 1 (0) | 2021.11.09 |
[엘리스 AI트랙] React Hook으로 상태관리 하기 (0) | 2021.11.06 |
[엘리스 AI트랙] 05-04 React UI (0) | 2021.11.02 |
Comments