SQLAlchemy 에서 비밀번호 특수문자 문제 해결

1. Intro

Python에서 SQLAlchemy나 다른 DB 라이브러리를 사용해 데이터베이스에 연결할 때, 가끔 예상치 못한 연결 오류가 발생할 수 있습니다.

그 중 자주 만날 수 있는 문제가 바로 DB 비밀번호에 특수문자가 포함된 경우입니다. 예를 들어 아래와 같은 DB 접속 정보가 있다고 가정해보겠습니다.

1
2
3
4
5
host = "x.y.z.q"
port = "3306"
user = "db_user"
pw = "abc123!@#"
db = "example"

이 정보를 바탕으로 DB URL을 만들면 보통 다음과 같은 형태가 됩니다.

1
db_url = "mysql+pymysql://db_user:abc123!@#@x.y.z.q:3306/example"

겉보기에는 문제가 없어 보이지만, 실제로는 이 URL이 올바르게 해석되지 않을 수 있습니다.

DB 연결 URL에서 @ 문자는 사용자 인증 정보와 호스트를 구분하는 역할을 합니다. 그런데 비밀번호 안에도 @ 문자가 포함되어 있기 때문에, SQLAlchemy나 DB 드라이버가 URL을 해석하는 과정에서 혼란이 생길 수 있습니다. 따라서 아래처럼 사용자의 의도와 URL 파서의 해석이 엇갈리게 됩니다.

1
2
3
4
5
6
7
# 사용자 의도
pw = "abc123!@#"
host = "x.y.z.q

# URL 파서 : 아..! password 와 host 는 아래와 같구나..?!
pw = "abc123!"
host = "#@x.y.z.q"

결과적으로 잘못된 호스트 정보로 접속을 시도하게 되고, DB 연결은 실패합니다. 그렇다면 비밀번호에 특수문자가 포함되어 있을 때는 어떻게 처리해야 할까요?

2. quote_plus

이 문제는 비밀번호를 URL 인코딩하면 해결할 수 있습니다.

quote_plusurllib.parse 모듈 하위의 함수로, 이는 문자열 안의 특수문자를 URL에서 안전하게 사용할 수 있는 형태로 변환해, 특수문자를 오해하는 일을 방지합니다.

사용법은 간단합니다. 해당 함수에 인코딩할 문자열을 넣어주기만 하면 됩니다.

1
2
3
4
5
from urllib.parse import quote_plus

pw = "abc123!@#"
encoded_pw = quote_plus(pw)
print(f"인코딩된 비밀번호 : {encoded_pw}")

실행 결과는 다음과 같습니다.

1
인코딩된 비밀번호 : abc123%21%40%23

특수문자가 아래와 같이 치환된 것을 알 수 있습니다.

1
2
3
!  -> %21
@  -> %40
#  -> %23

3. 인코딩된 비밀번호로 DB URL 만들기

이제 인코딩된 비밀번호로 DB URL 을 만들어보겠습니다.

1
2
3
4
5
6
7
8
9
10
from urllib.parse import quote_plus as qp

host = "x.y.z.q"
port = "3306"
user = "db_user"
pw = "abc123!@#"
db = "example"

db_url = f"mysql+pymysql://{user}:{qp(pw)}@{host}:{port}/{db}"
print(db_url)

실행 결과는 아래와 같습니다.

1
mysql+pymysql://db_user:abc123%21%40%23@x.y.z.q:3306/example

Comments