loading...

클라우드 네이티브 여정의 시작 – 애플리케이션 현대화

클라우드 네이티브 여정의 시작 – 애플리케이션 현대화

레거시 애플리케이션(이하 앱)은 다양한 기술 부채(Technical Debt)를 가지고 있습니다. 새로운 기능을 릴리즈 하기 어려우며 운영비용을 증가시킵니다. 또한 비즈니스의 요구에 의한 혁신적인 기능들을 제때 반영하기 어렵습니다. 기능 간 강하게 결합된 아키텍처를 가진 모놀리틱(Monolithic) 앱은 앱 자체가 복잡하고 변경의 여파를 측정하기 어렵습니다. 새로운 기능을 추가하거나 변경하려면 해당 기능을 검증하는 것 외에도 결합된 다른 기능까지 검증해야 하므로 시간이 많이 소요됩니다. 이는 결국 앱의 릴리즈 사이클을 길어지게 합니다. 이러한 이유로 레거시 모놀리틱 앱은 타임 투 마켓을 요구하는 비즈니스 민첩성 대응을 어렵게 만듭니다.

레거시 인프라 측면에서도 끊임없는 도전이 있습니다. 하드웨어와 운영 시스템이 노회됨에 따라 운영비용은 계속 증가하며 효율성, 신뢰성이 저하됩니다. 신규 시스템으로 교체를 지속적으로 수행해야 하므로 자본투자 역시 계속 증가합니다. 내, 외부 다양한 기관이 요구하는 보안이나 감사, 컴플라이언스에 대한 반영도 쉽지 않습니다.

이러한 도전에 효과적으로 대응하기 위해 다양한 조직에서 클라우드를 도입하는 수요가 지속되고 있습니다. 더 나아가 선진적인 조직들은 디지털 전환의 핵심 요소로서 클라우드의 이점을 더 적극적으로 활용하는 클라우드 네이티브 환경으로 전환하는 것을 우선순위 앞 단에 두고 있습니다. 클라우드 네이티브 환경으로 가기 위해서는 단순히 물리적으로 클라우드를 도입하는데 그쳐서는 안 됩니다. 클라우드 네이티브에 최적화되도록 조직의 인프라, 앱, 기술 역량을 전반적으로 강화해야 합니다.

하지만 클라우드 네이티브는 한 번의 큰 변경으로 달성하기 어렵습니다. 클라우드 네이티브는 여정으로 접근해야 합니다. 그 여정의 시작은 선택지가 몇 개 있을 수 있지만 가장 큰 효과를 볼 수 있는 분야가 앱 현대화입니다. 따라서 조직이 클라우드 네이티브로 가기 위해서는 앱 현대화를 클라우드 네이티브 여정의 시작으로 두는 전략을 가져가야 합니다.

앱 현대화란 무엇일까요?

앱 현대화란 기존 앱을 클라우드 네이티브 환경에서 가장 잘 구동될 수 있게 개선하는 활동을 의미합니다. 단순 레거시 인프라 환경에서 구동되는 앱을 클라우드에 포팅 하는 것이 아니라, 클라우드가 주는 이점을 최대한 살리기 위해 앱을 개선하는 것입니다. 앱 현대화는 앱의 아키텍처, 코드, 데이터, 보안, 개발 및 운영 방식을 개선하는 것을 포괄적으로 포함합니다. 이를 통해 앱의 효율성, 신뢰성, 보안성, 확장성, 유지보수성, 개발 및 운영 효율성을 향상시킬 수 있으며 비즈니스와 외부 환경 대응에 더욱 유연하고 민첩하게 대응할 수 있습니다.

특히 디지털 전환의 핵심 요소 기술인 AI/ML, 빅데이터, 블록체인, IoT, 메타버스 등의 기술 수준이 빠르게 성숙됨에 따라 앱이 이러한 기술들을 쉽게 활용하고 보조를 맞출 수 있도록 준비되어야 합니다.
이런 측면에서 앱 현대화는 기업이나 조직에서 피할 수 없는 활동이 되고 있으며, 앱 현대화를 위한 전략과 기술을 갖추지 않은 조직은 시장에서 뒤쳐지고 있습니다.

앱 현대화의 장점

앱 현대화의 장점을 하나씩 살펴보겠습니다.

1. 비즈니스 민첩성 대응
앱 현대화의 가장 큰 장점은 비즈니스의 요구사항과 환경에 빠르게 대응할 수 있다는 것입니다. 필요한 요소기술을 빠르게 적용하고 고객이 필요로 하는 기능이나 서비스를 빠르게 제공할 수 있습니다. 불특정 다수의 고객의 요구사항을 정의하기 힘들 때 고객의 빠른 피드백을 기반으로 앱을 개선해 나가는 A/B 테스팅이나 가설 기반 개발 방법도 쉽게 적용할 수 있게 됩니다.

2. 신뢰성 및 안정성
고가용성이나 재해복구 등의 기능을 쉽게 적용할 수 있습니다. 이러한 기능들은 앱의 신뢰성과 안정성을 높여줍니다. 클라우드 네이티브 방식의 접근이므로 클라우드가 제공하는 보안, 모니터링, 감사, 백업 등의 기능을 쉽게 적용할 수 있습니다.

