MS-SQL Select random rows from Table

머신러닝 혹은 딥 러닝 학습을 하기 위해서는 우선 학습할 데이터를 탐색해 보아야 한다. 만약, 많은 양의 Row 데이터를 가지고 있는 SQL Table을 가지고 해야 한다면 일부 표본만 추출해서 테스트를 해보는 것이 필요하다.

이런 경우 테이블에서 랜덤으로 데이터를 추출할 때 다음 Query를 사용하면, 간단하게 일정 비율로 랜덤한 데이터를 추출해 낼 수 있다.

select top 10 percent * from [Table Name] order by newid()

Jupyterhub on Azure Kubernetes Service

데이터 과학을 수행할때 주로 사용되는 언어로는 Python과 R이 있다. 그리고 이 2가지 언어를 지원하는 IDE 환경도 많이 나와 있는데, 그 중 협업 환경에서 많이 선호되는 Jupyterhub 사용에 대해서 알아보겠다.

Jupyterhub은 Project Jupyter라는 비영리 단체에서 개발한 오픈소스 프로젝트다. BSD라이선스를 따르고 있어서 누구나 100% 무료로 사용할 수 있다.

Jupyterhub는 특정 사용자 그룹별로 Jupyter Notebook(이하 Notebook)이라는 가상 개발 환경을 제공한다. 데이터 과학을 수행하는 사용자는 Notebook이라는 가상 개발 환경안에서 업무를 수행하면 된다. 즉, Jupyterhub는 여러 Notebook들을 공유하는 서버인 것이다. 때문에 사용자는 공유 서버를 통해서 자신이 원하는 Notebook 가상 환경 및 리소스를 제공받을 수 있기 때문에 설치 및 유지 관리 작업에 부담을주지 않는다. 또한 특정 사용자 혹은 그룹별로 별도의 가상환경을 구성할 수 있기 때문에 시스템 관리가 용이하다. 

Jupyterhub는 2가지 배포본을 제공되고 있는데 첫 번째는 가상머신 환경에 설치하는 배포본이고 두 번째는 Serverless 환경인 Kubernetes에 설치하는 배포본이다.

클라우드 상에서 운용하기에는 Scale Set을 자유롭게 확장 및 유지관리 할 수 있는 Kubernetes(Serverless framework)환경이 좋기 때문에 가상머신 설치방법은 건너띄고 Jupyterhub를 Kubernetes에 설치 및 구성하는 방법알 알아 보겠다.

참고로, 여기에서 사용된 Kubernetes는 Azure에서 제공하는 AKS(Azure Kubernetes Service)를 이용하였다.

Jupyterhub를 Azure Kubernetes에 설치하기

먼저, Jupyterhub를 설치할 AKS 클러스터에 대한 크리덴셜을 가져오고 최근 환경으로 설정한다.

RESOURCENAME = 'Jupyter'
CLUSTERNAME = 'Jupyterhub'

az aks get-credentials --resource-group=$RESOURCENAME --name=$CLUSTERNAME
kubectl config set-cluster $ClusterName

Jupyterhub를 바로 설치하기 전 jupyterhub를 환경을 구성할 내용을 준비해야 한다.

Jupyterhub 사전 준비작업

Kubernetes는 Serverless 환경이기 때문에 작업한 파일을 영구적으로 보존할 스토리지 볼륨이 필요하다. 다음과 같이 Storage Class를 만들어 준다.

vim storageclass.yaml

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: azurefile
provisioner: kubernetes.io/azure-file
mountOptions:
  - dir_mode=0777
  - file_mode=0777
  - uid=1000
  - gid=1000
  - mfsymlinks
  - nobrl
  - cache=none
parameters:
  skuName: Standard_LRS

kubectl apply -f storageclass.yaml

잘 만들어 졌는지 확인한다.

kubectl get storageclass

다음으로 jupyterhub에 접근할 Client들이 사용할 인증 보안 토큰을 다음과 같이 32byte 임의의 16진 문자열로 생성한다.

openssl rand -hex 32
36806100da02acb12199b94067a55c1231172123b05f061a428777eb65b238fd

위에서 준비한 환경설정 정보들을 가지고 다음과 같이 jupyter 환경을 구성한다. StorageClass, 초기 관리자 계정 정보, 인증토큰을 다음과 같이 넣어준다.

vim config.yaml

singleuser:
  extraEnv:
    EDITOR: "vim"
  storage:
    dynamic:
      storageClass: azurefile
