Python pymysql로 MySQL에 로그 저장하기 — INSERT·commit 기본 패턴
2021년에 짧게 정리해뒀던 pymysql 기록을 2026년 기준으로 다듬어 올립니다. 원본 코드의 오타를 정정하고 실무 팁을 보완했습니다.
핵심 패턴부터 먼저 짚으면, Python에서 pymysql 4줄로 MySQL에 로그 한 줄을 INSERT 하고 commit() 한 번으로 저장이 끝납니다. 연결부터 INSERT까지 단계별로 아래에서 살펴보겠습니다.
당시 배경은 이렇습니다. 실제 운영 환경에서 자동화 스크립트 로깅에 직접 쓰던 코드인데, 파일 형식의 로그는 지정한 PATH에 직접 들어가야만 볼 수 있었습니다. SQL 문법도 공부할 겸, 쉬고 있는 DB 서버도 쓸 겸 해서 겸사겸사 로그를 DB로 보내는 튜닝을 했습니다.
1. 권장 환경
- Python 3.x
pymysql1.x 계열 기준- 설치:
pip install pymysql
구체적인 패치 버전은 따지지 않겠습니다. 본 글 코드는 pymysql 1.x 계열 기준으로 동작합니다.
참고: PyPI · PyMySQL | GitHub · PyMySQL/PyMySQL
2. DB 연결 코드
다음 코드로 MySQL DB에 연결합니다.
import pymysql
db = pymysql.connect(
user='id',
passwd='pw',
host='host',
db='dbname',
port='port',
charset='utf8',
)
각 인자가 하는 역할입니다.
user— DB 접속 계정명passwd— 비밀번호host— DB 서버 주소db— 접속할 데이터베이스명port— 포트 번호 (정수형 int). 위 예시의'port'는 placeholder이며, 실제 사용 시 정수 값을 입력하세요.charset— 문자셋 (원본 기준'utf8'지정)
보안 팁 실무에서는
passwd='pw'처럼 코드에 자격증명을 평문으로 박지 않습니다. 환경변수(예:os.environ['DB_PASSWORD'])나.env파일에서 읽어오는 방식이 표준입니다. 본 글 예시는 단순화를 위해 placeholder 그대로 둔 것입니다.
3. 커서 생성
커서는 SQL을 DB에 전달하는 통로입니다. 아래처럼 생성합니다.
cursor = db.cursor(pymysql.cursors.DictCursor)
원본은
cusor로 표기되었으나 본 보완본에서는 표준 표기cursor로 정정합니다.
pymysql.cursors.DictCursor는 쿼리 결과를 튜플이 아니라 컬럼명을 키로 쓰는 dict 형태로 돌려받게 해주는 커서입니다. result[0]['date']처럼 컬럼명으로 값을 바로 꺼낼 수 있어 코드 가독성이 높아집니다.
이제 커서까지 준비됐습니다. 이후부터는 이 커서로 SQL을 DB에 전달합니다.
4. SELECT 예시
연결이 정상인지 확인하거나 테이블 전체를 조회할 때 씁니다.
select_sql = "SELECT * from table_name;"
cursor.execute(select_sql)
result = cursor.fetchall()
cursor.execute(select_sql)로 쿼리를 실행하고, cursor.fetchall()로 결과 전체를 가져옵니다. result는 테이블의 모든 행이 담긴 리스트(DictCursor 사용 시 dict 리스트)입니다. 행이 많다면 fetchone()이나 fetchmany(N)으로 일부만 가져오는 방법도 있습니다.
5. INSERT + commit
로그를 DB에 저장하는 핵심 코드입니다. date, code, id, result 4개 컬럼에 값을 INSERT 합니다.
전제: MySQL에
date,code,id,result컬럼을 가진 테이블(table_name)이 미리 생성되어 있어야 합니다. 테이블이 존재하지 않으면 INSERT가 동작하지 않습니다.
insert_sql = "INSERT into table_name(date, code, id, result) values(%s, %s, %s, %s)"
insert_val = (date, code, id, result)
cursor.execute(insert_sql, insert_val)
db.commit()
라인별로 짚어봅니다.
insert_sql—date,code,id,result4개 컬럼에 값을 넣는 INSERT SQL.%s는 값이 들어갈 자리표시자입니다.insert_val— 실제 들어갈 값을 튜플로 묶은 것입니다.date,code,id,result는 실제 저장할 로그 데이터를 담는 변수이며, 컬럼 구조를 보여주기 위한 자리표시자입니다. 실제 사용 시 각자 로그 데이터로 대체하면 됩니다.cursor.execute(insert_sql, insert_val)— SQL과 값을 함께 전달해 실행합니다. pymysql이insert_val의 값을%s자리에 끼워넣어 줍니다.db.commit()— 변경사항을 실제로 DB에 반영합니다. 이게 빠지면 INSERT가 적용되지 않습니다.
%s 파라미터 바인딩이란
여기서 쓰인 %s는 Python의 단순 문자열 포맷(%s % value)과 다릅니다. pymysql이 값을 안전하게 이스케이프해서 SQL에 끼워넣어 주는 자리표시자입니다. f"" 나 +로 문자열을 직접 이어붙이는 방식보다 SQL Injection 위험이 줄어드는 효과가 있습니다. 완전한 방어라는 단정은 어렵지만, 직접 이어붙이기보다 훨씬 안전한 선택입니다.
데이터를 삽입하고 commit() 하고 끝입니다.
6. 5년 뒤 회고 — 지금이라면 챙길 것
이 아래는 팩트보다 제 개인 의견에 가깝습니다. 그 점 감안하고 읽어주세요.
2021년 코드를 다시 보면서 “지금이라면 함께 볼 것”으로 꼽히는 후보 세 가지입니다. 단정이 아니라 후보로만 적습니다.
연결 close 보장 — 원본 코드에는 db.close()가 없습니다. 연결이 닫히지 않으면 DB 커넥션이 열린 채 남습니다. 지금이라면 with 문이나 try/finally로 작업이 끝난 뒤 연결을 닫아주는 구조를 후보로 볼 것 같습니다. 이 글에서 상세 코드를 신설하지는 않지만, 장기 운영 환경이라면 함께 찾아볼 만한 주제입니다.
charset='utf8' vs utf8mb4 — 원본은 charset='utf8'입니다. 이모지나 4바이트 유니코드 문자까지 안전하게 저장하려면 utf8mb4가 현재 표준으로 통용됩니다. 당시 로그에 해당 문자가 없었다면 문제없었겠지만, 신규 프로젝트라면 utf8mb4를 후보로 검토해볼 만합니다.
자격증명 분리 — §2 보안 팁에서 언급했지만 한 번 더 강조합니다. 실제 운영 환경에서는 코드에 계정·비밀번호를 직접 쓰지 않는 것이 표준입니다. 환경변수나 시크릿 매니저로 빼는 방식을 처음부터 후보로 올려두면 좋습니다.
마치며
파일 로그도 좋지만, DB로 모아두면 SQL 한 줄로 날짜 필터·특정 코드 검색·집계가 가능해서 운영이 한결 가벼워집니다. 연결 → 커서 생성 → SELECT 확인 → INSERT + commit, 이 흐름 그대로 각 단계 코드를 복사해서 접속 정보만 바꿔 바로 쓸 수 있게 단계별로 정리했습니다. 단, MySQL에 해당 컬럼 구조의 테이블이 미리 존재하는 환경임을 전제합니다.
출처: 본 글은 2021-01-20 작성한 자체 실습 기록 — 「Python pymysql로 DB에 로그 저장하기 – INSERT, commit 기본 패턴」(원본 티스토리 post ID: 81) — 을 기반으로 2026년 보완한 것입니다.