3. 개발 운영의 효율화
개발과 운영을 위한 효율성이 높아집니다. 현대화된 앱은 응집력이 높으면서 연결이 느슨하게 되어있습니다. 한 곳에서의 기능 변경이나 버그 수정이 다른 곳에 영향을 미치지 않습니다. 데브옵스의 실천법을 활용하여 개발 운영 프로세스를 자동화하고 간결화 하기 때문에 개발과 운영의 공수가 절감되고 더욱 혁신을 위해 노력할 수 있습니다.

앱 현대화의 단계

그러나 앱을 현대화하는 것은 쉬운 일은 아닙니다. 현재 가지고 있는 조직의 앱을 평가하고 현대화를 위한 전략을 세우고 단계적으로 전환해 나가야 합니다. 어떠한 레거시 앱들은 완전히 현대화를 할 수 없는 경우도 있습니다. 조직의 앱을 현대화하기 위해서는 다음과 같은 단계로 접근하는 것이 좋습니다.

1. 계획
첫 번째로 앱을 현대화하기 위한 목적과 전략을 세워야 합니다. 앱 현대화를 위한 전략은 조직의 비즈니스 전략에 맞춰 세워야 합니다. 기존 레거시 앱과 환경에 대해 변화의 준비 정도를 평가하고 조사해야 합니다.

2. 구현
구현 단계에서는 앱 현대화를 위한 역량을 키우고 기술 집합을 선택하여 현대화된 앱이 구동될 환경을 준비해야 합니다. 차세대 급의 Big Bang식 접근이 아니라 반복적이고 점진적인 방법을 선택할 수 있습니다. 이러한 반복적인 접근은 조직에게 앱 현대화의 범위와 전략을 필요에 따라 수정해 나갈 수 있게 하는 유연성을 제공하게 됩니다.

3. 운영
앱 현대화는 일회성으로 끝나는 프로세스가 아닙니다. 조직이 클라우드 우선 접근을 선택하면 클라우드 플랫폼 서비스 및 도구를 사용하여 앱의 보안을 유지하며 전반적인 통제와 지속적으로 최적화할 수 있는 환경을 제공합니다. 조직이 이러한 역량을 충분히 준비하기 어려울 수 있으므로 클라우드 우선 접근 전략이 매우 도움이 될 수 있습니다.

앱 현대화의 전략

이제 앱의 현대화를 위한 핵심 전략을 알아보겠습니다. 아래 소개되는 전략은 클라우드 전환 전략을 포함하고 있습니다. 현대화 전략은 조직의 앱 현대화의 목적과 얼마만큼이나 코드를 수정해야 하는지에 대한 의사결정에 따라 각기 다를 수 있습니다. 앱 현대화 전략은 계획단계에서 충분히 고려해서 정의되어야 하며 실제 구현 단계에서 효과를 발휘하게 됩니다. 이 때 앱 현대화 전략도 유연하게 수정하거나 개선할 수 있어야 합니다. 앱 현대화의 전략을 하나씩 알아보도록 하겠습니다.

1. 리호스트(Rehost)
리호스트는 말 그대로 호스팅 되는 환경을 변경한다는 것입니다. 쉽게 말해 기존 구동되는 환경에서 빼내어 새로운 환경인 클라우드 환경에 옮긴다는 것입니다. "리프트 앤 시프트" 방식으로 알려져 있으며 이 전략은 실질적으로 코드 변경이 없이 실행될 수 있으므로 빠르게 구현할 수 있습니다. 기존 사용하던 환경 그대로 옮기는 것이므로 리호스트 전략은 앱을 향상시키는 데는 거의 도움이 되지 않습니다. 리호스트 전략은 클라우드 전환 측면에서 하나의 전략으로 이야기할 수 있지만 앱 현대화에 포함시키지 않는 것이 일반적입니다. 왜냐하면 앱은 기존 환경 대비 거의 수정되지 않았기 때문입니다. 다만 클라우드 환경에 포팅 함으로써 클라우드 환경의 장점- 운영 위임을 통한 효율화, 관리 환경 자동화, 스케일링 아웃의 유연성, AI/ML, IoT, 데이터 분석 등의 클라우드 서비스와 손쉬운 연동 등 -을 활용할 수 있게 됩니다.

2. 리플랫폼(Replatform)
리플랫폼은 앱을 새로운 플랫폼으로 옮기는 것입니다. 쉽게 말해 기존에 사용하던 플랫폼에서 새로운 플랫폼으로 옮기는 것입니다. 리플랫폼은 리호스트와 마찬가지로 코드 변경이 거의 없지만 새로운 플랫폼에 맞춰 일부 코드가 수정됩니다. 예를 들면 로깅이나 모니터링을 위한 설정이나 PaaS 데이터베이스의 사용으로 커넥션 스트링이나 복원성(Resiliency) 코드 일부입니다. 최소한의 변경으로 직접 운영해야 했던 데이터베이스 같은 앱의 종속적인 환경을 클라우드 벤더의 관리 범위로 넘길 수 있습니다. 이 전략은 의견이 나뉘긴 하지만 앱 자체의 현대화를 위해 수정하는 전략이 아니므로 역시 앱 현대화가 아닌 클라우드 전환 전략으로 봐야 합니다.

