안녕하세요
캐치테이블 프로덕트센터 프론트엔드파트 개발자 장현석입니다.
캐치테이블은 B2C와 B2B 모두를 아우르는 외식업 전문 통합 솔루션으로 다양한 서비스와 프로덕트를 구성하고 있는데요. 그중 B2C 서비스 프론트엔드 환경을 개선했던 경험에 대해 나누고, 함께 했던 구성원들의 노력과 기여를 소개하고자 합니다.
이번에는 레거시를 정의하고 개선을 위해 고려해야 할 멘탈 모델을 주로 다루려고 하는데요. 플래닝 단계나 코드 레벨 수정에 대해서는 이후에 풀어보겠습니다.
다음 내용이 궁금하시다면 여기서 확인할 수 있습니다.
유산 (Legacy? Heritage?) 이란 무엇일까요?
우선 레거시에 대해 다루기 전에 레거시를 바라보는 또 다른 시각을 소개하고 싶은데요.
IT에서의 레거시(Legacy)는 대부분 낡은 시스템을 상징하는 부정적인 의미로 표현되는 경우가 대부분입니다. 낡은 기술이나 방법론 등을 생각할 수 있지만 난해한 구조의 Dead Code로 남아 지우고 싶어도 시스템 여기저기에 의존하고 있어, 또 쉽게 제거하거나 개선하기도 어렵습니다.
제대로 이해하지도 못하고 당장 수정하고 그 위에 새로운 기능을 얹어야 하는 상황에 놓이기도 하는데요. 오죽하면 레거시때문에 퇴사하겠다는 개발자들의 사연을 심심치 않게 들을 수 있습니다.
이런 레거시(Legacy)때문에 발생하는 에러, 병목, 장애는 최악의 경우 유저의 사용성을 망치고 비즈니스에 큰 손해를 안겨줄 수 있어 더 이상 개발자만의 문제라고 볼 수 없습니다.
반면 헤리티지(Heritage)는 (역사적으로 가치 있는) 유산을 의미하죠. UNESCO 유산으로 지정하여 인류의 중요한 기록을 보호하고 보존하며 전통적인 문화유산을 계승하고 있습니다.
이렇게 Legacy, Heritage 모두 (과거의) 유산이나 (물려받은) 유산으로 불린다는 것을 알 수 있었는데요. 같은 의미인 듯 보이지만 다양한 시각 차이로 그 해석을 달리할 수 있습니다. (IT 종사자라면 레거시를 재산이나 업적과 같은 유산으로 바라볼 수 없는 것처럼)
정리하자면 같은 유산이지만 앞세대나 부모님이 물려준 사물 혹은 문화, 상속에 의하여 물려받는 재산 등으로 정의할 수 있습니다.
기술 부채
그렇다면 부정적인 레거시가 발생하고 쌓이는 원인은 무엇일까요?
가장 큰 이유로는 기술 부채(Technical Debt)를 예로 들 수 있는데요.
역량, 일정, 상황, 환경 등 다양한 요인으로 기술 부채는 부정적인 레거시를 만들어내는 주요 원인 중 하나입니다.
이런 다양한 원인을 겪게 되면 대부분 목표나 목적 달성을 위해 타협을 반복하며 당장 눈앞의 문제 해결에만 초점을 두고 코드를 작성하게 되는데요.
부적절한 코드가 생산되며 기술 부채가 겹겹이 쌓이게 되고 레거시로 이어질 수밖에 악순환의 고리가 생겨납니다.
하지만 기술 부채를 부정적으로만 생각할 필요는 없습니다.
안타깝게도 우리가 작성하는 신선한 코드 또한 새로운 기술 부채의 시작이기 때문입니다.
미래를 고려하여 작성한 코드 또한 그 즉시 과거의 유물이 되어버립니다. 레거시 해결을 위해 고도화, 시스템 개선 프로젝트를 선보일 수 있겠지만 그 또한 세상 바깥으로 나서는 순간 낯선 이에게는 기술 부채로 느껴질 수 있습니다.
그러니 기술 부채를 마주하며 한탄하고 기술 부채를 생산하며 고통받을 필요는 없습니다. 관점을 달리하여 바라보면 레거시 코드는 활용 대상이며 기술 부채는 대출과 같습니다. 즉 트레이드 오프와 같이 모순된 관계를 발견할 수 있습니다.
미래에 지급해야 할 대가를 미리 지급하는 것으로, 어쩌면 빚을 내어 집을 사는 것과 마찬가지이기 때문입니다.
그때는 맞고 지금은 틀리다
코드의 가치는 서비스의 성장 단계에 따라 크게 달라지기 때문에 같은 코드라도 시기에 따라 비즈니스 임팩트에 차이가 있을 수 있습니다.
가령 프로토타입이나 PMF를 위해 빠른 가설 검증에 몰입해야 할 때도 있겠지만 서비스가 어느 정도 자리를 잡고 나면 빠르게 사업 확장까지 고려하게 될 수 있는거죠.
항상 미래를 염두에 두고 개발하면 좋겠지만 현재의 목표에 최선을 다해야 다음 단계로 넘어갈 수 있음을 명심해야 합니다.
화폐의 가치가 변하듯 어차피 기술과 코드는 계속 변화합니다.
오랜 시간을 들여 작성한 완벽한 코드라 생각했지만 금방 지워져 잊힐 수도 있고 방치되었던 코드의 가치를 뒤늦게 알아차릴 수도 있습니다.
문제 정의 (Problem Definition)
기술 부채나 레거시를 개선할 시간에 새로 만든다며 수많은 개발자가 노력합니다.
최초에 작성했던 코드나 히스토리를 무시하고 v1, v2… 1.0, 2.0 만들어보지만, 더한 문제가 발생하거나 리소스 낭비만 하는 경우가 부지기수입니다.
그렇다면 이런 레거시나 기술 부채를 해결하기 위해 가장 먼저 해야 하는 것은 무엇일까요?
바로 문제 정의입니다. 문제 해결(Problem Solving) 과정에서 문제 정의(Problem Definition)는 그 무엇보다도 중요합니다.
문제정의가 중요한 이유
- 방향성
잘못된 문제 정의는 방향성 자체를 잃게 할 수 있기 때문인데요.
개발자의 리소스는 한정적이기 때문에 잘못된 문제 정의는 결국 리소스 낭비로 이어질 수밖에 없고 스노우 볼 효과로 타 직군에게까지 피해를 줄 수도 있습니다. - 욕망
문제를 진단하기보다는 개발자의 입장만 생각하여 기술적인 문제만 해결하려는 경우가 많은데요. 상대적으로 새롭거나 힙해보이는 기술 도입에 매몰되어 있거나 역량 확장에 대한 욕망을 회사에 실현하기 위해 불필요한 시도를 하는 경우가 있습니다.
또는 성과에 집착하여 문제 정의 자체를 비즈니스 적인 문제 해결보다는 개인적인 욕망에 집중하기도 합니다. - 건너뛰기
문제 정의보다는 이미 정해놓은 답을 먼저 생각해 놓는 경우가 더러 있는데요.
모호하거나 광범위한 문제일수록 시야가 좁아지고 과거 비슷한 케이스의 문제 해결 경험이 있다면 더욱 개인적인 경험에 의존할 가능성이 큽니다. 내가 해봐서 아는데~ 와 같은 말로 의미 있는 논의를 원천 차단하거나 만족하는 대답을 얻을 때까지 끈질기게 반박하고 재질문하며 설득하고 정해진 답을 유도하기도 합니다.
만약 문제를 해결하기 위해 한 시간이 주어진다면, 문제를 정의하는 데 55분을 쓰고, 나머지 5분을 해법을 찾는 데 쓰겠다
- 아인슈타인
천재 과학자 아인슈타인에게도 문제정의는 해결책보다 훨씬 많은 시간을 할애할 정도로 중요한 것이었습니다. 문제해결에만 몰두하기보다는 한 발짝 물러서 올바른 문제를 찾고 정의하는 것에 더욱 집중해야 합니다.
문제 정의 어떻게 해야 할까요?
- 답부터 정해놓고 접근하지 않습니다. 서비스, 프로덕트, 요구사항, 프로세스, 환경 등을 고려하여 문제의 본질을 살펴봐야 논점이 흐려지지 않습니다.
- 문제를 진단하기 위해 다양한 시각을 고려해야 합니다. 누군가에게는 큰 문제이지만 다른 누군가에게는 작은 문제일 수 있기 때문입니다. 표면적인 관점을 넘어 그 이유나 본질을 파악 해봐야 합니다.
- 건강한 의사소통을 지향해야 합니다. 매번 반복되는 논의를 줄이거나 도출된 중간 정의로 더욱 발전된 논의할 수 있어야 합니다.
- 문제 정의 과정은 비선형적입니다. 많은 시간을 투자한다고 해서 완벽한 문제 정의가 나오지 않습니다. 불필요한 리소스 낭비를 경계해야 합니다.
- 추천 프레임워크 — 5 Whys
문제정의 완성도가 높다면 추가적인 우선순위 설정이 필요하지 않을 수 있습니다.
추가적인 우선순위 설정이 필요하다면 아래의 정렬 단계를 마친 후 프로젝트를 실행하며 고려할 수 있습니다.
정렬 (Alignment)
문제를 해결하여 이루고자 하는 목표가 무엇인지 확실하지 않고 모두의 생각이 다르다면 그 결과는 어떻게 될까요?
같은 Output에 다른 Input으로 리소스가 낭비될 수 있습니다. 즉 같은 Output이 나왔다고 생각했지만, 그 Input을 돌이켜보면 가성비 있는 리소스 활용이나 의미적인 성장을 경험하는 있는 집단이 있는 반면 잦은 야근으로 인해 구성원들의 피로도가 누적되거나 건강을 잃는 집단이 있을 수 있습니다.
전쟁에서 어느 편이 스스로를 승자라고 부를지라도 승자는 없고 모두 패배자뿐이다.
- Neville Chamberlain
전쟁에는 승자가 없다는 말이 있듯 원하는 결과를 성취했다고 생각했지만, 오히려 그 과정 속에서 더 많은 것을 잃을 수 있습니다.
그렇다면 더욱 건강한 방법으로 문제를 해결할 수 있는 방법은 무엇일까요?
이해관계자(Stakeholder)를 분석하고 식별하여 주요 목표를 구체화합니다.
- 이해관계자를 누락하는 것은 레거시를 누락하는 것과 같습니다.
- 히스토리, 관심도, 영향도를 핵심적으로 분석하여 이해관계자를 식별합니다.
- 이해관계자가 초기 단계에 투입되어야 브레인스토밍이나 이니셔티브 단계에 그 영향력이 본디 발휘됩니다.
- 영향력이 큰 이해관계자는 까다로울 수 있지만 사전에 문제를 파악하고 해결할 수 있어 후반부에 드는 리소스 낭비를 절약할 수 있습니다.
- 때로는 사내를 넘어 외부의 이해관계자가 있을 수 있습니다.
- 추천 프레임워크 - 이해관계자 매핑, 이해관계자 맵
어떠한 문제를 정의하고 결정하는 데 있어 침묵은 무엇을 의미할까요?
침묵이 누군가에게는 암시적인 동의일 수 있지만 누군가에게는 체념일 수도 있습니다.
문제를 잘 정의하고 해결했다고 생각했지만, 그 과정 때문에 정작 내실을 다지지 못하고 이도 저도 아니게 되는 또 다른 결과가 나올 수 있습니다.
정렬(Align)을 통해 서로의 이해도를 맞춰야 합니다.
- 어떤 문제를 왜? 어떻게? 해결해야 하는지 방향부터 맞추고 시작해야 합니다.
- 확증편향을 경계해야 합니다. 직관과 경험에 의존하면 목적을 위한 근거가 아닌 설득을 위한 근거만 보완하게 될 수 있습니다.
- 좋든 싫든 한번 결정되면 더 이상 문제가 재정의되지 않도록 해야 반복되는 의사소통을 줄일 수 있습니다.
- 건강한 논의를 위해 각자의 의견을 자유롭게 이야기할 수 있는 환경이 조성되어야 합니다.
비즈니스와 기술은 복잡하고 조직이나 특정 집단은 서로 많은 영향을 주고받습니다. 복잡하고 모호한 문제를 잘 해결하기 위해서는 이해관계자를 잘 파악하고 작업 담당자들의 방향을 충분히 정렬해야 합니다.
정리
- 때때로 레거시 코드는 활용 대상이며 기술 부채는 대출과도 같습니다.
- 문제 해결 이전에 문제를 찾고 정의하는 것이 우선입니다. (reference: 5 Whys, SWOT)
- 이해관계자(Stakeholder)를 분석하고 식별하여 주요 목표를 구체화합니다. (reference: 이해관계자 매핑, 이해관계자 맵)
- 정렬(Align)을 통해 서로의 이해도를 맞춰야 합니다.
- 레거시 코드를 개선하고 싶은데 시작조차 어렵다면 이미 정의된 프레임워크를 참고해도 좋습니다. (reference: MoSCoW, RICE, ICE, Kano Model, 아이젠하워 매트릭스, 맥킨지 문제해결 프로세스)