Contents

소..솔직히 유지보수는 아키텍트의 책임이라고 생각해요...

/img/035/goto_hitori.webp

메락아, 그게 무슨 소리니?

아니 일단 들어봐

서비스가 되었든, 소프트웨어가 되었든, 어떤 프로젝트에 대해 보통 기업은 신기술에 밝거나, 손이 빠르거나, 임원의 말을 잘 듣는 사람에게 첫 스타트를 시키는 경우가 많습니다. 하지만 단순히 그렇게 되어서는 서비스나 소프트웨어의 수명이 줄어들어서, 유지보수 비용의 증가 뿐만 아니라 해당 프로젝트를 대체할 새로운 프로젝트를 해야할 수 있어, 큰 지출로 다시 돌아올 수 있습니다.

그래서?

만약 아키텍트가 시작할 때, 어떠한 철학이나 체계 없이 주먹구구로 프로젝트를 진행하면 어떤 일이 벌어질까요?

  1. 프로젝트에 참여해 있는 사람들이 가이드라인 없이 인프라를 구성해서 전체 구조가 복잡해질 수 있습니다.
  2. 잘못된 설계로 인해 새로운 컴포넌트를 추가할 때, 어느 영역에 추가해야할 지 혼란이 올 수 있습니다.
  3. 무분별하거나 무책임한 gray zone이 생겨나서, 작업자들이 상호 간 업무 파악을 할 수 없을 수 있습니다.
  4. 잘못된 도메인/관심사 분리로 인해 내부 로직이 필요 이상으로 복잡해질 수 있습니다.
  5. 프론트엔드 - 백엔드 간의 API 호출에 대해 중복된 프로세스를 위한 코드가 생성될 수 있습니다.
  6. 잘못된 데이터 모델링으로 인해 무결성과 확장성을 확보하기 어려워 집니다.
  7. 경직된 권한과 보안 정책으로 인해 새로운 컴포넌트를 추가할 때마다 작업이 늘어날 수 있습니다.
  8. 일관되지 않은 로깅과 모니터링 과정으로 인해, 사후 처리에 어려움을 겪을 수 있습니다.
  9. 적절하지 않은 테스트 환경으로 인해 프로젝트의 안정성을 헤칠 수 있습니다.
  10. 필요 이상으로 경직된 운영 환경으로 인해 문제 파악에 필요 이상의 노력과 시간이 투자될 수 있습니다.
  11. 적절하지 않은 기술 도입으로 프로젝트 전체의 한계를 앞당길 수 있습니다.

전부 생각나는 대로 적은 거라 이해가 안되거나, 공감이 안되거나, 할 수 있습니다.

그럼 뭘 하길 원하는데?

모든 것은 트레이드오프입니다.
당연히 지금부터 쓰는 게 무조건 정답도 아니고, 경우에 따라서는 완벽한 오답일 수 있습니다.

사용자 요청과 도메인 분리는 별개의 레이어에서 해주세요.

사용자의 요청은 각 클라이언트에서 한 페이지나 컴포넌트에서 필요한 데이터를 한번에 요청할 것입니다. 그걸 위해 백엔드는 어떻게 구성되어야 적합할까요? 그건 프로젝트마다 다르겠지만 규모가 있는 프로젝트라면, 네임스페이스가 나뉘어지고 각 네임스페이스마다 담당할 부분이 할당될 겁니다. 그 나뉘는 기준이 도메인과 데이터를 중심으로 이루어졌으면 합니다.

요청할 때 같은 페이지 영역, 혹은 컴포넌트 영역에 있기 때문에 해당 하는 데이터의 관리 주체가 주로 사용하는 네임스페이스가 아닌 다른 네임스페이스로 넘어가는 일은 있어서는 안됩니다. 그러면 해당 데이터를 주로 사용하는 네임스페이스는 매번 자기는 쓰지도 않는 다른 네임스페이스에게 데이터 엑세스를 요청해야합니다. 이는 매우 불합리하고 비효율적인 구조입니다.

그러면 어떻게 해야 클라이언트 입장에서 같은 영역에서 쉽게 다룰 수 있으면서, 두 네임스페이스가 상호 간 데이터 관리 주체를 적절히 가져가게 할 수 있을까요? 일반적인 MSA라면 BFF(Backend-For-Front)나 Aggregator 패턴 등을 활용할 수 있을 것입니다. 그러면 같은 API 라우트 밑에서 서로 다른 네임스페이스의 데이터를 충돌 없이 가져와 제공할 수 있습니다.