3. 리팩토링(Refactoring)
리패키징(Repackaging)이라고 부르기도 하는데 그 이유는 앱을 컨테이너화 하기 때문입니다. 컨테이너화는 이 리팩토링 전략의 핵심입니다. 리팩토링은 앱을 부분적으로 수정해야 하는데 앱의 아키텍처 변경이 아니라 컨테이너 환경에 맞게 수정되는 것입니다. 기존 앱이 로그를 파일에 저장하였다고 하면 컨테이너 환경에서는 파일 저장 없이 스트림으로 출력되어야 하며, 앱이 특정상태(상태)를 저장하는 로직이 있다고 하면 상태를 없애거나 외부 리소스로 분리하는 코드 수정이 필요합니다. 앱이 모놀리틱 방식일지라도 컨테이너화를 위한 리팩토링은 수행할 수 있으며 컨테이너가 가진 일부 역량들, 즉 스케일 아웃, 자동 복구 등의 장점을 활용할 수 있습니다. 앱 현대화의 전략은 이 리팩토링 전략부터 포함시켜야 합니다. 리팩토링을 통해 현대화된 앱의 역량은 앞서 소개된 리호스트, 리플랫폼을 거친 앱과 비교해서 월등한 효과를 볼 수 있기 때문입니다. 마이크로서비스 아키텍처의 전단계인 미니서비스 아키텍처가 이 리팩토링 단계에서 활용될 수 있습니다. 리팩토링 단계를 거친 현대화된 앱은 이후 소개될 리아키텍트나 리빌드 등과 같은 더 고수준의 현대화로 갈 수 있는 발판이 됩니다.

4. 리아키텍트(Rearchitect)
리아키텍트는 앱 현대화를 위한 가장 어려운 전략 중에 하나입니다. 기존 앱의 아키텍처를 완전히 변경해야 하는 것입니다. 오랫동안 앱이 운영, 유지 보수되었다면 앱의 아키텍처 변경이 특히 어렵습니다. 모든 기능이 통합되어 있는 모놀리틱 앱은 변경과 유지보수가 어렵습니다. 왜냐하면 모놀리스 앱은 수많은 기능들이 서로 강하게 결합되어 있어 변경할 때 마다 수많은 부작용이 발생하기 때문입니다. 비즈니스 요구나 환경 변화에 필요한 기능들을 적용하거나 수정하는 것이 어렵기 때문에 유지보수 비용은 증가하며 앱의 민첩성은 저하됩니다. 리아키텍트는 이런 모놀리틱 앱을 마이크로서비스로 분리하는 것을 핵심으로 합니다. 서비스 별 퍼시스턴스 분리와 도메인 간 REST로 연계된 API방식으로 아키텍처를 구성함으로써 마이크로서비스로 재설계할 수 있습니다. 기본 원칙은 업무 도메인에 따라 서비스를 분리하고 서비스간 결합은 최소화하고 필요한 통신은 REST API로 수행합니다. 단위 서비스 내의 모든 기능은 타 서비스의 영향을 주거나 받지 않으면서 응집도는 높게 설계해야 합니다. 단위 서비스는 서비스만의 퍼시스턴스를 가지고 있으며 퍼시스턴스는 다른 서비스에서 직접 참조하지 않습니다. 이렇게 설계하면 서비스 간 변경이 서로 영향을 미치지 않습니다. 도메인 주도 설계(Domain Driven Design)는 마이크로서비스 아키텍처를 위한 전통적이고 훌륭한 방법론입니다. 그러나 신규 작성하는 앱에 적용하는 것은 적합하지만 레거시 앱에 적용하기가 매우 어렵습니다. [그림 1]의 Strangler 패턴의 레거시 앱 전환과정처럼 레거시 앱의 단위 서비스나 기능을 마이크로서비스로 하나씩 분리하여 기존 레거시 앱과 REST로 연계시키고 계속 반복적으로 현대화 된 앱으로 분리해 나가는 방법이 활용되기도 합니다.

stronger facade
  • -> 레거시 앱(monolith)
  • -> 현대화 앱(microservice)
  • 초기 전환
stronger facade
  • -> 레거시 앱(monolith)
  • -> 현대화 앱(microservice)
  • -> 현대화 앱(microservice)
  • -> 현대화 앱(microservice)
  • -> 현대화 앱(microservice)
  • 전환 가속화
  • -> 현대화 앱(microservice)
  • -> 현대화 앱(microservice)
  • -> 현대화 앱(microservice)
  • -> 현대화 앱(microservice)
  • -> 현대화 앱(microservice)
  • -> 현대화 앱(microservice)
  • 전환 완료
[그림 1] Strangler 패턴

