포스트 시스템 개편 회고

2022년 2월 5일

주의 ⛔️

  • 이 글이 작성된지 2년이 넘었어요.
  • 누구나 숨기고 싶은 흑역사가 있답니다.

무슨 업무를 했나?

  • 포스트 시스템 개편
    • 포스트 컴포넌트들의 UI 수정
    • 포스트를 사이트 곳곳에 노출하기 위한 타겟팅 시스템의 설계

업무별 정리

포스트 시스템 개편

기존 포스트 시스템에선, 어드민이 백오피스에서 포스트를 생성한 후, 메인 페이지의 캐러셀 배너 같은 정적인 위치에 노출시켰다.

어드민들이 포스트 같은 컨텐츠를 제작하고, 노출하기 까지 들이는 노력이 상당함에 비해, 유저가 그 컨텐츠를 소비하는 비중은 너무나도 적었다.

따라서 우리 사이트는 유저가 상품 이외의 컨텐츠를 더 많이, 자연스럽게 접할 수 있도록 하는 개선의 움직임이 필요했다. 그렇게 포스트 시스템 개편 작업이 시작됬다.

이미 포스트 시스템이 존재했기 때문에, 기존 구현이나 데이터 스키마를 수정하는 마이그레이션 작업이 주를 이루었다.

포스트 컴포넌트들의 UI 개편과, 포스트를 사이트 곳곳에 동적으로 노출시키기 위한 타겟팅 시스템의 구현을 위해서 백엔드 구현을 어떻게 수정해 나갈지에 대한 계획을 팀원과 함께 상의하고, 하나씩 개발을 시작했다.

그 과정에서 개발팀이 아니라 포스트를 관리하는 다른 팀과의 커뮤니케이션도 많이 필요했다. 개발자가 아닌 사람에게 기존 시스템에서 어떤 변경이 일어났고, 그에 따라 어떤 행동을 하면 되는지 이해하기 쉽게 설명하는 일은 결코 쉬운 일이 아니었다. 개발팀 밖에서 소통해본 경험이 많이 없었기 때문인 듯 하다.

특히나 변경사항에 대한 신속한 대응이 필요할 땐, 내가 다른 팀을 빠르게 이해시키기 위해 더 적극적으로 커뮤니케이션을 시도했어야 했다고 생각한다.

물리적인 관점에서는, 포스트를 관리하는 팀과 개발팀이 서로 다른 층(우리 회사는 건물 2층과 7층으로 나뉘어 있다.)에 있는 것도 영향이 있었던 것 같다. 슬랙에서의 멘션으로는 빠른 피드백이 어려운 상황이 발생할 수 있고, 메시지로는 표현이 어려운 경우도 있다. 이럴 땐 어느 한쪽이 먼저 물리적으로 가까워지려는 노력을 하는게 옳았다고 생각한다.

포스트 컴포넌트들의 UI 수정

포스트는 블록(Paragraph, Product, Youtube Embed, Heading, Space 등)으로 이루어져 있고, 프론트엔드에서는 어떤 블록이냐에 따라 switch-case해서 포스트를 렌더링한다.

  • 블록의 스키마에 새로운 프로퍼티 추가하기

    • 예를 들어, Product 블록은 productId 프로퍼티를 가지고 있을 것이다. 이 때 description이라는 새로운 프로퍼티를 추가하려면 어떻게 하는게 좋을까?
    • 정답은 백엔드에선 description 프로퍼티를 optional로 추가하되, 어드민의 에디터 상에선 description의 입력을 강제하는 것이었다.
    • 그렇게 하면 기존에 생성된 포스트들은 깨지지 않게 유지되고, 앞으로 새롭게 생성될 포스트들에는 변경된 스키마를 강제할 수 있다.
    • 또한, 기존 데이터들의 마이그레이션을 위한 작업 비용도 사라지게 된다.
  • DynamoDB 테이블 삭제 + 해당 테이블에 대한 접근 권한 삭제

    • 배경
      • 우리 서비스는 AWS Lambda를 사용한 serverless 백엔드에 기반하고 있다.
      • 따라서, serverless framework를 사용해 Lambda Function을 배포하고 있다.
      • 포스트에서 author(작성자) 프로퍼티가 필요가 없어져 삭제하게 되었다.
      • author는 별도의 테이블에서 따로 관리되고 있었다.
      • 따라서 serverless config 파일에서 author 테이블과 권한을 지우고, Lambda Function 코드를 수정해서 함께 배포했다.
    • 문제
      • 포스트 API들이 약 1분동안 중단되는 상황이 발생했다.
    • 원인
      • 에러 로그를 살펴보니, author 테이블에 대한 권한이 없다고 찍혀있었다.
      • CloudFormation 배포 순서상, DynamoDB 테이블 또는 권한을 삭제하는게 새로운 Lambda Function을 배포하는 것 보다 먼저인 듯 했다. 실제로 에러 로그도 배포중이던 34~35분에만 찍혔고, 배포가 완료된 36분 부터는 정상 작동했다.
    • 앞으로는 어떻게 하는가?
      • 수정된 Lambda Function을 먼저 배포하고, 그 다음에 테이블과 권한을 삭제하여 한번 더 배포해야 중단없이 서비스를 제공할 수 있을 듯 하다.

