콘텐츠로 이동

전략적 프론트엔드 설계

Architecture는 어떤 Store가 어떤 State를 관리할지, 또는 어떤 Mapper를 어디에 둘지 결정하는 것보다 더 앞에서 시작됩니다.

오랫동안 영향을 남기는 결정 중 상당수는 코드의 세부 구조를 만들기 전에 이루어집니다.

도메인 경계는 어디에 있어야 할까요? 어떤 부분은 함께 변화해야 하고, 어떤 부분은 가능한 한 독립적으로 유지되는 편이 좋을까요? 어떤 Responsibility를 어느 팀이 담당해야 할까요? Coupling은 어디에서 생기며, 지금은 실용적으로 보이는 결정이 몇 년 뒤에는 어떤 비용으로 돌아올까요?

이런 질문을 다루는 영역을 여기서는 전략적 프론트엔드 설계라고 부릅니다.

이 표현은 Domain-Driven Design의 Strategic Design에서 아이디어를 가져왔습니다.

DDD의 전략적 설계에서는 Entity, Value Object, Repository 같은 구체적인 구현 요소보다 더 큰 구조를 먼저 봅니다. Domain Boundary, Responsibility, Context 사이의 관계, 그리고 어떤 부분을 하나의 문제 영역으로 함께 다루어야 하는지를 고민합니다.

Frontend에서도 비슷한 질문이 필요합니다.

하나의 큰 Frontend를 계속 하나의 Application으로 유지하는 것이 좋을까요? 아니면 특정 부분은 독립적으로 개발할 수 있도록 분리하는 편이 나을까요? 하나의 Domain Area는 어디에서 끝나고 다른 영역은 어디에서 시작할까요?

Shared Service도 항상 좋은 답은 아닙니다. 여러 팀이 정말 같은 Capability를 공유하고 있는지, 아니면 Ownership이 명확하지 않아 Responsibility가 한곳에 모이고 있는지 살펴볼 필요가 있습니다.

두 팀이 같은 Model을 사용하는 것도 상황에 따라 합리적일 수 있습니다. 다만 그 Model의 변경이 서로의 개발 속도까지 묶기 시작한다면, Coupling의 비용도 함께 생각해야 합니다.

이런 결정들은 개별 Component나 Store보다 한 단계 위에서 이루어집니다.

그리고 이후의 구현이 움직일 수 있는 범위를 결정합니다.

그래서 전략적 프론트엔드 설계에서는 코드 내부의 세부 구조를 결정하기 전에 시스템 자체를 어떻게 나눌 것인가를 먼저 다룹니다.

Boundary는 기술 문제만은 아닙니다

섹션 제목: “Boundary는 기술 문제만은 아닙니다”

Architecture Problem은 처음에는 기술적인 문제처럼 보이는 경우가 많습니다.

Module이 계속 커지고, 여러 팀이 같은 파일을 자주 수정하고, Shared Model에 예외가 늘어나며, Deployment Coordination이 점점 어려워질 수 있습니다. Shared Package가 어느 순간 Application의 너무 많은 부분을 알고 있을 수도 있습니다.

하지만 이런 현상의 원인이 항상 Code Structure에만 있는 것은 아닙니다.

Domain Boundary가 충분히 명확하지 않을 수도 있습니다. 두 팀이 원래 분리할 수 있었던 Responsibility를 계속 공유하고 있을 수도 있습니다. 조직 구조를 그대로 Software Structure에 반영했지만, 실제 Domain은 다른 방식으로 나뉘어 있을 수도 있습니다.

초기에는 편리했던 Integration Model이 시스템과 조직이 커지면서 점점 더 많은 Coordination을 요구할 수도 있습니다.

그래서 전략적인 Architecture는 Code만 보고 판단하기 어렵습니다.

Domain, Technology, Organization, Cost를 함께 봐야 합니다.

기술적으로 아주 깔끔한 Boundary라도 Team Collaboration에는 불편할 수 있습니다. Team Autonomy를 높이는 선택이 Infrastructure Cost를 증가시킬 수도 있고, Independent Deployment가 새로운 Integration Problem을 만들 수도 있습니다.

따라서 전략적 설계의 목적은 완벽한 구조를 찾는 것이라기보다, 하나의 구조적 선택이 가져올 결과를 가능한 한 일찍 이해하는 것에 가깝습니다.

같은 Boundary를 바라보는 두 가지 관점

섹션 제목: “같은 Boundary를 바라보는 두 가지 관점”

이 영역에서 다루는 두 시리즈는 Boundary라는 같은 문제를 서로 다른 방향에서 바라봅니다.

