인공지능의 발전과 오픈소스 전략에 대하여

인공지능의 발전은 생각보다 오래 전부터 진행되었다. 1950년에 앨런 튜링이 “계산기계와 지성(Computing machinery and intelligence)”이라는 논문을 통해 처음으로 인공지능에 대한 개념의 토대를 마련했다. 이후, 1956년에 “다트머스 회의(Dartmouth Conference)”로 알려진 모임에서 처음으로 인공지능(AI: Artificial intelligence)이라는 용어를 사용하였고 튜링이 제안한 “생각하는 기계”를 구체화하기 위한 것들을 논의 하기 시작했다.

인공지능의 70년 역사

그리고 오늘날까지 눈에 띄지 않게 성장과 쇠퇴를 반복하다 2016년 인공지능 바둑 프로그램인 알파고가 등장하면서 그 동안 인공지능 기술 발전이 상당히 진행되었다는 것을 보여주었다. 사실, 이때만해도 알파고는 인공지능의 분야중 인지능력에 대한 가능성을 보여줬을뿐 직접적으로 무언가를 제시한 것은 아니었으며 알파고와 같은 인공지능 기술을 가지기 위해서 얼마나 많은 비용과 인력이 투자되었을지 파악하기도 어려운 것으로 느껴졌다.

하지만 알파고의 등장 이후 4년이 지난 지금은 어떤 산업군이든 인공지능 접목을 당연하게 생각하고 있다. 최근의 인공지능 기술들은 간단한 서비스 형태도 제공되어 어려운 기술적인 이해가 없어도 누구나 데이터만 있으면 이미 만들어진 인공지능 모델에 적용하여 학습시켜 볼 수 있으며 심지어 그 결과가 좋다면 제품에 바로 적용도 할 수 있다.

“도대체 최근 4년동안 무슨 일이 있었던 것일까?”

인공지능 기술 분야에서 글로벌 선도기업인 구글의 사례를 중심으로 살펴보자.

  • 2015년 구글의 인공지능 플랫폼 텐서플로우(Tensor Flow)를 무료로 공개 하였다.
  • 2016년 알파고로 유명한 구글 딥마인드에서 인공지능 기술 테스트 플랫폼인 딥마인드랩(DeepMind Lab)을 외부에 무료 공개 하였다.
  • 2017년 10월부터 고사양의 하드웨어(GPU, TPU)환경을 제공하는 인공지능 개발 환경 서비스 코랩(CoLab)을 무료로 사용할 수 있도록 하고 있다.

“인공지능 알고리즘을 구현하는 플랫폼 개발에는 대규모 자본이 투입되었으며, 고도의 기술력이 집약되어 있을 텐데 구글은 왜 무료로 외부에 공개했을까?”

인공지능 기술은 전통적인 ICT 산업부문을 넘어 전통산업을 포함하는 매우 광범위한 영역으로 응용된다. 그리고 응용대상 영역에서 얻어지는 데이터 및 사용자 피드백 등 케이스 의존적인 성격이 강하다. 이러한 이유로 인공지능의 기본 알고리즘은 금융, 의료, 제조, 교육 등 모든 분야에 응용가능하지만 각각의 응용대상 분야 자체에 대한 노하우가 없으면 수많은 알고리즘들은 실제로 구현 될 수 없다.

구글과 같은 글로벌 선도기업도 혼자만의 힘으로는 인공지능 기술의 보급 확산을 지금과 같은 수준으로 올릴 순 없었다. 오픈 소스 생태계를 활용하여 다양한 분야에서 인공지능 기술을 응용하는 주체들이 모두 협력했기 때문에 가능했던 것이다.

이러한 이유로, 구글뿐만 아니라 MS, IBM, Facebook, Open AI 등등 인공지능 기술을 이끄는 대부분의 글로벌 기업들이 오픈소스 생태계에 투자를 하고 있다. 그리고 이런 투자 덕분에 인공지능에 대한 보급과 화산이 그 전과 달리 매우 빠르게 진행 될 수 있었다.

“그러면 여기서 궁금한 것이 생긴다. 거대 글로벌 기업의 기술에 참여를 하여 발전을 도와주고 있는데, 정작 참여하고 있는 기업이나 개발자들 에게는 무엇이 남는 것일까?”

인공지능 연구 환경의 진입장벽이 매우 낮아졌다.

