기본 콘텐츠로 건너뛰기

3월, 2021의 게시물 표시

[Jenkins & Artifactory] Jenkins Freestyle Job 생성 및 Artifactory 구축

먼저 Jenkins Freestyle Job에 대해 알아보도록 하겠습니다. ​ 1. Jenkins 설정 1.1 사용자 정보(Credential)은 Manage Credential 화면에서 추가할 수 있습니다. 1.2 Plugin 설치 - MSBuild Plugin: MSBuild를 사용하기 위해서는 MSBuild Plugin을 설치해야 합니다. - change-assembly-version-plugin : .NET 프로젝트의 어셈블리 정보를 수정할때 필요합니다. - Environment File Plugin : 파일의 정보로 환경 변수를 바꿀때 사용합니다. - Email Extension Plugin : html 형식의 메일을 발송할때 사용합니다. 1.3 Jenkins 환경 설정 - Global properties를 설정합니다. 프로젝트 빌드에 필요한 파일들의 경로를 설정하였습니다. - 빌드 결과를 통보하기 위해 Email 설정을 합니다. - .NET 프로젝트를 MSBuild로 컴파일하기 때문에 필요한 Global Tool Configuration에서 MSBuild 를 추가합니다.

[Jenkins] Pipeline Job 구축

Pipeline 프로젝트를 생성하기 위해서는 Groovy 스크립트를 알아야 합니다. 하지만 Freestyle 프로젝트보다는 스크립트를 사용하기 때문에 한 군데서 빌드 흐름을 제어가 가능합니다. Freestyle의 경우는 설정하는 부분이 여기저기 흩어져 있어 설정하기에 산만한 것 같습니다. Jenkins Pipeline에 대해서는 여기 를 참조하면 좋을것 같습니다. 아래 2가지 종류의 프로젝트에 대해서 Jenkins 파이프 라인을 구축하였습니다. 둘다 흐름은 동일합니다. .NET 프로젝트 파이프라인 파이썬 프로젝트 파이프라인 우선 Jenkins의 " 시스템 설정 에서 프로젝트 빌드에 필요한 환경 변수들을 설정합니다. - 버전별 Python 실행 파일 경로 : Python 프로젝트 컴파일에 필요합니다. - MsBuild.exe 파일 경로 : .NET 솔류션 컴파일에 필요합니다. - WixToolSet 파일 경로들 : 설치 파일 생성에 필요합니다. - CURL, DOXYGEN .... : 필요한 파일들을 추가합니다. 1. git에서 소스 얻어오기 git에 접속하여 소스를 얻어올 사용자의 Credential을 추가합니다. ID/PASSWORD를 입력하면 됩니다. stage('Checkout') { steps { git branch: 'master', credentialsId: 'Your credentials id', url: '{Repository Path}' } 2. Python 가상 환경 구축     이전 글을 참조하시면 됩니다. 3. 버전 수정 Jenkins로 빌드할 때마다 Jenkins BUILD_NUMBER로 실행 파일 및 설치 파일의 빌드 넘버를 설정하도록 합니다. MSDN을 찾아보면 빌드 넘버는 Major.Minor.Build.Revision으로 구성되어 있습니다. Python 프

길 찾기 개선

  이전 글 참조 Dijkstra 알고리즘을 이용하여 출발점에서 종료점까지 가는 최소 비용의 경로를 찾을 수 있습니다. 하지만 시간 복잡도는 $$O(n^2)$$로 좋지 않습니다. Dijkstra 알고리즘은 종료점까지 도착한 경로들을 구한 뒤 가장 적은 비용의 경로를 선택합니다. 만일 각 노드마다 비용을 확인하여 도중에 탐색을 멈추게할 수 있다면 알고리즘을 개선할 수 있습니다.

[리팩토링] 신박한 정리

 유명한 그리고 한때 유명했던 사람들이 출연하여 자신들의 집을 정리하는 프로그램이 있습니다. 집 정리가 끝난 후 입을 쩍 벌리며 놀라워하는 사람들의 모습이 인상적인 프로그램입니다. 코로나 시국이라 이런 포맷의 프로그램도 등장하는 것 같습니다. 정신없이 프로젝트를 수행하다 보면 우리의 코드도 정리가 필요할 때가 옵니다. 우리도 입이 쩍 벌어질 정도의 깔끔한 코드를 짤 수 있습니다. 아래는 제가 코딩을 하면서 지키는 나름의 가이드입니다. 1. 메모리 관리에 신경쓰야 합니다. .NET Framework에서 가비지 컬렉션으로 메모리 관리를 하지만 프로그램에서 메모리를 과도하게 낭비하다보면 결국에 OutOfMemoryException을 경험하게 될겁니다. 위 코드에서 Map은 생성하자마자 쓰레기통에 쳐박히게 됩니다. 2. 멤버 변수의 노출을 최소화합니다. 멤버 변수를 가지고 외부에서 어떤 일을 할지 몰라 항상 위험이 존재하게 됩니다. 그리고 멤버 변수를 참조하게 되면 해당 멤버 변수를 수정했을때 참조하는 코드도 수정해야 합니다. 즉 결합도가 증가됩니다. 결합도는 줄이고 응집도는 높여야 좋은 코드가 됩니다. 따라서 메서드를 만들어 클래스에게 일을 시키는 방향으로 코드를 작성하는 것이 좋습니다. 데이터를 받아 일을 하는게 아니라 일을 위임하여 서비스를 받는다고 생각하면 될것 같습니다. 3. 오류가 노출되게 합니다. 가끔씩 오류가 발생할 가능성이 있는 부분 혹은 디버깅시 오류가 발생한 곳에 try/catch로 감싸놓은 코드를 볼 수가 있습니다. 이런 부분의 프로그램의 잠재적 위험이 됩니다. 프로그램이 죽지 않을뿐 우리가 원하지 않은 다른 결과를 얻게 됩니다. 그리고 점점더 위험한 프로그램을 만들게 됩니다. 오히려 우리의 예상과 다른 결과를 얻었을때 오류를 발생시키는 것이 좋습니다. /// <summary> /// start에서 end로 가는 최소 비용의 경로를 구한다 /// </summary> /// <param name="start

