마이크로서비스

최근에 트위터에서 보내는 시간이 늘어나면서 취업준비를 하는 분들의 고민과 면접 후기, 어떤 질문들을 받았는지에 대한 글들을 볼 기회가 있었습니다. 한가지 놀라웠던 점은 너무나 많은 회사가 구직자에게 마이크로서비스에 대한 이해를 요구하고 있었고, 심지어 신입으로 취업을 준비하는 분들에게도 단골 질문처럼 물어본다는 점이었습니다. 마이크로서비스에 대한 질문이 신입에게 물어보기 적절하지 않다는 제 개인의 의견은 둘째로 하고, 마이크로서비스에 대한 제 생각을 글로 남김으로서 다른 분들에게 참고자료가 될 수 있었으면 하는 바람으로 이 글을 씁니다. 이 글의 내용은 상당부분 개인의 경험과 이해를 바탕으로한 의견으로 틀린 내용이 있을 수 있습니다.

작은 조직의 시작

아주 특이한 경우가 아닌 이상 보통 조직은 작은 규모로 시작합니다. 이 작은 규모의 조직은 빠르게 움직이며 MVP를 만들어 시장에 선보여야 합니다. 이 시점의 조직에게 가장 중요한 것은 고객의 피드백입니다. 하지만 아직 알려지지 않은 작은 규모의 팀이 고객의 피드백을 받기란 쉽지 않습니다. 그러므로 이 작은 팀에게 속도는 더욱 중요한 과제입니다. 제품을 빠르게 시장에 선보일수록 피드백을 받는 속도도 빨라지기 때문입니다. 그렇기에 소프트웨어의 아키텍쳐는 단순할수록 유리합니다. 사실 아주 핵심적인 기능만을 갖춘 MVP에 복잡한 구조가 필요한 경우도 흔치않고 당연하게도 단 하나의 서비스로 구성된 제품으로 고객에게 다가갑니다.

제품의 성장과 조직의 성장

다행스럽게도 고객들의 반응이 좋습니다. 적극적으로 피드백을 주는 고객도 생겼습니다. 이제는 고객의 피드백을 반영하여 기민하게 대응하고 움직일 때입니다. 팀은 고객에게 더 많은 가치를 전달하며 제품 개발의 동력을 얻어야 합니다. 이제 팀은 본격적으로 인력을 채용하고 더 많은 인력을 바탕으로 제품의 개발 속도를 올리고 싶습니다.

기능팀과 피쳐팀

잠깐 다른 얘기를 해보겠습니다. 채용을 통해 조직의 규모가 커졌고 이제 조직의 효율적인 관리를 위해 팀을 어떻게 구성하는지가 중요한 과제로 떠오릅니다. 여러가지 방법이 있을 수 있겠지만 일반적으로 두 가지중 하나의 형태를 보게 됩니다. 기능팀과 피쳐팀입니다.

기능팀

기능팀은 팀을 기능단위로 나누는 방법입니다. 프론트엔드팀, 백엔드팀, 인프라팀 등으로 구성하는것이 그것입니다. 각 팀은 기술적 전문성을 중심으로 구성되어 구성원들끼리 동일한, 혹은 유사한 기술적 배경을 공유합니다. 이 기능팀 조직에서는 하나의 피쳐가 완성되기 위하여 여러 팀의 조율이 필요합니다. 하나의 팀은 한 피쳐의 일부분을 담당하고 이 부분적으로 완료된 작업은 다른 팀으로 넘어갑니다. 다른 팀으로 넘어간 작업은 그 팀에서 피쳐가 완성될 수도, 다시 다른팀으로 넘어갈 수도 있습니다. 대부분의 경우 한번의 조율로 일이 끝나는 경우는 거의 없습니다.

피쳐팀

