-
[MSA] 믿는 enum에 발등 찍힌다.Architecture 2020. 4. 7. 22:41
Enum is evil.
Enum은 자바에서 상수(이하 코드)를 선언하는 아주 중요하고 전통있는 방법입니다. 저도 이 부분에 대해서는 이견이 없습니다. 하지만 MSA(마이크로 서비스 아키텍처) 환경의 시스템들 사이에서 Enum이 얼마나 큰 걸림돌로 작용하는지 이야기 하고자 합니다. 자바 베이스 시스템을 기준으로 기술하고 있습니다만, 상수에 대한 이슈는 언어와 프레임워크를 초월하는 것으로 이해하시면 좋겠습니다.
REST API에서 코드를 전달할때.
자바 개발자들은 상수를 만들때 Enum 타입으로 만들어야 한다는 강박같은 것이 있습니다. 그런데 이런 강박이 시스템간 통신하는 API의 프로토콜에도 그대로 반영되어 나중에 회사의 개발 속도에 발목을 잡는 일이 발생합니다. MSA에서 API를 손쉽게 연동하기 위해 Producer가 제공하는 클라이언트 라이브러리에 Enum 클래스를 포함하여 Client Module(이하 어댑터)을 Consumer에게 제공합니다. API 개수가 늘어나면서 시스템간 디펜던시가 기하급수적으로 복잡해지고, 단순한 상수 코드 하나 추가/삭제가 굉장히 오랜 기간을 요구하게 됩니다. 이제부터 고통이 시작됩니다. 이런 현상이 발생하면 회사의 Product의 속도는 기하급수적으로 느려지고, 결국은 'MSA를 왜하는가?'라는 의구심이 들기도 합니다.
비즈니스의 요구사항 또는 시스템의 개편등으로 인해 Enum에 상수를 추가하거나 변경해야하는 상황이 발생하면 어댑터를 사용하는 모든 Consumer가 어댑터를 교체(Version Up)할때까지 기다려야 하고, 조직이 다른 경우 우선순위를 협의하는 길고 어려운 난항의 연속입니다. 하지만 이럴다 할지라도 안할 수는 없는 상황이니 참으로 이러지도 저러지도 못하는 상황입니다.
Rest API와 Mobile App과 코드로 연동할때
지금은 모바일 앱(이하 앱)과 연관을 안지을 수 없겠죠. Server-to-Server와 같은 이유입니다. 특히 앱의 경우 배포에 대한 제약이 있기 때문에 더욱더 코드 추가에 따른 유연성과 확장성을 갖춰야 합니다. 특히나 고객이 무엇인가를 주문시 선택하는 항목들은 서비스의 니즈에 따라 추가되고 삭제되는 경우가 빈번할 수 있습니다. 쿠팡이나 티몬에서 주문할때 선택하는 배송방법같은 것들이 좋은 예라고 생각합니다. 배송방법을 추가하기 위해서 다음 배포까지 기다려야 하고, 서비스들은 고객의 편의를 하루 빨리 제공하지 못하고 기다려야 하는 아쉬움을 갖게 됩니다. 다른 예로 설명하자면, 쿠팡의 쿠팡맨과 플렉스 배송, 배민의 라이더등 고객에게 서비스를 제공하기 위해 업무용 앱을 운영하는 회사들은 더욱더 공감할 것이라고 생각합니다. 몰론 불특정 다수의 고객에게 제공하는 앱보다는 배포 제약이 덜하지만 없는 것은 아니기 때문에 Enum으로 인한 비즈니스 속도와 타이밍에 걸림돌로 작용하는 것은 피할 수 없습니다.
각 시스템에서 Enum으로 관리되고 있는 상수들
API가 아니더라도 Enum은 시스템의 확장성에도 걸림돌로 작용합니다. 코드 레벨에서 상수를 사용할때 API 보다는 임팩트가 적지만 시스템의 발전 속도에 장애물로 작용합니다. 두가지 사례로 예를 들수 있습니다. 첫째는 Enum이 'Magic Number'로 작용하는 경우입니다. 엔지니어들은 코드내에 하드코딩이라고 일컫는 Magic Number를 사용하는 것이 코드 퀄리티를 떨어뜨리는 것이라는 것은 모두 다 알고 있는 사실입니다. 비즈니스의 니즈에 의해 상수를 추가하거나 변경하는 것은 그나마 수월합니다. 하지만 삭제하는 것은 이야기가 달라집니다. Enum이 사용된 모든 로직을 따라다니면서 사이드 임팩트를 조사해야하는 길고 무료한 작업을 해줘야 합니다. 왜 Magic Number가 되는 것에 대한 개념적인 이해를 위해 샘플 코드를 추가합니다. 아래와 같은 설계는 가급적 피해야 겠습니다.
// Magic Number if (myJobTitle == "ENGINEER") { return "개발자"; } // Magic Number as Enum if (myJobTitle == JobTitle.ENGINEER) { return "개발자" }
둘째는 자바 계열은 DB를 사용기 위해서 JPA를 많이 사용합니다. JPA에서 Entity에 스키마 설정시 상수 값은 Enum을 사용합니다. 스키마에 Enum을 사용할때 정말 신중에 신중을 해야하는 이유는 상수를 정하고 데이터를 입력하는 순간 그 코드는 천지개벽이 일어나더라도 유지해야 합니다. 왜냐하면 DB 테이블에 문자열 타입으로 상수가 입력되더라도 'String to Enum Routine'을 거칠 것이고 Enum을 찾을 수 없을 경우 NotFoundException이 발생하기 때문입니다. 몇년동안 데이터를 저장하고 있는 DB의 특성상 상수하나 수정/삭제를 하려고 하면 기존 데이터 값을 신규 상수로 대체하는 마이그레이션 작업을 해야 합니다. 데이터의 양이 적다면 쿼리로 한꺼번에 할 수 있겠지만 몇억, 몇십업하는 데이터를 핸들링해야 한다면 이 또한 엔지니어들의 골치를 아프게 하는 요인이 될 것입니다.
Solutions
Constants Data Management System
그럼 어떻게 해야 할까요? 여러가지 해법이 있을 수 있겠지만, 제가 말씀드리고 싶은 것은 상수를 관리하는 시스템을 구축하는 것입니다. 시스템의 규모에 따라서 Scope을 얼마나 크게 잡아야 할지 결정해야 하지만 Enum을 통해 정적으로 관리하는 것보다 시스템으로 동적으로 관리해서 코드가 아닌 데이터 레벨에서 관리하면 상수에 대한 의존도를 낮출 수 있을 것입니다. 이는 각각의 시스템간 상수에 대한 재해석 또는 오인하는 것을 방지하는 Dictionary 역할도 하기 때문에 조직적으로 Domain Context를 동일하게 유지할 수 있는 부가적인 효과도 갖고 있습니다.
Constants Common Library
굳이 상수를 관리하는 시스템을 만들 필요는 없을 수도 있습니다. 그때는 조금 큰 규모 조직단위로 Common Layer를 만들어서 상수를 라이브러리로 관리하는 것입니다. 라이브러리를 어떻게 잘 관리하느냐에 대한 숙제가 남아있긴 합니다만, 하나의 시스템을 구축하는 것이 부담된다면 쉽고 빠르게 적용할 수 있는 방법입니다.
Conclusion
Enum은 상수를 관리할 수 있는 좋은 방법인 것은 사실입니다. 적어도 모노리스 시스템에서는 효과가 충분히 입증이 됐습니다. 하지만 MSA로 넘어오면서 상수로 인해 발생하는 문제는 조직의 전체 생산성을 현저히 떨어뜨리는 요인으로 작용할 수 있습니다. 이렇게 많은 시스템이 공존하고 상호 협력하는 구조에서 우리가 당연하다고 생각하는 것들이 문제가 되는 상황들이 많이 있습니다. 환경이 바뀌면 우리가 당연하다고 생각하는 것들이 저해 요인이 될 수 있으니, 언제나 유연하고 열린 사고를 통해 조직의 속도를 방해하는 장애물을 찾도록 해야 겠습니다.
우리가 당연하다고 생각하는 것들을 의심해서 맹점을 찾는 통찰력을 가져야 합니다.
Thanks
Hans
'Architecture' 카테고리의 다른 글
Monolith를 MSA로 전환을 계획할때 필요한 세가지 (0) 2020.11.21 비즈니스 프로세스를 그리자. — BPMN 2.0 (2) 2020.10.24 슬기롭게 로그(Log)를 쌓는 법 (0) 2020.07.22 AWS에서 효율적인 비용으로 시스템을 운영하기 (0) 2020.06.27 [MSA] 딜레마 - 처음부터 분리해? 말어? (0) 2020.04.01