2025.04.01
[ORM 이란?]
ORM이란?
ORM (Object-Relational Mapping) 은
👉 객체 지향 언어(Python, Java 등)의 객체를
👉 데이터베이스의 테이블과 매핑해주는 기술
쉽게 말하면?
# sql
SELECT * FROM users WHERE id = 1;
ORM을 쓰면, 이렇게 Python 코드로 가능
# python
user = User.query.get(1)
ORM의 핵심 역할
- 클래스 ↔️ 테이블 매핑
- 인스턴스(객체) ↔️ 레코드(행) 매핑
- SQL 직접 안 쓰고도 데이터를 조회/삽입/수정/삭제 가능
ORM의 장점
- 가독성 좋아짐 (SQL 몰라도 기본적인 조작 가능)
- 코드 재사용성 ↑
- 데이터 조작 시 코드 스타일 통일
- 다양한 DB에 대한 추상화 (MySQL → SQLite 등 전환 쉬움)
단점
- 복잡한 쿼리는 직접 SQL 쓰는 게 더 나을 수도 있음
- 성능이 중요한 대용량 시스템에서는 ORM이 느릴 수 있음
정리하자면:
ORM은 객체지향 프로그래밍과 관계형 데이터베이스를 연결해주는 다리 역할을 하는 도구
1. ORM 라이브러리 설치
- 가상 환경 들어가기
C:> myproject
(myproject) c:\projects\myproject>pip install flask-migrate
2. 설정 파일 추가
[파일명 : "C:\projects\myproject\config.py"]
파이썬 idle 에서 config 열기
방법 1 ) 원래 위에 py 파일을 마우스 오른쪽 버튼 누르고 → 연결 프로그램에서 파이썬 선택하면 열려야 하는데..
* 내꺼는 바로 안뜸..^^
방법 2 ) 윈도우 탐색기에서 직접 열어서 파일 open 으로 불러오기