그리고 무엇보다 아키텍트는 설계할 때, 이러한 충돌이 발생할 것같으면 미리 두 네임스페이스의 담당자들과 이야기하여 적절히 관리 주체를 정해야할 것입니다.

아키텍처의 기본 골격을 우선 만들어 주세요.

도시가 원활히 돌아가려면 상-하수도, 전기, 가스, 도로 같은 기반 시설이 잘 설치되고 동작해야합니다. 버스, 지하철, 기차, 비행기 등의 운송 수단도 마련하고, 도로나 철도 및 철도역, 공항 등을 잘 설치하고 규칙을 제정해서 운영하면 사람과 물류가 막힘 없이 활발히 돌 것이고, 이는 도시의 활력으로 이어질 것입니다. 상-하수도 및 정수처리시설이 잘 발달되고 설치되어 있어야 도시의 기본적인 위생을 지킬 수 있을 것입니다. 전기와 가스가 잘 운반되고 제공되어야 생활 속에서, 산업에서 도시를 움직이게 할 것입니다.

우리는 이 도시의 구조에서 무엇을 느낄 수 있을까요? 저는 아키텍처에 기본적으로 필요한 것들에 대해 우선 확실히 하고 넘어가야, 그 위에서 어떤 컴포넌트가 올라가도 멀쩡히 돌아갈 수 있음을 느껴야 한다고 생각합니다.

당연히 프론트엔드와 백엔드 API 사이나 백엔드 내에서 각 컴포넌트 간에도 주고 받아야할 기본적인 운송 수단, 네트워크 상에서 어떤 통신 프로토콜(TCP, UDP, HTTP/1, HTTP/2, QUIC, HTTP/3, MessageQueue, gRPC 등)로 주고 받을 것인지 정하고, 화물이 되는 데이터를 어떻게 포장(JSON, protobuf, xml, CSV, flatbuf, 등)할 것인지, 그리고 각 데이터는 어떤 값이 필수적으로 포함되어야 하는지 등을 확실히 잡고 넘어가야 차후 각자 추가적인 서비스를 기획 및 개발하면서 중구난방으로 결과물이 튀는 상황을 방지할 수 있습니다.

또한 로그를 처리하는 것은 마치 하수도와 같다고 생각합니다. 모든 컴포넌트에서 로그는 마치 하수처럼 끊임없이 흘러내립니다. 이 하수도 설계 및 구성를 어떻게 하고, 로그 포맷과 수집을 얼마나 잘 잡냐에 따라 각 작업자들이 큰 고민 없이 각 플랫폼에 맞는 로그 라이브러리를 개발하고, 적용할 수 있을 것입니다. 그리고 차후 모니터링 시에 통일된 형식으로 인한 빠른 문제 파악에 기여할 수 있을 것입니다.

만약 아키텍트가 이에 가이드라인을 처리해주지 않는다면, 각 작업자들이 모여서 별도로 시간을 들여서 미팅 후 결정하고, 보통은 각 영역마다 각자에 맞는 데이터/로그 형식을 쓰게 되어, 추후 과도한 파편화로 인한 불편함을 겪게 됩니다.

적절한 기술과 구조를 도입해주세요.

각 컴포넌트에는 할당된 명확한 책임과 역할이 있을 것입니다. 그럼 그것에 부합하는 외부 솔루션이나 기존에 있는 best practice가 존재할 것입니다. 그들이 무엇으로, 어떻게 문제를 해결했었고, 운영하고 있는지 알아보고 힌트를 받아 적절한 기술과 구조를 도입할 수 있을 것입니다. 혹은 아예 새로운 것이라도, 필요하다면 PoC를 통해 동작을 확인하고 도입한 후에, 예상되는 운영 시의 문제에 대해 유연하게 대처하도록 가이드를 남겨야할 것입니다.

이는 공통적으로 작성 언어나 동작하는 플랫폼이 있을 것입니다. 그리고 프론트엔드라면 여러 상태관리 솔루션이나 컴포넌트 구성, 아키텍처 디자인 패턴 등이 있을 것입니다. 마지막으로 백엔드라면 메시지 큐나, 분산 캐시 솔루션, 서비스 디스커버리 등이 있을 것입니다.