5. 리빌드(Rebuild)
리빌드는 앱을 처음부터 클라우드의 역량과 솔루션을 활용하여 재작성하는 것입니다. 레거시 앱이 리펙토링이나 리아키텍트를 하기에 너무 낡은 앱이라면 아예 새로운 기술을 이용하여 새로 개발하는 것이 보다 나은 선택지가 될 수 있습니다. 새로 작성할 때에는 도메인 주도 설계 기법을 이용하여 마이크로서비스 아키텍처를 적용하는 것이 좋습니다. 레거시 앱은 이미 도메인이 상당부분 정의되어 있기 때문에 도메인 주도 설계 기법을 적용하기에 적합합니다. 설계 기법에 따라 적절히 분리된 도메인과 경계 정의, 도메인에서 단위 트랜잭션으로 처리되고 전용으로 관리할 수 있는 Aggregate 도출, 그리고 이를 구현하는 구현체를 적용한다면 리빌드는 레거시 앱을 가장 우수하게 현대화할 수 있는 방법이 됩니다.

만약 기능이 복잡하지 않고 단순 정보저장을 위한 퍼시스턴스와 워크플로우만 있는 경우라면 빠른 전환을 위해 Low-code 나 No-code 플랫폼을 활용할 수 있습니다.

  • application service
  • domain service ->
  • aggregate(root entity, entity,value object)
  • domain service ->
  • aggregate ->
  • domain event
  • client ->
  • API gateway ->
microservice
  • service ->
  • service
  • service ⁢
  • service ⁢ -
  • DevOps(user)
  • (user)
  • management / orchestration
[그림 2] 도메인 주도 설계와 마이크로서비스

6. 리플레이스(Replace)
리플레이스는 아예 레거시 앱을 버리고 SaaS로 제공하는 서비스를 도입하는 것입니다. 이 경우 레거시 앱을 더이상 유지보수 하지 않고 SaaS로 제공하는 서비스를 사용하게 됩니다. SaaS로 제공하는 서비스는 레거시 앱을 대체할 수 있는 기능을 제공하고 있어야 합니다. SaaS는 조직별 요구사항을 위한 커스터마이즈가 제한적이기 때문에 신중히 검토되어야 합니다. 그러나 일단 도입이 결정되면 IT 역량을 거의 사용하지 않고 서비스를 사용할 수 있습니다. 리플레이스는 앱 현대화로 볼 수 있을까요? 당연히 앱 현대화로 볼 수 없습니다. 레거시 앱을 현대화한다기 보다 레거시 앱을 버리고 새로운 패키지 소프트웨어를 클라우드에서 제공받아 사용하는 것이기 때문입니다.

위 소개된 6가지 전략을 넓은 관점에서 앱 현대화로 보는 의견도 있으므로 모두 앱 현대화 전략으로 소개하였지만, 엄밀히 말하면 앱을 직접 개선한다는 측면에서 앱 현대화에 속하는 것은 리팩토링, 리아키텍트, 리빌드 이 3가지만 해당된다고 보는 것이 일리가 있습니다. 나머지 전략은 앱 현대화 전략이라고 보기 보다는 클라우드 채택 전략으로 보는게 맞습니다. 클라우드 채택 전략으로도 관리/운영의 편의나 탄력적 자원 사용, 자동 스케일링 활용 등 일정 수준의 혜택을 볼 수 있으므로 조직의 앱 수준과 현대화 역량을 고려하여 우선순위를 정의하고 현대화 전략을 정렬하는 것이 필요합니다.

앱 현대화 구현을 위한 기본 - '12요소 앱 원칙"의 적용'

앱 현대화를 위해 12요소 앱 원칙을 적용하는 것은 앱 현대화의 기본입니다. 12요소 앱 원칙을 적용하는 것은 최소 리팩토링 수준의 전략을 수행한다는 것이고 이는 앱의 배포효율성이나 유지보수성, 관리 용이성 등이 비약적으로 상승할 것으로 기대되기 때문입니다. 12요소 앱 원칙은 앱을 클라우드 네이티브 앱으로 재 탄생시키는 실천법이며, 이미 많은 조직에서 검증되었습니다. 12요소 앱 원칙은 다음과 같은 12가지 원칙(혹은 실천법)으로 구성되어 있습니다.

1. 코드베이스
코드베이스는 모든 환경 정보는 코드로 구성되어 있고 코드 리파지토리에서 관리되어야 함을 의미합니다. 앱의 배포환경은 흔히 개발, 테스트, 스테이지, 운영 환경으로 분리되는데 환경 별 구성 정보는 각각 코드로 작성되며 코드 변경에 대한 관리가 버전 컨트롤 도구에 의해 이루어져야 합니다. 이 코드베이스의 원칙은 다양한 환경에 앱을 배포할 때 Immutable Infrastructure를 구성할 수 있도록 도와줍니다. Immutable Infrastructure란 코드에 의해서만 환경이 구성되고 변경을 하려면 기존 환경은 버리고 변경된 코드에 의해 새로 생성을 하는 것을 의미합니다.

