안녕하세요!
오늘은 설계하며 든 고민들을 정리하면 어떨까 싶어서 작성해 보는 글입니다
저희 방끗 팀은 11월 수료 이후 간단한 유지 보수를 제외하고는 추가적인 기능 개발을 진행하지 않았어요 홍보와 유저 유치에 집중을 하던 시기였습니다 🎉
그러나! 여러 논의 끝에 이제 새로운 기능을 추가해 보기로 하여 가장 먼저 개발할 두 가지 기능을 픽스하였어요
그 기능 중 첫번째가 체크리스트 질문을 유저가 추가 가능하도록 하는 부분이에요
두 가지 기능 중 어느 기능을, 누가 담당할지에 대한 논의가 이루어지기 전에 먼저 설계를 해 보고 싶어 위 글을 작성하게 되었어요 👍

기존에는 위와 같이 서비스에서 제공해 주는 질문을 추가하거나 빼는 것으로 유저 개인의 체크리스트를 커스텀할 수 있었어요

저희는 4차례 이상의 데모데이로 직접 유저에게 피드백을 듣는 시간을 가졌고, 이후에도 꾸준히 VoC를 통해 유저의 이야기를 들어왔어요
그 결과 가장 많이 나온 의견 중 하나가 "유저가 질문을 추가할 수 있게 해 주세요" 였답니다
해당 피드백은 정말 처음부터 꾸준히 나온 의견인데요,
방끗 팀 논의 당시에는 정해진 시간 안에 배포를 해야 했기 때문에 최대한 많은 질문을 저희가 제공하는 것으로 보완하여 출시하였습니다
하지만 새로운 기능을 추가하기로 한 이상! 해당 부분에 도전해 보려고 합니다
해당 부분이 변경될 경우 크게 영향을 받는 API를 정리해 봅시다
추가로 구현되어야 할 API를 정리해 봅시다
저는 해당 부분을 고민할 때 시스템 제공 질문은 추가, 삭제가 불가하다는 가정 하에 설계했습니다
개인이 자율적으로 추가한 질문만 추가, 삭제가 가능한 방향이에요
시스템 제공 질문의 경우, 가장 기본적인 것들로 추가를 해 두어서 질문의 역할 뿐만 아니라 집을 봐야 할 때 어떤 것을 봐야할지 알려 주는 가이드라인의 역할 또한 하고 있습니다
시스템 질문의 삭제하거나 수정하게 되면 해당 부분의 정확도가 떨어진다고 판단하여 코어 질문들은 유지하는 방향으로 가고자 합니다!
해당 부분은 고민이 되는 API 중 하나입니다
생각해 본 시나리오 중 하나가 있는데요
만약, 유저가 커스텀 질문을 추가한 후 해당 질문을 바탕으로 체크리스트를 작성하고 해당 질문을 수정한 후 체크리스트를 조회하게 되면
저희의 설계상으로 작성 당시의 체크리스트 질문이 아닌 수정 후의 질문이 보여지게 됩니다
유저가 간단한 어휘를 바꾼 정도라면 해당 답변에 문제가 없지만 아예 다른 내용으로 바꾼 경우에는 해당 체크리스트의 신뢰도가 떨어지게 됩니다
이러한 설계를 유저가 모르기 때문에 충분히 발생 가능한 시나리오라고 판단하였습니다
그럼 설계상으로 이렇게 안 되도록 변경하면 되지 않나? 를 고민해 보자면
체크리스트를 작성할 때마다 해당 질문의 내용까지 저장하는 방식을 떠올릴 수 있는데요
하나의 작은 시나리오를 예방하고자 많은 불필요한 데이터를 저장하는 것과 커스텀 질문 수정 기능을 유지하는 것 중 무엇이 더 합리적일까? 커스텀 질문 수정 기능을 그만큼 유저가 필요로 할까? 를 고민해 봤을 때 질문 추가, 삭제를 두고 질문 복사 버튼을 추가하는 것으로 충분히 대체 가능하다 판단하였습니다
그 외에도 다양한 방안이 떠올랐으나 실현 불가능하다 생각하여 보류하였습니다
따라서 해당 API는 구현을 하지 않는 방향으로 가는 것이 적합할 거라고 생각해요
위의 내용을 생각해 보다가, 그렇다면 커스텀 질문을 삭제할 때도 문제가 생기겠는데? 라는 생각이 문득 들었어요
만약, 유저가 커스텀 질문을 추가한 후 해당 질문을 바탕으로 체크리스트를 작성하고 해당 질문을 삭제한 후 체크리스트를 조회하게 되면 현재의 경우에는 질문이 삭제되어 해당 질문과 답변을 조회할 수 없습니다
사실 현재 저희 서비스에서는 일부 부분에 한정하여 논리적 삭제를 도입하였어요
저희의 판단 하에 유의미하다 생각한 데이터 일부는 논리적 삭제를 통해 처리하고 있습니다
이러한 논리적 삭제된 데이터는 다른 History DB에 옮겨지고 있지 않고, 같은 테이블 내에서 관리하고 있어요
따라서 해당 부분은 논리적 삭제를 잘 조절한다면 해결 가능한 부분입니다
하지만, 논리적 삭제가 된다는 사실을 비즈니스 코드가 알게 되어도 괜찮을까요?
저희가 기존에 논리적 삭제를 도입한 것은 유의미하다 생각한 데이터를 분석하기 위함이었고, 다른 DB로 옮기지 않은 이유는 저희가 다른 환경을 구축할 만큼 많은 유저가 있는 서비스가 아니었기 때문입니다
만약 유저가 많아진다면 충분히 DB를 분리할 수도 있는 상황이에요
현재 환경적 특성을 이용하는 비즈니스 코드를 작성해도 괜찮을지 고민이 되었어요
그렇다고 해서 커스텀 질문 삭제 기능 자체를 구현하지 않는 것은 유저 사용에 있어서 큰 불편을 초래할 것임이 분명했어요
따라서 고민 끝에 user_deleted 와 같은 논리적 삭제와 비슷하지만, 좀 더 비즈니스 코드에서 사용하기 위한 플래그 칼럼을 추가하는 것이 어떨까라는 생각이 들었습니다
해당 플래그를 통해 유저는 이 질문을 삭제했지만 체크리스트를 볼 때는 해당 질문을 보여 주어야 해라는 의도를 드러낼 수 있다 생각해요
물론, 해당 방안에도 문제점이 떠올라요
사실상 논리적 삭제 플래그와 동일하게 동작하기 때문에 현 시점에서는 불필요한 코드예요
따라서 논리적 삭제 DB를 분리하는 시점해서 해당 칼럼을 추가해 줘도 될 듯합니다
하지만 그렇게 한다면 내가 아닌 다른 개발자가 DB를 옮길 때에 이를 인지할 수 있을까? 라는 부분에서는 코드에 의도가 명확히 드러나지 않아 파악하기 힘들고, 이로 인해 치명적인 에러가 발생할 수도 있을 것 같다는 생각이 듭니다
따라서 저는 플래그 칼럼을 추가하는 것이 가장 합리적이라고 판단하였습니다
그렇다면 기존의 시스템 질문만 있는 테이블과 개인 질문이 있는 테이블은 같이 사용해도 될까요 분리해야 할까요?
사실 이 부분을 고민할 때 굳이 합칠 이유도, 굳이 분리해야 할 이유도 명확히 떠오르지 않았습니다
그래서 각각의 경우를 비교해보고, 데이터 조회 및 관리의 복잡성을 고려했을 때 어떤 방식이 더 적절한지 정리해보겠습니다
질문 ID를 공통적으로 사용하기 때문에 한 테이블에서 관리하는 것이 조회하기 쉽습니다
만약 테이블을 분리할 경우, 커스텀 질문 테이블에서 해당 질문이 어느 테이블에서 왔는지 식별해야 하는 문제가 발생합니다
이를 해결하려면 아래와 같은 방법이 필요합니다
하지만 이런 방식은 조회할 때 IF문으로 분기 처리를 해야 하고, 데이터 정합성을 유지하는 것도 복잡해지므로 성능 저하가 발생할 가능성이 높습니다
반면, 한 테이블에서 관리하면 이러한 불필요한 로직이 필요하지 않아 쿼리가 단순해지고, ID 체계를 유지하기도 훨씬 수월합니다
질문을 조회할 때 단일 테이블에서 검색할 수 있어 쿼리가 간결해집니다
반대로 테이블이 분리되어 있으면, 시스템 질문과 개인 질문을 함께 조회할 경우 UNION을 사용하거나 두 개의 쿼리를 실행해야 합니다
이는 성능 저하뿐만 아니라 데이터를 조회하는 로직이 복잡해지는 원인이 됩니다
개인 질문의 경우 생성한 유저 ID, 삭제 여부 등의 칼럼이 필요하지만, 시스템 질문에는 불필요합니다
따라서 테이블을 통합하면 일부 칼럼이 비어 있는 상태로 저장될 수 있습니다
하지만 시스템 질문의 개수가 많지 않다면, 이로 인한 저장 비용이 크게 문제 되지 않을 가능성이 높습니다
즉, 공간 낭비는 존재하지만, 성능과 관리의 복잡성 측면에서 얻는 이점이 더 크다면 감수할 수 있는 부분입니다
이로 인해 저는 테이블을 합치는 것이 더 합리적이라고 판단하였습니다!
이렇게 고려할 부분을 고려하여 설계를 해 보았는데요
제가 어느 부분을 담당할지는 모르겠지만!
몇 시간에 걸쳐 고민하고 선택을 하니 어렵기도 하면서 즐겁게 느껴져요
설계에 대한 조언이나 토론 댓글은 언제나 환영입니다 🙇♂️