학습일지

[스나이퍼팩토리] 한컴AI아카데미(26.04.29)

cd-record 2026. 4. 29. 18:58
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
  • 동작 흐름:
    1. 사용자가 주소/css/main.css로 접속합니다.
    2. dir은 css, filename은 main.css가 됩니다.
    3. 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/ 등)
사용 목적 사용자마다 다른 화면을 보여줄 때 모든 사용자에게 똑같은 파일을 줄 때

review.ipynb
0.00MB

 

 

 

 

jsonify

 

jsonify는 Flask가 제공하는 아주 유용한 함수로, 파이썬의 데이터를 JSON 형식의 응답(Response)으로 변환해주는 역할을 합니다.


1. jsonify가 하는 핵심 작업

  1. 데이터 직렬화 (Serialization): 파이썬의 리스트나 딕셔너리 데이터를 JSON 문자열({"key": "value"})로 바꿉니다.
  2. 헤더(Header) 설정: 응답 헤더의 Content-Type을 application/json으로 자동 설정합니다. (이게 있어야 받는 쪽에서 데이터로 처리합니다.)
  3. 편의성: 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 데이터 흐름)

  1. 클라이언트: "회원 목록 줘! (GET /members)"
  2. 서버(Flask): DB에서 데이터를 꺼내 member_list라는 파이썬 객체를 만듦.
  3. jsonify: 파이썬 객체를 예쁘게 포장해서 JSON 상자에 담음.
  4. 전송: 브라우저나 모바일 앱이 이 상자를 받아서 화면에 뿌려줌.

* json.dumps() vs jsonify()

구분 json.dumps() (import json) jsonify() (from flask import ...)
결과물 단순한 문자열 (String) Flask 응답 객체 (Response Object)
Content-Type 설정 안 함 (기본 text/html로 인식될 수 있음) application/json으로 자동 설정
사용처 데이터를 파일로 저장하거나 로그 찍을 때 웹 브라우저/앱에 데이터를 보낼 때
편의성 리스트, 딕셔너리 변환만 수행 딕셔너리, 리스트 변환 + HTTP 상태 코드 전달 가능

flask.py
0.00MB

 

 

 

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 다운로드 사이트

https://sqlitebrowser.org/

 

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()

 

app.py
0.00MB

 

 

 

느낀점

 

벌써 백엔드를 들어가기 시작했다. 완전히 백엔드 부분을 들어갔다고 할 수 없지만 SQLite를 통해 db에 내용을 저장하고 저장한 내용을 프론트로 꺼내는 부분을 해보았다. 이걸 flask를 통해 백엔드와 프론트엔드를 연결하니까 코드가 엄청 복잡하게 생기는 것 같다. 물론 처음보는 명령어에 새로운 개념이다 보니 어색한 건 당연하겠지만 결국 내가 이 부분들을 습득해야 나중에 풀스택은 기본이고 AI까지 접목해서 나아갈 수 있기 때문에 되게 중요한 개념인만큼 다시 한번 되짚어가며 넘어가야겠다.

 

 

 

 

 

 

——————————————————————————

본 후기는 [한글과컴퓨터x한국생산성본부x스나이퍼팩토리] 한컴 AI 아카데미 (B-log) 리뷰로 작성 되었습니다.