코드베이스
  • ⁢ / > ->
  • terraform, bicep, heim chart, kustomize file, KBS manifests
  • 개발계
  • 테스트계
  • 운영계
[그림 3] 코드베이스

2. 의존성
의존성은 앱을 실행하는데 필요한 모든 종속성을 명시적으로 선언해야 함을 의미합니다. 선언되는 대상은 라이브러리, 도구, 프레임워크, 퍼시스턴스/메시징 클라이언트 등입니다. 의존성 역시 코드로 명시되어야 하며 코드 리파지토리에서 관리되어야 합니다. 자바의 Gradle이나 Maven과 같은 도구로 외부 라이브러리를 선언적으로 관리하고 리파지토리를 통해 관리하는 것이 대표적인 예입니다.

선언파일
  • plugins, spring library, logging, JSON handing, marshalling, ...
  • local cache
  • maven : -> 배포 -> 리소스 준비 -> 컴파일 -> 테스트 ->패키지
외부저장소
  • in-house repository
  • maven central
  • 3rd party
[그림 4] 의존성 관리도구 Maven 예시

3. 구성정보(Configuration)
구성정보는 앱이 필요한 구성정보를 어떻게 관리할 것인지에 대한 실천법입니다. 소스 코드에 어떠한 형태로도 하드코딩 되어서는 안 됩니다. 개발, 테스트, 스테이지, 운영 등 다양한 배포환경에 맞는 구성정보는 별도의 코드로 작성되고 실제 앱이 배포될 때 구성정보가 주입되어 배포환경에 전달됩니다. 앱의 스케일링이나 장애복구 등의 이유로 앱이 재 시작되는 경우에도 구성정보는 변경되지 않아야 합니다. 이러한 구성정보는 코드베이스에 의해 관리되어야 합니다. 앱이 수많은 인스턴스로 스케일 아웃 되어있는 경우에도 구성정보는 배포할 때나 런타임 구동 시 실시간으로 주입되어야 합니다.

코드베이스
  • ⁢ / >
  • Terraform, Bicep, Helm Chart, Kustomize file, KBS Manifests
구성정보 주입
  • 개발계 구성정보
  • 테스트계 구성정보
  • 운영계 구성정보
  • DB접속정보, JVM options, HPA, logging store, diag/monitoring
  • 개발계
  • 테스트계
  • 운영계
[그림 5] 구성정보 예시

4. 리소스 로서의 서비스(Backing Service)
앱은 상태를 가지고 있으면 안 됩니다. 상태를 가져야 할 때에는 명시적으로 선언된 외부의 리소스를 첨부하는 식으로 상태를 관리해야 합니다. 예를 들어 앱이 특정 블랍에 어떠한 이미지 정보를 써야 할 때, 그 블랍 정보는 특정 프로토콜을 사용하여 (예: HTTPS) 외부 리소스로서 통신하는 구성으로 적용되어야 합니다. 앱이 로컬 디스크에 데이터베이스를 사용하였다고 하면 이 데이터베이스는 외부 리소스로 분리, 앱과 명시적인 방식으로 선언, 통신하는 구조로 변경되어야 합니다.

  • application / 내부 상태저장 제거
  • home/admin/database
  • 외부 리소스 URL로 참조 ->
  • -> MYSQL
  • -> Redis
  • -> Rabbit MQ
  • -> Biob Storage
[그림 6] 외부 리소스 참조

5. 빌드, 릴리즈, 실행
이 실천법은 앱 배포가 빌드, 릴리즈, 실행 단계와 완전히 분리되어야 함을 의미합니다. 앱을 빌드할 때에는 특정 배포환경에 완전히 독립적이어야 합니다. 앱이 빌드 되면 해당 환경을 위한 구성정보가 주입되어 특정 배포환경에 릴리즈 됩니다.

코드베이스
  • ⁢ / >
아티팩트
  • package 혹은 이미지
  • 빌드 ->
구성정보 주입
  • 개발계 구성정보
  • 테스트계 구성정보
  • 운영계 구성정보
  • 릴리즈 ->
  • 개발계
  • 테스트계
  • 운영계
  • 실행
[그림 7] 빌드, 릴리즈, 실행

6. 프로세스
마이크로서비스는 언제나 상태를 갖지 않고 오직 요청을 받은 트랜잭션을 처리하는데 필요한 정보만 가지고 있어야 합니다. 마이크로서비스는 인스턴스가 종료되더라도 데이터가 손실되면 안 됩니다. 언제든지 종료되어도 새 인스턴스로 교체될 수 있어야 하는 것입니다. 데이터가 손실된다는 것은 마이크로서비스가 상태를 갖고 있다는 것이고 이를 피하는 설계를 해야 합니다. 상태의 저장이 필요하면 위에서 설명한 “리소스로서 서비스”에 저장해야 합니다. 쉽게 말하면 상태를 mySQL이나 Redis와 같은 외부 리소스에 저장하는 것입니다.

  • application / 내부 상태저장 제거
  • session flag
  • home/admin/database
  • 외부에 상태저장 ->
  • -> 외부 리소스
[그림 8] 프로세스