피쳐팀은 팀을 피쳐 단위로 나누는 방법입니다. 피쳐팀 조직에서 하나의 피쳐는 하나의 팀 안에서 완성됩니다. 각각의 피쳐팀은 하나의 피쳐를 완성하기 위한 모든 인력을 갖추고 있습니다. 프론트엔드 개발자, 백엔드 개발자, 데이터베이스 전문가, 인프라 전문가 등이 한 팀에서 하나의 가치를 위해 협력합니다. 피쳐 개발을 위해 필요한 커뮤니케이션의 범위는 팀 안으로 제한됩니다. Ron Jeffries는 The Nature of Software Development 에서 이 피쳐 중심의 팀이 비록 어렵지만 나아가야 할 방향이라고 이야기합니다.

모노리딕과 피쳐팀

성장한 조직은 드디어 피쳐 중심의 팀을 구성하였습니다. 각각의 팀은 담당하는 피쳐에 집중하여 고객에게 가치를 전달하기 위해 노력합니다. 팀은 여러개로 나누어졌지만 아직 서비스는 하나의 덩어리, 모노리딕입니다. 여러 피쳐팀으로 구성된 하나의 모노리딕 서비스는 이제 기존의 작은 조직에서는 없었던 새로운 문제들을 마주하게 됩니다.

배포의 문제

각각의 팀은 배포의 주기를 독립적으로 결정할 수 없습니다. 아주 이상적인 환경이라면 모든 코드는 main 브랜치에 합쳐지기 전에 충분한 테스트를 거치고 바로 배포될 수 있는 준비상태에 있어야 할 것 같습니다. 하지만 현실에서 그런일은 없습니다. 우리는 이제 배포를 위해 각 팀이 한 자리에 모여 조율 과정을 거쳐야 합니다. 이전 버젼과 비교하여 변경사항이 무엇인지, 다른팀의 변경사항과 충돌은 없는지, 충분한 테스트를 거쳤는지 확인하고 배포를 통해 고객에게 전달됩니다. 피쳐 개발을 한 팀에서 온전히 책임지기 위하여 피쳐 중심의 팀을 구성하였으나 여전히 팀 사이의 조율이 필요합니다. 생각만큼 충분히 빠른 속도로 나아가지 못하는 것 같습니다.

이슈 대응

이슈는 모든 소프트웨어 제품에서 발생합니다. 제아무리 견고한 테스트를 작성하여도, 혹은 고도로 성숙한 QA팀을 보유하고 있더라도 문제는 반드시 발생합니다. 그러므로 우리는 문제에 어떻게 대응할지를 고민해야 합니다. 서비스를 모니터링 하기위한 대시보드를 구성하고 알람을 설정합니다. 서비스에 장애가 발생하였을 때 빠르게 공지를 받을 수 있게 만듭니다.

그럼 이제 다음 질문으로 넘어가게 됩니다. 서비스에 문제가 생기면, 누가 대응을 해야할까요? 우리는 팀을 피쳐 중심으로 구성하였지만 기능들은 하나의 모노리딕 서비스, 일반적으로 하나의 프로세스 안에서 동작합니다. 코드의 어느 부분에서 문제가 발생했던지 상관없이 프로세스가 죽으면 제품의 모든 기능이 중단됩니다. 문제의 원인이 메모리 릭과 같은 복잡한 문제라면 프로세스가 죽는 순간에 마지막으로 남아있는 서비스 로그가 실제 문제와 아무런 관계가 없을 수도 있습니다. 이제 서비스의 장애 대응을 위해서도 모든 팀이 모여 조율의 과정을 거쳐야 합니다. 그리고 이것은 속도를 늦추고, 고객은 불편함을 느낍니다.

다시, 배포의 문제

모든 팀이 모여 머리를 맞대었고 문제의 원인을 찾았습니다. 마지막 배포 이후 리팩토링을 위해 수정했던 코드가 몇가지 예외상황을 제대로 처리하지 못하는 것으로 보입니다. 서비스를 이전 버젼으로 롤백하면 문제는 사라질 것이고 코드에서 문제를 수정할 시간을 벌 수 있을 것 같습니다. 간단히 해결할 수 있는 상황이라 다행이라고 안도합니다.