인공지능 기술은 쉽게 생각하면 주어진 데이터들을 다양한 차원으로 비교 탐색 및 분석하여 의미 있는 패턴을 찾아주는 것이다. 여기에는 여러 기술들이 요구되는데 크게 보면 2가지로 구분 할 수 있다. 분석을 할 데이터를 인공지능이 학습할 수 있도록 데이터를 탐색하고 정제하는 전처리 기술과 인공지능 모델을 실제로 연구하고 구현 할 플랫폼이다.

그 동안, 이런 인공지능 기술은 바로 상용화가 불확실한 경우가 많아서 자본이 부족한 기업은 투자가 어려웠고, 하더라도 리스크를 줄이기 위해 대학원이나 전문 연구기관 연구과제를 빌려와 진행하는 경우가 많았다. 이런 경우 굉장히 학문적으로 접근하기 때문에 현실적으로 매출에 좋은 영향을 주지 못 했다.

그러나 글로벌 기업이 엄청난 기술과 자본을 들여 만든 인공지능 연구/개발 플랫폼 기술을 모두 오픈소스로 공개 함으로써 인공지능 기술을 도입하려는 기업은 초기 기술 개발 비용에 대한 부담없이 오픈소스를 통해서 글로벌 기업의 기술력을 제공 받아 연구개발을 시작할 수 있게 된 것이다.

데이터 분석에 사용되는 알고리즘 기법들의 표준화이다.

오픈소스 프로젝트를 사용하는 참가 기업들이 많아지면 각 산업 분야의 다양한 정보와 최신 트랜드에 대한 문제점의 해결책을 공유하여 운영되기 때문에 유연하고 호환성이 높은 표준 모듈/라이브러리들이 개발 될 수 있다.

데이터 분석에 사용되는 알고리즘들은 크게 Classification(분류), Clustering(군집), Regression(회귀), Forecast(예측), Dimensional reduction(차원 축소) 등의 유형로 나누어진다. 그리고 각 유형에는 다양한 분석/학습 알고리즘 기법들로 세분화 된다. 이러한 것 때문에 인공지능 구현을 위해서는 알고리즘에 대한 많은 지식이 있어야 했고 최소 대학원 석사 이상이어야 인공지능 분야에서 일을 할 수 있었다.

Select Algorithm

하지만 최근 몇년사이에 오픈소스 생태계에 참여한 기업과 개발자들의 노력 덕분에 이러한 어려운 내용들이 정형화 되고 패키지/모듈로 간단히 제공되면서 이론에 대한 이해만 있으면 쉽게 가져다가 원하는 인공지능 모델을 구현해 낼 수 있게 되었다.

이러한 오픈소스 생태계의 이점들로 인해서 자원이 부족한 기업들도 잘 만들어진 글로벌 기업의 기술을 적은 비용으로 가져다가 사용할 수 있는 기회를 얻게 된 것이다.

국내 기업들은 오픈소스를 하면 기업의 기술이나 노하우가 노출된다고 생각하여 잘 시도 하지 않는다. 하지만 다르게 생각해보면 정말 잘 만든 기술도 많은 사람들로부터 활용되지 않으면 피드백이 적을 수 밖에 없고 빠르게 변화하는 IT 트랜드를 놓치기 쉽다. 많은 글로벌 IT 선도 기업들이 이러한 개념을 잘 이해하고 오픈소스 생태계를 전략적으로 잘 활용하고 있다. 국내 기업과 연구자들도 오픈소스 생태계를 적극 참여하여 미래 글로벌 IT 시장을 선도해 나가는 기회로 삼을 수 있기록 하는 것이 중요할 것 같다.

Python redact sensitive information in text

text 데이터를 처리하다 보면 그 안에 개인정보(phone, email 등) 등의 민감정보가 포함 되어 있는 경우가 있다. 이것들은 정규식(regular expression)을 사용하여 알아 볼 수 없도록 편집 (masking) 할 수 있다.

import re

text = '안녕하세요. 문의드릴 것이 있어서 연락드렸습니다. 제 연락처는 010-1234-1234 / thenewth@gmail.com 입니다. 연락가능 하실때 연락 부탁 드립니다. 감사합니다.'

phoneRegular = "\d{2,3}-\d{3,4}-\d{4}"
emailReqular = "(\w+\.)*\w+@(\w+\.)+[A-Za-z]+"

phonePattern = re.compile(phoneRegular)
emailPattern = re.compile(emailReqular)

#Masking 문자 대신 공백을 사용하면 민감정보 표시 자체를 삭제 할 수 있다.
redactedPhoneText = re.sub(phonePattern, "***-****-****", text)
redactedEmailText = re.sub(emailPattern , "****@****.***", text)

#전화번호 정보 masking 결과 확인
print(redactedPhoneText)