7. 포트 바인딩
마이크로서비스가 제공하는 포트와 외부에 노출하는 포트를 명시적으로 연결하는 것을 포트 바인딩이라고 합니다. 마이크로서비스는 필요한 모든 라이브러리를 보유하며 스스로 구동될 수 있도록 패키징 되어야 합니다. Tomcat이나 WebLogic과 같은 외부의 WAS(Web Application Service) 컨테이너가 없이도 스스로 구동되어야 합니다. 이 때 포트 바인딩으로 정의된 HTTP 포트로 외부에 공개되어야 하며 내, 외부 포트는 변경에 유연해야 합니다.

8. 동시성
여기서 말하는 동시성은 멀티스레드나 동시프로그래밍을 이야기하는 것이 아닙니다. 마이크로서비스의 인스턴스가 수평적으로 동시에 서비스를 제공하는 능력을 의미합니다. 서비스의 성능을 확장하기 위해 CPU나 메모리를 업그레이드할 수 있으나 이러한 방법은 성능 확장에 한계를 가져옵니다. 따라서 적은 CPU와 메모리를 가진 인스턴스를 수평적으로 여러 개 배치하여 성능을 확장하는 것이 요구됩니다. 이 원칙은 클라우드 네이티브 앱을 실현시키는데 가장 중요한 원칙으로 작동합니다.

스케일 아웃
  • 2core/2G, 2core/2G, 2core/2G, 2core/2G, 2core/2G
스케일 업
  • 2core/2G -> 10core/10G
[그림 9] 동시성

9. 폐기성
마이크로서비스의 폐기성은 언제나 “폐기 가능한” 상태로 설계되어야 함을 의미합니다. 즉, 언제나 수요에 맞춰 시작되거나 폐기되어야 함을 의미하며 탄력적인 성능 대응에 필수적인 요소가 됩니다. 마이크로서비스는 구동되는데 매우 짧은 시간만 소요되어야 하는데 컨테이너 환경이라면 일반적으로 수 초 내에 구동이 완료되어야 합니다. 리소스 모듈 등 다양한 모듈을 메모리에 적재한다 해도 수십 초 내에 구동되어야 합니다. 또한 특정 인스턴스가 장애나 스케일링 인으로 인해 다운된다고 해도 다른 인스턴스에 영향을 끼쳐서는 안됩니다.

10. 개발/운영 일치성
개발계, 테스트계, 운영계 등의 다양한 앱 구동환경이 존재할 때 이 환경은 최대한 일치성을 보유하고 있어야 합니다. 즉, 환경 별 구성정보는 별개의 설정으로 정의되나 다른 요소들 - 앱, 네트워크 환경, 앱이 구동되는 컨테이너 환경 - 은 모두 환경이 일치되어야 합니다. 지속적 배포 환경을 위해서는 이 일치성이 매우 중요한데, 코드가 Commit 되는 순간 단위테스트가 수행되고 개발, 테스트계에 배포되고 통합테스트나 인수테스트가 자동으로 수행되어 운영계로 배포될 때까지 복잡한 과정에서의 오류나 불일치성을 피하려면 이 원칙은 반드시 구현되어야 하는 것입니다. 개발계에서는 문제가 없었고 테스트계에서 테스트가 완전히 수행되었어도 운영계에서 오류가 발생하는 사례가 아직도 흔하게 발생합니다. 배포 시 발생하는 환경 불일치를 줄이기 위해 개발과 운영 환경을 최대한 일치하게 구성하고 단일 코드 베이스의 앱에 환경 별 구성정보를 주입하는 방식으로 배포 작업을 구성해야 합니다.

11. 로그
로그는 항상 스트림으로 출력되어야 합니다. 이 스트림으로 출력된 것을 Log Stash나 다른 외부 로그 수집 도구로 중앙 집중된 수집 환경을 구성해야 합니다. 마이크로서비스는 로그가 어떻게 어디로 수집되는지 고려하지 않고 오직 스트림 출력만을 고려하면 됩니다.

  • STDOUT
  • log 수집/분석 -> 시각화, 분산Log 추적
[그림 10] 스트림 로그 및 처리 예시

12. 관리프로세스
개발자나 운영자는 데이터 이관이나 변환, 디버깅을 위한 툴 사용 등의 관리적 일을 수행합니다. 이 때, 해당 인스턴스로 직접 들어가서 임시로 수행하는 것이 아니라 코드 저장소에서 코드로 관리되고 유지되는 스크립트만 수행해야 합니다. 마이크로서비스 실행 시 필요한 관리 작업 유형이 사전에 정의되어야 하고 이를 통해서만 관리 작업을 수행해야 하는데, 사전에 모든 관리 작업이 도출되지 않아 임시 작업이 발생한다고 하면 그 임시 작업을 새로운 작업 유형에 포함시켜 코드 저장소에서 관리되도록 해야 합니다.

위에서 설명한 12개의 모든 요소는 중장기적으로 앱 현대화를 위해 모두 반영이 되어야 합니다. 하지만 당장의 조직이 보유한 리소스나 시간적 한계로 인해 단계적으로 적용이 필요하다고 하면 우선순위와 난이도를 정의할 수 있습니다. (일부 성격이 유사한 원칙은 통합)

