대니
danny's blog@dannywon_dev
발행 94 · 대기 164

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

클로드 코드

정규식 (?<![\w.]) 때문에 public.fairs 9개를 통째로 놓쳤다

테이블 이름을 바꾸며 붙인 검사가, 목록을 만든 것과 같은 정규식이었다

배포가 끝나고 임시 통로까지 철거한 뒤에 로컬에서 다음 작업을 돌리다 멈췄다.

relation "public.fairs" does not exist

마이그레이션 맨 끝에 「빠뜨린 게 없나」 검사를 붙여뒀고, 그 검사는 「없음」이라고 답했었다.

검사가 통과한 이유

2026-08-12 에 DB 테이블 이름을 fairs 에서 exhibitions 로 바꿨다. 이름만 바뀌고 데이터는 안 움직이는 작업이라 손이 갈 곳은 셋이었다 — 테이블 자체, 그 이름을 부르는 DB 함수들, 앱 코드.

함수를 찾을 때 이 규칙을 썼다.

(?<![\w.])fairs      ← 앞이 글자나 점이면 제외

exhibitor_artists 같은 다른 이름 속에 들어 있는 조각을 지키려고 넣은 조건이었다. 그리고 검사에도 같은 규칙을 썼다.

세어 보니 함수 9개가 public.fairs 라고만 쓰고 있었다. public. 의 점이 「앞이 점이면 제외」에 걸려서 목록에서도 검사에서도 통째로 빠졌다. 페어 참가 신청 · 부스 번호 변경 · 작품 등록 · 관람객 대화 목록 · 순위 조회가 그 함수들이었다.

같은 벽을 두 번 그렸다

처음엔 「정규식을 잘못 썼다」로 봤다. 맞지만 그게 전부가 아니었다.

검사를 붙인 이유는 「내가 목록을 잘못 만들었을 때 잡으려고」였다. 그런데 그 검사가 목록을 만든 것과 똑같은 자로 재고 있었다. 목록이 틀린 이유가 그 자였으니 검사도 같은 곳에서 눈이 멀었다.

두 번째 방어선을 세운 줄 알았는데 실은 같은 벽을 두 번 그린 것이었다.

여기서 갈린 건 **「검사를 엄밀하게 할 것인가, 넓게 할 것인가」**였다. 엄밀하면 잡음이 없고, 넓으면 사람이 한 번 더 봐야 한다. 넓은 쪽이 옳다. 잡히는 게 많아 한 번 더 보는 건 몇 초짜리 비용이고, 못 잡는 건 운영에서 터진다. 비대칭이 너무 크다.

뭘 바꿨나

하나 — 검사를 치환보다 넓게 잡는다.

치환:  \bfairs\b 로 넓게 잡고, 지켜야 할 이름은 따로 보호한다
검사:  \mfairs\M  ← 점 뒤도 포함. 치환보다 넓다

둘 — 두 종류의 「앞에 붙는 것」을 구분한다. public. 같은 스키마 접두어와 exhibitor_ 같은 이름 결합은 다른 물건인데, 「앞 글자 제외」 하나로 둘 다 처리하려다 사고가 났다. 지켜야 할 이름은 치환 전에 표시해 두고 끝나고 되돌리는 쪽이 안전하다.

셋 — 기계가 검증할 수 있는 건 기계에게 시킨다. PostgreSQL 은 SQL 함수를 다시 만들 때 본문을 스키마에 대고 검사한다. 그래서 「모든 SQL 함수를 그대로 다시 만들어 본다」를 검사에 넣었다. 글자를 훑는 것보다 훨씬 세다.

⚠️ 다만 절차형 함수(plpgsql)는 그 검증이 안 걸린다. 이번에 놓친 9개 중 5개가 그랬다. 그건 실제로 호출해 봐야 안다.

곁가지 — 확인이 단계마다 얇아졌다

같은 날 같은 종류의 작업을 여러 번 했다. 앞 단계에서는 화면을 12개 넘게 열어 확인했는데 뒤로 갈수록 2개로 줄었다. "같은 방식이니 괜찮다" 로 넘겼기 때문이다.

그런데 이번에 깨진 함수 9개는 그 2개 화면이 하나도 안 불렀다. 절차를 건너뛴 게 아니라 얕게 한 것이 원인이었다.

그래서 판정을 바꿨다 — 「화면을 봤나」가 아니라 「바뀐 것이 지나가는 화면을 봤나」. 앞의 것은 아무 화면이나 열어도 통과한다. 실제로 그렇게 통과했다.

← 목록으로