개발 slecs

JSON 경로 부재 시 DB 업데이트 결과 누락되던 버그

목차

자동화 워커 스크립트에서 JSON 필드를 갱신할 때, 부모 요소가 없으면 실제로는 데이터베이스 변경이 일어나지 않았는데도 영향 받은 행 수를 제대로 추적하지 못하는 버그를 발견했다. 이 글에선 왜 이런 일이 생기고, 실무에서 어떤 영향을 미치는지 풀어본다.

버그의 본질: 경로가 없을 때의 처리 미스

데이터베이스에서 JSON 필드를 다룰 때 자주 쓰는 패턴이 있다. JSON_SET() 같은 함수를 써서 깊숙한 경로에 값을 넣는 것인데, 이때 상위 객체가 존재하지 않으면 몇 가지 경로가 갈린다.

예를 들어 $.seo 필드가 없는 레코드에 대해 JSON_SET(data, '$.seo.title', '...')를 시도하면:
- 데이터베이스는 no-op (아무것도 변경하지 않음)을 수행하거나
- 새 객체를 생성해서 값을 넣거나
- 혹은 NULL을 반환할 수 있다

문제는 이 상황에서 "영향 받은 행 수"를 어떻게 해석하는가에 있었다. 워커 스크립트는 affected=0이라고 기록해야 하는데, 실제로는 다른 값으로 카운트되고 있었던 것.

왜 이게 문제였나: 가시성 손실

자동화 작업이 제대로 진행되고 있는지 감시하려면, "이 배치에서 몇 개 레코드를 수정했나?"를 정확히 알아야 한다. 로그나 모니터링 대시보드에 affected=5 라고 나와도, 실제로 5개가 변경됐는지 3개만 변경되고 2개는 건너뛴 건지 구분할 수 없다면 문제다.

특히 이 케이스처럼 부모 경로 부재라는 명확한 조건에서는 더욱 그렇다. "$.seo가 없는 레코드 중 몇 개를 처리했는가"를 추적해야 하는데, affected 값이 부정확하면:

상황 예상 실제 영향
부모 없음 (no-op) affected=0 affected≠0 (또는 기타) 미처리 레코드 미검출
부모 있음 (변경됨) affected≥1 정상 모니터링 혼란

이렇게 되면 감사(audit) 추적도 어려워진다. "정말로 100개 레코드가 SEO 정보를 얻었나?" 하는 질문에 답할 수 없게 되는 것.

비슷한 패턴들: 중첩된 JSON의 덫

이런 류의 버그는 JSON 조작할 때마다 숨어있을 수 있다:

  • 중첩 객체의 부분 경로 부재: $.metadata.tracking.utm_source 중에 $.metadata만 있고 $.metadata.tracking은 없을 때
  • 배열 인덱스 범위 초과: $.items[10].name을 설정하려는데 배열 길이가 5일 때
  • NULL 값과의 상호작용: 부모가 NULL인 상태에서 자식을 설정하려 할 때
  • 타입 불일치: 부모가 배열인데 객체 경로를 설정하려 할 때

워커 스크립트처럼 대량의 데이터를 배치로 처리하는 곳에서는 이런 엣지 케이스가 누적되기 쉽다. 개별 테스트에선 발견 안 되다가 운영 환경의 다양한 레코드 조합에서 터진다.

배운 점: JSON 조작 후 항상 확인하라

이 버그를 수정하면서 얻은 교훈:

  • JSON 함수의 반환값과 affected의 관계를 명시적으로 확인: 쿼리가 "성공"해도 실제 변경이 일어났는지는 별개
  • 부모 경로 검증을 먼저: 자동 생성에 의존하기보다 상위 구조가 존재하는지 명시적으로 체크
  • 테스트에 엣지 케이스 포함: 부모 없음, 타입 불일치, NULL 등을 테스트 케이스로 명시
  • 로깅에 상세함 더하기: "affected=0"뿐 아니라 "왜 0인가" (부모 없음 / 값 동일 / 기타)를 함께 기록

이 수정은 작은 버그처럼 보이지만, 자동화 작업의 신뢰도를 크게 올린다. 다음에 유사한 데이터 처리 로직을 짤 땐 처음부터 이 관점을 고려할 생각이다.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.