관리프로세스
원칙 우선순위 난이도 도구
코드베이스 컨테이너 환경은 모두 lac로 되어있으므로 구성난이도가 “하” VM환경에서는 별도의 IaC구성을 해야 하므로 “중” Kubernetes Manifests, Charts, Ansible, Chef …
의존성 하 - 현대적 빌드 툴은 대다수가 명시적 의존성 사용 Maven, Gradle, Ivy…
구성정보
빌드/릴리즈/실행
하 - 프레임워크나 클라우드 벤더 등에서 다양한 도구 제공. 배포 파이프라인에서 빌드된 앱과 구성정보과 결합되어 배포될 수 있도록 구성 Spring Config, Azure Key Vault, Hashicorp Vaults, K8S Configmap, Secret …
리소스로서의
서비스/프로세스/동시성/폐기성
중 - 앱의 상태저장을 외부 리소스로 변경하고 자체적인 상태 저장소를 가지지 않게 변경필요 N/A
포트바인딩 하 - 대다수 구동환경에서 선언만으로 사용가능 N/A
개발/운영 패리티 상 - 각 환경이 IaC로 구성되어 최대한 유사한 환경으로 구성하고 수작업의 변경이나 작업을 극소화해야 함 Kubernetes Manifests, Charts, Ansible, Chef, Terraform …
로그 하 - 파일에 기록하던 로그를 간단한 설정변경으로 스트림으로 변환가능 Logback, ELK, Loki, Application Insight, Sleuth/Zipkin …
관리프로세스 상 - 필요한 운영 수작업을 정의하고 스크립트로 작성한 후 코드로 관리. 사전에 정의하기 어렵고 운영상 Ad-hoc작업이 많이 발생한다면 정형화 어려움 Bash, Powershell …

앱 개발 현대화

앱 현대화는 레거시 앱 자체에 대한 현대화를 다루고 있으나 이것만으로 고도의 비즈니스 민첩성과 효과적인 운영/유지보수성을 달성할 수는 없습니다. 앱 현대화는 앱을 개발하는 방식, 개발하는 방법론, 문화를 현대화하는 활동과 함께 진행되어야 합니다. 조직은 중장기적인 관점에서 개발 방법론 현대화를 위한 전략을 세워야 합니다. 앱 개발 현대화는 Developer Velocity로도 불립니다. 앱 개발 현대화는 개발자가 새로운 기능을 구현하고 출시하는 속도를 높일 수 있기 때문입니다. 앱 개발 현대화는 개발팀이 사용하는 툴, 프로세스의 현대화하는 것을 포함합니다. 비즈니스의 고성과를 위해 개발 프로세스의 혁신도 가속화되어야 하기 때문에 조직은 앱 개발 자체가 조직의 핵심 역량이 되어야 함을 강조해야 합니다. 맥킨지 앤 컴퍼니의 "Driving business outcomes through Developer Velocity 2020" 보고서에 의하면 비즈니스 성과를 위한 가장 중요한 동인은 최고의 개발자 도구라고 설파하고 있습니다. 우수하고 강력한 개발자 도구를 활용하는 조직에서는 개발 혁신성 측면에서 65%가 더 우수하고, 개발자 만족도나 우수 개발자들의 유지 비율이 47% 더 높다고 밝히고 있습니다. 이 개발 혁신성이 결국 조직의 매출에도 4~5배나 성장시키는 동인이 되고 있다고 말합니다. 이만큼 최고수준의 개발 방법과 도구의 도입은 비즈니스 성과에도 직결되고 있음을 알 수 있습니다. 마이크로소프트에서 제시하는 개발도구와 플랫폼의 모범사례를 가지고 예로 들어 보겠습니다. 개발자는 Ready-made 클라우드 개발환경인 GitHub Codespaces에서 개발과 테스트를 수행합니다. VS Code로 코드를 작성하며 GitHub Copilot을 통해 AI와 페어프로그래밍을 수행합니다. 코드를 GitHub에 커밋하여 Pull Request(PR)를 통해 동료들과 코드를 리뷰합니다. PR 시 Continuous Integration(CI)을 통해 단위 및 통합테스트, 정적 분석 - 코드, 보안, 의존성 분석 - 이 수행됩니다. PR이 일단 승인되면 CI는 앱을 패키징하여 Azure Container Registry(ACR)에 배포합니다. ACR은 패키징된 이미지를 다시 한번 보안 취약점 스캐닝을 실시합니다. 패키징이 완료되면 Continuous Deployment(CD)를 통해 배포 환경에 맞는 구성정보를 주입해 배포작업이 수행됩니다. 배포 시 조직이 정의한 각종 보안, 권한 정책 등이 자동으로 반영되며 Azure Security Center를 통해 각종 보안위협과 통제 상황을 실시간으로 모니터링하게 됩니다. Azure Security Center는 AI/ML기술을 통해 지능화된 보안 위협을 능동적으로 탐지하고 사전에 방지해 줍니다. 앱 현대화를 추진하는 조직은 개발부터 운영까지 End to End의 현대적이고 통합적인 도구와 플랫폼을 활용할 수 있습니다.