현재 두 시리즈의 상세 콘텐츠는 영어로 제공됩니다.

영어 버전의 Big Ball of Mud 시리즈는 Boundary가 시간이 지나면서 어떻게 약해질 수 있는지를 살펴봅니다.

Big Ball of Mud는 보통 누군가가 처음부터 복잡한 시스템을 만들기로 결정해서 생기지 않습니다.

Responsibility가 조금씩 공유되고, Boundary가 서서히 흐려지고, 임시 Shortcut이 예상보다 오래 남으며, 시스템의 Knowledge가 점점 더 많은 부분에 퍼집니다.

각각의 결정은 당시 상황에서는 충분히 이해할 수 있었을지도 모릅니다.

하지만 그런 선택들이 오랫동안 쌓이면, 작은 변경에도 더 많은 Coordination이 필요해지는 구조가 만들어질 수 있습니다.

이 시리즈는 그래서 Code만 보지 않습니다. 이런 구조가 만들어지는 조직적, 경제적 조건과, 시간이 지난 뒤 다시 Boundary를 만들기 어려운 이유도 함께 다룹니다.

영어 버전의 Microfrontends 시리즈는 반대 방향에서 Boundary를 바라봅니다.

여기서는 분리가 의도된 선택입니다.

팀이 더 독립적으로 일하고, Application의 여러 부분을 분리해서 개발하며, 필요한 경우 독립적으로 Deployment하는 것이 목표가 될 수 있습니다.

하지만 시스템을 여러 부분으로 나눈다고 해서 Boundary 문제가 자동으로 해결되는 것은 아닙니다.

오히려 어떤 Boundary를 선택했는지가 더 중요해집니다.

적절한 Microfrontend Boundary는 실제 Team Autonomy를 만들 수 있습니다. 반대로 잘 맞지 않는 Boundary는 기존 Coupling을 여러 Application, Repository, Deployment로 나누어 놓는 결과가 될 수도 있습니다.

그래서 중요한 질문은 Microfrontends가 좋은지 나쁜지가 아닙니다.

더 유용한 질문은 다음과 같습니다.

어떤 Boundary를 보호하려고 하는가, 그리고 그 독립성을 위해 어떤 비용을 받아들일 수 있는가?

Strategy가 Tactics를 위한 공간을 만듭니다

섹션 제목: “Strategy가 Tactics를 위한 공간을 만듭니다”

전략적 설계와 전술적 설계는 서로 경쟁하는 접근법이 아닙니다.

서로 다른 수준의 질문을 다룹니다.

전략적 프론트엔드 설계는 Frontend Landscape의 큰 Boundary, Responsibility, 그리고 각 영역 사이의 관계를 살펴봅니다.

전술적 프론트엔드 설계는 그보다 한 단계 아래로 내려갑니다. Boundary가 의미 있다고 판단되면, 이제 그 Boundary와 Responsibility를 실제 Code에 어떻게 표현할지 고민할 수 있습니다.

Strategic Design은 다음을 묻습니다.

Boundary는 어디에 있어야 하는가?

Tactical Design은 이어서 묻습니다.

그 Boundary는 Code 안에서 어떤 형태를 가져야 하는가?

두 질문은 함께 필요합니다.

아무리 잘 설계된 Store라도 적절하지 않은 System Boundary를 해결할 수는 없습니다. 반대로 좋은 Domain Boundary가 있어도 그 안에서 Responsibility가 다시 섞이면 유지보수는 어려워질 수 있습니다.

Architecture를 위한 Architecture는 필요하지 않습니다

섹션 제목: “Architecture를 위한 Architecture는 필요하지 않습니다”

전략적 Architecture라는 표현은 필요 이상으로 거창하게 들릴 수도 있습니다.

하지만 모든 Frontend에 여러 Deployment, Platform Team, 복잡한 Integration Model이 필요한 것은 아닙니다.

상황에 따라서는 Boundary가 잘 정의된 Monolith가 가장 적절한 선택일 수 있습니다.

중요한 것은 Architecture의 양이 아닙니다.

더 중요한 것은 어떤 부분이 함께 변화해야 하는지, 어떤 부분은 독립적으로 유지되어야 하는지, 그리고 장기적으로 어느 정도의 Coupling을 감당할 수 있는지 의식적으로 결정하는 것입니다.

이 영역에서는 그런 결정을 다룹니다.

큰 Diagram을 만드는 것이 목적은 아닙니다.

처음 그 결정을 구현했던 Code보다 더 오래 영향을 남길 수 있는 선택들을 이해하는 것이 목적입니다.