auth:
  admin:
    users:
      - administrator
proxy:
  secretToken: "36806100da02acb12199b94067a55c1231172123b05f061a428777eb65b238fd"

마지막으로, Jupyterhub 배포본을 제공 받기 위한 helm repository를 설정해 준다.

helm repo list
helm repo add jupyterhub https://jupyterhub.github.io/helm-chart/
helm repo add stable https://kubernetes-charts.storage.googleapis.com
helm repo update

이제, 준비를 다했으니 설치해 보자.

Jupyterhub 설치하기

Kubernetes에 Jupyterhub가 설치될 네임스페이스를 만들어준다.

RELEASE=jupyterhub
NAMESPACE=jupyterhub

kubectl create namespace  $NAMESPACE 

사전 준비단계에서 만들어 둔 config.yaml을 다음과 같이 실행한다.

helm upgrade --install $RELEASE jupyterhub/jupyterhub --namespace $NAMESPACE --values config.yaml

위 명령을 실행하고 나면 설치 과정이 백그라운드로 실행 되기 때문에 어떻게 진행 되고 있는지 확인 하기 어렵다.
아래 명령어를 통해서 pod가 정상적으로 올라오는지 확인 해야 한다.

kubectl get pod --namespace $NAMESPACE

정상적으로 Running 상태를 확인 했다면, 정상 설치가 된것이다.
아래 명령을 통해서 서비스에 할당된 Public IP를 확인해 본다.

kubectl get service --namespace $NAMESPACE

확인 된 Public IP를 웹브라우저를 통해서 들어가면 로그인 하라고 나올 것이다.
위에서 설정한 admin계정 이름을 사용하여 접속하면 된다.

여기까지 간단히 Jupyterhub를 Azure Kubernetes Service에 설치하고 접속하는 것 까지 알아보았다. 이제 여러 Notebook 가상 환경을 구성하고 여러 사용자 혹은 그룹과 함께 사용해 보길 바란다.

Programming Paradigm의 변화

최근 AI에 대한 연구가 붐이 일면서 그에 따라 Programming Paradigm도 변화가 생기고 있다. Programming Paradigm은 개발자에게 개발 관점을 갖게 하고, 개발 방법을 결정하는 역할을 하기 때문에 개발자는 이런 변화에 대해서 항상 신경써야 한다.

최근에는 FP(Functional Programming)이라는 것이 Paradigm 변화에 많은 영향을 주고 있는데, 이 것이 무언인지, Paradigm에 주는 변화는 어떠한지 대해서 정리해보려고 한다.

Google에 검색을 해보면 다음과 같이 진화의 관점으로 표현 하고 있다.

개인적인 생각으로는 절반은 동의하고 절반은 동의하지 않는다.

Programming Paradigm은 방법론으로써 개발자가 제품 개발을 할 때, 환경에 따라 선택을 하면 되는 것이다. 그리고 실제로 처음 시작된 시기를 따져 보면 FP 방법론은 1930년대 알론조 처치라는 미국 수학자가 쓴 람다 대수 논문을 근간으로 시작된 것이라, 1960년대에 시작된 OOP(Object-Oriented Programming)보다 그 시기가 오래 되었다. 이런 이유 때문에 동의할 수 없다.