#이메일 정보 masking 결과 확인
print(redactedEmailText)

출력한 결과를 확인해 보면 정규식에 해당하는 민감정보가 편집(Masking)된 것을 확인 할 수 있다.

WSL(Windows Subsystem for Linux) Ubuntu Config user password

WSL(Windows Subsystem for Linux)을 사용하다 보면 user password를 잃어 버리는 경우가 있다. WSL이 아닌 경우 여러가지 복원 절차를 통해야 하지만 WSL인 경우 MS(Microsoft)에서 개발한 리눅스 호환 커털 인터페이스를 제공하기 때문에 간단히 user password를 초기화 할 수 있다.

먼저, 설치된 WSL 버전을 확인 해야 한다.
명령 실행 창에서 ‘CMD’를 실행하고 아래 명령어를 입력하면, 설치된 WSL 버전 정보를 확인 할 수 있다. (여기서는 Ubuntu 1804 Linux를 기준으로 한다.)

c:\> wslconfig /list /all

Windows Subsystem for Linux Distributions:
Ubuntu-18.04 (Default)

설치된 WSL은 Ubuntu-18.04이고, 실행 명령어는 ‘Ubuntu1804’가 된다.
(만약, Ubuntu(Default)로 나왔다면 실행 명령어는 ‘Ubuntu’가 된다.)

위에서 확인한 실행 명령어를 가지고 CMD창에서 다음과 같이 Ubuntu 기본 사용자를 root(관리자)로 변경해 준다.

c:\> Ubuntu1804 config --default-user root

이제, WSL Ubuntu를 실행하면 기본사용자가 root로 되어 있기 때문에 root로 로그인 된다.
바로, 대상 user의 password를 변경해 주고 로그아웃 한다.

$ passwd user

Enter new UNIX password: (type password)
Retype new UNIX password: (type password)

$ exit

다시 CMD창으로 돌아와 Ubuntu 기본 사용자를 기존 user로 변경해 준다.

c:\> Ubuntu1804 config --default-user user

이제, 다시 WSL Ubuntu를 실행하여 확인해 보면 password가 변경된 것을 확인 할 수 있다.

About Raspbian

Raspbian은 하드웨어 제품인 RPi(Raspberry Pi)와 Linux계열의 OS(Operating System)인 Debian의 합성어로 Raspberry Pi Foundation이 개발한 RPi 전용 OS다.

RPi는 Raspberry Pi Foundation에서 학교와 개발도상국에서 기초 컴퓨터 과학의 교육을 증진시키기 위해 개발한 신용카드 크기의 싱글 보드 컴퓨터이다.
크기가 작고 전력 소비가 5V-2A로 동작하도록 설계되어 있기 때문에 Raspbian은 저전력 ARM CPU에 상당히 최적화되 도록 만들어 졌다.

Raspberry Pi 4 board

Raspbian을 사용하기 위해서는 앞서 설명한 RPi라는 하드웨어가 필요하다.

(Desktop 버전을 사용하여 live Disc를 생성하거나, 가상머신을 이용하여 PC에 설치 할 수도 있다.)

RPi Model B+RPi 2 Model BRPi 3 Model BRPi 4 Model B
SoCBCM2835BCM2836BCM2837BCM2711
CPUARM11 @700MHzQuad Cortex
A7@900MHz
Quad Cortex
A53@1.2Ghz
Quad Cortex
A72@1.5Ghz
Instruction SetARMv6ARMv7-AARMv8-AARMv8-A
GPU250MHz VideoCore IV250MHz VideoCore IV400MHz VideoCore IV500MHz VideoCore VI
RAM512MB SDRAM1GB SDRAM1GB SDRAM1, 2 or 4 GB
WirelessNoneNone802.11n/Bluetooth 4.0802.11n/Bluetooth 5.0
VideoHDMI/CompositeHDMI/CompositeHDMI/Composite2x micro-HDMI/Composite
AudioHDMI/HeadphoneHDMI/HeadphoneHDMI/HeadphoneHDMI/Headphone
RPi는 그래픽 성능을 띄어나지만 매우 저렴한 가격(약 25~35$)에 구입할 수 있다.

RPi는 OSHW(Open Source Hardware)라서 하드웨어 스팩은 물론이고 전용 OS인 Raspbian역시 오픈소스로 공개 되어 있기 때문에 하드웨어만 구입하면 나머지 사용하는 것에 대해서는 100% 무료로 사용할 수 있다.

