집요함의 미학에 대하여 (부제. 사용자가 느끼지 못한다고 문제가 없는게 아니다)

DevSeoRex·2025년 2월 16일
2
post-thumbnail

🥹 에러란 무엇인가?

이번에 Drive-Servie를 개편하면서 크고 작은 실수들로 다양한 에러를 맞이하고 여러 번 hotfix를 진행하며 시스템의 안정성을 올리고 테스트 방법에 대해 수많은 고민을 해왔습니다.

갑자기 이런 생각이 들었습니다. 우리에게 있어서 "에러" 라는 것은 어떤 것을 의미하나요?
클라이언트에게 500번, 400번 상태코드가 내려가는 것만이 에러인가요? 아니면 사용자는 인지하지 못하지만 내부적으로 데이터 정합성이 맞지 않거나 기타 문제가 생기게 되는 것까지도 에러라고 봐야 할까요?

물론 전부 에러라고 보는 것이 맞지만, 우리가 시스템을 개선하거나 에러를 처리할 때 눈에 잘 드러나지 않는 데이터가 꼬이고 있는 오류라던지 이런 시스템 깊숙이 오래전부터 대대로 내려오는 심각한 논리 오류를 어떻게 잡아내고 개선할 수 있는지에 대한 고민을 나누고자 합니다.

에러는 항상 우리를 피해 도망가고, 우리는 에러를 잡아 없애려 나날이 추격전을 벌입니다.

우리는 숨어서 많은 문제를 만드는 잘 보이지 않는 오류를 어떻게 잡을 수 있을까요?

☺️ 드러난 문제와 숨어서 보이지 않는 문제

Drive-Service를 작업하면서 드러난 문제와 숨어서 보이지 않는 문제를 겪으며 많은 생각을 하게 되었습니다. 드러난 문제란 사용자에게 바로 보이는 에러를 뜻하고, 보이지 않는 문제는 데이터가 틀어져있으나 응답에는 전혀 문제가 없이 보이는 문제입니다.

첫 번째 예시를 들어보겠습니다.
드라이브에서 특정 폴더파일을 삭제하고 휴지통에서 해당 폴더나 파일을 완전 삭제하려고 할때 파일과 폴더는 데이터들의 PK가 휴지통의 테이블의 필드가 되기 때문에 휴지통을 완전삭제 하면서 파일과 폴더도 완전 삭제하게 됩니다.

여기서 휴지통을 생성할때 폴더파일의 PK 대신, 드라이브의 PK를 반대로 넣어서 휴지통에서 폴더와 파일을 완전 삭제할 때 내부 데이터 검증에 통과하지 못하여 삭제되지 않는 문제가 있었습니다.

이 문제는 왜 생겼을까요?

fun registerWastebasket(driveId: Long, objectId: Long) : Wastebasket

이런 함수가 있다고 해보겠습니다.
두 개의 파라미터를 받는 이 함수는 파라미터의 타입이 같기 때문에 서로 위치를 바꾸어 넣어도 전혀 에러가 발생하지 않습니다. 이로 인해 문제발생하는 것입니다.

또한 이렇게 데이터를 저장해도 잘못된 파라미터로 SQL이 실행될때 오류를 발생시키지 않기 때문에 이 데이터는 그대로 저장되게 되고 사용자가 휴지통을 완전 삭제하는 동작을 실행시키기 전까지는 전혀 문제를 알 수 없다는 것입니다.

그렇다면 왜 이 문제는 사전에 방지할 수 없었을까요?
테스트 코드를 작성했으나 Business-Layer Test는 모두 Mocking 해서 작성했기 때문에 실제 구현체를 동작시켜 데이터를 저장하고 값을 검증하는 완벽한 검증을 수행하지 않았기 때문입니다.

데이터 정합성 문제를 발생시키는 이런 오류들은 즉시 오류가 발생하지 않고 잠재적 문제를 만들어내는 존재이므로 빠른 시일내로 파악이 되야 최소한의 수정으로 논리적 오류를 잠재울 수 있습니다.

이 문제는 object_id가 잘못 저장되어 있는 데이터를 찾아서 원본 파일/폴더 데이터를 찾고 키를 업데이트 시키는 방식으로 잘못된 데이터를 모두 바로잡았습니다.

또 문제가 되는 데이터를 수정함과 동시에 잘못된 코드를 hotfix 함으로써 이 문제를 해결했습니다.

그렇다면 문제만 해결하면 해피 엔딩일까요?

🧐 오류 해결 후 재발방지 대책이 더 중요하다!

Drive-Service는 생각보다 큰 서비스라서 여러가지 의존성으로 인해 Classist 스타일의 테스팅이 굉장히 어렵다는 단점이 있습니다. 정말 필요한 Bean만 로드해서 가볍게 테스트 할 수 있는 구조를 만들어야 하는데, 다른 서버에서 데이터를 받아오거나 외부 통신을 하는 일이 굉장히 많습니다.

이 논리 오류가 생각보다 큰 문제를 야기하는 이유는 데이터저장할때는 전혀 문제가 되지 않는다는 것입니다. 그 말은 즉슨, 사용자가 파일이나 폴더를 영구삭제 하지 않고 휴지통에만 넣어 둔다면 이 문제가 확인되지 않는다는 뜻이기도 합니다.

