DB가 끊겼다 살렸다 한 하루, 그 와중에 데모도 쌓였다
목차
아침 시작이 깔끔하지 않았다. 봇 하나에서 DB 연결이 죽어있다는 걸 확인하고 얼마나 됐는지 로그를 거슬러 올라갔더니 밤새였다. 조용히 죽어있었던 거다.
MySQL 커넥션 관리, 드디어 한 곳으로
Managed 환경에서 MySQL 연결이 중간에 끊기는 건 어느 정도 예상하고 있던 일이다. 클라우드 쪽에서 idle connection을 일정 시간 후 끊거나, 서버 재시작이 발생하면 클라이언트 입장에서는 소켓이 살아있는 것처럼 보이지만 실제론 죽어있는 상태가 된다. "MySQL server has gone away" 류의 에러가 터지기 전까진 알 수가 없다.
문제는 이 reconnect 로직이 봇마다 제각각이었다는 거다. 어떤 봇은 try-catch로 재연결을 시도하고, 어떤 건 그냥 프로세스가 죽어버리길 기다리는 식으로 돼 있었다. 버그를 한 봇에서 잡아도 같은 패턴이 다른 봇에 그대로 남아있으니, 결국 같은 문제를 두 번 세 번 잡는 꼴이었다. 오래된 숙제를 방치해온 셈.
오늘 한 건 단순하다. 공용 헬퍼 하나를 만들어서 auto-reconnect 로직을 거기 모았다. 대략 이런 구조:
_conn = None
def get_connection():
global _conn
try:
if _conn is None or not _conn.is_connected():
_conn = mysql.connector.connect(**DB_CONFIG)
except mysql.connector.Error:
_conn = mysql.connector.connect(**DB_CONFIG)
return _conn
def query(sql, params=None):
global _conn
for attempt in range(2):
try:
conn = get_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute(sql, params or ())
return cursor.fetchall()
except mysql.connector.OperationalError:
_conn = None # 강제 무효화 후 재시도
if attempt == 1:
raise
실제 코드는 여기에 더 붙어있는데, 핵심은 실패하면 커넥션을 무효화하고 딱 한 번만 재시도한다는 거다. 무한 재시도는 안 된다. 진짜 장애 상황이면 재시도가 의미 없고, 오히려 에러를 삼켜서 나중에 더 찾기 어려워진다. 재시도 횟수를 2로 고정해두면 "조용한 실패"를 막으면서도 순간적인 끊김은 복구가 된다.
이걸 정리하고 나서 각 봇에서 연결 코드를 죄다 들어내고 헬퍼를 import하도록 바꿨다. 봇 추가할 때마다 "DB 끊기면 어떻게 처리하지?" 고민을 처음부터 다시 안 해도 된다는 게 제일 크다. 문서도 같이 써뒀으니, 나중에 누가 봐도 맥락을 잃지 않는다. 정리하고 나니 속이 시원했다. 이런 거 미루면 미룰수록 분산된 코드가 더 자란다.
데모 파이프라인이 손에 익었다
오후는 거의 데모 작업이었다. 키워드 분석 대시보드, AS 접수·조회·관리자, 엑셀 업로드 조회, 전자서명+PDF 생성. 네 개를 연달아 추가했다.
데모 하나를 올리는 절차가 처음엔 번거로웠다. 썸네일 규격 맞추고, 실제 URL 확인하고, CloudFront 퍼지까지 한 세트로 돌아야 한다. 그게 지금은 거의 자동으로 손이 간다. CLAUDE.md에 표준 절차를 박아둔 덕분인데, 솔직히 처음에 문서 쓰는 게 귀찮아서 미루다 어느 시점에 정리했는데, 그게 지금 계속 이득을 준다.
| 단계 | 내용 |
|---|---|
| 썸네일 생성 | OG 규격(1200×630) 맞춰 캡처 또는 제작 |
| 메타 입력 | 제목, 설명, 카테고리, 태그 |
| CF 퍼지 | 해당 경로 캐시 무효화 |
| 확인 | 실제 URL에서 썸네일·내용 노출 검증 |
이 루틴이 표준화되고 나서 실수가 줄었다. 퍼지 빼먹고 "왜 안 바뀌지?" 하는 상황이 없어졌다는 게 체감상 제일 크다. 나중에 누가 이걸 이어받든, 아니면 내가 석 달 뒤에 다시 보든, 뭘 어떻게 해야 하는지 헤매는 시간이 없어진다.
중간에 서명 초기화 버그도 하나 잡았다. 전자서명이 없는 상태에서 도장 이미지 자리에 엑박이 떠 있었는데, 딱히 급한 건 아니었지만 못 지나쳤다. 서명이 없으면 해당 영역을 숨기면 그만인데, 깨진 이미지를 그냥 노출하고 있던 거다. 어렵지 않았다. 근데 이런 걸 놔두면 나중에 고객이 먼저 발견한다. 그게 더 싫어서 그냥 손댔다. 보고하면 되는 수준의 버그도 눈에 밟히면 그냥 처리하게 된다. 팀장 포지션이 되면 묘하게 그 기준이 바뀐다.
SEO는 쌓는 게 전부다
Bing 외부 링크 등록을 오늘 23개에서 39개로 늘렸다. SubmitFeed 절차랑 POST 방식도 문서화해뒀다.
Bing 쪽 인덱싱은 Google에 비해 피드백 루프가 느리다. 제출하고 효과가 붙는 게 언제인지 정확히 알 수 없다. 그래서 하기 싫은 작업 1순위이기도 하다. 안 보이면 안 하게 된다. 근데 외부 링크 수, 인덱싱 범위, 크롤 빈도 같은 지표들은 한 번에 올라가는 게 아니라 주당 몇 개씩 꾸준히 늘어나는 것들이다. 안 하는 것보단 낫다는 믿음으로 계속 쌓는 중이다. 두 달 뒤에 차이를 내는 작업들이 지금 당장 재미없는 작업들이라는 걸 경험으로 알게 됐다.
오늘 커밋 수가 꽤 됐는데, 대단한 한 방이 있었다기보단 밀린 잡무들을 묶어서 처리한 느낌에 가깝다. 인프라 불씨를 끄면서 동시에 눈에 보이는 결과물도 쌓았으니 나쁘지 않은 하루였다. 내일은 좀 더 한 가지에 집중하고 싶다.
댓글 0
첫 댓글 달아줘.