Juicycrunch Carrot Blog
목록으로
Engineering

The Second-System Effect

첫 번째 시스템의 성공이 두 번째 시스템의 복잡성을 키우는 현상인 두 번째 시스템 효과(The Second-System Effect)에 대해 정리합니다.

두 번째 시스템 효과

The general tendency is to over-design the second system, using all the ideas and frills that were cautiously sidetracked on the first one.

Fred Brooks — The Mythical Man-Month (1975)

두 번째 시스템 효과는 시스템 설계 과정에서 관찰되는 하나의 패턴을 설명합니다. 그리고 거창한 재설계에 대해 엔지니어들이 경계해야 한다는 점을 다시한번 상기시켜 줍니다.

Fred Brooks

설계자는 처음 만드는 작품은 간결하고 깔끔한 경향이 있다. 그리고 두 번째 시스템은 설계자가 만들 수 있는 가장 위험한 시스템이다.

프레드 브룩스는 IBM 에서 근무하며 이러한 현상들을 관찰하였고 The Mythical Man-Month (1975) 에세이에 Second-System Syndrome 으로 표현하였습니다.

과잉 설계 (Over Engineering)

할 수 있다 나라면!

실무를 뛰며 개발자들은 이미 몸으로 체득하였습니다. 그렇지만 머리로 알고 스스로 경계한다해도 과잉 설계의 유혹에서 완전히 자유로울 수는 없습니다.

첫 번째 시스템을 개발할 때는 시간과 자원의 제약으로 많은 것을 포기해야 합니다. 당장 필요한 기능에 집중하고 복잡한 문제는 단순한 방법으로 해결하며 언젠가 필요할 것이라고 생각한 기능은 뒤로 미룹니다. 하지만 첫 번째 시스템을 성공적으로 완성하고 나면 상황이 달라집니다.

새로운 기술을 익히게되고 기존 설계의 한계도 경험했습니다. 처음부터 다시 만든다면 더 잘할 수 있을 것이라는 자신감도 생깁니다. 문제는 이때부터 시작됩니다.

구현할 수 있다는 사실이 반드시 구현해야 한다는 의미는 아닙니다.

첫 번째 시스템에서 포기했던 기능을 모두 추가하고 기존 설계의 한계를 극복하기 위한 추상화를 도입하며 미래의 요구사항까지 대비하려 합니다. 각각의 결정은 합리적으로 보일 수 있지만 이러한 결정이 누적되면 시스템은 필요 이상으로 복잡해집니다.

이것이 두 번째 시스템 효과가 경계하는 지점입니다.

미래의 요구사항을 모두 예측할 수는 없다

존재하지않거나 도입계획이없는 요구사항을 해결하기위해 과하게 설계를 하는 경우가 있습니다. 이 뜻은 절대 ‘유연성을 포기하라’ 라는 뜻이 아닙니다.

추측에 기반한 유연성에 비용을 들이지 마라

라는 뜻입니다.

저도 프로젝트를 진행하면 과도한 걱정에 추상화하고 모듈로 만들고 지금 해야할 작업이 아닌것에 비용을 들인적이 있었습니다. 과거 선배는 그런 저에게 Rule of Three 를 강조했었습니다.

같은 패턴이 세 번 나오면 그때 추상화한다.

첫 번째는 구현, 두 번째는 중복을 감수, 세 번째에 추상화

여담으로 꼭 추상화가 아니고 기능추가에 관해서도 도움이 많이됩니다.

DB 로 조회해서 하는 업무가 있다고 가정하고 개발자가 쿼리를 통해 직접 조회하고 있을 때, 이 과정이 3번 이상 반복된다면 유저에게도 필요한 정보일지도 모릅니다. 그리고 그걸 볼 수 있는 페이지가 필요하다는 신호가 될수도 있습니다.

새로운 기술을 적극적으로 도입하는 설계

대부분의 개발자는 실무를 뛰고 경험이 쌓이면 새로운 기술을 사용하고싶은 욕구가 생깁니다.

새로운 시스템을 설계하면서 이벤트 기반 아키텍처, 메시지 브로커, 분산 시스템, 복잡한 캐싱 전략 등을 도입하고 싶어질 수 있습니다. 이러한 기술은 적절한 상황에서 시스템을 개선합니다. 그러나 기술을 도입하는 목적이 해결해야 할 문제보다 기술 자체에 대한 관심에 가까워지면 문제가 발생합니다.

반드시 trade off 를 고려해야합니다. 은탄환은 없기 때문입니다.

