대니
danny's blog@dannywon_dev
발행 142 · 대기 176

1인 개발자. 클로드 코드를 팀처럼 굴린다. 매일 겪은 것만 쓴다.

← 클로드 코드

마이그레이션 가드가 운영 배포를 막았다 — 환경마다 다른 id

PDF 에서 작가 961명을 뽑아 넣는 작업에서 검사 셋에 걸렸고, 셋 다 진짜였다

로컬에서 잘 돌아간 SQL 이 운영에서 멈추면, 보통 먼저 의심하는 건 권한이나 스키마 차이다. 이번엔 내가 몇 주 전에 심어둔 가드였다.

2026-08-27. 아트페어 도록 PDF(179쪽)에서 참가 작가 961명을 뽑아 DB 에 넣는 작업을 했다. 관람객이 부스를 누르면 「참가 작가」가 뜨는 화면인데, 175곳 중 1곳만 차 있는 상태였다.

그날 검사에 세 번 걸렸다. 셋 다 진짜였다.

① 도록이 틀렸다

뽑아낸 뒤 습관처럼 검사를 돌렸다 — 한 부스에 갤러리 이름이 둘 이상 붙은 게 있나. 19건이 나왔고, 한 갤러리 이름이 반복해서 끼어 있었다.

파싱 버그인 줄 알고 파고들었다. 원본 좌표를 찍어 보니 그 줄은 내부적으로 멀쩡했다 — 작가·갤러리·부스가 전부 같은 높이(y=496.6)에 나란히 있었다. 그런데 같은 도록의 다른 색인은 그 갤러리를 다른 부스로 적고 있었다.

여기서 두 갈래였다. 「내 파싱이 틀렸다」와 「원본이 틀렸다」. 기본값은 당연히 전자다. 남의 공식 자료를 의심하는 건 대개 오만이다.

갈랐던 건 이웃 줄이었다. 같은 방식으로 뽑은 옆줄 셋(다른 갤러리 셋)은 두 색인이 정확히 일치했다. 파싱이 틀렸다면 옆줄도 같이 틀려야 한다. 안 틀렸으니 파싱이 아니다.

도록이 틀린 것이었다. 그 갤러리 소속 13명이 연속된 부스 번호로 흩어져 있었다.

→ 부스 칸을 통째로 버리고 「작가 ↔ 갤러리」 짝만 썼다.

② 환경마다 다른 id

SQL 을 만들 때 참가 행의 id 를 그대로 적었다. 로컬에서 잘 돌았다. 운영에 밀자 내가 심어둔 가드가 막았다.

"없는 참가를 가리키는 줄이 있다. 중단한다."

id 는 환경마다 다르다. 통과했으면 961줄이 아무 데도 안 붙은 채 들어갔을 것이다. 에러도 안 나고, 화면만 조용히 비어 있었을 것이다.

→ 환경을 안 타는 값으로 다시 만들었다. 양쪽에서 유일함을 확인한 자연키만 쓴다.

여기엔 갈릴 게 없었다. 가드가 정확히 그 경우를 막으려고 있었고, 정확히 그 경우가 왔다. 의미 있는 건 내가 그 가드를 쓸 줄 몰랐다는 점이다. 쓸 일 없을 줄 알고 넣었다.

③ 내 조회가 틀렸다

중간에 "175곳 중 36곳에 이름이 없다" 는 결과가 나왔다. 개막 6일 전이라 큰일이라고 생각했다.

보고하기 전에 한 번 더 확인했더니 내 조회가 틀렸다. 이름이 옮겨간 테이블을 엉뚱한 키로 잇고 있었다. 실제로는 175곳 다 이름이 있었다.

바꾼 것

  • 부스 번호를 키에서 뺐다 — 원본이 못 미더운 칸은 안 쓴다
  • SQL 에서 환경 의존 id 를 전부 뺐다. 자연키로만 잇는다
  • 가드를 「혹시 몰라서」 넣는 습관을 유지하기로 했다. 이번에 걸린 가드는 셋 다 "이럴 리 없는데" 하면서 넣은 것이다. 걸리기 전까지는 쓸모없어 보였고, 걸린 순간 하루를 벌었다

남은 생각

검사 셋이 전부 **「값이 맞나」가 아니라 「관계가 맞나」**를 봤다.

형식 검사로는 셋 다 못 잡는다. 부스 번호는 형식이 완벽했다. id 도 형식이 완벽했다. 조회 결과도 형식이 완벽했다. 숫자는 숫자였고 키는 키였다.

잡은 건 「이 값이 다른 곳과 어긋나나」 하나였다. 도록의 다른 색인, 참조 대상 테이블, 그리고 이상한 숫자를 본 뒤의 재확인.

← 목록으로