포스트를 사이트 곳곳에 노출하기 위한 타겟팅 시스템의 설계

  • 포스트와 포스트 타겟을 하나의 API로 제공할 것인가?
    • 배경
      • 포스트와 포스트 타겟은 별도의 테이블로 분리했다. 포스트와 포스트 타겟의 관계는 1:n이므로, 포스트 테이블 내에 포함시키면 포스트 타겟에 대해 쿼리를 할 수가 없기 때문이다. 또한 포스트 타겟은 포스트의 노출 순서도 포함하고 있기 때문이다.
      • 그렇다면 getPost API(GET /posts/:postId)의 응답에는 포스트 타겟 리스트가 포함되어야 할까? 아니면 getPostTargets API(GET /posts/:postId/targets)를 따로 만들고, 2개의 API를 요청해야할까?
    • 고민
      • 유저 서비스 & 백오피스 사이의 관점
        • 포스트 타겟의 CRUD는 오직 백오피스에서만 이루어진다.
        • 즉, 포스트 타겟은 유저 서비스에는 필요가 없는 데이터이다.
        • 따라서 getPost와 getPostTargets로 분리하는게 더 좋을 것이다.
      • read & write 비율에서의 관점
        • 포스트는 write에 비해 read가 매우 많다. read에 비하면 write는 그냥 없는편이다.
        • getPost에 포스트 타겟을 포함시키려면, 유저의 read 한 번에 2개의 테이블을 조회해야 한다.
        • 위에서 언급했듯이, 포스트 타겟은 백오피스에서만 필요한 기능이고, 유저에겐 필요하지 않다. 또한, 포스트의 read도 당연히 백오피스보단 유저 서비스가 훨씬 많다.
        • 따라서 getPost, getPostTargets API를 따로 분리하는게 read 비용상 이득이다.
      • 프론트엔드 개발자로써의 관점
        • getPost와 getPostTargets를 분리할지는 프론트엔드에서 포스트와 포스트 타겟을 서로 별개의 모델로써 여길지에 달려있다.
        • 서로 분리된 모델로 생각한다면, 포스트를 불러왔을 때 포스트 타겟도 불러와야 할 것이다. 그리고 백오피스의 포스트 에디터에서는 포스트와 포스트 타겟이 하나의 Form으로 보이지만, 내부적으로는 두 개의 update API를 호출해야 할 것이다.
        • 서로 합쳐진 모델로 생각한다면, 포스트를 불러오면 포스트 타겟도 불러와진다. 또한 에디터에서도 하나의 update API만 호출하면 된다.
        • 포스트 리스트에서는 리스트 아이템 하나당 getPostTargets를 계속 호출해서 포스트 타겟들을 보여줘야 하므로, API 호출이 급격히 많아질 가능성이 있다.
        • 따라서 getPost에 포스트 타겟을 포함하는게 합리적이다.
      • Microservices Architecture에서의 관점
        • 우리 서비스는 MSA 백엔드로 이루어져 있다.
        • 유저 서비스의 API Gateway 또는 백오피스 서비스의 API Gateway를 거쳐 Post Service를 호출하게 된다.
        • Post Service에서는 getPost, getPostTargets를 분리한 뒤, 유저 서비스의 API Gateway에서는 getPost만 호출하고, 백오피스 서비스의 API Gateway에서는 getPost, getPostTargets를 호출하면 된다.
        • 그러면 결과적으로 프론트엔드에서는 하나의 API만 호출하도록 만들 수 있다.
    • 결정
      • 종합적으로 봤을 때 getPost, getPostTargets를 분리하는게 맞다고 생각했다. 유저 서비스와 백오피스의 API Gateway가 서로 분리되어 있기 때문에, 각각의 관점에서의 요구를 통합하여 충족시킬 수 있다.

생각 / 목표 정리

올해 시작부터 프론트엔드 / 백엔드 전체를 포괄하여 설계하고 개발하는 업무를 맡게 되었는데, 내가 생각보다 너무나 부족한 상태라는걸 많이 깨달았다.

여러 관점을 넘나들며 생각해보고 의사결정을 해볼 수 있었던 경험은 정말 가치있었던 것 같다. 물론 동료 개발자의 도움이 매우 컸긴 했지만 말이다.

그냥 프론트엔드 개발할 줄 알고, 백엔드 API 만들 줄 알고, DB 테이블 만들 줄 알면 풀스택 개발자로 일할 수 있을 것 같다고 간단하게 생각했던 나 자신이 부끄럽기도 했다. 저런 것들은 매우 당연한 역량일 뿐이고, 그 뒤에는 수많은 경험과 깊은 생각에 기반한 의사결정 능력이 숨어있었다.

앞으로도 아래의 리스트에 나열한 것들은 계속해서 연습해야 할 것 같다.

  • 단일적인 생각에 의해 결정하지 않고, 여러 관점을 아울러 생각하여 합리적인 결정을 내리기
  • 개발자가 아닌 사람들에게, 혹은 내 작업에 대해 모르는 사람들에게 이해하기 쉽게 설명하기