RPi 전용 OS인 Rapbian은 Debian을 기반으로 만들어 졌기 때문에 대부분의 주요 명령어는 Debian과 거의 동일하게 사용하는 하다.

  • APT(Advanced Package Tool)을 통한 소프트웨어 설치 / 업데이트
  • dpkg(Debian package) 형식의 패키지 소프트웨어 사용

PIXEL(Pi Improved Xwindows Environment, Lightweight)이라는 GUI 기능 제공을 한다. 이를 통해서 데스크탑 환경을 사용할 수 있다. 특히, 데스크탑 환경 중 App Store와 동일한 개념의 PI Store 제공하여 호환되는 Package들을 쉽게 제공 받을 수 있도록 되어 있다.

Raspbian Pi Store

오픈소스 싱글 보드계열 중에서 저렴하고 파워풀한 기능을 제공하고 있어서 가성비가 좋은 제품으로 많은 개발자들에게 사랑 받고 있다.

전 세계적으로 많은 개발자들이 사용하고 있다 보니 많은 관련 개발 커뮤니티들도 분야별로 자연스럽게 형성되고 있다. 초급자라면 관심 있는 분야의 커뮤니티에서 많은 정보(Tip)들을 제공 받을 수 있다. (오픈소스의 장점이 잘 살려진 것 같다.)

커뮤니티 링크: https://www.raspberrypi.org/community/

Python connect to MS-SQL with pymssql

Python에서 MS-SQL을 사용하려면 일단, MS-SQL DB를 지원하는 Python 모듈을 설치해야 한다. MS-SQL에 대한 모듈은 크게 pyodbc와 pymssql 두가지가 있는데 여기서는 pymssql을 사용 할 것이다.

(DB에 관련된 모듈은 무수히 많은 것들이 있다. 참고: https://www.lfd.uci.edu/~gohlke/pythonlibs/)

다음과 같이 pymssql을 설치한다.

(설치 방법은 Ubuntu Linux대상 이다. 다른 OS를 사용하는 경우는 여기를 참고하면 된다.)

$ apt-get --assume-yes update
$ apt-get --assume-yes install freetds-dev freetds-bin
$ pip install pymssql

이제 Python에서 설치한 모듈을 가지고 MS-SQL에 접근해 보자.

import json
import pymssql 

#[Tip]json 문자열을 환경변수 파일로 저장하여 사용한다면 서버정보를 노출 하지 않을 수 있다.
json_string = 
'{
    "host":"Server Address",
    "port":1433,
    "user":"User ID@Server Name",
    "password":"P@ssW0rd",
    "database":"Database Name"
}'
json_data = json.load(json_string)

#pymssql 모듈을 이용하여 Connection 생성을 한다.
conn = pymssql.connect(host=json_data['host'], port=json_data['port'], user=json_data['user'], password=json_data['password'], database=json_data['database'])

여기까지 하면 MS-SQL서버에 접근(Connection 완료) 한 것이다.
다음으로 Select query문을 실행하여 데이터를 가져와 보자.

#Connection으로부터 cursor 생성
cursor = conn.cursor() 

#Select Query 실행
cursor.execute('select * from [Target Table Name]') 

#결과 데이터를 데이터프레임에 저장
df = pd.DataFrame(cursor.fetchall())

#실행이 끝나면 항상 연결 객체를 닫아 주어야 한다.
conn.close() 

잘 실행 되었다면 결과를 담은 데이터프레임을 출력 해보자.

#결과 출력
print(df)

실행한 Select Query한 결과를 확인 할 수 있을 것이다.

MS-SQL Table Copy

학습 데이터를 준비 하려다 보면 기존의 데이터를 변형해야 될 때가 있다. 이때 원본 테이블을 가지고 바로 작업을 하게 되면 데이터가 손실 될 수 있다.
백업 데이터가 있다고 하면 그나마 다행이지만 보통 학습에 사용되는 데이터는 양이 많기 때문에 100% 복구하려면 시간이 걸린다.
이런 점들 때문에 될 수 있으면 테이블(혹은 데이터)을 복사해서 사용하면 좋다.

  1. 새 테이블을 생성 하면서 데이터 복사
select * into [New Table Name] from [Source Data]
  1. 테이블 구조만 복사
select * into [New Table Name] from [Source Table Name] where 1=2
  1. 기존 테이블에 데이터만 복사
insert into [Destination Table Name] select * from [Source Table Name]

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 가상 환경을 구성하고 여러 사용자 혹은 그룹과 함께 사용해 보길 바란다.

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를 처음 도입한다던가 규모가 작아 축소 운영을 해야하는 상황이라면 고려해 볼 수 있을 것 같다.