Develop apps securely with a unified solution from Microsoft
  • Dev
  • VSCode Dev / Codespaces
  • GitHub Repo
  • GitHub Acbons
  • GitHub Advanced Security(code scanning, secret scanning, dependency scanning)
  • Azure container registry
  • Azure
  • SecOps
  • Azure AD
  • Aco config
  • Azure monitor
  • secure ARM / secure Azure policy / Azure key value
  • Azure security center(Azure secure score, Azure depenser, WAF/ DOos, Azure firewall)
  • serwall
[그림 11] 생산성을 혁신하는 개발도구와 플랫폼 예시 – GitHub, VS Code, Azure

현대화된 개발 도구와 플랫폼은 개발 프로세스 혁신과 더불어 활용될 때 효과를 극대화할 수 있습니다. 개발 프로세스 혁신은 데브옵스와 애자일의 도입으로 실천할 수 있는데 이와 관련된 내용은 필자의 기존 블로그를 참고할 수 있습니다.

맺음말

이상으로 앱 현대화를 위한 개념과 적용 전략, 12 요소 앱 원칙, 개발 방법론 등을 살펴보았습니다. 레거시 앱을 조직이 원하는 수준의 민첩성을 가진 앱으로 현대화 하는 것은 쉬운 일은 아닙니다. 하지만 조직의 비즈니스 성과나 생존을 위해 더 이상 미루거나 피할 수 없습니다. 차세대 같은 전면 재개발이라는 거대한 접근 방식보다 앱 현대화를 위한 목표와 전략을 세우고 우선순위에 따라 작게 시작할 수 있습니다. 앞서 소개된 Strangler 패턴은 좋은 예시입니다. 다양한 조직에서 이미 작게 시작하여 단계적으로 앱을 현대화하는 경험을 축적하고 있습니다. 조직의 앱과 개발/운영 역량, 비즈니스 목표와 정렬을 평가하여 단계적으로 시작할 우선순위를 정하십시오. 그리고 앱 별 적용할 앱 현대화 3대 전략- 리팩토링, 리아키텍트, 리빌드 -을 적용하여 1개의 성공 사례를 만들기 위해 집중하십시오. 1~2개의 사례가 쌓여 지속적으로 문제점과 개선점을 찾아내어 다음 앱의 현대화에 반영한다면 앱 현대화의 수준도 더욱 높아질 것입니다. 마지막에 소개된 개발/운영 방법, 도구의 현대화는 항상 더불어 수행되어야 합니다. 앱 현대화를 통해 더 많은 조직이 더 많은 성과를 이루기를 바랍니다.



References
[1] 앱 현대화, Microsoft: https://azure.microsoft.com/ko-kr/solutions/application-modernization/
[2] 앱 현대화, IBM: https://www.ibm.com/kr-ko/cloud/learn/application-modernization
[3] The Twelve Factor App: https://12factor.net/ko/
[4] 마이크로서비스, Microsoft: https: //azure.microsoft.com/ko-kr/solutions/microservice-applications
[5] 도메인분석을 사용한 마이크로서비스 모델링: https://learn.microsoft.com/ko-kr/azure/architecture/microservices/model/domain-analysis
[6] Spring Microservices in Action, John Carnnell, Packt, 2021
[7] Microservices with Spring Boot and Spring Cloud, Marnus Larson, Packt, 2021
[8] 데브옵스 가속화를 위한 엔지니어링 성공요소는 무엇인가? SDS Insight, 2022




▶   해당 콘텐츠는 저작권법에 의하여 보호받는 저작물로 기고자에게 저작권이 있습니다.
▶   해당 콘텐츠는 사전 동의 없이 2차 가공 및 영리적인 이용을 금하고 있습니다.


이 글이 좋으셨다면 구독&좋아요

여러분의 “구독”과 “좋아요”는
저자에게 큰 힘이 됩니다.

subscribe

구독하기

subscribe

Andrew Min
Andrew Min

SI회사에서 솔루션개발센터, SI, ITO, 데브옵스Lab 등의 부서에서 다양한 개발현장을 체험하였습니다. 이후 IBM Watson(Weather) 글로벌 개발팀에서 세계 10대 트래픽의 초대형 백엔드를 클라우드 네이티브 아키텍처로 개발, 운영하는 리드 소프트웨어 엔지니어 역할을 수행하였습니다. IBM 개발자 컨퍼런스, KT, 국민은행(KB)그룹, 하나은행, 한국 정보과학회, 한국 정보시스템 감사통제협회, 경희대학교 등 다수의 기관에서 클라우드 네이티브와 데브옵스를 주제로 강연하였습니다. 현재는 마이크로소프트에서 어플리케이션 혁신과 인프라 현대화를 위한 클라우드 네이티브 컴퓨팅 아키텍트 역할을 수행하고 있습니다.

공유하기