이 때, 누군가가 롤백은 안된다고 이야기합니다. 이번 버젼에서 배포된 기능중에 중요한 고객 문제를 해결하는 코드가 들어가 있습니다. 우리는 이미 이 사실을 고객에게 알렸고 고객은 크게 만족했습니다. 또 다른 문제가 제기됩니다. 이번 버젼에서 새로운 API가 추가되었고, 이미 그 새로운 API를 사용하는 CLI 툴이 배포되었습니다. 웹서비스와 다르게 CLI는 한번 배포되면 사용자의 환경에 설치된 버젼을 컨트롤 하기가 쉽지 않습니다. 롤백은 최신 버젼의 CLI툴로 업데이트한 고객들의 작업에 오류를 발생시킬 것입니다. 결국은 문제를 수정하고 새로 배포를 해야합니다. 배포는 또다시 각 팀의 조율을 필요로하고, 팀들은 피쳐 개발에 투자하는 시간이 점점 줄어만 갑니다.

팀의 독립성

팀의 구성원들은 점점 지쳐갑니다. 서비스에 장애가 발생하였을 때 문제의 원인이 무엇이든 문제의 영향은 제품 전체에 미치고, 팀의 책임을 벗어난 부분의 코드를 보며 문제를 분석하는데 피로감을 느낍니다. 고객에게 가치를 전달하는 속도는 점점 떨어지고 팀원들은 점점 낮아지는 성과에 스트레스를 받기 시작합니다. 고객들도, 팀원들도 모두 행복하지 못한것 같습니다. 이제 팀원들은 이전의 작은 조직에서 MVP를 개발하던 시절의 빠른 속도를 그리워합니다. 팀이 독립적이길 바랍니다. 단지 피쳐의 개발뿐만 아니라 운영과 배포를 포함한 모든 면에서 독립적이고 빠르게 움직이길 원합니다. 서비스에 장애가 발생하였을 때 문제의 원인을 중심으로 그 영향이 최소화 되길 바랍니다. 팀은 문제를 수정하여 다른 팀과의 조율없이 독립적이고 빠르게 배포하길 원합니다. 팀은 그 팀이 담당하는 피쳐에 한하여 처음부터 끝까지 온전한 책임을 가지기를 원합니다.

마이크로서비스

마이크로서비스 아키텍쳐를 정의하는 명확한 문장은 없는 것 같습니다. 다만 마이크로서비스 아키텍쳐라고 하는 시스템들은 보통 몇가지 공통적인 사항들이 있습니다. 하나의 제품이 여러개의 서비스로 이루어지고, 각각의 서비스는 제품의 서로다른 피쳐를 담당합니다. 그리고 각각의 서비스들은 필요한 경우 정해진 프로토콜을 이용하여 네트워크를 통해 서로 통신합니다. 각각의 서비스는 독립된 인프라를 가지고, 독립된 배포 주기를 가집니다. 하나의 팀은 필요에 의해 (이것이 바람직한지와는 별개로) 두개 이상의 서비스를 가질 수도 있지만, 하나의 서비스를 서로다른 두 팀이 공동으로 소유하지는 않습니다. 이렇게 팀은 빠른 속도를 가능하게 하는 독립성을 확보합니다.

결론

마이크로서비스에 관하여는 정말 많은 말들이 있습니다. 마치 당연히 따라야하는 트렌드인양 이야기되기도 하고, 모노리딕으로 운영되고 있는 몇몇 대규모 서비스들을 예로들며 필요 없는 것이라고 주장하기도 합니다. 저는 마이크로서비스가 은탄환처럼 여겨지는것을 매우 경계하지만 반대로 문제만 일으키는 골치덩어리 취급을 받는거도 옳지는 않다고 생각합니다. 마이크로서비스가 앞서 말한 모든 문제를 극적으로 해결해 주지는 않습니다. 사실 또다른 많은 문제를 일으키기기도 합니다. 다만 저는 이 글에서 한 조직의 소프트웨어 아키텍쳐가 어떻게 점진적으로 마이크로서비스로 변화해 나가는지, 그 변화의 필요와 동력이 무엇인지를 저의 관점에서 풀어보고 싶었습니다.

참고자료

Written on July 24, 2022