[최적화] 계산하는데 10분이나 걸려요

동료가 고객사에서 "2~3분 걸리는 작업을 10분 걸린다고 말한다"며 화면에 걸리는 시간을 표시해야겠다고 합니다. 10분은 아니지만 2~3분도 사용자의 인내심을 요구하는 시간이기 때문에 프로그램 최적화를 하기로 했습니다. 아래는 진행중인 프로젝트(Cable AutoRouting) 대상으로 진행한 최적화에 대한 내용입니다. 1. 상황에 맞는 자료 구조를 선택해야 합니다. Map 클래스의 Node 접근이 빈번하게 일어난다고 할때, Nodes 자료 구조로 List를 사용했다고 하면 접근을 위해 아래와 같은 코드가 필요합니다. return map.Nodes.Cast<Node>().Where(c1 => c1.ObjectID == oFeature.ObjectID).FirstOrDefault(); 이때 걸리는 시간은 $O(n)$이 됩니다. 하지만 자료 구조를 Dictionary를 사용한다면 접근하는데 걸리는 시간은 $O(1)$이 됩니다. if(this._Nodes.ContainsKey(oFeature)) { return this._Nodes[oFeature]; }

[WIX] 사용자 화면 추가하기

 회사에서 WIX(Windows Installer XML)으로 빌드 패키지를 작성하고 Jenkins를 이용하여 설치 파일을 생성하고 있습니다. 며칠 전 고객사에서 설치 파일 수정 요청이 들어왔습니다. 협력사에 프로그램을 배포하려고 하는데 프로그램 복제를 막기위해 프로그램 설치 시 라이선스 코드를 입력받도록 해달라는 것이었습니다. 라이선스를 입력받는 화면이 필요한데 사용자 화면을 추가해본적이 없어 웹 검색을 통하여 얻은 내용을 여기에 기록합니다. WIX에서는 미리 정의된 몇가지 UI 모드를 지원합니다. WixUI_Advanced WixUI_FeatureTree WixUI_InstallDir WixUI_Minimal WixUI_Mondo 각 UI 모드마다 사용하는 Dialog와 나타나는 순서가 정의되어 있습니다. 사용자 화면을 추가하기 위해서는 WixUI_FeatureTree 모드를 사용하는 것이 좋다고 합니다. 먼저 추가할 사용자 화면을 디자인합니다. WIX 파일에 직접 XML 형식으로 작성을 해도 되고  Wix Edit라는 툴을 이용하여 작성해도 됩니다. Wix Edit 라이선스 입력 화면을 아래와 같이 디자인했습니다. 그리고 WIX 파일(.*.wxs)에 UI를 위한 섹션을 추가합니다. UI 섹션에는 Font와 UI Mode에 대한 내용이 꼭 추가되어야 합니다. <TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" /> <TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" /> <TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" /> <Property I

[Cable Auto Routing] 맵 생성하기

 Cable AutoRouting을 하기 위해서는 Cable이 지나는 모든 CableTray에 대한 맵을 구성해야 합니다. 맵을 구성하기 위해 먼저 각 CableTray에 대해서 Node와 Edge를 구성합니다. 프로젝트 수행을 위해 고객사에서 보여준 제안서의 CableTray는 끊어진 Feature 없이 매끄럽게 연결되어 있었습니다. 하지만 막상 실제 프로젝트 수행이 끝난 3D Model을 받아 보니 군데군데 이빠지듯 Feature가 빠진 CableTray도 다수 있고 CableTray의 Feature 순서도 뒤죽박죽이었습니다. 우리가 생각한것보다 모델링의 품질이 좋지 않았습니다. CableTray1과 CableTray2가 하나의 CableTray로 구성될거라 생각했었는데 다른 CableTray로 만들어져 있습니다. [CableTray의 Feature가 서로 떨어져 있는 경우] CableTray는 여러 Feature들로 구성되어 있습니다. 그리고 Feature는 Part를 가지고 있습니다. Feature의 타입에는 Straight, Branch, End, Turn, AlongLegFeature등이 있습니다. Part가 있는 Feature만 노드를 생성합니다. End, Branch Feature등 물리적 형상의 나타내는 Part를 가지고 있지 않는 Feature에 대해서는 노드를 생성하지 않습니다. 노드를 생성한 Feature의 OrientedRangeBox의 Intersects 함수를 이용하여 Feature와 Feature간의 에지를 생성합니다. class CableTray: def __init__ ( ) : self ._nodes = [ ]   def build_network ( ) : for feature in self ._features: if feature. has_part : self ._nodes. append ( new Node ( feature ) )   for i in range ( l