template
1. send_from_directory: Flask에서 서버의 특정 폴더에 저장된 파일(이미지, CSS, JS 등)을 클라이언트(브라우저)에게 안전하게 전송할 때 사용하는 함수
- 기본 문법: send_from_directory(디렉토리_경로, 파일_이름)
@app.route('/<string:dir>/<path:filename>')
def serve_files(dir, filename):
if dir in ['css','images','js','fonts']:
# f-string 안에서 변수를 쓰려면 {dir}로 써야 합니다.
# 이 코드는 'resource/css' 같은 폴더에서 'style.css'를 찾아 보냅니다.
return send_from_directory(f'resource/{dir}', filename)
else:
return "Directory not found", 404
- 동작 흐름:
- 사용자가 주소/css/main.css로 접속합니다.
- dir은 css, filename은 main.css가 됩니다.
- send_from_directory가 서버의 resource/css/ 폴더 안에서 main.css를 찾아 응답합니다.
Q. 왜 그냥 파일을 직접 읽지 않고 이 함수를 쓰나요? (보안)
만약 이 함수를 쓰지 않고 직접 경로를 조합해서 파일을 열게 되면, 해커가 "상위 디렉토리 참조 공격(Directory Traversal)"을 시도할 수 있습니다.
위험 예시: 사용자가 파일 이름으로 ../../etc/passwd 같은 값을 보낸다면? 서버의 중요한 시스템 설정 파일이 유출될 수 있습니다.
send_from_directory는 요청된 파일 이름에 .. 같은 위험한 문자가 섞여 있어도, 지정된 디렉토리 밖으로 나가지 못하도록 보안 검사를 자동으로 해줍니다.
*render_template, send_from_directory 차이점
| 구분 | render_template | send_from_directory |
| 대상 파일 | 주로 HTML 파일 | 정적 파일 (이미지, CSS, JS, PDF 등) |
| 처리 과정 | Jinja2 템플릿 엔진이 내용을 수정함 (데이터 주입) | 아무런 수정 없이 파일 원본을 그대로 전송 |
| 저장 위치 | 기본적으로 templates/ 폴더 | 개발자가 지정한 폴더 (보통 static/ 등) |
| 사용 목적 | 사용자마다 다른 화면을 보여줄 때 | 모든 사용자에게 똑같은 파일을 줄 때 |
jsonify
jsonify는 Flask가 제공하는 아주 유용한 함수로, 파이썬의 데이터를 JSON 형식의 응답(Response)으로 변환해주는 역할을 합니다.
1. jsonify가 하는 핵심 작업
- 데이터 직렬화 (Serialization): 파이썬의 리스트나 딕셔너리 데이터를 JSON 문자열({"key": "value"})로 바꿉니다.
- 헤더(Header) 설정: 응답 헤더의 Content-Type을 application/json으로 자동 설정합니다. (이게 있어야 받는 쪽에서 데이터로 처리합니다.)
- 편의성: json.dumps()를 쓰고 직접 응답 객체를 만드는 번거로움을 줄여줍니다.
2. 코드 속 jsonify 분석
@app.route('/members', methods=['GET'])
def read_members():
with get_db_connection() as conn:
rows = conn.execute("SELECT * FROM members").fetchall()
# 1. DB에서 가져온 Row 객체들을 파이썬 딕셔너리 리스트로 변환
member_list = [dict(row) for row in rows]
# 2. 파이썬 리스트를 JSON 응답으로 변환하여 반환
return jsonify(member_list)
만약 member_list가 [{'name': '홍길동', 'age': 30}] 형태라면, jsonify는 브라우저에게 다음과 같은 데이터를 보냅니다.
- 본문(Body): [{"name": "\ud64d\uae38\ub3d9", "age": 30}]
- 헤더(Header): Content-Type: application/json
Q. 그냥 딕셔너리를 리턴하는 것과 무엇이 다른가요?
최신 Flask 버전에서는 return {"message": "success"} 처럼 딕셔너리를 그대로 리턴해도 자동으로 JSON으로 변환해 주긴 합니다. 하지만 jsonify를 직접 쓰는 이유는 분명합니다.
- 리스트 반환 가능: 딕셔너리가 아닌 리스트([])를 바로 응답으로 보낼 때는 반드시 jsonify()가 필요합니다. (작성하신 코드의 read_members가 이 경우입니다.)
- 명시적 의도: "이 함수는 API 응답으로 JSON을 보낸다"는 것을 코드를 읽는 사람에게 명확히 전달합니다.
4. 시각적 이해 (JSON 데이터 흐름)
- 클라이언트: "회원 목록 줘! (GET /members)"
- 서버(Flask): DB에서 데이터를 꺼내 member_list라는 파이썬 객체를 만듦.
- jsonify: 파이썬 객체를 예쁘게 포장해서 JSON 상자에 담음.
- 전송: 브라우저나 모바일 앱이 이 상자를 받아서 화면에 뿌려줌.
* json.dumps() vs jsonify()
| 구분 | json.dumps() (import json) | jsonify() (from flask import ...) |
| 결과물 | 단순한 문자열 (String) | Flask 응답 객체 (Response Object) |
| Content-Type | 설정 안 함 (기본 text/html로 인식될 수 있음) | application/json으로 자동 설정 |
| 사용처 | 데이터를 파일로 저장하거나 로그 찍을 때 | 웹 브라우저/앱에 데이터를 보낼 때 |
| 편의성 | 리스트, 딕셔너리 변환만 수행 | 딕셔너리, 리스트 변환 + HTTP 상태 코드 전달 가능 |
SQLite
SQL
SQL(Structured Query Language)은 데이터베이스라는 '데이터 창고'와 대화하기 위해 사용하는 표준 언어입니다.
데이터베이스에 데이터를 저장하거나, 수정하거나, 특정 조건의 데이터를 뽑아낼 때 모두 SQL을 사용합니다. SQL은 그 기능에 따라 크게 DDL, DML, DCL, TCL 네 가지로 분류합니다.
1. DDL (Data Definition Language) - 데이터 정의어
창고 자체를 짓거나, 선반을 배치하거나, 부수는 등 '구조'를 결정하는 명령어입니다. 대상이 데이터 자체가 아니라 테이블(틀)입니다.
- CREATE: 새로운 테이블이나 데이터베이스를 생성합니다. (창고 짓기)
- ALTER: 기존 테이블의 구조를 수정합니다. (컬럼 추가, 타입 변경 등)
- DROP: 테이블이나 데이터베이스를 완전히 삭제합니다. (창고 철거)
- TRUNCATE: 테이블의 구조는 남겨두고 데이터만 전부 비웁니다.
-- 예시: '회원' 테이블 만들기 (CREATE)
CREATE TABLE members (
id INTEGER PRIMARY KEY,
name TEXT,
email TEXT
);
2. DML (Data Manipulation Language) - 데이터 조작어
만들어진 테이블 안에 데이터를 넣고, 조회하고, 수정하고, 지우는 명령어입니다. 실무에서 가장 많이 사용하게 될 부분입니다.
- SELECT: 데이터를 조회합니다. (가장 중요!)
- INSERT: 새로운 데이터를 삽입합니다.
- UPDATE: 기존 데이터를 수정합니다.
- DELETE: 특정 데이터를 삭제합니다.
-- 예시: 데이터 넣고 조회하기
INSERT INTO members (name, email) VALUES ('Gemini', 'gemini@example.com');
SELECT * FROM members WHERE name = 'Gemini';
3. DCL & TCL (기타 분류)
개념적으로 함께 알아두면 좋은 용어들입니다.
- DCL (Data Control Language): 데이터 제어어. 누가 데이터베이스에 접근할 수 있는지 권한을 주거나(GRANT) 뺏는(REVOKE) 명령어입니다.
- TCL (Transaction Control Language): 트랜잭션 제어어. 작업 내용을 확정(COMMIT)하거나, 문제가 생겼을 때 작업 전으로 되돌리는(ROLLBACK) 명령어입니다.
4. 한눈에 보는 요약표
| 분류 | 역할 | 주요 명령어 | 비유 |
| DDL | 구조 정의 | CREATE, ALTER, DROP | 건물 짓기 |
| DML | 데이터 관리 | SELECT, INSERT, UPDATE, DELETE | 이삿짐 옮기기 |
| DCL | 권한 관리 | GRANT, REVOKE | 출입증 발급 |
| TCL | 작업 확정 | COMMIT, ROLLBACK | 저장 및 실행 취소 |
- SQLite DB 다운로드 사이트
DB Browser for SQLite
DB Browser for SQLite DB Browser for SQLite (DB4S) is a high quality, visual, open source tool designed for people who want to create, search, and edit SQLite or SQLCipher database files. DB4S gives a familiar spreadsheet-like interface on the database in
sqlitebrowser.org
* MYSQL vs SQLite
| 특징 | MySQL | SQLite |
| 구조 | 서버-클라이언트 (네트워크 필요) | 파일 기반 (라이브러리 형태) |
| 동시성 | 높음 (여러 사용자 동시 쓰기 가능) | 낮음 (동시 쓰기 제한, 파일 락) |
| 설치/관리 | 복잡 (설치 및 설정 필요) | 없음 (Zero-configuration) |
| 적합한 용도 | 웹사이트, 대규모 서비스 | 앱(모바일/데스크탑), 소규모 기기 |
| 데이터 크기 | 매우 큰 데이터셋 | 작거나 중간 규모의 데이터셋 |
1. SQLite
SQLite는 이름에서 알 수 있듯이 '가볍고(Lite)' '간편한' 관계형 데이터베이스 관리 시스템(RDBMS)입니다. 우리가 흔히 아는 MySQL이나 Oracle처럼 거대한 서버를 설치해서 사용하는 방식이 아니라, 파일 하나에 모든 데이터를 담아 관리하는 방식이 가장 큰 특징입니다.
1-1. SQLite의 핵심 특징
- 서버가 없음 (Serverless): 별도의 데이터베이스 서버 프로세스를 설치하거나 실행할 필요가 없습니다. 그냥 라이브러리 형태로 프로그램에 포함되어 작동합니다.
- 파일 기반: 데이터베이스 전체가 컴퓨터의 단 하나의 파일(.sqlite, .db 등)로 저장됩니다. 복사나 이동이 매우 쉽습니다.
- 설정 불필요 (Zero-Configuration): 사용자 권한 설정이나 복잡한 설치 과정이 없습니다. 파일 경로만 지정하면 바로 사용할 수 있습니다.
- 표준 SQL 지원: 작지만 강력합니다. 우리가 아는 대부분의 표준 SQL 구문을 그대로 사용할 수 있습니다.
1-2. 파이썬에서 SQLite 사용하기 (예시 코드)
파이썬은 sqlite3 모듈을 기본으로 내장하고 있어 별도의 설치 없이 바로 사용할 수 있습니다.
import sqlite3
# 1. 데이터베이스 파일 연결 (파일이 없으면 새로 생성됨)
# 메모리상에서만 연습하고 싶다면 ':memory:'를 입력하세요.
conn = sqlite3.connect('example.db')
# 2. 커서(Cursor) 생성 (명령어를 전달하는 심부름꾼)
cur = conn.cursor()
# 3. 테이블 생성
cur.execute('''CREATE TABLE IF NOT EXISTS users
(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)''')
# 4. 데이터 삽입
cur.execute("INSERT INTO users (name, age) VALUES ('홍길동', 25)")
cur.execute("INSERT INTO users (name, age) VALUES ('김철수', 30)")
# 5. 변경사항 저장(Commit) 및 연결 종료
conn.commit()
# 6. 데이터 조회
cur.execute("SELECT * FROM users")
rows = cur.fetchall()
for row in rows:
print(row)
conn.close()
느낀점
벌써 백엔드를 들어가기 시작했다. 완전히 백엔드 부분을 들어갔다고 할 수 없지만 SQLite를 통해 db에 내용을 저장하고 저장한 내용을 프론트로 꺼내는 부분을 해보았다. 이걸 flask를 통해 백엔드와 프론트엔드를 연결하니까 코드가 엄청 복잡하게 생기는 것 같다. 물론 처음보는 명령어에 새로운 개념이다 보니 어색한 건 당연하겠지만 결국 내가 이 부분들을 습득해야 나중에 풀스택은 기본이고 AI까지 접목해서 나아갈 수 있기 때문에 되게 중요한 개념인만큼 다시 한번 되짚어가며 넘어가야겠다.
——————————————————————————
본 후기는 [한글과컴퓨터x한국생산성본부x스나이퍼팩토리] 한컴 AI 아카데미 (B-log) 리뷰로 작성 되었습니다.
'학습일지' 카테고리의 다른 글
| [스나이퍼팩토리] 한컴AI아카데미(26.05.04) (0) | 2026.05.04 |
|---|---|
| [스나이퍼팩토리] 한컴AI아카데미(영단어장 리뷰) (0) | 2026.04.30 |
| [스나이퍼팩토리] 한컴AI아카데미(26.04.28) (0) | 2026.04.28 |
| [스나이퍼팩토리] 한컴AI아카데미(26.04.27) (0) | 2026.04.28 |
| [스나이퍼팩토리] 한컴AI아카데미(26.04.24) (0) | 2026.04.24 |