(이미 오랫동안 FP 개발 언어들이 사용되어 오고 있다. ex. LISP, Python, Scala, R, Clojure, F# 등등 )

다만, 기술 발전의 흐름에 따라 보면 다르게 생각할 수 있다.
FP 방법론은 수학적 사고와 밀접한 관련이 있어서 표현 자체가 수학적 정의에 가까운 형식을 띄고 있다. 이 것은 수학적으로 표현되는 데이터 분석 알고리즘들에 적용되어 좋은 성능과 그 동안 OOP으로는 해결하기 어려웠던 문제들이 해결되고 있기 때문에 어느 정도 동의 할 수 있다.

그러면, OOP와 FP의 어떤 특징이 있는지 알아보자.

  • OOP(Object-Oriented Programming)
    1. 실제 세계를 프로그램에 담기 위한 것이기 때문에 Object(Class) 정의가 중요하다.
    2. 클래스 상속을 통해 다형성을 구현 할 수 있다.
    3. 함수 표현 수식은 ‘O.f(x)’ 형태로 표현 된며, O(Object)의 참조 값에 따라 f(x)의 결과가 달라질 수 있다.(부작용)
  • FP(Functional Programming)
    1. 수학적 동작 및 기능을 구현하기 위해서 데이터와 함수를 독립시켰기 때문에 데이터로부터 완전히 독립된 순수 함수 구현이 중요하다.
    2. 데이터로 부터 독립적이기 때문에, 동일한 입력에 대해서 동일한 결과를 보여 준다.
    3. 함수 표현 수식은 ‘f(x)’ 형태로 표현 되며, 입력 변수가 함수인 ‘F(x) -> F(f(x))’형태(Lambda, 고계함수)로 연속적인 표현이 가능 하다.

위 특징들로 보면, FP가 OOP를 완전히 대체를 하는 것은 아닌 것을 알 수 있다. 각 방법론이 시작된 관점의 근거가 다르기 때문이다.

OOP는 현실세계의 Object를 가상세계에 표현하고 각 Object들 간의 상호작용을 나타내는 집합으로 보는 관점으로 시작 되었다. 그리고 FP은 추상적인 수학을 표현하기 위한 연속적인 함수들의 연결로 보는 관점으로 시작되었다.

이런한 다른 이유로 OOP보단 FP이 수학적 알고리즘으로 접근하는 Big Data 분석이나 AI 분야에 적합하게 되었다. 그리고 이런 FP의 부가적인 효과로 연속적인 함수 즉, Lambda(고계함수)를 사용할 수 있게 되다보니 코딩하는 입장에서 코드를 조금 더 간결하게 만들 수 있게 되어서 개발자들이 선호하고 있다. 이로 인해서 FP이 Programming Paradigm에 영향을 주고 있는 것이다.

하지만, 근본적으로 Program이란 것은 현실세계의 것을 가상세계에 표현하는 것이기 때문에 Object를 완전히 배제 할 수는 없다. 때문에 OOP과 FP은 상호보완적으로 이해하고 사용하는 것이 변화하는 Programming Paradigm에 대응하는 올바른 접근 방법이 아닐까 생각한다.

About Digital Transformation

지난 수 년간 사업 전반에 걸쳐 회자되고 있는 Digital Transformation에 대해서 생각해 보려고 한다.

Digital Transformation이란 무엇일까?

영어 단어를 그대로 풀이해보면,
Digital의 뜻은 “(통신 등이)디지털(방식)을 쓰는 / (시계 등이)디지털(방식)의” 라는 의미이며, Transformation의 뜻은 “(완전한) 변화[탈바꿈], 변신”을 의미한다.
단순히 이어 붙여보면 “디지털 방식을 쓰는 완전한 변화, 변신”이란 의미로 다시 정리하면, “정보의 완전한 디지털화”를 의미한다.

그러면, 정보의 완전한 디지털화라는 것이 무슨 의미 일까?

세계적으로 Digital Transformation을 주도하고 있는 글로벌 기업들이 두는 의미에 대해서 살펴보자.

  • Microsoft – 회사를 혁신하고 고객가치를 창출하기 위해 인력, 데이터, 프로세스를 통합하고 창조적 기술 파괴가 일어나는 것.
  • IDC – 기업이 새로운 비즈니스 모델, 제품, 서비스를 창출하기 위해 디지털 역량을 활용함으로써 고객 및 시장(외부 생태계)의 파괴적인 변화에 적응하거나 이를 추진하는 지속적인 프로세스.
  • IBM – 기업이 디지털과 물리적인 요소들을 통합하여 비즈니스 모델을 변화시키고, 산업에 새로운 방향을 정립하는 전략.
  • A.T Kearney – ICBM 등 디지털 신기술로 촉발 되는 경영 환경상의 변화 동인에 선제적으로 대응함으로써 현행 비즈니스의 경쟁력을 획기적으로 높이거나 새로운 비즈니스를 통한 신규 성장을 추구하는 기업 활동.

위 내용의 공통적인 키워드는 다음과 같다.

  1. 고객 가치 창출
  2. 경영 환경(외부 생태계)의 변화
  3. 선제적 대응
  4. 새로운 비즈니스 추구

정리하면, Digital Transformation이 함은 회사 정보의 완전한 디지털화를 뜻하며 이를 통하여, 빠르게 변화하는 경영 환경(외부 생태계)에 선제적으로 대응 할 수 있는 새로운 비즈니스를 추구하는 것이라 볼 수 있다.

여기까지 보면, 정말 이상적이고 좋은 말이다. 그럼면, 정말로 Digital Transformation이란 것이 산업 전반에 얼마나 긍정적인 영향을 미치고 있는 것인가?를 알아봐야한다.

다음은 Microsoft에서 발표한 자료로 Digital Transformation이 GDP에 미치는 영향에 대한 자료이다.

Asia Pacific의 GDP가 매년 성장함에 따라 2017년 6%에 그쳤던 영향력이 19년에는 25%, 21년 예측에는 60%까지 올라갈 것으로 보고 있다. 한국은 영향력이 더 클 것으로 보고 있다.

또한, Digital Transformation에 대해서 Leader역할을 할 경우 Follower역할일 경우 보다 많은 부분에서 2배 이상의 성과(성장)을 얻을 수 있다고 한다.

(비교 부분 : 이익 마진, 생산성, 고객 충성도, 원가 절감, 새로운 제품/서비스의 수익)

위 자료들의 지표에서 볼 수 있듯이 Digital Transformation을 하게 되면, 기존 비즈니스를 혁신을 하여, 많은 이익을 얻을 수 있다고 생각 할 수 있다.

2019년 11월 현재 Digital Transformation을 ‘도입해야 한다’, ‘아직이다’를 논하는 것은 뒤처진 이야기 이다. 이미 정부 주도로 많은 산업군들에서 Digital Transformation을 하고 있기 때문이다. 다만, 이제 관련 개선안들이 추진되고 도입하고 있는 단계라서 많은 제도적인 장치가 마련되지 않다. 이런 이유로 기업들은 기본적인 것들만 적용하지 정말 선진화된 기술들에 대해서는 섣불리 적용하길 꺼려한다.

정말로 제대로 된 Digital Transformation을 갖추기 위해서는 시대에 맞춘 규제완화와 대안 책들이 하루 빨리 처리 되야만 가능 할 것으로 생각된다.

Dependency Injection 개념과 Ninject 사용법

소프트웨어를 잘 만들기 위해서 많은 디자인 패턴들이 사용되는데, 그중에서 DI(Dependency Injection, 의존성 주입)에 대한 개념과 .NET MVC에서 많이 사용되는 DI Framework들 중 하나인 Ninject(Open Source Project)에 대해서 알아보겠다.

DI(Dependency Injection) 란?

프로그래밍에서 사용되는 객체들 사이의 의존관계를 소스코드가 아닌 외부 설정파일 등을 통해 정의하게 하는 디자인 패턴이다. 개발자는 각 객체의 의존관계를 일일이 소스코드에 작성할 필요 없이 설정파일에 의존관계가 필요하다는 정보만 된다. 그러면 객체들이 생성될때, 외부로부터 의존관계를 주입 받아 관계가 설정 된다.

DI를 적용하면, 의존관계 설정이 컴파일시 고정 되는 것이 아니라 실행시 설정파일을 통해 이루어져 모듈간의 결합도(Coupling)을 낮출 수 있다.
결합도가 낮아지면, 코드의 재사용성이 높아져서 모듈을 여러 곳에서 수정 없이 사용할 수 있게 되고, 모의 객체를 구성하기 쉬워지기 때문에 단위 테스트에 용이해 진다.

이제, .NET에서 MVC 프로젝트를 만들때 DI를 구현하기 위해 가장 많이 사용하는 Open Source인 Ninject에 대해서 알아보자.

NInject 알아보기

(공식 페이지 : http://www.ninject.org/)

간단히 이름부터 살펴보면, NInject는, N(Ninja) + Inject로 대표 이미지로도 Ninja로 되어 있다.

홈페이지 대문에 보면 “Be fast, be agile, be precise”라는 슬로건이 있는데 닌자처럼 빠르고 민첩하며 정확하게 프로그램을 만들수 있게 하겠다는 정신이 담겨있는 것 같다.

(Nate Kohari라는 소프트웨어 엔지니어가 최초 개발을 했는데, 개인적인 생각으로는 N을 중의적인 의미로 사용한게 아닌가 싶다. 참고 : https://www.infoq.com/articles/ninject10-released/)

NInject는 Open Source 라이브러리로 Apache License 2.0에 따라 배포되었으며,
2007년 부터 .NET 어플리케이션의 DI를 구현하기 쉽게 해주도록 지원하고 있다.

이제, 실제로 사용해 보자

NInject 사용해 보기

  1. Package Install
    • Visual Studio에서 제공하는 Nuget Package Installer를 사용하여 다음 Package들을 설치한다.
      – Ninject
      – Ninject.Web.WebApi
      – Ninject.Web.Common
      – Ninject.Web.Common.WebHost
  2. Edit Ninject.Web.Common.cs
    • 위 Package 설치가 완료되면, 프로젝트 최상단에서 App_Start 폴더에 Ninject.Web.Common.cs 파일이 생성된 것을 확인 할 수 있다.
    • 해당 파일을 열어 보면, CreateKernel이라는 method가 있는데 다음 코드를 추가한다. 그러면 NInject가 controller의 의존성 주입을 구성해 줄 수 있게 된다.
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;
  1. Register Service
    • 스크롤을 조금 내려 보면, RegisterServices라는 method를 확인 할 수 있는데, 실제로 의존관계를 설정(bind)하는 곳이다. 의존성을 주입할 객체들의 관계를 다음과 같이 추가한다.
private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<ICommonStore>().To<CommonStore>();
}
  1. Use it on controller
    • 이제 의존성 주입을 위한 IoC 설정과, 의존관계 설정(bind)작업을 모두 하였으니 Controller에서 사용해보자.
public class CommonStoreController : Controller
{    
    public CommonStoreController(ICommonStore common)
    {
        this.commonStore = common;
    }

    private ICommonStore commonStore;

    public int GetItemCount(string id)
    {
        return commonStore.Add(id);
    }
}

Design Pattern 중 DI(Dependency Injection, 의존성 주입)이라는 패턴에은 표준 프로그래밍을 할 때 중요한 요소이긴하지만 무조건 사용해야 하는 것은 아니다. 간단한 프로그램이나 객체간의 결합이 명확하여 구분하지 않아도 되는 경우 굳이 프로젝트를 무겁게(?) 만들 필요없다.

그리고 Ninject는 .NET에서 많이 사용되는 Open Source DI Framework 중 하나로 DI를 할 때 쉽게 구현할 수 있어서 선호되는 편이지만 다양한 DI Open Source Framework들이 있으며, 성능 면에서도 훨씬 더 좋은 것들이 있으니 확인하고 사용하길 바란다.
(참고 : https://www.claudiobernasconi.ch/2019/01/24/the-ultimate-list-of-net-dependency-injection-frameworks/)

Azure DevOps 개요

DevOps 란?

데브옵스(DevOps)는 소프트웨어의 개발(Development)과 운영(Operations)의 합성어로서, 소프트웨어 개발자와 정보기술 전문가 간의 소통, 협업 및 통합을 강조하는 개발 환경이나 문화를 말한다.

주로 아래 그림과 같이 개발과 운영간의 연속적인 사이클로 설명할 수 있다.

이를 통해서 얻는 장점은 다음과 같다.

  1. 신속한 제공
    • 릴리스의 빈도와 속도를 개선하여 제품을 더 빠르게 혁신하고 향상할 수 있다. 새로운 기능의 릴리스와 버그 수정 속도가 빨라질수록 고객의 요구에 더 빠르게 대응할 수 있다.
  2. 안정성
    • 최종 사용자에게 지속적으로 긍정적인 경험을 제공하는 한편 더욱 빠르게 안정적으로 제공할 수 있도록, 애플리케이션 업데이트와 인프라 변경의 품질을 보장할 수 있다.
  3. 협업 강화
    • 개발자와 운영 팀은 긴밀하게 협력하고, 많은 책임을 공유할 수 있도록, 워크플로를 결합한다. 이를 통해 비효율성을 줄이고 시간을 절약할 할 수 있다.
  4. 보안
    • 제어를 유지하고 규정을 준수하면서 신속하게 진행할 수 있다. 자동화된 규정 준수 정책, 세분화된 제어 및 구성 관리 기술을 사용할 수 있다.

그럼, DevOps를 실현하기 위해서는 어떻게 해야 하는가?

DevOps를 실현하기 위해서는 CI(Continuous Integration)/CD(Continuous Deployment(Delivery))라는 2가지 작업을 해야 한다.

CI(Continuous Integration)은 Development에 속하는 작업으로 지속적으로 프로젝트의 요구사항을 추적하며, 개발된 코드를 테스트 및 빌드를 수행한다.

  1. 프로젝트 기획 + 요구사항 추적
    • 프로젝트 시작
    • 기획(프로젝트 방법론 채택)
    • 작업관리(Backlog 관리)
    • 진행상황 추적
  2. 개발 + 테스트
    • 코드작성
    • 단위 테스트
    • 소스제어
    • 빌드
    • 빌드 확인

CD(Continuous Deployment(Delivery))는 Operations에 속하는 작업으로 CI가 완료되어 빌드된 소스를 통합 테스트(개발, QA, Staging)를 거쳐 배포를 하며, 배포된 사항들을 지속적으로 모니터링하고 프로젝트 요구사항에 피드백하는 작업을 수행한다.

  1. 빌드 + 배포
    • 자동화된 기능 테스트
    • 통합 테스트 환경(Dev)
    • 사전 제작 환경
      (QA, Load testing)
    • 스테이징 환경(Staging)
  2. 모니터링 + 피드백
    • 모니터링
    • 피드백

이제, DevOps를 하기위한 구체적인 작업을 알았으니, 실제 구성을 하도록 하는 제품들에 대해서 알아보자.

Azure DevOps vs Other Software

DevOps를 하기 위한 솔루션들은 이미 시중에 엄청나게 나와 있으며, 대게 오픈소스 형태로 많이 제공되고 있어서 바로 가져다 사용할 수 있다.

위 그림에서 볼 수 있듯이 DevOps의 각 단계에 맞추어서 원하는 (특화된)제품을 선택하여 사용하면 된다.

모든 단계를 빠짐 없이 구현한다고 가정하여, 예를 들면 다음과 같이 DevOps가 구현 될 수 있다.

  1. Slack으로 요구사항 관리를 하고
  2. Git으로 소스코드 관리를 하고
  3. Maven으로 빌드를 하고
  4. JUnit으로 테스트하고
  5. Jenkins로 Docker에 배포하고
  6. Kubernetes로 운영하며
  7. Splunk로 모니터링 한다.

그런데 이런 경우, 벌써 필요한 제품에 8개나 된다. 프로젝트에 참여하는 모든인원이 이 제품들에 대해서 이해하고 사용하기 어려우며, 각 제품에대한 담당자들있어야 제대로 운영 될 수 있을 것이다. 게다가, 각기 다른 제품이라 다음 단계로 넘어가기 위한 추가적인 관리를 해야할 것이다.

이렇게 되면, 규모가 작은 곳에서는 몇가지 단계를 건너띄고 관리를 하게 되는데 이런 부분에서 예외사항이 생기기 시작하고, 결국 프로젝트 끝에서는 DevOps를 거의하지 못하는 상황이 생길 수 도있다.

반면, Azure DevOps는 하나의 DevOps 관리 솔루션을 제공한다. 때문에 Azure DevOps 하나만 사용해도 모든 절차를 구성 할 수 있다.
그리고 만약, 기존에 사용하던 제품이 있다 하더라도 아래 그림과 같이 3rd-party를 마이그레이션 혹은 연동 설정 할 수 있도록 하기 때문에 Azure DevOps 제품안에서 하나로 통합 관리 할 수 있다.

마지막으로, Azure DevOps를 사용하는 간단한 시나리오에 대해서 알아보자.

Azure DevOps에서는 파이프라인이라는 형태로 CI/CD를 구성하도록 되어 있으며, 각 단계 구성은 아래 그림과 같다.

  1. Project (Agile) Board를 통해서 프로젝트 요구사항 추적 관리를 하고
  2. Repo에서 각 Agile Board Task에 대한 소스코드 관리를 하고
  3. 소스가 커밋이 되면 CI 파이프라인을 통해 빌드 + 테스트를 수행하고
  4. CI가 완료되면 Trigger 형태로 CD 파이프라인을 실행하고
  5. CD 파이프라인을 통해 통합 테스트 + 배포를 하고
  6. (옵션)담당자에게 최종 승인을 받고
  7. 운영 적용 및 모니터링을 한다.

Azure DevOps 이 외의 제품을 사용 했을 때와 단계는 거의 동일 하지만, 여기서 주목 할 점은 Azure DevOps 단일 제품에서 모두 제공 받고 구성 할 수 있다는 것이다.

(**여기서 다 설명 못한 부분이지만 CI/CD 과정 중에 Function(Trigger) 형태로 여러 기능들을 다양하게 엮을 수도 있다. 예를 들어 6번)

각각의 솔루션 전문가들이 있어서 운영한다면 문제가 없겠지만, DevOps를 처음 도입한다던가 규모가 작아 축소 운영을 해야하는 상황이라면 고려해 볼 수 있을 것 같다.