새 코스 종류가 레거시 코드에서 터진 날

26년 05월 15일

백엔드에서 NoMethodError

이날은 새 코스 종류 도입이 백엔드에서 터진 날이었다.

프론트엔드는 다

잡았는데, 백엔드에서 새 코스 종류가 기존 코드 경로를 만나서 에러가 났다.

그리고 잠금 UI 검증 마무리랑 깃 정리도 이어갔다.

가장 큰 사건은 백엔드 에러였다.

특정 코스에서 기존 계정을 초대하면 NoMethodError가 났다.

원인을 추적해보니, 초대 서비스 코드에서 기존 코스 종류 정보를 조회하고 있었다.

이 코스는 새 종류라서 기존 코스 종류 정보가 없다.

없는데 거기서 메서드를 호출하니까, nil에 메서드를 호출하는 꼴이 된 거다.

NoMethodError. 이건 전형적인 “새 엔티티 타입이 오래된 nil-unsafe 분기를 만나는” 결함이다.

기존 코드는 코스 종류 정보가 항상 있다고 가정했다.

기존 두 종류에서는 항상 있었으니까. 근데 새 종류에서는 없다.

그러니까 터진 거다.

해결

즉시 해결은 누락된 데이터베이스 레코드를 수동으로 만드는 거였다.

해당 코스에 기존 코스 종류 정보 레코드를 추가했다.

그러니까 에러가 안 났다.

근데 이건 근본 해결이 아니다.

근본 해결은 코드에 nil 가드를 넣는 거다.

정보가 없으면 거기서 멈추고 에러를 내지 않게 만드는 거다.

근데 당장은 데이터를 넣어서 막았다.

더 깊은 원인은, 새 코스 종류가 기존 종류 전용 코드 경로를 타고 있다는 거다.

이건 전체 분기 로직을 손봐야 해결되는 문제다.

며칠 전에 8단계로 분기를 다시 만든 게 이런 문제를 해결하기 위한 거였다.

근데 아직 모든 경로를 커버 못 한 거다.

잠금 UI 검증 마무리

백엔드 에러 외에 프론트엔드 잠금 UI 검증도 마무리했다.

어제 3-way 교차 검증으로 불일치 7개를 찾았다.

오늘은 그걸 픽셀 퍼펙트까지 밀어붙였다.

폰트 굵기, 줄 높이, 자간, 패딩, 마진, 간격, 색상까지 전부 디자인 토큰에 맞췄다.

화면을 캡처해서 디자인이랑 비교해서, 불일치가 0개가 됐다.

테스트 데이터베이스에 잠금 상태를 재현할 수 있는 데이터를 심었다.

완전 잠금, 부분 잠금, 임계값 초과 시나리오를 만들 수 있게 했다.

이 상태들에서 화면이 어떻게 나와야 하는지 검증했다.

타입스크립트 결과물 290개 정리

그리고 깃 정리도 이어갔다.

어제 시작한 거다.

타입스크립트 컴파일 결과물이 깃에 잡히고 있었다.

어제 패턴을 추가하고 이미 커밋된 결과물을 추적 해제했다.

오늘은 결과물 290개를 더 쓸어냈다.

원인은 컴파일 출력 디렉토리 설정이 깃이그노어랑 맞지 않았던 거다.

그래서 컴파일 결과물이 소스 트리 안에 생기고 깃이 그걸 추적하고 있었다.

설정을 맞추고 추적을 해제하니까, 작업 트리가 깨끗해졌다.

290개나 쌓여 있었다는 건, 설정 불일치가 꽤 오래됐다는 뜻이다.

결과물이 계속 생성되면서 계속 추적되고 있었던 거다.

이런 건 빨리 잡을수록 좋다.

나중에 잡으면 더 많이 쌓인다.

마무리

이날의 핵심은 새 코스 종류가 백엔드에서 터진 거다.

프론트엔드는 픽셀 퍼펙트까지 잡았는데, 백엔드에서 아직 커버 못 한 경로가 있었다.

새 엔티티 타입을 기존 시스템에 도입하면, 이런 일이 생긴다.

기존 코드는 새 타입을 모른다.

항상 있다고 가정했던 데이터가 새 타입에서는 없다.

그러면 nil 에러가 난다.

이걸 막으려면 두 가지가 필요하다.

하나는 코드에 nil 가드를 넣는 거다.

데이터가 없어도 에러가 안 나게. 다른 하나는 분기 로직을 전체적으로 손보는 거다.

새 타입이 기존 전용 경로를 안 타게. 전자는 즉각적인 방어고 후자는 근본 해결이다.

둘 다

해야 한다.

이날은 전자로 막고 후자는 계속 진행 중이었다.