- 데이터베이스 접속 주소 : SQLALCHEMY_DATABASE_URI = 'sqlite:///{ }'.format( os.path.join(BASE_DIR,'pybo.db')
- SQLALchemy의 이벤트를 처리하는 옵션 : SQLALCHEMY_TRACK_MODIFICATIONS = False
- False : 파이보에는 필요하지 않은 옵션이라서 비활성화
하나하나 코드 쓰려니까 좀 힘들군..
3. ORM 적용
어제 사용한 __init__.py 사용 !
[파일명 : "C:\projects\myproject\pybo\__init__.py"]
원래 있던 코드에서 수정 및 추가
[코드 설명]
# Flask 앱 생성 및 초기 설정 관련 모듈
from flask import Flask
# SQLAlchemy: ORM 기능 제공
from flask_sqlalchemy import SQLAlchemy
# Flask-Migrate: 데이터베이스 마이그레이션(스키마 변경 관리)
from flask_migrate import Migrate
# 설정값을 담은 별도 파일(config.py) 불러오기
import config
# SQLAlchemy 객체와 Migrate 객체 생성 (아직 앱과 연결하지 않음)
db = SQLAlchemy()
migrate = Migrate()
def create_app():
# Flask 앱 인스턴스 생성
app = Flask(__name__)
# config.py의 설정값(app.config['SQLALCHEMY_DATABASE_URI'] 등)을 앱에 적용
app.config.from_object(config)
# SQLAlchemy 객체를 Flask 앱에 연결 → ORM 기능 활성화
db.init_app(app)
# Flask-Migrate를 앱과 db에 연결 → DB 구조 변경을 자동으로 추적할 수 있게 됨
migrate.init_app(app, db)
# views 디렉토리 안의 main_views 모듈에서 블루프린트(bp) 불러오기
from .views import main_views
# 블루프린트를 앱에 등록 → URL 라우팅 기능 활성화
app.register_blueprint(main_views.bp)
# 최종적으로 설정 완료된 Flask 앱 객체 반환
return app
전체 구조 이해 포인트
- SQLAlchemy(): 파이썬 클래스를 DB 테이블로 연결해주는 ORM 도구
- Migrate(): DB 구조 변경사항을 쉽게 관리해주는 도구 (flask db migrate, upgrade 등)
- create_app(): 앱 실행 시 호출되는 함수로, Flask에서 권장하는 앱 팩토리 패턴 사용
- Blueprint: 다양한 라우팅 파일을 구조적으로 분리 관리하기 위한 기능
저장하고
4. 데이터베이스 초기화
(myproject) c:\projects\myproject>flask db init
- flask db init 명령은 데이터베이스를 관리하는 초기 파일들을 다음처럼 migrations 디렉터리에 자동으로 생성한다.
- 데이터베이스를 초기화하는 flask db init 명령은 최초 한 번만 수행
5. 데이터베이스 관리 명령어 정리
모델을 추가하거나 변경할 때,
> flask db migrate
> flask db upgrade
flask db migrate | 모델을 새로 생성하거나 변경할 때 사용 (실행하면 작업파일이 생성된다.) |
flask db upgrade | 모델의 변경 내용을 실제 데이터베이스에 적용할 때 사용 (위에서 생성된 작업파일을 실행하여 데이터베이스를 변경한다.) |
6. 질문/답변 모델 생성
- pybo 폴더 안에 → .py 파일 생성
models.py 파일에는 모델 클래스들을 정의하여 사용
[파일명: projects/myproject/pybo/models.py]
- models.py 파일 열어서 질문/ 답변 모델 생성 코드 짜기
# models.py - ORM 모델 정의 파일
from pybo import db # SQLAlchemy 인스턴스 가져오기
# 질문 테이블 정의
class Question(db.Model):
# 고유 ID (기본 키)
id = db.Column(db.Integer, primary_key=True)
# 질문 제목 (최대 200자, 필수 입력)
subject = db.Column(db.String(200), nullable=False)
# 질문 내용 (길이 제한 없음, 필수 입력)
content = db.Column(db.Text(), nullable=False)
# 질문 생성 날짜 (필수 입력)
create_date = db.Column(db.DateTime(), nullable=False)
# 답변 테이블 정의
class Answer(db.Model):
# 고유 ID (기본 키)
id = db.Column(db.Integer, primary_key=True)
# 외래 키: 어떤 질문에 대한 답변인지 지정
question_id = db.Column(
db.Integer,
db.ForeignKey('question.id', ondelete='CASCADE')) # 질문 삭제 시 연결된 답변도 삭제
# 관계 설정: Answer → Question
# answer.question 으로 연결된 질문 객체 접근 가능
# question.answer_set 으로 해당 질문에 달린 답변 목록 접근 가능
question = db.relationship('Question', backref=db.backref('answer_set'))
# 답변 내용 (필수 입력)
content = db.Column(db.Text(), nullable=False)
# 답변 생성 날짜 (필수 입력)
create_date = db.Column(db.DateTime(), nullable=False)
models.py에는 질문(Question)과 답변(Answer)을 위한 ORM 모델이 정의되어 있으며,
두 모델은 1:N 관계로 연결되어 있음
ondelete = 'CASCADE' 쿼리를 이용하여 질문 데이터를 삭제할 경우 답변도 함께 삭제된다.
파이썬 코드로 질문 데이터를 삭제하면
해당 질문과 연결된 답변 데이터는 삭제되지 않고
답변 데이터의 question_id 컬럼만 빈값으로 업데이트
파이썬 코드로 질문 데이터를 삭제할 때
연결된 답변 모두를 삭제하려면,
db.backref 설정에 cascade = 'all, delete-orphan'
7. 모델 import
아까 init 파일에서 orm 또 수정
[파일명: projects/myproject/pybo/__init__.py]
8. 리비전 파일 생성
(myproject) c:\projects\myproject>flask db migrate
하면 마이그레이션 폴더 -> 버젼 폴더 -> 임의의 숫자.py 파일 생성
9. 리비전 파일 실행
(myproject) c:\projects\myproject>flask db upgrade
10. DB 브라우저에서 pybo.db 열기
설치한 DB 브라우저를 실행
메뉴에서 [파일 → 데이터베이스 열기]를 선택.
그리고 앞선 실습에서 생성한 projects/myproject/pybo.db 데이터베이스 파일을 선택하고 <열기>를 누르기
11. 플라스크 셸 실행하기
(myproject) c:\projects\myproject>flask shell
12. 질문 저장하기
# 1. Question, Answer 모델 불러오기
>>> from pybo.models import Question, Answer
# 2. 현재 시각을 저장하기 위해 datetime 모듈 사용
>>> from datetime import datetime
# 3. Question 클래스 인스턴스 생성
# 아직 DB에 저장된 건 아니고, 메모리에만 존재하는 상태
>>> q = Question(
subject='pybo가 무엇인가요?', # 질문 제목
content='pybo에 대해서 알고 싶습니다.', # 질문 내용
create_date=datetime.now()) # 생성 시각
# 4. SQLAlchemy의 db 객체 불러오기 (세션을 통해 DB 조작 가능)
>>> from pybo import db
# 5. 위에서 만든 질문 객체를 DB 세션에 추가 (등록만 해두는 상태)
>>> db.session.add(q)
# 6. 세션의 변경사항을 커밋 → 실제로 DB에 저장됨
>>> db.session.commit()
+ 추가 질문
>>> q.id
1
>>> q = Question(subject='플라스크 모델 질문입니다.', content='id는 자동으로 생성되나요?', create_date=datetime.now())
>>> db.session.add(q)
>>> db.session.commit()
>>> q.id
2
13. 데이터 수정
- 수정할 때는 단순히 대입 연산자 사용
>>> q = Question.query.get(2)
>>> q
<Question 2>
>>> q.subject = 'Flask Model Question'
>>> db.session.commit()
14. 데이터 삭제
- delete 함수를 이용해 삭제
>>> q = Question.query.get(1)
>>> db.session.delete(q)
>>> db.session.commit()
15. 답변 데이터 저장
>>> from datetime import datetime
>>> from pybo.models import Question, Answer
>>> from pybo import db
>>> q = Question.query.get(2)
>>> a = Answer(question=q, content='네 자동으로 생성됩니다.', create_date=datetime.now())
>>> db.session.add(a)
>>> db.session.commit()
16. 답변에 연결된 질문 찾기
- Answer 모델의 question 속성을 이용하면 "답변에 연결된 질문"을 조회할 수 있다.
>>> a.question
<Question 2>
17. 질문에 달린 답변 찾기
- answer_set 을 사용하면 질문에 연결된 답변들을 쉽게 가져올 수 있다.
>>> q.answer_set
[<Answer 1>]
18. 플라스크 셸 종료
- 플라스크 셸에서 빠져 나오려면 <Ctrl+Z>를 누르고 <Enter>를 입력한다. 또는 quit()를 입력한다.
'[LG U+ 5기] > Study' 카테고리의 다른 글
[4월][1주차] 플라스크 개발 (2) + html (0) | 2025.04.04 |
---|---|
[3월][5주차] PYTHON WEB (4) + 실습 (0) | 2025.03.31 |
[3월][5주차] PYTHON WEB (3) / 쉬운.ver (0) | 2025.03.31 |
[3월][5주차] PYTHON WEB (2) (1) | 2025.03.31 |
[3월][5주차] PYTHON WEB (1) (0) | 2025.03.31 |