개요
CGI(Common Gateway Interface)는 웹 서버가 외부 프로그램을 실행하고 그 결과를 브라우저로 전달하는 표준 인터페이스입니다. Python CGI 스크립트를 활용하면 HTML 폼에서 전송된 데이터를 받아 MySQL 데이터베이스와 직접 상호 작용할 수 있습니다.
이 글에서는 사용자가 이메일과 비밀번호를 입력해 로그인하는 간단한 예제를 통해 Python CGI와 MySQL의 연동 과정을 단계별로 살펴보겠습니다.
1단계: 로그인 폼 작성 (login.html)
먼저 사용자로부터 이메일과 비밀번호를 입력받는 HTML 폼을 만듭니다. form 태그의 action 속성은 데이터를 처리할 CGI 스크립트(login.py)를 지정하고, method는 get 방식을 사용합니다.
<html>
<body>
<form action="login.py" method="get">
email: <input type="text" name="e1">
password: <input type="password" name="p1">
<input type="submit" value="register">
</form>
</body>
</html>
2단계: CGI 스크립트 작성 (login.py)
다음은 폼에서 전달된 값을 받아 MySQL의 user 테이블에서 일치하는 사용자를 조회하는 Python CGI 스크립트입니다. 로그인에 성공하면 24시간 유효한 쿠키를 발급하고 성공 화면을 출력하며, 실패하면 실패 메시지를 반환합니다.
#!C:\Python27\python.exe
import MySQLdb
import cgi
import Cookie
# 데이터베이스 연결 열기
db = MySQLdb.connect("localhost","root","","student")
# cursor() 메서드로 커서 객체 준비
cursor = db.cursor()
data = cgi.FieldStorage()
a = data.getvalue('e1')
b = data.getvalue('p1')
# 데이터베이스에서 레코드를 조회하는 SQL 쿼리 준비
sql = "select id,email,password from user where email='"+a+"' AND password='"+b+"'"
try:
# SQL 명령 실행
if(cursor.execute(sql)):
# 변경 사항 커밋
db.commit()
c = Cookie.SimpleCookie()
# 쿠키에 값 할당
c['mou'] = a
# 만료 시간 설정
c['mou']['expires'] = 24*60*60
# 쿠키를 포함한 헤더 출력
print c
print("Content-type: text/html")
print('''<html>
<head>
<title>Hello Word - First CGI Program</title>
</head>
<body>
<h2>successfully login</h2>
</body>
</html>''')
else:
# 변경 사항 커밋
db.commit()
print("Content-type: text/html")
print("<html>")
print("<body>")
print("<h2>fail</h2>")
print("</body>")
print("</html>")
except:
# 오류 발생 시 롤백
db.rollback()
# 서버 연결 종료
db.close()
주요 코드 설명
- MySQLdb.connect("localhost", "root", "", "student") — 호스트, 사용자 계정, 비밀번호, 데이터베이스 이름을 순서대로 지정해 MySQL 서버에 연결합니다.
- cgi.FieldStorage() — GET/POST 방식으로 전송된 폼 데이터를 파싱하며, getvalue('e1')과 getvalue('p1')로 이메일과 비밀번호를 추출합니다.
- cursor.execute(sql) — SQL 쿼리를 실행하고, 조건에 맞는 레코드가 존재하면 참을 반환합니다.
- Cookie.SimpleCookie() — 로그인 성공 시 사용자 이메일을 담은 쿠키를 생성하고, expires 옵션으로 만료 시간을 24시간(24×60×60초)으로 설정합니다.
- db.commit() / db.rollback() — 작업을 확정하거나, 예외 발생 시 트랜잭션을 되돌린 후 연결을 종료합니다.
보안 주의사항: SQL 인젝션
위 예제는 문자열 연결 방식으로 SQL 쿼리를 작성하기 때문에 SQL 인젝션 공격에 취약합니다. 실제 서비스에서는 반드시 아래처럼 파라미터화된 쿼리(placeholder)를 사용해야 합니다.
sql = "select id,email,password from user where email=%s AND password=%s" cursor.execute(sql, (a, b))
또한 비밀번호는 평문 그대로 저장하지 말고, bcrypt나 PBKDF2 같은 해시 알고리즘으로 암호화해 저장하고 검증하는 것이 안전합니다.
참고: 최신 개발 환경에서는
위 예제는 Python 2와 MySQLdb 모듈을 사용하는 전통적인 방식입니다. 최근에는 Flask나 Django 같은 WSGI 기반 프레임워크와 PyMySQL, mysql-connector-python 같은 드라이버를 조합해 웹 애플리케이션을 개발하는 것이 일반적입니다. 다만 CGI의 동작 원리를 이해하면 웹의 기본 구조를 파악하는 데 큰 도움이 됩니다.