블로그에 쓰는 200번째 글이다. 그래서 좀 좋은 걸 들고 오고 싶어서 나름 11편에 예고했던 대로, three.js관련 내용을 들고 오려고 했다. 기왕이면 기분 좋게 200회를 맞이하는 게 좋지 않은가? (비공개글도 포함인지라 여러분은 뭔 소린가 싶을 수도 있다.) 근데 사고를 쳐도 정말이지 거하게 쳐버렸고, 내 팀원들에게 어떤 사고를 쳤는지 설명할 자료도 필요해서 관계로 이 글을 쓰려고 한다. 어떤 사고를 쳤고, 경과가 어떻게 되었는지 기록해두려고 한다. 결국 지옥을 내다모는 건 언제나 자신인가... 싶은 하루였다.
다시 돌아보자면 : 내가 친 사고에는 3가지 중요한 중심 원인이 있었는데,
1. aggregate의 $out에 대한 몰이해
2. aggregate를 코드로 하려고 했음(사실, 이럴 필요가 없다는 것을 배웠다. 나중에 후술 할 것이다.)
3. backup이 존재하지 않음
이다. 솔직히 이 중 1개라도 없었다면 아예 프로덕션 데이터베이스를 날리는 이런 어처구니 없는 사태를 적어도 어느 정도 복구하거나 방지할 수 있었을 텐데... 백업은 대체 왜 안 해놓은 거지 나 개발 잔데? 바본가? 아아아아아아아 군대에서 밥먹듯이 했던 작업인데? 미쳐버린 건가?
10시정도에, 나는 우리 팀의 mongodb에 aggregate를 이용해서 totalworkoutoneweek -> totalworkout에 더하는 파이프라인을 만드려고 했다. 나는 당시에 aggregate 정확히는 $out을 정확히 이해하고 있지 못했다.
aggregate는 그 일련의 동작을 "파이프라인"이라 부른다. $lookup, $project, $unwind 등의 연산을 순차적으로 진행한 레코드들을 반환하기 때문이다. 순차적이라는 게 포인트인데, 예를 들어 이런 파이프라인이 있을 수도 있겠다.
1. User에서 Photo schema를 $lookup해서 같은 id를 가지는 스키마를 합친다. -> JOIN
2. 앞에서 받은 schema를 $unwind 해서 도큐먼트를 해제해서 인수로 만든다. -> {... } js operator
3. $project로 합쳐진 인수 중 원하는 것만 가져온다. -> SELECT
이 경우에, 만든 컬렉션은 붕떠서 db에 영향을 주지 못한 채 쿼리만 하고 끝나게 된다. 이런 식으로 열람만 하고 끝내는 것도 aggregate의 사용법 중 하나다.
오늘의 문제는 그 마지막에 오는 $out 연산이다. 거창할 거 없고 sql이라던가 orm의 COMMIT과도 일맥상통한다. 인수로 받은 db, collection 명에 해당하는 자리에 연산된 레코드를 쓴다. 앞에 이야기한 파이프라인의 맨 마지막에 $out 연산을 이용하면 내가 만든 컬렉션을 실제로 db에 쓰게 된다.
나는 이 "쓴다"라는게 아예 replace, 기존에 존재하는 컬렉션이 있다면 이를 아예 대체해 버린다는 특성이 있을 걸로는 생각하지 못하고 작업을 하게 되었고, 그게 큰 문제 중에 하나가 되었다. 존재하던 컬렉션과 합쳐지는 방식으로 동작할 것으로 생각했던 것이다.
본래는 이 착각이 그렇게까지 큰 문제가 되지 않을 수도 있었는데, 나는 이것을 보통 aggregate의 제일 앞에 쓰는 $match연산자와 같이 쓴 게 문제가 되었다.
$match는 "이 조건에 해당하는 도큐먼트에만 작업"한다는 의미이다. 그래서 이것과 $out을 같이 써버린 나는 user table이 날아가는 마술을 경험했다.
$match로 어떤 특정한 도큐먼트만 선택된 채로, 그것만 남아 있는 컬렉션이 원래의 컬렉션을 밀어버리고 남아버린 것이다.
atlas를 보면서 user의 상당수가 날아갔음을 인지한지 얼마간은 뭐지? 싶었다. 그러다가 갑자기 이해가 탁 되면서 날아갔나 싶었고, 결과는... 진짜 날아간 것이었다. 날아가고 10분간은 이걸 되돌릴 방법을 찾았었다. 근데 정말 놀랍도록 그런 속 편한 방법 따윈 없었다. 그래서 망했구나 싶었을 때 팀원에게서 전화가 왔고, 뭐... 날렸다는 이야기를 제외하고 해 줄 말이 없었다. 그래도 웹 캐시라던가 뭐 복구할 방법을 1시간 정도 더 찾아보고 확실히 없다 싶었고, 스키마에 남아있는 다른 정보를 이용해서 유저를 강제로 복구하는 것이 한계였다.
그것도 팀원이 로그가 있다고 이야기 하기 전까지는 생각도 못하고 있었다.
그리고 그 로그에서 데이터 뽑아내서 oid에서 타임스탬프를 뽑아내면서 별의 별짓을 다했지만 100% 복구하는 것은 일단 불가능했고, 이 짓하면서 원래 하려던 작업도 못하게 되었다.
https://steveridout.com/mongo-object-time/
2번 요인, aggregate를 굳이 코드로 할 필요 없다는 것은 atlas인터페이스를 쓰자는 것이다. atlas에서 데이터를 조작할 때, 보통은 collection browser를 제일 많이 쓰겠지만, 탭을 살짝 옮기면 aggregate도 있다. 나는 여기서 aggregate를 테스트만 할 수 있는 줄 알아서 내가 만든 어드민 툴에 그 파이프라인 코드를 넣어서 관리하고 있었다. atlas에서 작업하면 preview sample을 볼 수 있고, 결정적으로 $out의 동작방식이 replace라는 설명을 볼 수 있다...
이걸 로그에서 유저 사용시간을 복구하면서 겨우 알았다. 너무 자신이 바보 같았다.
3번째는 굳이 설명할 필요도 없이 백업이 없다는 것이다. 일단 관련한 것은 곧 작업하려 갈 예정이다.
하아... 마지막으로, 그냥 푸념 한 스푼 넣자면... 코로나도 걸린 것 같다는 것이다. 이 글 쓰면서 지금도 목이 칼칼하다. 오늘은 팀원들과 대면도 못했다. 머리 아프고, 피곤한 채로 작업하는데 미칠 것 같았다... 지금 한바탕 자고 나서 괜찮아지긴 했다만. 내 탓이라 누구한테 말할 것도 없다. 언제나 지옥으로 내모는 건 자신인데 뭐 누가 해 줄 말이 있을 리가. 악으로 깡으로 버텨야지! 싶다.
... 팀원들한테 정말 미안하다. 수도 없이 이야기 했지만... 후... 다행히 지금 테스트 규모가 크지 않아서 다행이지 안그랬으면 정말 큰일 날뻔 했다.
'일지 > 헬키' 카테고리의 다른 글
[AWS s3] 헬키 개발일지 11. aws 다시 세팅, s3에서 sign된 url을 가져오자 (0) | 2024.08.25 |
---|---|
[RN 죽어] 헬키 개발일지 10. PWA 찍먹 (0) | 2024.07.24 |
헬키 개발일지 9. 개발의 슬럼프 (1) | 2024.07.18 |
헬키 개발일지 8. 2024 06 29 React의 복잡한 hooking (0) | 2024.06.30 |
헬키 개발일지 7. 2024 06 26 React Native + Expo 앱 배포 방법 정리 (0) | 2024.06.27 |