이에 대해 저로서는 최대한 최소 비용에 최대 효과를 얻을 수 있는 방법을 고르는 편입니다. 물론 이는 현재 상황과 1차원적인 목적 뿐만 아니라, 추가로 기획이 추가되었을 때 어느정도는 유연하게 대처할 수 있는 정도, 프로젝트가 잘되어 많은 트래픽이나 작업을 처리해야할 때 최소한의 대처만으로 부담할 수 있는 정도가 필요하다 생각합니다.

그렇기에 어느정도의 오버 엔지니어링을 용인되어야 합니다. 지금 당장의 요구 사항과 기획에만 맞추어 엔지니어링을 하는 것은 프로젝트의 구조적, 기술적 한계를 앞당겨 경직되게 만들고, 수명을 단축시킬 수 있습니다.

각자의 바운더리가 되는 부분에 대해 명확히 해주세요.

기본적으로 도메인이든 페이지든 R&R을 잘 나누었다 하더라도, 결국에는 경계에 아슬아슬하게 겹치는 부분이 생길 것입니다. 이 부분에 대해서 리드가 제대로 역할해주지 않는 다면, 해당 부분은 그 누구도 적극적으로 관리하려 하지 않을 것이고, 이내 곪아 누구도 감히 손대지 못하는 부분이 될 것입니다.

이에 대해 리드라면 솔로몬처럼 반토막을 내서라도 각 담당 도메인에 보내줘야 합니다. 대표적인 gray zone으로 MSA에선 aggregator 패턴이나 BFF가 있습니다. 이 영역은 클라이언트가 필요로 하고, 여러 서비스 앱에서 데이터를 제공해야합니다. 누가 주도적으로 비즈니스 로직을 작성할 것인지는 매우 모호해집니다. 기본적으로 정한 아키텍처의 구조가 있다면, 그걸 지키기 위해 이러한 구조를 적용해야한다면, 과감하게 개입해서 정해주었으면 합니다.

원하는 개발 방향성과 방법론을 제시해주세요.

각 작업자는 서로 다른 개발 방식, 테스트 방식, 버저닝 방법, 배포 수단 등을 가지고 있습니다. Git을 다룰 때, 공통적으로 크게 어떤 식으로 브랜치를 나누고 머지를 할 것인지가 있을 수 있습니다. 작업의 시작과 과정, 끝을 어떻게 수행할 것인지를 보여줄 수도 있을 겁니다. 배포에 대해서 스크립트나 별도의 배포를 위한 ant를 사용할 수도 있으며, gitlab runner나 jenkins같은 CI/CD 툴을 이용할 수도 있을 것입니다.

혹은 테스트 방식에 대해서도, 어느정도 고민을 미리 하여 효과적인 테스트 환경을 구성하는 것에 일조할 수 있을 것입니다. 예를 들어, 전체 통합 테스트를 위한 스테이징을 만들더라도, 서로 다른 개발 중인 기능을 테스트 하고 싶다면 어떻게 해야하는 지, 만약 좋은 방법이 있다면 추가적으로 필요한 인프라 요소나 기능은 무엇이 있는 지를 검토 후 적용해주었으면 합니다. 혹은 개발 과정에서의 생산성과 안정성을 확보하기 위한 문화, 코드 리뷰나 버저닝 등에 대해서도 최소한의 가이드라인은 제시하면 좋을 것같습니다.

그렇지 않았을 때, 해당 컴포넌트를 받은 작업자들의 역량에 따라 결과물이 천차만별로 달라지는 결과를 맞이해서, 전체적인 결과물이 조화롭게 구성되지 못하는 상황이 펼쳐질 것입니다. 이상적인 조직 구성에선 문제 없이 돌아갈 것이지만, 일반적으론 그렇게 되지 않을 확률이 높다고 느낍니다. 전반적인 코드 품질에 대해서도 아키텍트는 어느정도 책임을 져야한다 생각합니다.

결론은

아키텍트는 매우 어려운 위치라고 생각됩니다. 하지만 많은 부분에 영향을 주고, 그에 대한 책임을 질 수 있기에, 정말 멋지고 매력적인 직책이라 생각합니다. 언젠가 저도 기회가 된다면, 이러한 아키텍트로서 역할을 할 수 있길 바랍니다.