단일 애플리케이션으로 충분한 서비스에 MSA 를 도입하면 서비스 간 통신, 장애 전파, 분산 추적, 데이터 일관성 등 새로운 문제를 해결해야 합니다. 기존에는 존재하지 않았던 운영 부담이 추가되는 것입니다.

기술의 복잡도를 감당할 수 있다는 것과 그 복잡도를 감당할 가치가 있다는 것은 다릅니다.

언제 조심해야할까?

저의 짧은 경험이지만 개인적으론 이 순간이 두 번쨰 시스템 효과 를 다시한번 생각해볼 필요가 있는 순간이라고 생각합니다.

경험이 자신감으로 바뀌는 순간

시스템을 완성하고 나면 시야가 넓어집니다. 아는것이 더 많아지고 코드가 부끄러워지는 순간도 있습니다. 그리고 그랜드 오픈을 무사히 넘기고 나면 어디선가 자신감이 생깁니다.

분명히 경험은 더 나은 판단을 가능하게 합니다. 문제는 그 자신감이 다음 시스템의 모든 문제를 미리 해결할 수 있다는 확신이 아니란걸 인지해야합니다.

완벽 주의

세상에는 자신의 코드가 부끄러운 결과물이 되기를 바라는 개발자는 없습니다. 누구나 조금 더 읽기 쉽고, 일관성 있으며, 유연한 코드를 작성하고 싶어 합니다.

하지만 이러한 개선을 끊임없이 추구하다 보면 코드는 점점 늘어나고 복잡도는 높아집니다. 개발에 필요한 시간과 비용 역시 함께 증가합니다. 마치 90:90 법칙처럼 말입니다.

시간, 비용, 인력과 같은 자원은 무한하지 않습니다. 프로젝트란 주어진 자원 안에서 최선의 결과물을 만들어 가는 과정입니다. 그리고 그 과정에서 어떤 선택을 했고 무엇을 포기해야 했는지는 실제로 프로젝트에 참여했던 사람들만 온전히 이해할 수 있습니다.

경험이 있는 개발자라면 코드만으로 그 결과물을 쉽게 판단할 수 없다는 사실을 알고 있습니다. 지금은 아쉬워 보이는 코드에도 당시에는 나름의 이유와 제약이 있었을 수 있기 때문입니다.

그러니 과거에 작성한 코드가 마음에 들지 않더라도 지나치게 자책할 필요는 없습니다. 지금의 기준으로 과거의 코드를 평가하기보다 당시의 상황에서 왜 그런 선택을 했는지 돌아보고 다음에는 더 나은 선택을 할 수 있다면 그것으로 충분합니다.

무엇보다 중요한 것은 코드의 완벽함 자체가 아닙니다. 요구사항을 충족하고 의도한 대로 동작하며 예상치 못한 상황에서도 적절하게 대응할 수 있는가. 그리고 주어진 자원 안에서 그 목적을 얼마나 잘 달성했는가입니다.

마치며

‘두 번째 시스템 효과’ 는 개발자가 경험이 쌓이는 과정에서 발생할 수 있는 문제를 이야기합니다.

경험은 더 나은 시스템을 설계하는데 분명히 도움을 줍니다. 이전에 경험했던 문제를 이해하고, 더 적절한 기술을 선택하며, 구조를 개선할 수 있기 때문입니다. 반대로 경험이 많아질수록 더 많은 문제를 예상하게 되고 그 문제들을 모두 해결하려는 유혹도 커집니다.

그 결과 아직 발생하지 않은 문제를 해결하기 위한 코드가 늘어나고, 시스템은 실제 요구사항보다 더 복잡해질 수 있습니다. 좋은 설계는 가능한 모든 문제를 미리 해결하는 설계가 아닙니다. 어떤 문제를 지금 해결해야 하고, 어떤 문제는 아직 해결하지 않아도 되는지 판단하는 설계입니다.

새로운 시스템을 설계할 때는 이전보다 더 많은 것을 할 수 있다는 사실만큼이나 이전과 마찬가지로 무엇을 하지 않을 것인지도 중요합니다.

두 번째 시스템 효과는 실무에서 꽤 자주 마주하는 현상이라고 생각합니다. 굳이 개념으로 설명하지 않더라도 많은 개발자가 실무를 경험하며 체득하고 각자의 방식으로 경계하고 있을 것입니다. 저 역시 막연하게 인식하고 있던 생각을 하나의 개념으로 정리해 보고 싶었습니다.