따라서, 이 문제는 Business-Layer Test에서 데이터 저장(변경)이 이루어진 뒤에 다시 DB 조회를 통해 검증했다면 기대값과 실제값이 달라서 테스트가 실패했을 것이므로 애초에 Mocking 하지 않은 테스트를 했다면 문제없이 동작했을 것입니다.

이 일이 발생한 이후부터 저는 잠재적인 위협을 주는 다양한 논리 오류가 내가 유지보수 하는 서비스에 포함되어 있는지에 대해 사려깊게 생각하고 고민하기 시작했습니다.

😞 끝나지 않는 삽질.. 아주 오래된 논리 오류의 발견

최근 두 가지 케이스 정도의 데이터 정합성 이슈를 발견했습니다.

  • 휴지통은 삭제 상태인데, 폴더 또는 파일이 완전 삭제 상태
  • 폴더 또는 파일은 삭제 상태인데, 휴지통은 완전 삭제 상태

이 오류를 파악하면서, 코드레벨에서 문제를 찾기는 어려웠습니다.
또 이 문제가 여러 케이스에서 접근해서 테스트를 해봤지만 제가 동작시켰을때는 모두 정상이였습니다.

하지만 데이터를 직접 분석하기 시작하니 문제가 보였습니다.
첫 번째 케이스는 문제가 되는 데이터가 매일 250건이 생겼고, 데이터 업데이트 일시가 밀리초 단위밖에 차이나지 않았습니다. 그 말은 즉슨, 특정 스케쥴러가 순차적으로 데이터를 업데이트 하는 중에 문제발생시켰다는 말이 된다고 판단했습니다.

그런데 갑자기 궁금해졌습니다.
혹시 이 케이스 말고 반대의 문제 케이스는 없을까? 그렇게 두 번째 문제 케이스를 보게 되었습니다.

이 문제를 살펴보다보니 정말 심각한 문제는 다른 곳에 있다는 것을 알게 되었습니다.
첫째로, 첫 번째 케이스의 문제는 정말 단순히 스케쥴러에서 에러가 발생하여 모니터링 중에 알게된 문제로 그렇게 어려운 문제가 아니였습니다.

진짜 큰 문제는 두 번째 케이스였는데 이 케이스의 잘못된 데이터는 약 7만건 이상이며 6년전부터 이미 이 문제는 발생하고 있었지만 사용자에게 에러가 발생하지 않아 아무도 몰랐던 것입니다.

7만건의 데이터는 대부분 파일 데이터로, S3 Bucket의 물리 삭제가 데이터 불일치 이슈로 인해 6년 동안 지워지지 않고 있었던 것입니다.

파일을 물리 삭제하는 코드는 반복문을 돌면서 여러 트랜잭션과 결합되어 있기 때문에 실제 파일이 삭제됬지만 파일 삭제 예정 데이터를 넣는 테이블에는 아직 삭제가 필요한 상태로 남아서 불필요한 요청을 S3에 보낼 가능성도 굉장히 높습니다.

환율도 높아진 시점에 AWS 비용을 낭비하고 있는 이 문제는 6년 동안 알려지지 않았지만 이번에 시스템을 분석하고 데이터 형태를 보면서 찾아내게 되었고 현재 팀에 공유하고 이 문제를 분석 & 해결 중입니다.

다음 글은 이 문제를 해결하고 어떻게 유연하게 문제를 풀어낼 수 있었는지 작성하게 될 것 같습니다.

파일비정상적으로 삭제되지 않고 오랜시간 완전 삭제 상태로 방치되고 있었다면 모니터링 스케줄러라도 개발되어 알람을 줄 수 있었다면 이런 문제가 생기지 않았을거라 생각합니다.

어떻게 하면 스케줄러를 확신할 수 있을까? 매일 매일 도는 스케줄러가 논리 오류를 만들어 내는 존재가 되어버렸다면 정말 상상도 하기 싫을 만큼 끔찍한 결과를 가져오게 됩니다.

😎 개발자로서의 나의 마음가짐

처음부터 제가 맡아서 유지보수애플리케이션이 아니라면, 다양한 가설을 세우고 많은 검증을 통해 문제가 있거나 개선할 수 있는 부분을 늘 고민해야 한다는 것을 느꼈습니다.

이번 애플리케이션 아키텍처를 수정하고 구조 개선을 할때 논리적인 오류 발생을 최소화하기 위해 구조개선하고 함수를 분리하는 등의 작업을 주 업무로하고 현재 애플리케이션의 코드는 무결하게 동작한다고 믿고 업무수행했습니다.

지금 이 업무를 돌아본다면, 가장 잘못된 결정 중에 하나가 아니었을까 생각합니다.
다음에 구조를 개선하거나 코드 리팩토링 등의 업무를 해야한다면 현재 시스템에 대해서도 무결성 검증을 진행하며 점진적 리팩토링 방식을 택하여 조금씩 시스템을 개선해 나갈 것입니다.

내가 만들어가는 프로덕트를 사랑하고 그 마음 하나로 조금만 관심을 가지고 꼼꼼히 모니터링을 한다면 충분히 개선오류 포착개선등을 할 수 있다는 것을 배우게 되었고 앞으로도 우리 프로덕트를 사랑하고 진심으로 돌보고 관심가져 관찰해야겠다는 마음을 가지게 되었습니다.

늘 숨어있는 에러를 잡아 헤매는 많은 개발자 분들 언제나 화이팅입니다!
에러장애박멸하는 그날까지 매일 고민하고 머리를 싸매는 사람이 되겠습니다 😎

0개의 댓글

관련 채용 정보