12화에서 새우깡 사건을 이야기했습니다. 2,434건의 잘못된 매칭. 1,045개 제품에 표시된 틀린 영양정보. 그리고 제가 직접 발견하기 전까지 아무도 모르고 있었다는 사실.
그날 이후, 저는 원칙을 만들기로 했습니다.
첫 번째 원칙.
새로운 방법으로 데이터를 연결하기 전에, 반드시 교차 검증을 한다.
교차 검증이란 이런 겁니다.
“이름이 비슷해서 연결했다”면, 그 연결이 맞는지를 이름이 아닌 다른 기준으로 확인하는 것. 품목보고번호라든가, 바코드라든가, 제조사의 인허가번호라든가.
새우깡 사건에서 배운 건 정확히 이것이었습니다. 이름으로 연결한 2,434건을 품목보고번호로 교차 확인했더니 일치하는 것이 단 한 건도 없었다고요.
교차 검증 한 번이면 바로 발견됐을 문제를, “비슷하니까 맞겠지” 하고 넘겨서 놓친 거였습니다.
두 번째 원칙.
매칭을 적용한 후에는, 반드시 전체 검증을 돌린다.
매칭 결과를 저장한 다음에, 자동으로 데이터가 정상인지 확인하는 검사를 만들었습니다.
이건 비유하자면 이런 거예요. 시험을 보고 나서 답안지를 제출하기 전에 한번 더 쭉 훑어보는 것.
“영양정보가 연결된 제품 수가 갑자기 크게 변하지 않았는가?” “같은 제품에 두 개의 영양정보가 연결되어 있지는 않은가?” “매칭 신뢰도가 낮은 건의 비율이 비정상적으로 높지는 않은가?”
이런 항목들을 자동으로 확인하고, 하나라도 이상하면 알려주도록 만들었습니다.
세 번째 원칙.
검증 없는 매칭은 저장하지 않는다.
아무리 그럴듯해 보여도, 교차 검증을 거치지 않은 매칭 결과는 데이터베이스에 반영하지 않기로 했습니다.
이건 좀 불편한 원칙이에요. “일단 넣어놓고 나중에 확인하자”가 훨씬 편하거든요. 하지만 새우깡 사건이 보여줬듯이, 한번 잘못 들어간 데이터는 발견하기가 정말 어렵습니다.
차라리 넣기 전에 확인하는 게 낫습니다.
그리고 이 시점에서 한 가지 변화가 있었습니다.
저는 AI 두 명과 함께 일하고 있었습니다.
하나는 제가 처음부터 함께 해온 AI예요. 아키텍처를 설계하고, 코드를 작성하고, 데이터 구조를 만드는 역할.
다른 하나는 중간에 합류한 AI인데, 코드를 비판적으로 검토하는 역할을 맡았습니다.
왜 두 명이 필요했냐면요.
사람도 자기가 쓴 글에서 오타를 잘 못 찾잖아요. 너무 익숙하니까 눈이 그냥 지나가거든요. AI도 비슷했습니다. 자기가 만든 코드의 문제를 자기가 발견하기는 쉽지 않았어요.
그래서 다른 AI에게 “이 코드에 문제가 없는지 비판해달라”고 맡겼습니다.
두 번째 AI의 역할은 구체적이었습니다.
메모리를 너무 많이 쓰는 코드가 없는지. 데이터베이스에 불필요하게 많이 접근하는 코드가 없는지. 데이터가 깨질 수 있는 경우를 놓치고 있지는 않은지.
주로 성능과 안정성 측면에서 검토해줬어요.
이 과정에서 실제로 개선된 것들이 있었습니다.
원래 데이터 4만 건을 한꺼번에 메모리에 올렸던 코드를, 필요한 부분만 가져오도록 바꿨고.
데이터를 저장할 때 하나씩 저장하던 것을, 묶어서 한 번에 저장하도록 바꿔서 속도를 높였고.
매칭 사전에서 이름이 충돌하는 경우를 감지하는 로직도 추가했습니다.
이런 과정을 거치면서, 저는 한 가지를 깨달았습니다.
이 프로젝트에서 가장 중요한 것은 화면이 예쁜 것도 아니고, 기능이 많은 것도 아니었습니다.
데이터가 정확한 것.
사용자가 새우깡을 검색했을 때, 새우깡의 정보가 정확하게 나와야 합니다. 다른 제품의 정보가 섞여 나오면 안 됩니다.
이건 식품 정보를 다루는 서비스의 가장 기본적인 약속이에요. 그리고 새우깡 사건은 그 약속을 제가 한번 어겼다는 뜻이기도 했습니다.
다시는 어기지 않겠다고 다짐했습니다.
원칙을 정리하면 이렇습니다.
- 연결하기 전에 교차 검증한다.
- 연결한 후에 전체 검증을 돌린다.
- 검증 없는 데이터는 저장하지 않는다.
- 두 번째 시선으로 코드를 검토한다.
거창한 것은 아닙니다. 하지만 이 네 가지를 지키는 것만으로도 같은 실수를 반복하지 않을 수 있었습니다.
다음 화에서는 조금 다른 이야기를 하겠습니다. 영양정보 데이터의 또 다른 문제. API에서 제공하는 영양성분 데이터가 기대했던 것과는 많이 달랐던 이야기요.