스토리 홈

인터뷰

피드

뉴스

조회수 2274

스포카에서 쓰는 오픈소스와 오픈소스 라이센스 (1)

안녕하세요. 스포카 프로그래머 박종규입니다. 이번 시간에는 스포카에서 쓰고있는 클라이언트 측 오픈소스와 그 오픈소스가 어떠한 라이센스가 적용이 되었는지 알아 보겠습니다.오픈소스(Open Source)먼저 간략하게 오픈소스의 정의에 대해서 짚어가도록 하겠습니다. 오픈소스는 소스코드를 외부에 공개하여 누구든지 제한없이 소프트웨어를 쓰고 소스코드를 볼 수 있는 소프트웨어를 말합니다. 통상적으로 오픈소스 소프트웨어를 오픈소스라고 부르기도 합니다. 대표적인 오픈소스로는 우리가 많이 쓰는 안드로이드OS와 크로미움 브라우저를 볼 수 있죠.프로젝트에 오픈소스를 적용?그렇다면 오픈소스의 정의도 알았고 제한없이 쓸 수도 있다고 하고 이렇게 많은 장점이 있는 오픈소스를 우리회사 프로젝트에 한 번 도입해볼까?라는 생각을 가지신 분들이 있겠지만 잠시만 기다려 주시길 바랍니다. 이러한 오픈소스는 오픈소스 라이센스라는 일종의 저작권이 적용이 되어 있어서 그 라이센스를 준수 해야합니다.오픈소스 라이센스(Open Source License)오픈소스 라이센스의 정의를 간략하게 보면오픈소스 라이센스는 오픈소스SW 개발자와 이용자간에 사용 방법 및 조건의 범위를 명시한 계약을 말한다. 따라서 오픈소스SW를 이용하기 위해서는 오픈소스SW 개발자가 만들어놓은 사용 방법 및 조건의 범위에 따라 해당 SW를 사용해야 하며, 이를 위반할 경우에는 라이선스를 위반함과 동시에 저작권 침해로 인해서 이에 대한 처벌을 받게 된다.라고 나와 있습니다. 즉 오픈소스이긴 하지만 오픈소스에 적용된 라이센스를 준수하지 않는다면 법적인 처벌을 받는다는 거죠. 그렇기 때문에 프로젝트에 오픈소스를 적용하려면 제일 먼저 라이센스를 확인해야 합니다.스포카 클라이언트에서는 어떠한 오픈소스를 쓰고 있을까?현재 스포카의 클라이언트측에서 사용하고 있는 오픈소스는 다음과 같습니다.jQueryLESSBackbone.jsD3.jsDataTables.js그럼 간략하게 이 오픈소스가 어떠한 역할을 하는지 간략하게 알아보겠습니다.jQueryjQuery(제이쿼리)는 브라우저 호환성이 있는 HTML 속 자바스크립트 라이브러리이며 클라이언트 사이드 스크립트 언어를 단순화 할 수 있도록 설계되었습니다. 즉 자바스크립트를 좀 더 편하게 쓸 수 있도록 개발된 라이브러리이죠.LESSLESS는 css를 동적으로 쓸 수 있게 해주는 자바스크립트 라이브러리 입니다. 기존 css에서 제공하지 않는 변수 및 연산식을 제공하기 때문에 코드를 재사용 할 수 있을 뿐만 아니라 개발시 소요되는 시간을 줄여줍니다. *.less로 개발된 코드는 less 컴파일러를 통해 *.css로 변환이 되어 클라이언트 페이지에 적용됩니다.Backbone.jsBackbone.js는 자바스크립트를 MVC 패턴으로 개발할 수 있게 도와주는 자바스크립트 라이브러리입니다.D3.jsD3.js는 데이터를 우리가 쉽게 볼 수있게 다양한 차트, 표, 그림으로 표현 할 수 있도록 기능을 제공해주는 자바스크립트 라이브러리입니다.DataTables.jsDataTables.js는 table를 만들어주는 기능을 제공하는 자바스크립트 라이브러리입니다.그렇다면 위 오픈소스에는 어떠한 라이센스가 적용되어 있을까?위의 오픈소스에 적용되어 있는 라이센스를 살펴보면jQuery : MIT, GPLv2LESS : apache license 2Backbone.js : MITD3.js : BSDDataTables.js : BSD, GPLv2같은 라이센스가 적용이 되어 있습니다. 그럼 하나씩 살펴보도록 하죠.듀얼라이센스먼저 jQuery와 DataTables.js에는 다른 오픈소스와 다르게 라이센스가 두개가 적용이 되어 있는 것을 볼 수 있습니다.이것을 흔히 듀얼라이센스라고 하는데 이 라이센스는 오픈소스를 쓰는 사용자가 두개의 라이센스중에서 하나를 선택해서 쓸 수 있는 라이센스입니다. 예를 들면 jQuery를 쓰는 사용자는 GPL 라이센스를 적용을 할 수도 있고 MIT 라이센스를 적용해서 쓸 수 있다는 뜻이죠.GPL 라이센스jQuery와 DataTables.js에 적용되있는 GPL라이센스에 대해서 알아 보겠습니다. GPL라이센스는 오픈소스에 가장 많이 적용된 라이센스 중에 하나입니다. 이 라이센스는 자유소프트웨어재단에서 만든 라이센스로 이 라이센스를 가진 오픈소스를 이용하여 응용 프로그램을 개발하는 경우에는 GPL라이센스가 적용이 됩니다. 그리고 GPL라이센스는 3가지의 버전이 있습니다.GPLv1GPL의 버전 1은 1989년 1월에 발표되었다(GPLv1 전문). 이것은 자유 소프트웨어에서의 두 가지 중요한 자유를 보장해 주었는데, 하나는 프로그램의 소스코드를 공개하지 않은 채 바이너리 파일만 배포하는 것을 막는 경우로 이것을 막기 위해 GPLv1에는 프로그램을 GPLv1로 배포할 때는 사람이 이해하기 쉬운 소스 코드를 같이 배포해야 한다는 조건이 들어갔다. 두 번째 문제는 프로그램에 추가적인 제약을 걸 가능성이 있다는 점이었고, 이를 막기 위해 GPLv1 프로그램을 수정한 프로그램은 원래 프로그램과 마찬가지로 GPLv1을 따라야 한다는 조건이 들어갔다.GPLv2자유 소프트웨어 재단(OSF)에서 만든 자유 소프트웨어 라이선스다. 미국의 리처드 스톨만(Richard Stallman)이 GNU-프로젝트로 배포된 프로그램의 라이선스로 사용하기 위해 작성했다. ‘① 컴퓨터 프로그램을 어떤 목적으로든지 사용할 수 있다 ② 컴퓨터 프로그램의 복사를 언제나 프로그램의 코드와 함께 판매 또는 무료로 배포할 수 있다 ③ 컴퓨터 프로그램의 코드를 용도에 따라 결정할 수 있다 ④ 변경된 컴퓨터 프로그램 역시 프로그램의 코드와 함께 자유로이 배포할 수 있다’라는 네 가지 조항을 명시하고 있다. 대부분의 소프트웨어에 대한 라이선스는 소프트웨어를 공유하거나 수정할 수 있는 자유를 금지하기 위 고안되었다. 반면에 GNU 일반 공중 라이선스는 자유 소프트웨어를 공유하고 수정할 수 있는 자유를 보장하기 위해 의도되었다. 즉, 소프트웨어가 사용자 모두에게 자유롭게 이용될 수 있도록 하는 것이다. 이 일반 공중 라이선스는 자유 소프트웨어 재단의 소프트웨어 대부분을 비롯하여, 저작자가 이 라이선스의 사용을 지정한 기타 모든 프로그램에 적용된다. (자유 소프트웨어 재단의 소프트웨어 중 일부는 이 라이선스 대신 GNU 라이브러리 일반 공중 라이선스가 적용된다.) 누구나 자신의 프로그램에 이 라이선스를 적용시킬 수 있다.GPLv3자유 소프트웨어 재단(FSF)과 이 재단의 GNU 프로젝트에 의해 배포되며 GNU 소프트웨어에 적용되는 공개 소프트웨어의 대표적인 라이선스 체계. GNU GPL이라고도 하며, 저작권(COPYRIGHT)의 반대라는 의미로 카피레프트(COPYLEFT)라고도 한다. 라이선스 사용료나 사용상의 제약 조건을 자유롭게 하여 소프트웨어 유통을 활성화하기 위한 의도에서 출발한 것으로 GNU 소프트웨어로 공개되는 원시 부호는 누구나 변경 또는 일반 공중 라이선스(GPL)로 재배포하고, 이를 이용하여 상업적 웹 사이트를 구축할 수도 있다. 그렇다고 저작권의 완전한 포기를 의미하는 것은 아니어서 GPL의 기본 원칙과 공개하는 측이 정의한 바를 충실하게 따르도록 되어 있다. 1990년대에 마련된 GPL V2.0에 이어 2005년에 V3.0이 발표되었다. GPL 버전 3은 2007년 6월 29일에 발표되었다. 2005년 후반에 자유 소프트웨어 재단에서 GPL의 세번째 판을 개발할 것이라고 발표했다. 바뀐 점 중에서 가장 중요한 4가지를 말하자면, 소프트웨어 특허에 대처하는 것, 다른 라이선스와의 호환성, 어떤 부분의 원시 코드와 무엇이 GPL이 포함되어야 하는 원시 코드를 구성하는지와 디지털 제한 관리(DIGITAL RESTRICTIONS MANAGEMENT)에 신경을 썼다.※참고GPL 라이센스가 적용된 오픈소스를 사용했다고 무조건 소스코드를 공개해야 하는 것은 아닙니다. 예를 들면 MySQL db를 이용하여 웹서비스를 개발해서 직접 서비스만 운영하는 경우 이것은 다른 곳에 배포하는 것이 아니므로 GPL 라이센스 의무사항이 적용되지 않습니다. 하지만 다른 곳에 제공하거나 파는 경우(쇼핑몰을 제작해서 파는 경우)에는 배포하는 것이 되므로 GPL라이센스가 적용이 됩니다. 따라서 이런 경우에는 상용라이센스를 구매해서 써야 합니다.MySQL에서 정의한 배포하는 대표적인 예는 다음과 같습니다.MySQL을 포함하고 있는 소프트웨어를 고객에게 팔아 그 소프트웨어를 고객이 소유한 장비에 설치하는 경우고객이 소유한 장비에 기본적으로 MySQL을 설치해야하는 소프트웨어를 파는 경우MySQL을 포함하고 있는 하드웨어 시스템을 고객에게 팔아서 고객이 있는 곳에 설치하는 경우MIT 라이센스MIT 라이센스는 MIT 공과대학교에서 학교 학생들의 소프트웨어 학습을 돕기 위해서 개발한 허가서입니다. 이 라이센스는 강력한 조항이 없어서 MIT 라이센스가 적용된 오픈소스를 이용하여 응용 프로그램을 개발할 시에 응용 프로그램을 오픈소스로 해야할 필요도 없고 소스코드를 공개할 의무가 없습니다. 또 상업적인 제한도 없습니다. 다만 응용 프로그램에 MIT 라이센스라고 표시와 라이센스 사본을 첨부만 해주면 됩니다.BSD 라이센스버클리의 캘리포니아 대학에서 배포하는 공개 소프트웨어의 라이선스입니다. BSD 라이센스는 자유소프트웨어 자작권의 하나로 BSD 계열 소프트웨어를 포함한 많은 프로그램에서 사용하고 있습니다. 이 라이센스는 라이센스라고 할 수 없을 만큼 미약해서 아무나 수정하고 배포하고 소스코드를 공개해야 할 의무가 없습니다. MIT 라이센스와 마찬가지로 라이센스 표시만 해주면 됩니다.Apach license 2아파치 라이센스는 아파치 소프트웨어 재단에서 만든 라이센스입니다. 이 라이센스 또한 MIT,BSD와 마찬가지로 소스코드 공개의 의무는 발생하지 않습니다. 하지만 “Apache”라는 이름에 대한 상표권을 침해하지 않아야 한다는 조항이 있어서 BSD라이센스보다 법적으로 완결된 내용을 담고 있습니다. 라이센스의 표시와 아파치 소프트웨어 재단에 개발된 소프트웨어라는 것을 밝혀야 합니다.참고한국저작권위원회위키백과KLDPwikiGNU공개SW포털MySQL KOREAKLDP 오픈소스라이센스가이드오픈소스 라이센스 비교표#스포카 #운영 #개발 #오픈소스 #개발자 #개발팀 #꿀팁 #인사이트 #조언
조회수 2867

iOS 개발을 위한 11가지 노하우

Overview기고 제안을 받자마자 iOS 개발을 시작했을 때가 떠올랐습니다. 신대륙을 마주한 것 같았던 그때의 기분을 아직도 잊지 못하기 때문입니다. 당시까지만 해도 Android 개발만 했기 때문에 iOS는 그야말로 미지의 영역이었습니다. 게다가 개발을 시작하려고 조심스럽게 첫 발을 내딛은 순간, 입이 떡 벌어질 수밖에 없었죠.“이렇게 느린 IDE가 있다니…““개발자 프로그램이 뭐 이렇게 비싸?”XCodeXCode는 그동안 접했던 IDE 중에서도 가장 최악이었고, 개발자 프로그램 등록은 13만 원 상당의 비용을 지불해야 했습니다. 가장 중요한 건 맥 컴퓨터(Macintosh)를 보유해야만 했죠. 처음 개발을 시작하려니 넘어야 할 산이 매우 많았습니다. 맞습니다. 팜므파탈의 대명사 마타하리(Mata Hari)처럼 iOS 개발은 밀당과도 같습니다. 분명 매력적인 일이지만 XCode와 개발자 프로그램 등록은 빙산의 일각이기 때문입니다. iOS는 곳곳에 구덩이를 파고 초보 개발자들을 집어삼킬 준비를 하고있습니다. (예를 들면 리소스를 묶어놓은 R.java 파일 같은 레퍼런스가 없습니다. 흑.)그래서 준비했습니다. 수많은 초보 개발자들이 iOS의 구덩이를 피해갈 수 있는 팁을 말이죠.iOS의 구덩이를 피하는 11가지 방법1.비싼 맥(Macintosh)을 사세요.iOS 개발자에게 MacOS는 필수입니다. XCode가 MacOS만 지원하기 때문입니다. 오픈 소스로 공개된 Swift에는 제약이 없지만 XCode는 MacOS에서만 동작하는 제약이 있습니다. 따라서 맥은 iOS 개발자에게 가장 필요한 준비물입니다. 게다가 하드웨어 리소스를 많이 사용하는 XCode 탓에 더 크고, 더 비싸고, 더 아름다운 맥을 구매하셔야 합니다. Macbook이나 Macbook Air 모두 추천하지 않습니다. 15형 Macbook Pro 모델을 비롯해, Mac Pro나 iMac Pro 등의 고급 모델을 사용하면.. 개발이 잘 됩니다.2.돈을 내세요.iOS를 개발하려면 가장 먼저 Apple Developer Portal에서 연 129,000원의 개발자 프로그램에 등록해야 합니다. XCode를 사용해서 코드만 볼 것이라면 문제가 되지 않지만, 디바이스에 앱을 설치하고, 테스트하며, AppStore에 배포할 거라면 반드시 구매해야 합니다. 이 계정은 앞서 말한 것처럼 1년이 지나면 다시 구매해야 합니다. 만약 기업 개발자로 등록하려면 Enterprise Program이 따로 준비되어 있습니다. 기업을 위해 특화된 In-House 배포 등의 이점이 있습니다. 구매해야할 것이 꽤 많죠? 이제 익숙해져야 합니다.3.XCode를 설치하세요.XCode는 Mac App Store에서 설치할 수 있습니다. 용량이 크기 때문에 설치하기 전에 하드디스크 저장공간부터 확인하는 것이 좋습니다. 처음 실행하면 추가 컴포넌트를 다운로드하는 과정이 실행되고, 그 이후에 XCode를 사용할 수 있습니다. XCode와 관련된 자세한 내용은 아래에서 자세하게 다루겠습니다.4.어려운 것에 대비하세요.1)인증서‘들’XCode 설치 이후에도 몇 가지를 발급 받고, 셋업해야 합니다. 방 탈출 게임처럼 한 단계 한 단계 거치는 과정이 필요합니다. 첫 번째로 인증서‘들’을 발급받아야 합니다. 애플을 대신해 앱을 설치하고, 배포할 수 있는 권한을 위임 받는 과정입니다. 이 인증서들은 Apple Developer Portal의 ‘Certificates, IDS & Profiles’ 항목에서 발급 받을 수 있으며, MacOS의 키체인 앱을 이용해 개인 키를 생성하는 방식으로도 방식으로 발급 받을 수 있습니다. 2)디바이스 등록디바이스-iOS-에 개발한 앱을 설치하려면 애플 개발자 계정에 개발용 디바이스를 등록해야 합니다. 이 과정은 XCode에 신규 디바이스를 연결하고, 빌드 및 배포를 할 때 XCode가 알아서 합니다. 만약 디바이스를 보유하고 있지 않은 상황이라면 해당 디바이스의 UUID를 받아서 개발자 포털에 직접 등록할 수도 있습니다. 3)Bundle IDBundle ID는, 앱의 고유한 ID입니다. iOS가 앱을 식별할 때 사용하는 식별자이며, 보통 ‘com.companyname.appname’ 의 형식으로 회사나 개인의 도메인을 거꾸로 쓰는 것이 보편적입니다. 하지만 Bundle ID는 어디까지나 개발자가 결정하는 영역이므로 인스턴스 이름 지정하듯이 자신만의 고유한 방법을 사용해서 Bundle ID를 지정해도 문제가 없습니다. 4)Provisioning ProfileProvisioning Profile은 디바이스 정보와 앱 정보, 인증서 정보를 매핑해주는 Profile입니다. 최신 XCode에서는 이 Provisioning Profile을 자동으로 관리해주기 때문에 따로 신경쓰지 않아도 좋습니다.5.개발자 포럼에 질문하거나, StackOverflow에 질문하거나!질문하는 사람은 아름답습니다. 궁금하거나, 잘 안 풀리는 코드는 개발자 포럼에서 질문할 수 있습니다. 대신 영어 실력이 좋아야 합니다.크게 기대는 하지 않는 것이 좋습니다. 등록된 discussion에 대한 답글들이 ‘나도 같은 상황이다’, ‘나도 궁금한 점이다’ 등의 다른 개발자들의 답변 정도가 일반적이기 때문이죠.그들의 답변...저는 개발자 포럼보다 StackOverflow를 더 선호합니다. 참여하는 개발자 규모가 다르기 때문에 보다 양질의 정보를 빠르게 찾을 수 있습니다. (하지만 허위 정보도 존재합니다.) Vote 시스템으로 신뢰 높은 정보를 필터링할 수 있으나, 어떤 정보를 선택할지는 당신의 몫입니다.6. iTunesConnect와 친하게 지내세요.앱을 개발했다면, iTunesConnect를 통해 앱을 전 세계의 사용자들에게 배포할 수 있습니다. iTunesConnect는 iOS용으로 개발된 바이너리를 배포하는 등 앱 배포/테스트와 관련된 전반적인 사항들을 관리할 수 있는 포털입니다. AppStore에서 앱을 판매하려면 이 iTunesConnect를 통해 애플과 계약을 해야만 가능합니다. 출시할 앱을 등록하기도 하고, 앱의 사용자들이 어떤 경향을 보이는지 Trend Analysis를 확인할 수도 있습니다.iTunesConnectiTunesConnect에는 다양한 메뉴들이 있고, 앱을 배포하고 관리하는데 필요한 여러 툴이 있으므로 개발 중에 시선을 환기하고자 한다면 iTunesConnect를 한 바퀴 둘러보는 것도 좋습니다. 언젠가는 다 사용하게 될 테니까요.7.앱 개발을 마쳐도 XCode를 사용하세요.앱을 개발하고 iTunesConnect에 업로드하려면, XCode를 통해 간접적으로 바이너리를 업로드하게 됩니다. 서드파티 앱을 사용할 수도 있지만, 제가 주로 많이 사용하는 방식은 XCode입니다. 소스코드가 준비되었다면, XCode 메뉴의 Product > Archive 메뉴를 선택해 XCode가 배포용 앱을 빌드합니다. 빌드가 완료되면, 자동으로 Organizer 창이 열리면서 앱을 업로드할 수 있게 되죠. 이 때 미리 구매한 개발자 계정의 인증서가 준비되어 있어야 합니다. 모든 준비가 완료되고 아카이빙이 완료되면, Organizer의 Archives 탭에서 우측단의 ‘Upload to App Store…’ 버튼으로 바이너리 업로드를 진행할 수 있습니다.8.배포 전에 시험비행을 해봅시다.앱을 개발했다면, 테스트플라이트(TestFlight)를 통해 실제로 앱을 배포하기 전 ‘시험비행’을 할 수 있습니다. iTunesConnect에 관련 테스터들을 등록하고, 등록된 사용자들을 대상으로 미리 앱을 테스트할 수 있도록 요청하는 것이죠. 이 테스트플라이트에 배포된 바이너리를 그대로 AppStore에 배포하게 되므로, 테스트용으로 유용합니다.TestFlight테스트플라이트는 원래 iOS 배포 관리 솔루션을 제공하는 업체였지만 지금은 애플이 인수해 iTunesConnect에서 관리하도록 제공하고 있습니다.9.앱이 죽는다면 Organizer로 확인하세요.iOS는 충돌보고 Crash Report를 Organizer를 통해 오류를 확인합니다. 앱을 설치한 사용자가 동의하면 XCode는 iOS가 앱을 실행하면서 발생한 Crash Report를 애플에 자동으로 업로드합니다. 업로드된 Crash Report들은 XCode의 Organizer를 통해 다운로드하고, 확인할 수 있습니다. Organizer는 XCode > Window > Organizer 항목에서 실행하세요.Organizer와 Crash ReportCrash Report는 Organizer의 상단 Crashes 탭에서 확인이 가능합니다. 또 현재 보고 있는 Crash Report의 어느 부분에서 오류가 발생했는지 알고 싶다면 우측단의 ‘Open in Porject…’ 버튼을 눌러보면 됩니다.10.내 친구 XCode최근 XCode는 메이저 업데이트를 통해 사용성과 퍼포먼스를 향상시켰습니다. 하지만 이만큼 무겁고 느린 통합개발툴 IDE는 이클립스(Eclipse) 이후에 처음입니다. 안드로이드의 경우 IntelliJ 기반의 Android Studio로 쾌적한 개발환경을 제공하고 있는 반면, XCode의 업데이트는 퍼포먼스나 사용성 개선보다는 Swift의 메이저 버전 반영에 더 급급한 느낌입니다. (업데이트 때마다 속지만 ‘혹시 이번에는..’하고 또 속아 넘어갑니다.) XCode 사용을 위한 네 가지 팁을 소개합니다.1)XCode는 모노로그입니다.XCode는 로그를 따로 ‘예쁘게’ 볼 수 없습니다. 검은 화면에 흰 로그가 정리되지 않은 상태로 마구마구 출력됩니다. 개발자들에게는 쥐약같은 상황이죠. 이런 불편한 로그 출력 방식 때문에 저는 별도의 GlobalLogger 모듈을 작성해서 다음과 같은 스타일로 로그를 출력하도록 하고 있습니다.$$ BrandiLogger Error Log ##MESSAGE: Initial Parameter is not exist. ##LOCATION: BRLogPringer.swift @Line: 122 2)iOS개발자를 위한 휴식시간, 빌드 타임XCode의 빌드 타임은 개발자에겐 기나긴 휴식 시간입니다. 소스가 비대해질수록 퍼포먼스는 떨어지며, 담배 한 대를 태우고, 화장실에서 손을 씻고 들어와도 빌드가 절반도 안 된 상황을 마주할 겁니다. 빌드 타임을 줄이고자 구글링을 하면 몇 가지 팁을 발견할 수 있는데, 특히 빌드 타임을 가장 많이 단축할 수 있는 방법이 있습니다.짜잔! 공개합니다!먼저, 프로젝트 셋팅의 ‘Build Settings’ 항목에서 ‘Optimization Level’을 검색합니다. ‘Swift Compiler - Code Generation’ 항목을 찾을 수 있는데요. 여기서 Optimization Level의 Debug 항목을 ‘None’으로 설정하면, 빌드시간이 엄청나게 줄어든 것을 확인할 수 있습니다. Brandi iOS 버전의 소스코드는 원래 컴파일에 7분 이상이 소요되었지만, Optimization Level을 변경한 후 1분 내외로 단축되었습니다. Optimization Setting을 변경할 때는 꼭 Debug 항목만 변경하고, Release 버전은 기존 설정을 유지하는 것이 좋습니다. 그래야 빌드 과정에서의 버그를 막을 수 있기 때문이죠. 만약 이 설정으로 개발하던 도중 소스가 충돌되면 Command+Shift+K 단축키를 눌러 소스를 한 번 클린하고, 재빌드하세요. 충돌이 사라지는 경우가 많습니다. 빠른 빌드를 위해 종종 감수해야 하는 부분이기도 합니다. 3)Derived Data빌드가 자꾸 안되고 꼬일 때는 Derived Data 폴더를 삭제 해 보세요. Derived Data 폴더는 XCode > File > Project Settings(Workspace Settings) 항목에서 ‘Derived Data’ 항목 아래의 폴더 경로에서 접근할 수 있습니다. Derived Data 접근 경로Derived Data 폴더를 삭제하면 거짓말처럼 빌드 오류가 사라지는 기적을 만날 수 있습니다. 4)CocoaPods‘바퀴를 두 번 발명할 필요는 없다’는 격언이 있습니다. 이것을 개발에 적용하면 ‘잘 만들어진 라이브러리를 사용하라’ 정도가 되겠습니다. 개발자의 개발 시간을 현저하게 단축시키는 오픈소스 라이브러리. 이것들을 간편하게 사용하는 방식이 iOS에도 존재하는데, 바로 CocoaPods입니다. 프로젝트 Root 폴더에 Podfile을 생성하고, 원하는 오픈소스 라이브러리들을 명시한 후에 ‘pod install’ 명령어를 입력해주면….CocoaPods오픈소스 라이브러리가 설치되었습니다. 귀찮은 소스 다운로드와 임포트 과정을 거치지 않아도 됩니다. CocoaPods 설치와 사용에 관한 글은 구글링으로 쉽게 찾을 수 있습니다. 꼭 사용하길 권합니다.Mac App Store에서의 XCode 평점XCode는 느리고 불편합니다. 숨겨진 편의기능도 많지만 고질적인 빌드 문제와 사용성 문제를 마주하면 높은 평점을 줄 수가 없습니다. 그런데, 저만 그렇게 생각하진 않더라고요.(위 스크린샷 참조) XCode의 사용법은 기회가 되면 따로 정리하겠습니다.11.어떤 경우에도 대응할 수 있는 화면 구성을 원한다면, AutoLayoutiOS를 사용하면서, 금융권이나 쇼핑 앱들을 사용하다 보면 이런 상황이 발생합니다. 금융권 앱. 화면에 꽉 차지 않는 레이아웃 혹은 비정상적으로 커진 글씨본래 iOS는 단일 디바이스를 지향하는 플랫폼이었습니다. 아이폰 시리즈도 해상도가 변하지 않았기 때문에, 디바이스 종류가 많은 안드로이드처럼 다양한 스크린 사이즈를 지원할 필요가 없었습니다. 하지만 이제는 iPhone SE, iPhone 8, iPhone 8 Plus의 해상도에 iPhone X의 해상도까지 더해지면서 그야말로 ‘해상도 춘추전국시대’가 되었습니다.이런 다양한 해상도를 모두 지원하는 레이아웃을 구성하려면, iOS에서는 AutoLayout을 사용해야 합니다. AutoLayout은 Xib Editor에서 AutoLayout을 활성화하는 방식으로 사용할 수 있습니다. 거기에 한 가지 덧붙이면 Layout Constraints라는 개념도 있습니다. 레이아웃에 조건을 주는 방식입니다. 예를 들어 ‘어떤 해상도에서든 이 컴포넌트는 왼쪽 끝으로부터 10Point의 여백을 가지도록 한다’ 라는 식이죠. AutoLayout, Layout Constraint이 Layout Constraint를 이용하면 짧은 시간 안에 다양한 해상도를 지원하는 레이아웃을 쉽게 만들 수 있습니다. 가히 AutoLayout의 꽃입니다.ConclusionXCode/iOS 개발과 관련된 팁은 대부분 구글링으로 찾을 수 있습니다. 다룰 내용이 많지만 초보 iOS개발자들이 당황할 수 있는 내용을 중심으로 글을 썼습니다. 소소한 이야기지만, 분명 도움을 받을 수 있을 겁니다.글이정환 과장 | R&D 개발1팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #iOS #개발기 #업무환경 #인사이트 #경험공유 
조회수 396

프로그래밍 수업의 모든 것 — 엘리스 코스 매니저 인터뷰.

안녕하세요 엘리스입니다:)엘리스의 프로그래밍 수업은 누구에 의해서, 어떻게, 어떤 생각을 바탕으로 만들어질까요? 미래를 이끌어나갈 컴퓨터 사이언스 기술과 그 근간이 되는 교육 사이에서 좋은 프로그래밍 수업을 만들기 위해 치열하게 고민하는 엘리스의 코스 매니저가 직접 이야기합니다! 마침 엘리스는 코스 매니저 채용 중에 있으니 관심이 있다면 눈여겨 봐주세요.코스 매니저가 관여한 프로덕트로 인하여 사용자가 성장을 하고 있다면 그것은 충분히 의미 있는 일.# 안녕하세요 저는,“트라우마를 극복한 프로그래밍 수업 크리에이터.”Q. 자기소개 부탁드려요.A. 엘리스의 프로그래밍 과목을 만드는 코스 매니저 이용희입니다.Q. 엘리스에서 일하게 된 이유는 무엇인가요?A. 원래는 프로그래밍에 대한 트라우마가 있었어요. 하지만 기술 창업에 대한 꿈이 있었기 때문에 프로그래밍은 극복해야 할 산이었죠. 엘리스는 가장 뛰어난 기술자들이 모여 창업한 스타트업이에요. 당연히 기술 창업을 가장 가까이에서 경험할 수 있는 매력적인 곳으로 느껴졌죠. 그리고 프로그래밍 교육을 제공한다는 것 역시 기회로 느껴졌어요. 저와 같이 프로그래밍을 미워하고 두려워하는 사람들에게 보다 쉽게 배울 수 있는 환경을 마련해주고 싶다는 기대로 일을 시작하게 되었습니다.Q. 두려운 대상을 향해 몸을 던지셨군요! 그런데 코스 매니저가 프로그래밍을 몰라도 되나요?A. 많이 알면 알수록 당연히 좋아요. 많이 알고 있을수록 시도할 수 있는 것도 많고 학생에게 전달해줄 수 있는 것은 더욱더 많기 때문에요. 하지만 최소한으로는 Class가 뭔지 알고 있으면 OK. 예를 들어서 코드를 보고 이 코드가 어떤 목적을 갖는지 알 수 있으면 직접 코딩을 하지는 못한다고 해도 괜찮아요.Q. 코스 매니징 외에도 라이브 수업 참여, 조교, 챌린지 사회자 등 많은 역할을 하셨는데 이유가 있나요?A. 좋은 수업을 만들기 위한 첫 번째 방법은 코스를 만드는 모든 과정에 참여하는 사람들의 역할을 직접 체험해 보는 것이라고 생각했어요. 학생으로서, 조교로서, 사회자나 라이브 어시스턴트로서. 이렇게 하니까 학생으로서 수업을 접할 때의 감상은 무엇인지, 조교로서 가르쳤을 때는 어떤 어려움이 있는지를 알 수 있었어요. 라이브 수업 어시스턴트로 참여했을 때는 방송하시는 선생님들의 애로사항을 알 수 있겠더라고요.# 코스 매니징의 정수.“프로그래밍적 성장을 도움으로써 가치를 만들어 냅니다.”Q. 코스 매니징의 A to Z는? 구체적인 업무 프로세스가 궁금해요.A. 크게 기획 — 모집 — 제작 — 분석의 네 단계로 이루어져 있어요.수업 기획 — 어떤 과목을 만들 것인가? 주차별로 무엇을 다룰 것인가? 흥미로운 콘텐츠는?선생님, 조교 모집 — 엘리스가 구상한 수업을 가장 잘 전달할 수 있는 선생님과 조교를 모집.수업 제작 및 운영 — 실습 문제, 강의 자료 등을 엘리스의 색깔로 제작하여 수업을 운영.데이터 분석 — 학생들의 피드백과 데이터를 다음 수업의 발전 및 교육자와의 관계 개선에 반영.Q. 업무 방식은? 어떤 메리트가 있나요?A. 처음부터 끝까지 모든 과정을 주도해나가는 방식이에요. 어떤 회사를 가도 프로덕트의 end to end 프로세스를 전부 경험하기는 어려운데 엘리스에서는 그 전 과정을 경험할 수 있어요. 저는 이러한 경험이 교육 업계나 특정 프로덕트에만 적용할 수 있는게 아니라 다른 업계에 간다고 하더라도 충분히 전환될 수 있는 좋은 경험이라고 생각해요.Q. 미래 산업의 근간이 될 교육을 직접 만든다는 중책을 맡고 계신다고 생각하는데요, 좋은 프로그래밍 수업을 만들기 위해 어떤 노력들을 하시나요?A. 그런 영향을 미칠 수 있다는 게 무서운 일인 것도 같아요. 어떤 사람들은 엘리스를 통해서 프로그래밍을 처음 접하는 것일 수도 있는데 그 경험이 불쾌했다면 앞으로 프로그래밍을 배울 생각이 전혀 들지 않을 수도 있는 거잖아요. 그래서 최대한 다양한 피드백을 받아서 수렴하려고 해요. 외적으로는 대학강의, 수많은 수업들을 참고해요. 여러 강의를 보다보면 좋은 예도 많지만 모든 수업이 재미있지는 않아요. 중간에 듣다 마는 경우도 있고요. 그럴 때마다 내가 왜 중단했고 어떤 요소를 바꾸면 엘리스에서는 학생들이 끝까지 들을 수 있을까 고민해서 반영하려고 하죠.Q. 언제 보람을 느끼나요?A. 내가 관여한 프로덕트가 누군가에게 임팩트를 만들어내고 나뿐만 아니라 프로덕트를 사용하는 사람들이 성장을 하고 있다면 그것은 충분히 가치 있는 일인 것 같아요. 저희 플랫폼에서는 대시보드를 통해서, 그리고 학생이 코드를 어떻게 짜고 있는지 보면서 그 결과를 가시적으로 확인할 수 있어요. 누군가 제가 만든 코스를 수강함으로써 실질적으로 성장하는 게 눈에 보일 때 가장 큰 보람을 느끼는 것 같아요.한 번은 한 선생님께서 학생으로부터 ‘선생님 덕분에 취업할 수 있었어요’라는 메시지를 받은 것을 엘리스와 공유해주셨는데 그때 정말 행복하더라고요. 이게 엘리스가 추구하는 거다,라는 생각을 했어요. 엘리스도 하나의 커뮤니티이고 싶거든요. 이 경우에는 학생-선생님-엘리스가 서로의 영향으로 좋은 결과를 만들어 낸 거죠. 이런 접점을 앞으로 더 많이 만들려고 생각하고 있어요.대시보드에 나타나는 학생들의 학습 현황 및 성취도.# 엘리스는 이런 팀.“가치, 성장, 사람. 포기할 수 없는 세 가지가 있는 곳.”Q. 함께 일하는 동료들은 어떤 사람들인가요? 총평을 하자면?A. 항상 내가 최고의 사람들과 함께하고 있다라는 확신이 있어요. 각자 자기 분야에서 최고의 실력을 가진 사람들과 함께 일한다는 것만으로도 큰 자극이 되죠. 프로그래밍이든 스타트업 생존 노하우든 항상 뭔가를 새롭게 배우고 성장하게끔 동기부여를 해주는 사람들이에요. 저는 트라우마가 있었을 정도로 프로그래밍을 두려워했지만 이들과 함께 일하며 작은 피드백을 하나 듣는 것만으로도 제 실력이 빠르게 성장한다는 것을 몸소 느낄 수 있었어요. Q. 엘리스의 분위기, 팀 문화는 어떤가요?A. 새로운 것에 도전하는 것을 환영하는 수평적이고 자유로운 팀. 인턴도 아이디어를 제시할 수 있어요. 이 다음이 더 중요한데, 아이디어에서 그치는 게 아니라 활발한 피드백이 오가요. 아이디어를 실행하기 어렵다고 판단하더라도 왜 그렇고 어떻게 발전시킬 수 있는지 이야기하죠. 실행하게 되었을 때는 아이디어를 제시한 사람에게 일에 대한 권한이 전적으로 주어지고요. 저도 처음엔 파트타임 인턴이었지만, 이런 팀문화 덕분에 계속해서 업무 범위를 확장하고 제 역량을 키울 수 있었어요.# 코스 매니저 채용.“Generalist & Infinite Learner”Q. 현재 코스 매니저를 구인 중인데요. 코스 매니저에 적합한 성향이 있나요?A. Generalist, 그리고 Infinite Learner. 깊게 한 분야를 아는 사람보다는 얕고 넓게 아는 사람이 더 적합하다고 생각해요. 다르게 말하면 새로운 것을 시도하는 것을 좋아하고 새로운 것을 접할 때 포용력이 높은 사람이요. 두 번째로는 배움에 재미를 느끼는 사람. 엘리스는 교육 스타트업이고 코스 매니저는 직접 교육의 경험을 만드는 사람이니 스스로가 배움에서 행복을 느끼는 사람이라면 훨씬 더 재미있게 일할 수 있겠죠. 한 가지 덧붙이면, 데이터 분석을 배우고 싶은 분께 엘리스는 최고의 장소입니다.Q. 코스 매니저로서 갖추고 있으면 좋은 역량이나 자질이 있다면?A. 소통 능력과 균형 감각. 코스 매니저는 수업을 만드는 모든 단계에서 다양한 이해당사자들과 일하게 돼요. 이들과 원활하게 소통하고 의견을 공유하는 게 중요하죠. 그리고 다양한 사람들 사이에서 최고의 균형을 찾아내는 것도 중요해요. 예를 들어서 선생님의 경우 개발만 해왔고 교육이라는 것을 접해본 적이 없는 분들이 대부분이고, 학생은 프로그래밍을 처음 접하면 그 수업이 좋은 건지 아닌지 평가하기 어려워요. 때문에 코스 매니저가 이 둘 사이에 다리를 놓는 중재자의 역할을 하기 위해서는 다양한 시각에서 볼 수 있는 균형 감각이 필요하다고 생각해요.최고의 실력자들과 함께 일하며 프로덕트의 처음부터 끝까지를 만드는 경험을 통해서 사람들의 성장을 돕는 가치를 창출하고 싶으신 분이라면,>> 코스 매니저에 도전해 보세요! <<#엘리스 #코딩교육 #교육기업 #기업문화 #조직문화 #서비스소개 #팀원인터뷰 #팀원소개
조회수 2526

BLSTM Tutorial

Summary:이 포스팅은 Bidirectional LSTM에 대한 기본 개념을 소개하고, tensorflow와 MNIST 데이터를 이용하여 구현해 봅니다.Bidirectional LSTM1. 개념 설명앞에서 RNN 과 LSTM 모델에 대해 소개했습니다.기본적인 LSTM 모델은 이전 시간의 step들이 다음 step에 영향을 줄 것이라는 가정을 했습니다.하지만 이후의 step 또한 앞의 step 에 영향을 줄 수 있다면 이 모델을 어떻게 적용시킬 수 있을까요?이후의 step 의 영향도 반영한 모델이 Bidirectional LSTM 모델입니다.위의 그림과 같이 BLSTM 은 두 개의 LSTM 모델을 Concatenate 하여 사용합니다.Time step 이 1부터 t 까지 있다고 가정할 때 forward lstm model 에서는 input 을 Time step 이 1 일때부터 t 까지 순차적으로 주고 학습합니다.반대로 backward lstm model 에서 input 을 T = t 일때부터 1까지 거꾸로 input 주고 학습을 하게 됩니다.time step 마다 두 모델에서 나온 2개의hidden vector은 학습된 가중치를 통해 하나의 hidden vector로 만들어지게 됩니다.2. 구현전체 코드는 Github page 를 참고해주세요.MNIST image 를 input 으로 넣었을 때 이 image 가 0 에서 9 중에 어떤 숫자인지 맞추는 BLSTM 모델을 만들어 보고자 합니다.MNIST 는 0 - 9 의 숫자 image data 이며 각 데이터는 28 x 28 의 matrix (data 는 28 x 28 길이의 array) 로 이루어져 있습니다.앞에서 봤듯이 LSTM 은 sequence 형태를 요구합니다.그래서 데이터 하나를 한 번에 넣는 것이 아니라 각 데이터의 matrix 를 row 만큼, 즉 28번의 time step 으로 나누어 넣어주게 됩니다.그래서 input_sequence 를 28 길이로 설정합니다. learning_rate = 0.001 training_epochs = 10 # 전체 데이터를 몇번 반복하여 학습 시킬 것인가 batch_size = 256 # 한 번에 받을 데이터 개수 # model # 입력되는 이미지 사이즈 28*28 input_size = 28 # input size(=input dimension)는 셀에 입력되는 리스트 길이 input_steps = 28 # input step(=sequence length)은 입력되는 리스트를 몇개의 time-step에 나누어 담을 것인가? n_hidden = 128 n_classes = 10 # classification label 개수 X = tf.placeholder(tf.float32,[None, input_steps, input_size]) Y = tf.placeholder(tf.float32,[None, n_classes]) W = tf.Variable(tf.random_normal([n_hidden * 2, n_classes])) b = tf.Variable(tf.random_normal([n_classes])) X 는 28 x 28 의 matrix 로 이루어진 데이터를 받고 Y 는 실제 class (0 - 9) 를 의미하는 length 10 의 vector 를 받습니다.그리고 각 forward lstm 모델과 backward lstm 모델에서 들어오는 weight 값을 받을 변수를 설정합니다.DropoutWrapper 는 모델에서 input 으로 주어진 data 에 대한 Overfitting 이 발생하지 않도록 만들어주는 모델입니다.각 state 를 랜덤하게 비활성화시켜서 데이터를 더 random 하게 만들어줍니다. keep_prob 변수를 통해서 dropoutWrapper 의 확률값을 조정합니다.keep_prob = tf.placeholder(tf.float32) forward lstm 과 backward lstm 에서 사용할 cell을 생성합니다# lstm cell 생성 lstm_fw_cell = tf.nn.rnn_cell.LSTMCell(num_units = n_hidden, state_is_tuple = True) lstm_fw_cell = tf.nn.rnn_cell.DropoutWrapper(lstm_fw_cell, output_keep_prob=keep_prob) lstm_bw_cell = tf.nn.rnn_cell.LSTMCell(num_units = n_hidden, state_is_tuple = True) lstm_bw_cell = tf.nn.rnn_cell.DropoutWrapper(lstm_bw_cell, output_keep_prob=keep_prob) 학습할 모델을 생성합니다outputs,_ = tf.nn.bidirectional_dynamic_rnn(lstm_fw_cell,lstm_bw_cell, X, dtype = tf.float32) 기존의 lstm 과 달리 output 이 2개의 LSTMStateTuple 로 이루어져 있습니다.각 output 에 가중치를 더해서 하나의 output 으로 만들어주는 과정이 필요합니다.여기서 가장 헷갈리는 부분이 transpose 입니다. 왜 output 에 대해서 transpose를 하는 것인지 의문이 들 수 있습니다.tf.nn.bidirectional_dynamic_rnn 문서를 보시면 output 의 default 는 [batch_size,max_time,depth] 라고 나와있습니다.각각 mini batch 의 크기 그리고 time step, hidden state 의 depth 를 의미합니다.우리는 각 데이터마다 마지막 time step 의 결과값을 output 으로 선택해야 합니다.그래야지 전체 step 이 반영된 output 을 얻을 수 있습니다.outputs_fw = tf.transpose(outputs[0], [1,0,2]) outputs_bw = tf.transpose(outputs[1], [1,0,2]) pred = tf.matmul(outputs_fw[-1],w_fw) +tf.matmul(outputs_bw[-1],w_bw) + biases matmul operation 연산 속도를 위해서 다음과 같이 하나의 output 으로 먼저 합치고 전체에 대한 가중치를 주는 것이 더 좋은 방법입니다.outputs_concat = tf.concat([outputs_fw[-1], outputs_bw[-1]], axis=1) pred = tf.matmul(outputs_concat,W) + b 이하 코드는 이전의 tutorial 과 동일합니다.
조회수 9475

AWS 비용 얼마까지 줄여봤니?

최근 들어 스타트업의 인프라는 DevOps의 유행과 함께 IDC에서 클라우드로 급속도로 이전해가고 있습니다. 많은 클라우드 업체가 있지만 그중에서도 Amazon Web Service (AWS) 가 가장 선호되고 있고 잔디도 AWS를 이용하여 서버 인프라를 구성하고 있습니다. 하지만 AWS 비용은 예상보다 만만치 않습니다. 잔디에서는 비용을 줄이기 위해 여러 가지 노력을 하고 있는데 이 글에서는 스케쥴링 기능을 이용하여 비용을 줄이는 방법에 대해 공유하도록 하겠습니다.AWS는 저렴한가?AWS는 ‘저렴한 비용’을 자사 서비스의 큰 강점이라고 홍보하지만 실제 사용해보면 막상 ‘과연 정말 저렴한가?’ 라는 의문을 가지게 됩니다. 여러 클라우드 업체의 비용을 비교한 리포트를 보더라도 AWS는 절대 저렴하지 않습니다. 오히려 클라우드 업체 중 가장 비싼 곳 중 하나입니다. 그렇다고 이제 와서 클라우드 업체를 옮기는 건 배보다 배꼽이 더 클 수도… (들어올때는 맘대로지만 나갈땐 아니란다.)예약 인스턴스? 스팟 인스턴스? 온디맨드?AWS에서는 제공하는 요금 할인 방법은 예약 인스턴스나 스팟 인스턴스를 이용하는 것입니다.예약 인스턴스는 계약 기간에 따라 최대 60%까지 저렴한 가격으로 이용할 수 있습니다. 하지만 정확한 기간과 수요예측을 하지 못한다면 잉여 인스턴스가 될 수 있습니다.스팟 인스턴스는 입찰가격을 정해놓고 저렴할 때 이용할 수 있습니다. 하지만 그때가 언제일지도 알 수 없고 인스턴스를 가져갔다고 하더라도 더 높은 입찰가격을 제시한 사용자에게 인스턴스를 뺏길 수 있습니다. 마치 KTX를 입석 티켓으로 빈 좌석에 앉아서 가다가 좌석 티켓 주인이 나타나 ‘내 자린데요?’ 하면 얄짤없면 좌석을 내줘야 하는 느낌입니다. 그때 느끼는 그 서러움은 느껴보지 못한 자는 알 수 없습니다.온디맨드는 사용한 만큼 할인 없이 비용을 지불하는 것입니다. 언제든지 필요할 때 사용하고 사용한 만큼만 과금되어 가장 적절해 보이지만 예약이나 스팟에 비해 역시나 비쌉니다. 비싸지만 현실적으로 가장 많이 사용됩니다.개발서버는 얼마 안쓰는데 좀 깍아줘!일반적으로 개발서버도 라이브와 같이 구성합니다. 고가용성은 고려하지 않더라도 아키텍쳐는 똑같이 구성하게 됩니다. 그리고 아키텍쳐가 복잡해질수록 구성하는 서버도 많아지고 언제부턴가는 개발서버도 비용을 무시할 수 없는 수준에 이르게 됩니다. 하지만 개발서버는 24시간 사용하지도 않고 업무시간에만 사용합니다. 이쯤 되면 한 번쯤 이런 생각을 하게 됩니다. ‘개발서버는 실제로 얼마 쓰지도 않는데 좀 깍아줘야 되는 거 아냐?’ 개발서버뿐만 아니라 정해진 시간만 사용하는 모든 서버들이 해당될 것입니다.EC2 SchedulerAWS는 이러한 원성(?)을 들었는지 EC2 Scheduler 라는 간단한 솔루션을 소개했습니다. 내용을 보면 설정된 시간과 요일에 자동으로 EC2 인스턴스가 자동으로 켜지고 꺼집니다. 하루 10시간 가용한다면 주말 제외 월~금요일만 작동시켜 비용을 70%나 절감할 수 있습니다.이대로만 된다면 왠만한 스팟이나 예약 인스턴스보다 더 저렴하게 개발서버를 이용할 수 있습니다. 하지만 이 솔루션을 그대로 도입하기에는 문제점들이 있었습니다.EC2 Scheduler 의 문제점EC2 Scheduler는 다음과 같은 문제점들이 있습니다.서버 아키텍쳐에 따라서 의존성이 있어 서버 실행 순서가 보장되어야 하는 경우가 고려되지 않는다.단순히 EC2 한두 대 띄워서 사용하는 게 아니고 훨씬 더 복잡한 서버 의존 관계를 가지게 됩니다. 예를 들어 DB -> Middleware -> API -> Batch 같은 관계가 있다고 한다면 의존관계에 있는 서버들이 순차적으로 실행되어야 합니다.스케쥴 시간이 UTC로만 작동한다.UTC로만 작동하기 때문에 시간 설정을 할 때는 항상 UTC 기준으로 변환해야 하는 불편함이 있습니다.스케쥴링의 예외적인 상황이 고려되지 않는다.평일이 공휴일인 경우에는 서버를 작동할 필요가 없고 평소보다 서버를 일찍 켜야 하거나 야근을 하게 되어 중지 시간을 변경해야 되는 경우에는 해당 일자에만 변경이 가능해야 했습니다.EC2에 대해서만 작동하도록 되어 있다.EC2보다 비싼 RDS도 최근에 Stop 시킬 수 있도록 추가되었습니다. Aurora는 미지원잔디의 서버 아키텍쳐는 훨씬 복잡하여 서버의 실행 순서가 맞지 않으면 정상작동을 하지 않기 때문에 1번은 반드시 해결되어야 하는 가장 치명적인 문제였습니다.AWS Instance SchedulerEC2 Scheduler의 문제점을 보안한 Instance Scheduler를 소개하겠습니다. EC2나 RDS 모두 하나의 서버를 Instance로 부르기 때문에 Instance Scheduler라 하였습니다. Instance Scheduler는 Serverless 아키텍쳐인 Cloudwatch + Lambda를 이용하여 구성되어 있습니다.작동방식Cloudwatch Event를 이용하여 Lambda를 함수를 실행시키고 Dynamo DB에 저장된 스케쥴 정보와 Instance의 Tag 값을 기반으로 RDS와 EC2를 조회하고 Instance를 시작하거나 중지합니다. 그리고 JANDI의 Incoming Webhook을 이용하여 토픽에 알림 메시지를 보내줍니다.Cloudwatch EventInstance Scheduler Lambda 함수를 작동시키는 트리거는 Cloudwatch Event를 이용합니다. 5분마다 작동시키도록 되어 있으며 각각의 사용 환경에 따라 변경할 수 있습니다.Cron 식 0/5 * * * ? *, 대상은 Instance Scheduler Lambda를 지정합니다.Dynamo DBDynamo DB에는 Schedule, Schedule 예외 설정, Schedule 서버 그룹에 대한 정보가 정의되어 있습니다.1. ScheduleSchedule 작동에 대한 기본 정보를 정의하고 있습니다.{ "ScheduleName": "Development", "TagValue": "Development", "DaysActive": "weekdays", "Enabled": true, "StartTime": "09:30", "StopTime": "22:00", "ForceStart": false } ScheduleNameSchedule 이름 입니다.TagValue적용 대상 Instance를 조회할 때 참조하는 Tag 값입니다. Instance를 Schedule에 적용 대상에 포함시키기 위해서는 해당 Instance의 Tag에 ScheduleName이라는 Key에 TagValue를 Tagging 하면 됩니다.DaysActiveSchedule 적용 요일입니다. 아래와 같은 옵션이 적용됩니다.all : 매일weekdays : 월~금mon,wed,fri : 월,수,금요일EnabledSchedule의 작동 여부입니다.StartTime, StopTime서버 시작 시간과 중지 시간입니다.ForceStartSchedule 강제 시작 여부를 나타냅니다. (Enabled 여부에 상관없이 작동합니다.)2. Schedule Server Group하나의 Schedule에는 N 개의 서버 그룹을 정의할 수 있고 각각은 먼저 실행되어야 하는 의존관계 서버 그룹을 정의하고 있습니다. 의존관계에 있는 서버 그룹의 Instance Status를 확인하여 시작 여부를 결정하도록 하였습니다. 그러면 의존관계가 없는 서버 그룹부터 시작하고 의존관계의 Depth 가장 깊은 서버 그룹은 가장 늦게 시작하게 되어 서버 실행 순서를 보장하게 됩니다.{ "Dependency": [ "GROUP1", "GROUP2", "GROUP3", "GROUP4" ], "GroupName": "GROUP5", "InstanceType": "EC2", "ScheduleName": "Development" } Dependency의존관계 서버 그룹 목록입니다.GroupName서버 그룹 이름입니다.InstanceTypeEC2와 RDS를 지원합니다.3. Schedule Exception공휴일이나 야근 등으로 인해 스케쥴을 미작동 시키거나 시간을 변경해야 하는 경우에 예외사항들을 정의하고 있습니다.{ "ExceptionUuid": "414faf09-5f6a-4182-b8fd-65522d7612b2", "ScheduleName": "Development", "ExceptionDate": "2017-07-10", "ExceptionType": "stop", "ExceptionValue": "21:00" } ScheduleName예외 적용 대상 Schedule의 이름입니다.ExceptionDate예외발생일 (YYYY-MM-DD)ExceptionTypestart : 시작stop : 중지ExceptionValueNone : 미작동H:M : 변경시간LambdaInstance Scheduler의 Lambda 코드는 Python으로 개발되었으며 Github에 오픈소스로 공개하였습니다. boto3는 배포 package에 Dependency를 추가하지 않아도 Lambda 실행환경에서 가용 라이브러리로 사용할 수 있습니다. 하지만 현재 기본적으로 사용할 수 있는 boto3 버전에서는 RDS Instance를 stop 할 수 있는 함수가 없기 때문에 최신 버전이 필요합니다. 따라서 boto3 버전을 변경하여 함께 packaging 하여 업로드하여야 합니다. 배포는 Lambda 관리 도구인 Apex를 이용합니다. Apex를 이용하면 Dependency package 및 Lambda 생성 및 업데이트, 환경 변수 설정 등을 모두 한 번에 할 수 있습니다.참조 : Lambda Execution Environment and Available LibrariesAWS SDK는 Python boto3 (botocore:1.5.75, boto3:1.4.4) 를 이용합니다.TimeZone 설정Lambda는 기본적으로 UTC TimeZone으로 설정되어 있으며 Instance Scheduler에서는 TimeZone을 변경할 수 있도록 하였습니다. 기본 설정은 Asiz/Seoul이고 아래 코드를 수정하여 변경할 수 있습니다.os.environ['TZ'] = 'Asia/Seoul' time.tzset() JANDI 메신저와 연동Instance Scheduler는 JANDI 메신저의 Incoming Wehbook 을 이용하여 Webhook URL을 Lambda의 환경 변수에 설정하면 서버의 시작과 중지에 대한 알람과 중지 10분 전부터 곧 서버가 중지된다는 알람을 발송하여 필요하다면 서버 중지 시간을 연장할 수 있도록 합니다.Incoming Webhook 설정JANDI의 토픽에서 Incoming Webhook을 연결하고 Webhook URL을 복사합니다.배포된 Lambda 함수의 Code 탭에서 Environment variables에 WEBHOOK_URL을 설정하거나 function.json에서 변경 후 재배포 하여도 됩니다.Instance Scheduler 알람서버 그룹이 시작되면 아래와 같이 알람 메시지를 표시합니다.서버가 중지되기 전에 알람 메시지를 표시합니다.정리Instance Scheduler는 EC2 Scheduler에 비해서 다음과 같은 기능이 추가되었습니다.스케쥴 시간의 타임존 적용서버 그룹 설정 및 의존관계 설정스케쥴의 예외 설정RDS 스케쥴 추가스케쥴에 상관없이 강제 시작 및 중지메신저로 상태 알람EC2 Scheduler에 비해 아쉬운 부분이나 예외사항에 대해서 좀 더 유동적으로 대응할 수 있도록 개선하였습니다.다음 장에는 스케쥴을 컨트롤을 위한 Bot 적용기를 소개하도록 하겠습니다.#토스랩 #잔디 #JANDI #AWS #서버개발 #개발 #개발자 #개발팀 #경험공유 #인사이트 #후기 #일지
조회수 986

HyperCut으로 인물사진 필터를 만들었습니다

얼마전 하이퍼커넥트의 아이디어 제안 채널에서 나온 이야기입니다.mel 은 사업그룹의 터키지역 담당 팀에 있는 친구인데, 꾸준히 좋은 제안과 아이디어를 주는 훌륭한 동료입니다. 이번에는 최근 여러 스마트폰이나 사진 앱들에서 나타나기 시작한 인물사진 모드 를 아자르에서도 지원하는게 좋겠다는 제안이었습니다.스마트폰이 자체 기능으로 인물사진 필터를 제공하는 경우는 보통 듀얼 카메라를 사용해 인물 외의 배경을 흐릿하게 만들어 심도를 표현합니다. 하지만 모두가 듀얼 카메라를 탑재한 스마트폰을 쓰는 것은 아니기 때문에, 이런 인물사진 모드를 소프트웨어적으로 구현하는 앱들도 존재합니다. mel 이 보여준 링크의 인스타그램도 그렇게 구현했네요.인물사진 모드를 소프트웨어적으로 구현하려면, 영상에서 얼굴을 포함한 사람을 배경으로부터 정확히 분리해 내는 기술이 필요합니다. 그리고 사진을 찍을 때에 실시간으로 프리뷰를 보아야 할테니까 이것을 실시간으로 처리할 수 있을 정도의 성능도 필요하구요.하이퍼커넥트에서는 머신러닝, 특히 영상과 이미지를 다루는 분야에 대해 지속적으로 투자와 연구를 해 왔습니다. 영상에서 인물을 분리해내는 문제는 크게 Image Segmentation 의 범주에 속합니다. 좀 더 직접적으로 Portrait segmentation 이라고 부를 수도 있습니다. 이를 잘 하기 위해서 하이퍼커넥트에서는 자체적인 학습 데이터를 만드는 것부터 시작하여 기술 개발을 지속적으로 추진해 왔고, 그 결과 Machine Learning 팀에서 이미 실시간으로 얼굴과 배경을 분리해내는 - HyperCut - 이라는 기술을 확보한 상태입니다. 아직 실제 서비스에 탑재되진 않았지만 이미 하이퍼커넥트의 주요 서비스인 아자르의 개발 버전에서는 HyperCut을 응용한 여러가지 이펙트를 사용할 수가 있습니다. 그리고, 그 중에 인물사진 모드 필터도 이미 있습니다.mel 의 제안이 있던 날 오후 아이디어 제안 채널에 이런 답이 달렸습니다.모델이 되어 주신 분은 하이퍼커넥트의 CTO 인 ken 이네요. 아자르 개발 버전에서 HyperCut 을 응용한 인물사진모드 필터를 사용하고 찍은 사진입니다. 아자르의 저장하기 기능을 사용했더니 UI 없이 오른쪽 아래에 아자르 로고만 남게 되었네요. 아직 실서비스에는 포함되지 않았지만, 최적화와 튜닝 과정을 거쳐 조만간 많은 사용자들이 HyperCut 을 사용한 이펙트를 쓸 수 있게 될 예정입니다.#하이퍼커넥트 #개발 #개발자 #아이디어 #아이디에이션 #구체화 #협업 #팀워크 #팀플레이
조회수 12631

Jekyll을 이용하여 github에 블로그 만들기

티스토리에서 여러 불편함들을 느껴 깃헙 블로그로 갈아타려고 한다. 자유도가 높아보여 티스토리에 블로그를 개설했으나 오히려 글이 노출되는 디자인이나 (줄간격, 글씨 크기 등등) 기존 테마를 변경하기에 불편했다. 결정적으로 gist 스크립트를 삽입했을 때 미리보기가 안돼서 고민 끝에 깃헙 블로그를 선택했다. 워드프레스도 개설해봤지만 왠지 모르게 마음에 안들어서 깃헙 블로그로 갈아타기로 마음먹었다. 그 후에 이것저것 알아보니 내 마음에 쏙 드는 요소들이 많았다.마음에 드는 부분git을 이용해 커밋, 푸시로 글을 포스팅함. 그 덕분에 블로그에 대한 모든게 로컬에 있고 모든 글들을 로컬에서 관리 할 수 있음.마크다운을 이용하여 글 작성. 글과 html을 마음대로 오갈 수 있어서 좋음. 마크다운 에디터가 없었다면 불편했겠지만 세상은 넓고 좋은 에디터는 많다..! 다만 이미지 삽입에서는 좀 불편.다른 웹 프로젝트처럼 웹스톰에서 블로그 관리 가능. 인텔리 제이를 사랑하는 나로서는 이 부분 또한 큰 장점.아무튼 이런 이유로 깃헙 블로그로 갈아타기로 결정. 구글링을 통해서 깃헙 블로그를 개설하는 방법에 대해 잘 정리해놓은 블로그를 찾았다. 놀부 블로그를 참고하여 깃헙 블로그를 개설했다. 아래에는 내가 보기 편하도록 더 간략하게 정리해보았다.깃헙 블로그 만들기 (Mac OS X)1. Jekyll 설치터미널에서 아래 명령어 입력으로 설치. $ sudo gem install jekyll2. 설치한 Jekyll을 이용하여 블로그 생성블로그를 만들고자 하는 위치에서 아래 명령어로 생성.$ jekyll new [github사용자명].github.com블로그 생성후 생성된 위치로 이동하여 아래의 명령어 실행 후 브라우저에서 http://localhost:4000으로 접속하면 로컬에 생성된 블로그를 볼 수 있음.$ jekyll serve --watch3. github에 온라인 저장소 만들기위에서 생성한 블로그 이름과 동일한 이름([github사용자명].github.com)으로 github에 온라인 저장소를 생성. 그 후 로컬에 있는 블로그와 만들어준 저장소를 remote 해주면 끝.$ git init$ git remote add origin [저장소URL]$ git add .$ git commit -m "Initialize Blog"$ git push origin master생성된 블로그는 http://[github사용자명].github.com으로 접속하면 볼 수 있다. 처음 생성하는 경우 몇 분의 시간이 걸리는 경우도 있다고 함.포스팅하기글은 _post 파일 안에 YYYY-MM-DD-[글 제목].markdown 형식으로 파일명을 지정하여 생성한 후 커밋, 푸시하면 업로드됨.테마 적용하기테마를 직접 만들기에는 시간이 너무 많이 소요되니 인터넷에 공유되어있는 테마를 사용하면 좋다. 테마를 적용하는 부분에서 여러모로 애를 먹었는데 제일 쉬운 방법은 테마가 올라가있는 저장소를 포크하여 [github사용자명].github.com으로 이름을 바꾸는게 제일 쉽다. 내 블로그는 심플한 테마를 적용하였다.다른 테마들은 Jekyll Themes 사이트에서 찾아볼 수 있다. 훨씬 이쁘고 좋은 테마들도 많음.Jeykll 더 알아보기Jeykll 공식 번역 사이트에서 몇 개의 문서를 읽어보면 더 다양하게 활용해 볼 수 있다. _config.yml파일이나 _post, _include, _layout 파일 정도는 기본으로 살펴보아야 함.#트레바리 #개발자 #안드로이드 #앱개발 #Jeykll #백엔드 #인사이트 #경험공유
조회수 2235

스포카 서버의 구조

안녕하세요. 스포카 개발팀에서 서버 관련 개발 업무를 담당하고 있는 문성원입니다. 오늘은 스포카 서버의 구조와 사용된 기술들에 대해서 함께 살펴보겠습니다.스택이란?먼저 스택(Stack)이란 용어에 대해서 함께 생각해보죠. 컴퓨터 과학을 공부하신 분들이라면 선입후출(FILO)이나 스택 오버플로우(Stack Overflow)등의 개념으로 익숙하실만한 용어기도 합니다. 그런데 서버 구조를 설명한다면서 왠 스택이냐구요? 다행히(?)도 지금부터 살펴 볼 스택은 솔루션 스택(Solution Stack)입니다. 스포카 서버라는 큰 솔루션이 원활히 동작하기 위해서 쓰이고 있는 각종 서브 시스템과 컴포넌트들의 묶음을 이야기하는 것으로 바꿔말하자면 이 글에서 다룰 기술 이야기는 모두 이 스택에 관한 이야기입니다.2011년 12월 현재 스포카 서버를 구성하고 있는 스택은 다음과 같습니다.DotcloudLinux 2.6.38.2nginx 0.8.53uwsgi 0.9.8.5Python 2.6.5Redis 2.2.2Celery 2.2.7Amazon Relational Database ServiceMySQL 5.5.12Amazon Simple Storage ServiceDotcloudDotcloud는 지금부터 설명드릴 스택을 묶어서 제공해주는 PaaS(Platform as a Service)의 일종입니다. Amazon Elastic Cloud Computing(Amazon EC2) 기반으로 동작하며 거기에 더해 손쉬운 확장과 배포가 장점입니다. 스포카 서버는 데이터베이스(Amazon RDS)와 업로드되는 데이터(Amazon S3) 이외의 모든 서비스를 Dotcloud를 통하여 제공하고 있습니다.nginx, uwsgi. 그리고 WSGI기본적으로 스포카 서버는 HTTP 형식의 요청을 받아 응답을 돌려주는 웹 어플리케이션입니다. 이러한 처리는 1차적으로 nginx를 통해 이뤄지는데, 이 중 서버사이드에서 처리가 필요한 경우에는 uwsgi라는 데몬이 이 처리를 담당합니다. (구버젼의 Apache Tomcat을 사용하시던 Java개발자분들은 Apache Tomcat과 Apache httpd와의 관계를 떠올리시면 편합니다.)이 경우 uwsgi는 일종의 어플리케이션 컨테이너(Application Container)로 동작하게 됩니다. 적재한 어플리케이션을 실행만 시켜주는 역할이죠. 이러한 uwsgi에 적재할 어플리케이션(스포카 서버)에는 일종의 규격이 존재하는데, 이걸 WSGI라고 합니다.(정확히는 WSGI에 의해 정의된 어플리케이션을 돌릴 수 있게 설계된 컨테이너가 uwsgi라고 봐야겠지만요.) WSGI는 Python표준(PEP-033)으로 HTTP를 통해 요청을 받아 응답하는 어플리케이션에 대한 명세로 이러한 명세를 만족시키는 클래스나 함수, (__call__을 통해 부를 수 있는)객체를 WSGI 어플리케이션이라고 합니다.정리하자면 스포카 서버는 WSGI에 맞게 작성된 프로그램을 nginx와 uwsgi를 통해 운용하여 요청을 처리하는 웹 어플리케이션이라고 할 수 있습니다.RedisRedis란 키-값(Key-Value) 저장 서버로 확장이 용이하며 속도가 우수합니다. 스포카 서버에선 이를 내부적인 임시 데이터 관리와 Celery의 작업(Task) 분배에 사용하고 있습니다.CeleryCelery는 Python으로 작성된 비동기 작업 큐(Asynchronous task queue/job queue)입니다. 앞서 소개한 작업(Task)를 브로커(Broker, 스포카 서버는 Redis를 사용)를 통해 전달하면 하나 이상의 워커(Worker)가 이를 처리하는 구조입니다. 포인트 적립-공유에 따른 분배처리, 포스팅 기능, 페이스북/트위터 공유등의 비동기 처리가 필요한 작업을 Celery에 위임하여 처리하고 있습니다.Amazon Relational Database Service대부분의 웹 어플리케이션과 마찬가지로 스포카 서버는 영속적으로 저장되어야하는 정보(회원 목록, 구매 내역)들을 디스크 기반의 데이터베이스(Database)에 저장합니다. Amazon Relational Database Service(Amazon RDS)는 Amazon EC2를 기반으로 그러한 데이터베이스를 간편하게 관리(모니터링, 백업, 접근제어)할 수 있게 도와주는 웹서비스입니다. Oracle과 MySQL을 지원하는데 스포카 서버는 그 중 MySQL을 사용하고 있습니다.Amazon Simple Storage ServiceAmazon Simple Storage Service(Amazon S3)는 Amazon RDS와 마찬가지로 Amazon EC2를 기반으로 한 데이터 저장 관리 서비스입니다. 스포카 서버에 업로드 되는 사진이나 문서등의 파일들을 통합하여 관리하여 서버의 인스턴스를 늘려 확장하는 경우에도 문제없이 대처할 수 있도록 하는 것이 주 목적입니다.#스포카 #스택 #개발 #개발자 #개발팀 #인사이트 #조언 #스킬스택 #스택설명
조회수 2165

Android Gradle Tips

안드로이드와 GradleAndroid 가 Gradle 을 이용하기 시작한 것도 3년이 다 되어 갑니다. 이제는 많은 유저가 당연히 Gradle 을 Android 기본 개발 환경으로 사용하고 있습니다.하지만 기본 설정으로만 Gradle 을 사용하는 사용자들이 많습니다. 게다가 구글에서 Android Gradle Build DSL 을 끊임없이 변경했기 때문에 많은 사용자들이 이를 이해하기도 전에 변경이 되는 경우가 매우 빈번했습니다.Gradle Dependency 분리하기안드로이드 자동화 툴위 두번의 포스팅을 통해서 TossLab 에서 사용하고 있는 Gradle 에 대해서 소개를 해드렸습니다.오늘은 Android 팀이 사용하는 Custom 설정들에 대해서 정리하도록 하겠습니다.1. 초기화 값 검증 및 설정하기개발자들이나 CI 에서 관리해야하는 속성 값에 대해서는 각각 다르게 설정할 필요가 있습니다.안드로이드 팀은 3개의 추가적인 속성값을 추가하여 사용하고 있습니다.# gradle.properties inhouse_version=2 # 배포/qa 버전의 hofix version 을 관리학 ㅣ위함 report_coverage=false # coverage 측정에 대한 on/off 기능 dev_min_sdk=21 # minSDK 의 개별적인 관리를 위함 위의 3개의 값은 존재 하지 않으면 빌드가 되지 않도록 하는 강제사항으로 만들었으나 새로운 개발자가 입사하게 되었을 때 또는 CI 서버에 실수로 기입하지 못하게 되었을 때 Project Import 나 빌드가 아예 되지 않는 현상이 발생하였기에 초기 값을 설정할 수 있도록 하였습니다.report_coverage 는 5. Android Gradle DSL 에서 buildTypes.debug.testCoverageEnabled 에서 사용되며 이 값은 설정에 따라서 디버그 과정에서 변수값들이 제대로 노출되지 않게 됩니다. report 가 필요한 CI 서버 용으로 만들어진 값입니다.// valid.gradle def checkValidProperties() { println "Properties Valid Checking.........." if (!project.hasProperty("inhouse_version")) { println "set up to gradle.propeties --> inhouse_version = 1 (default)" project.ext.inhouse_version = 1 } if (!project.hasProperty("report_coverage")) { println "set up to gradle.propeties --> report_coverage = false (default)" project.ext.report_coverage = false } if (!project.hasProperty("dev_min_sdk")) { println "set up to gradle.propeties --> dev_min_sdk = 19 (default)" project.ext.dev_min_sdk = 19 } println "Properties Valid Check OK" } checkValidProperties() // ------------------------------- // build.gradle apply from: 'valid.gradle' 위와 같이 설정한 뒤 gradle.properties 에 아무런 값을 설정하지 않고 빌드를 하게 되면 빌드 최초에 다음과 같은 log 를 보실 수 있습니다.================================================================================ Properties Valid Checking.......... set up to gradle.propeties --> inhouse_version = 1 (default) set up to gradle.propeties --> report_coverage = false (default) set up to gradle.propeties --> dev_min_sdk = 19 (default) Properties Valid Check OK ================================================================================ 2. APK Copy 하기QA 팀 전달 또는 스토어 배포시에 Android Studio 의 기본 기능을 이용하지 않고 Gradle Task 를 사용하여 빌드를 하게 되면 /app/build/outputs/apk 에 있는 패키지를 복사하는 것이 여간 귀찮은 작업이 아닐 수 없습니다.그래서 Gradle 에서 기본적으로 제공되는 Copy Task 를 이용하여 APK Copy Task 를 만들었습니다.// apk-copy.gradle android.applicationVariants.all { variant -> // 1. Copy Task 생성 def task = project.tasks.create("copy${variant.name}Apk", Copy) task.from(variant.outputs[0].outputFile) // 2. 바탕화면 Task 로 복사 task.into("${System.properties['user.home']}/Desktop/") // 3. 복사하는 과정에서 APK 이름 변경 def targetName = "jandi-${variant.baseName}-${variant.versionName}.apk" task.rename ".*", targetName task.doFirst { println "copy from ${source.singleFile.name} to $destinationDir" } task.doLast { value -> println "completed to copy : $targetName" } } // --------------- // build.gradle apply from: 'apk-copy.gradle' 위의 Task 는 총 3개의 단계로 구분할 수 있습니다.Copy Task 생성~/Desktop 으로 복사복사 할 때 APK 이름 변경Task 를 정의하는 과정에서 application 의 flavor, build-type, version 을 기반으로 복사하도록 한 것입니다.위와 같이 설정하면 다음과 같이 사용할 수 있습니다.# flavor : qa , build-type : Debug $> ./gradlew assembleQaDebug copyqaDebugApk # 또는 줄여서 아래와 같이 쓸 수 있습니다. $> ./gradlew aQD copyQDA Application Variant 에 대한 변수는 링크에서 확인하실 수 있습니다.3. CI TasksCI 용으로 CheckStyle 과 PMD 를 사용하기 때문에 관련 설정 또한 별도로 처리하였습니다.task pmd(type: Pmd) { source 'src/main' include '**/*.java' ruleSetFiles = files('../pmd.xml') ignoreFailures = true } task checkstyles(type: Checkstyle) { configFile file('../checkstyle.xml') source('src/main') include '**/*.java' classpath = files() showViolations = true ignoreFailures = true } // --------------- // build.gradle apply from: 'ci-tasks.gradle' CheckStyle 과 PMD 설정에 필요한 정보 또한 별도의 script 로 설정하였습니다.4. Gradle Properties빠른 빌드를 위해 추가적인 설정을 하고 있습니다.# gradle.properties # 백그라운드 빌드 org.gradle.daemon=true # 동시 빌드 org.gradle.parallel=true # jvm heap size org.gradle.jvmargs=-Xmx4346m # build jdk org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home 위의 설정 중에서 제일 보셔야 할 것이 org.gradle.jvmargs 입니다. Android Gradle 설정 중에서 위의 값이 적으면 빌드속도가 현저히 느려집니다.빌드 할 때 console log 를 확인하시고 값을 적절하게 맞춰주실 것을 권장합니다.5. Android Gradle DSL 추가 정의하기 // build.gradle // ...중략 android { // 특정 Flavor에서 Release Build 막기 android.variantFilter { variant -> if (variant.buildType.name.equals('release') && (variant.getFlavors().get(0).name.equals('qa') || variant.getFlavors().get(0).name.equals('dev'))) { variant.setIgnore(true); } } buildTypes { debug { debuggable true testCoverageEnabled = project.hasProperty("report_coverage") && report_coverage.toBoolean() } // ..중략... } productFlavors { dev { // demo version applicationId 'com.tosslab.jandi.app.dev' versionName(defaultConfig.versionName + ".dev." + inhouse_version) minSdkVersion project.hasProperty("dev_min_sdk") ? dev_min_sdk : 19 } // ..중략.. } // 빌드 과정에서 CPU 와 Ram 최적화 하기 dexOptions { javaMaxHeapSize "2g" maxProcessCount Math.max(1, ((int) (Runtime.getRuntime().availableProcessors() / 2))) } } variant-filter 를 이용해서 qa 나 dev 용 빌드는 release 버전이 빌드되지 않도록 하였습니다.buildTypes 와 productFlavors 에서는 앞서 설정한 gradle-properties 에 대해서 설정에 따라 기본값이 지정되도록 하였습니다.dexOptions 설정은 개발하는 기기의 PC 환경에 따라 다를 수 있습니다.Android DSL 에 의하면 Dex 빌드 과정에서 최종적으로 사용하는 메모리는 heapsize * process-count 라고 합니다.heapsize 기본값 : 2048MBprocess-count 기본값 : 4참고문서6. Android Resource Image 의 EXIF 정보 삭제하기보통 디자이너가 Photoshop 과 같은 툴을 이용하여 이미지를 만들게 되면 자동으로 adobe 와 관련된 exif 정보가 붙게 됩니다. 그래서 빌드 할 때 libpng warning : iCCP ... 와 같은 warning 메세지를 보실 수 있습니다. 이는 Android Build 과정에서 aapt 가 이미지 최적화 하는 과정에서 불필요한 exif 정보로 인해서 오류를 내게 됩니다.따라서 exif 정보를 초기화 해주는 작업이 필요합니다.맥 사용자에 한해서 지원됩니다.HomeBrew 를 이용해서 exiftool 을 설치하셔야 합니다. exiftool 설명find . -path '*src/main/res/*' -name '*.png' -exec exiftool -overwrite_original -all= {} \; 저는 별도로 쉘 스크립트를 만들어서 실행합니다.아래를 복사해서 붙여넣기로 실행하시면 됩니다.echo "find . -path '*src/main/res/*' -name '*.png' -exec exiftool -overwrite_original -all= {} \;" > exif_clean.sh chmod 744 exif_clean.sh 관련 정보 : adt-dev google group 에서 제시된 해결책Wrap up안드로이드 팀은 Gradle 을 이용하여 반복적일 수 있는 작업을 자동화 하고 다양한 초기화 설정과 편의를 가지고자 하였습니다.초기화 값 검증 및 설정Apk 복사 자동화CI Task 정의Gradle Properties 지정Android Gradle DSL 정의Android Resource Image EXIF 삭제Gradle 을 얼마나 잘 활용하냐에 따라서 조직에 필요한 Task 를 금방 만드실 수 있습니다. 이번 포스팅이 도움이 되었기를 바라며 활용해보실 것을 권장합니다.#토스랩 #잔디 #JANDI #개발자 #개발팀 #앱개발 #안드로이드 #인사이트
조회수 950

AI 스쿨 필기 노트 ① 선형회귀분석(Linear Regression)

전세계가 AI first를 외치고 있습니다! 엘리스 인공지능 오프라인 교육과정인 AI 스쿨의 필기노트를 8주간 연재합니다. 인공지능 개론과 알고리즘에 대해 함께 공부해요.지난 5월 8일 구글의 연례 개발자 콘퍼런스 I/O에서 구글은 구글 듀플렉스라는 새로운 AI 기술을 선보였습니다. 구글 듀플렉스가 직접 미용실에 전화를 걸어서 예약에 성공하는 이 시연은 매우 인상적인 장면이었는데요. 국내의 여러 기업에서도 이미 인공지능 스피커를 출시하는 등 우리의 일상 생활 곳곳에도 인공지능 기술이 스며들고 있습니다.IDC, Tractica, Markets and Markets 등 글로벌 시장조사기관들은 2020년까지 세계 인공지능 시장이 연평균 50% 이상 가파르게 성장할 것이라고 예측하기도 합니다. 이미 세계 각국의 주요 IT 기업들은 AI 시장에서 영역을 넓히고 경쟁력을 확보하고자 전력을 투입하고 있는데요. 국내 기업들 역시 인수합병과 조직개편 등으로 인공지능 기술과 인재 확보를 위해 발 빠르게 움직이고 있습니다.엘리스에서는 IT 분야 및 연구 기관에 취업하고자 하는 분들을 위한 오프라인 교육과정을 운영하고 있습니다. 지난해에 이어 올해에는 양재 RNCD 혁신허브와 함께 인공지능 R&D 실무자 양성과정을 운영하게 되었는데요! 이론 수업(8주)과 팀 프로젝트(6주), 커리어 코칭 과정(2주)로 이루어진 이번 과정은 수료증 및 입사 추천서 발급, 테크니컬 인터뷰와 포트폴리오 준비, 국내 IT 기업과의 채용 연계 등으로 구성되어 있어 관련 분야에 취업을 희망하시는 분들의 많은 관심이 있었습니다.300명 가까운 분들이 지원해주셨고, 이 중 선발 과정을 거친 40여 명의 분들이 16주간 오프라인+온라인 교육을 받게 되었습니다. 이 중 기계학습과 알고리즘 개론에 대한 8주간의 교육 내용을 앞으로 8주간 여러분과 함께 공유하고자 합니다. 컴퓨터 공학과에 재학 중인 AI 스쿨 수강생이 직접 필기노트를 공유해 준다고 하니 함께 AI 개론에 대해서 공부해 봐요. :)안녕하세요! 저는 숭실대학교 컴퓨터학부 4학년에 재학 중인 대학생이에요. 저는 평소에 AI에 대해 관심이 많아서 제대로 된 교육을 받고 싶어서 이번 과정을 수강하게 되었어요. 앞으로 AI 스쿨에서 받는 수업이 제가 AI 엔지니어로 성장할 수 있는 밑거름이 될 것이라고 생각해요. 아직 배우는 단계이기 때문에 많이 부족하지만 앞으로 8주 동안 이 글을 통해서 함께 공부한다고 생각하며 그 주에 배운 내용을 요약해보려고 합니다!AI 스쿨 첫 수업에서는 ‘Linear Regression(선형 회귀)’에 대해 배웠어요. 대학교 2학년 때 전공 과목으로 ‘선형대수학’이 있었는데요, 배우면서 이런 학문은 도대체 어디에 쓰이는지 혹시 필요 없는 것을 배우느라 시간 낭비를 하는 것은 아닌지 힘들게 공부했던 기억이 나네요. 그런데 제가 읽은 한 기사에서 미국의 연구팀이 ‘장기적인 공기 정화 노력이 성장기 아이들의 폐기능을 개선시켰다’는 연구 결과를 증명한 후 캘리포니아 남부지역에서 ‘공기오염의 질 관리 정책’을 시행하여 오염 수준이 꾸준히 감소하고 있다는 내용이 있었는데요. 연구팀은 공기오염의 감소와 소아 호흡기 질환의 개선 사이에 개연성을 평가했고 이 연구에서 사용한 방법이 선형회귀분석(linear regression model)이라고 해요!첫 수업에서는 앤드류 응 교수님 강의 자료의 쉬운 예시를 바탕으로 Linear Regression(선형회귀)을 공부했어요.이 예시에서는 집 크기에 관한 정보 하나로 집의 가격을 예측하는 할 수 있는 데이터가 있다는 가정을 하고, 이 가정이 직선의 방정식 y = ax + b의 형태를 따른다고 가정했어요.인공지능은 예측을 기본으로 다루는데, 우리는 과거의 데이터를 학습함으로써 최적의 예측 모델을 만들게 돼요.이때 다루는 데이터를 Training set이라고 부르고, m은 학습 데이터의 숫자, x는 입력 변수 또는 feature, 그리고 y는 출력 변수 또는 타깃 변수라고 불러요.기존의 Training set으로 Learning 알고리즘을 학습시키면 그 학습된 부분이 h, 즉 가설이 돼요. h를 통해서 우리는 어떠한 집 크기에 대한 예측된 가격을 구할 수 있어요. 그런데 이때 보다 정확히 예측을 하려면 error를 최소로 하는 a, b의 최적의 값을 설정해야 해요.우리의 모델인 직선의 방정식을 통해 오차가 적은 예측값을 얻기 위해서는 a와 b에 어떠한 값을 넣어야 좋을까요? 위에서 언급했듯이 우리에게는 주어진 학습 데이터가 있죠. 이를 이용하여 최적의 값을 도출해야 해요. Cost function 이란 a, b가 주어진 학습 데이터인 Training set을 가장 적은 오차로 표현하고 있는지 알 수 있는 방법인데요. Loss function 또는 Objective function이라고도 해요. Linear Regression에서는 Cost function으로 Squared error function을 사용해요. Squared error function 이란 가설에 Training data의 입력값을 넣었을 때의 출력값과 해당 입력값에 대한 training data의 실제 출력값의 차를 제곱하여 이용하는 방법이에요.그렇다면 우리는 a, b를 어떻게 구할 수 있을까요? 이 방법을 산을 내려가는 예시를 통해서 쉽게 이해할 수 있었어요.만약 깜깜한 밤에 산꼭대기에서 길을 잃었다면 랜턴을 키고 주변을 살펴본 후 아래로 내려가는 길을 찾아 그 방향으로 내려가고, 도달한 지점에서 또다시 랜턴을 켜 주변을 살펴 아래로 향하는 길로 가야 산 아래까지 내려갈 수 있겠죠. 이것이 최적의 a, b를 구하는 Gradient descent의 기본 방식이에요.Gradient descent는 임의의 a, b를 지정한 후, 그 점으로부터 감소하는 기울기를 구간을 찾아 이동하는 것을 반복함으로써 해를 구하는 방법입니다!이번 주 수업의 과제로는 Loss Function과 Linear Regression을 구하는 과제가 주어졌어요. 첫 번째 과제인 만큼 난이도가 많이 높지는 않았지만 파이썬이 익숙하지 않다면 조금 헷갈릴 여지가 있는 문제였던 것 같아요. 강의를 해주신 주재걸 교수님께서는 첫 시간에 배운 개념들이 Linear regression에서 뿐만 아니라 인공지능, 머신 러닝, 딥러닝 분야에서 많이 쓰이기 때문에 첫 시간에 배운 것만 제대로 이해하고 가도 많은 것을 얻어 가는 것이라고 하셨어요. 위의 개념에 대해서 다른 자료들도 찾아보면서 공부하고, 다음 필기 노트로 만나요!#엘리스 #코딩교육 #교육기업 #기업문화 #조직문화 #서비스소개
조회수 1405

웹 서비스 개발자가 APM을 사용해야 하는 이유

백엔드 서비스를 만들고 운영하는 개발자라면, 지금 바로 APM 서비스를 사용해 보세요. 와탭의 APM은 국내 수많은 Enterprise 기업에서 자사의 서비스를 분석하기 위해 사용되고 있으며 많은 효과를 보고 있습니다. 북미에서는 이미 수많은 스타트업이 DevOps의 기본 도구로 APM을 선택하고 있습니다. APM은 원래 대규모 서비스를 운영하는 분들이 전문적으로 사용하고 있었지만 최근 트렌드는 운영자에서 개발자로 이동하고 있는 서비스 이기도 합니다. 특히 와탭의 APM은 개발자 분들을 위한 스택 분석 기능이 있습니다. 개발자라면 와탭 APM 서비스가 제공하는 아래의 3가지 스택 분석 기능을 꼭 사용해 보세요. 유니크 스택탑 스택액티브 스택많은 개발자들이 자신이 만든 서비스가 어떻게 동작하는지 또는 웹 서비스에 어떤 영향을 주고 있는지 알지 못합니다. 하지만 와탭 애플리케이션 성능 모니터링(APM) 서비스를 사용하면 메소드가 애플리케이션에서 어떻게 사용되는지 얼마나 사용되는지 알수 있습니다. 와탭은 다른 APM 서비스와 다르게 10초에 한번씩 활동중인 트랜잭션을 검사하여 트랜잭션에 콜스택정보를 저장하고 있습니다. 그리고 이렇게 저장된 스택정보를 가지고 3가지 형태로 가공하여 보여주는데, 이 것이 유니크 스택 / 탑 스택 / 액티브 스택입니다. 먼저 유니크 스택은 가장 많이 사용된 스택 정보를 보여주는 방식입니다. 트랜잭션에서 실행되고 있는 메소드가 A 이고 이를 호출한 메소드가 모두 일치하는 스택을 유니크 스택이라고 합니다.1. A() ← C()2. A() ← C()3. B() ← D()4. B() ← E()5. B() ← F()위와 같은 경유 유니크 스택은 아래와 같이 통계를 내어 보여 줍니다. 40% A()    A()    C()20% B()    B()    D()20% B()    B()    E()20% B()    B()    F()이렇게 콜스택 정보 전체를 기준으로 분석을 하는 경우에는 성능에 영향을 주는 기능 단위의 분석이 가능합니다. 하지만 성능에 영향을 많이 주는 메소드를 알고 싶을 때가 있습니다. 이런 경우에 사용하는 것이 탑 스택 분석입니다. 아까와 같은 상황을 예를 들겠습니다.1. A() ← C()2. A() ← C()3. B() ← D()4. B() ← E()5. B() ← F()이런 상황에서 탑 스택 분석은 아래와 같이 가장 많이 사용되느 메소드를 알려줍니다. 60% B()    33% D()    33% E()    33% F()40% A()    100% C()유니크 스택에서는 A() ← C() 가 가장 많이 사용된 스택이라는 것을 알려주지만 탑 스택에서는 B() 메소드가 가장 많이 사용된 메소드라는 것을 알려줍니다. 이 두가지 내용을 통해 가장 많이 사용되는 메소드의 집합가 가장 많이 호출되는 메소드를 알아 낼 수 있습니다. 만일 서비스를 메소드 단위에서 개선하고 싶다면 이 정보를 기반으로 개선 작업을 진행하면 많은 도움을 받을 수 있습니다. 위에 화면에서 메소드를 선택하면 메소드를 호출한 스택들의 정보를 확인 할 수 있습니다. 마지막으로 액티브 스택입니다. 액티브 스택은 WAS 서버와 URL 그리고 발생 시간을 기준으로 저장된 콜스택의 정보를 보여줍니다. 서비스 성능이 떨어진 시간대의 콜스택 정보를 확인 함으로써 메소드 구간에서의 튜닝 정보를 제공합니다. 액티브 스택은 핵심 기능이 하나더 있습니다. 바로 서비스가 동작하는 스탭정보에 통합됨으로써 문제를 바로 확인할 수 있는 기능입니다. 와탭의 APM에서만 분석가능한 기능이며 특허로 등록되어 있습니다. 액티브 스택은 통계 관점이 아니라 실행 관점에서 문제를 바라보고 있습니다. 우리가 만든 웹 어플리케이션을 고객에 입장에서 보면 아래와 같이 동작합니다. 고객 → 웹 서비스 요청 → 서버 접속 → 서비스 접속 → 애플리케이션1 → 메소드 1 → DB 1접근 → Query 1 → Query 2 → 메소드 2 → 파일 접근 → 메소드 3 → 결과 취합 → WAS 통과 → 웹 서비스 결과 반환 일반적으로 애플리케이션 모니터링은 이런 상항을 아래와 같이 보여줍니다. 서비스 접속 → Query 1 → Query 2 → 파일 접근 → 트랜잭션 종료와탭의 애플리케이션 모니터링은 수집된 콜 스택 정보를 기반으로 아래와 같이 보여줍니다.  서비스 접속 → Query 1 → 메소드 2 → Query 2 → 파일 접근 →메소드 3 → 트랜잭션 종료위에 상황은 트랜잭션에서 메소드 2와 메소드 3이 수집된 경우에 트랜잭션의 스탭의 실행시간에 맞쳐서 정보를 재구성하는 것을 보여주고 있습니다. 이렇게 확인하게 된다면 메소드에서 발생하는 성능 문제를 확인 할 수 있습니다. APM 서비스는 와탭 / 뉴렐렉 / 데이터 독과 같은 서비스들을 통해서 2주에서 한달간 언제든 무료로 사용가능합니다. 다만 메소드에 대한 분석 기능은 와탭의 APM에서만 제공하는 기능들이 많습니다. 개발자라면 한번쯤 와탭의 APM 서비스를 통해 자신이 만들고 운영하고 있는 서비스에서 가장 많이 사용되는 메소드가 무엇인지 확인 해 보시기 바랍니다. Tip!! APM은 개발시에 사용하는 디버깅 도구라기 보다는 막대한 량의 트랜잭션이 발생하는 운영과정에서 사용되는 도구입니다. 트랜잭션 자체가 적다면 원하는 데이타가 안 나올 수 도 있습니다. 와탭으로 모니터링 하기 - 목차 바로가기#와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지 #서비스소개
조회수 2848

Retrofit2 로 전환

Android 와 NetworkAndroid 에서 Network 라이브러리들은 다양하지만 근 1년 사이에 주로 사용되는 라이브러리들이 점차적으로 적어지고 있습니다.오늘은 그 중에서 Retrofit 에 대해 이야기 하고자 합니다.토스랩의 Android Network Library1. Spring-Android, Retrofit 그리고 Retrofit2토스랩은 총 3개의 네트워크 라이브러리를 사용하였습니다. 초창기에는 AndroidAnnotations 에 연동되어 있는 Spring-Android 를 사용하였습니다. 하지만 다중 쓰레드 환경에서 동일한 Request 객체를 사용하면서 저사양 단말에서 문제로 두각되기 시작하였습니다.그래서 Retrofit 으로 2015년 중순쯤 전환을 하였습니다. 그러다 2016년 초 Retrofit2 가 정식 배포가 되면서 자연스럽게 Retrofit2 로의 전환이 대두되기 시작하였습니다. 전환의 이유는 내부의 네트워크 모듈에 대한 Refactoring 이었는데 그와 동시에 Retrofit2 로의 전환도 함께 진행되었습니다.2. 이슈들What the CALL기존의 Retrofit 은 200~399 에러에 대해서는 정상적인 Body 를 반환하고 400 이상의 경우에는 Typed Exception 형태로 로직을 진행하였습니다. 하지만 이정도로는 Response Status 나 Header 정보를 알기에는 추가적인 로직이 필요로 하였습니다. 물론 Success 케이스에도 마찬가지이긴 하였습니다.이는 Retrofit 의 기본적인 목적에 부합되지 않는다는 문제가 있었습니다. Retrofit 의 가장 기본적인 목적은 Okhttp 의 상위 구현체로써 쉽게 Request 와 Response 를 구현한다는 것입니다. 손쉬운 구현이 필요한 정보를 제외시킨다는 것은 별개의 문제이기 때문입니다.그래서 Retrofit2 에서는 Call 객체를 통해서 Request 와 Response 에 적용된 Header, StatusCode, Body 등을 직접 접근 할 수 있도록 인터페이스를 추가하였습니다.이 객체는 불변성을 가지고 있기 때문에 Getter 만이 존재하며 Request 에 필요한 정보는 다른 부분에서 적용되어야 함을 명시하셔야 합니다.Call 객체의 적용Call 객체를 적용하는 과정에서 2가지의 이슈가 있었습니다.Interface 의 모든 Return Value 를 Call 로 전환할 것Request Error 를 직접 핸들링 하도록 수정해야 함이 2가지 때문에 여러가지가 연쇄적으로 수정되어야 했습니다.먼저 수정과정을 설명하기 앞서 Jandi 앱의 Network 통신 전제조건에 대해서 설명해드리도록 하겠습니다.Jandi 앱은 모든 Network 통신은 Current Thread 에서 한다는 것을 전제로 합니다. 이는 MainThread 에서의 통신이 아니라 호출자의 Thread 를 따라간다는 것을 전제로 하고 있습니다. 또한 이를 위해 Reponse 반환, Error Handling, 세션 자동 갱신을 위해 Generic 으로 선언된 Facade 용도의 Wrapper Class 를 별도로 두고 있습니다.따라서 수정해야할 1,2 번을 위해 아래와 같은 수정을 하였습니다.Facade Class 내에서 성공여부를 직접 파악한다.성공시 Return Value 를 직접 반환할 수 있도록 한다.실패시 Status, Response 정보를 이용하여 throw Exception 을 한다. (세션 정보를 갱신 로직은 당연히 포함되어 있습니다.)그래서 아래와 같은 코드 형태가 되었습니다.Response response = apiExecutor.execute(); if (response.isSuccessful()) { RESULT object = response.body(); retryCnt = 0; return object; } else { // 400 이상 오류에 대해 처리 return handleException(apiExecutor, response, null); } Network 통신 과정에서의 Exception 이 나는 경우는 2가지 입니다.기기의 Network 자체가 끊겨 있거나 비정상인 경우Response 의 Parsing 과정에서 오류가 발생한 경우Annotation 의 변화Annotation 의 가장 큰 변화는 DELETE 였습니다. 기존의 Retrofit 에서는 DELETE 요청은 GET 방식으로 가능하였습니다. 즉 POST 처럼 Body 를 설정할 수 없게 되어 있었습니다. 따라서 DELETE 를 쓰기 위해서는 별도의 Custom HTTP Annotation 을 설정 할 적용하여야 했습니다.Retrofit2 에서는 이런 경우에 대비하기 위해 @HTTP 를 개방하였습니다. @HTTP(path = "{url}", method = "DELETE", hasBody = true) 와 같이 사용해야만 Custom HTTP Method 를 적용하실 수 있습니다.Jackson2-Converter 대응Jackson2-Converter 의 이슈는 최근에서야 알게 되었습니다. Jandi 앱은 그동안 Jackson 1.x 를 사용하였고 최근에서야 Jackson2 로 전환을 하였습니다.그 과정에서 Retrofit2 의 converter-jackson 라이브러리를 사용하려 하였으나 중대한 문제가 있었습니다.Retrofit2 에서 Reqeust Body 의 Serialize 는 메소드의 참조변수로 선언된 클래스만 지원하며 상속한 자녀클래스를 넣어도 부모 클래스의 결과만을 리턴 하는것이었습니다. (gson 과 여타 converter 에 대해는 해당 이슈에 대해 파악해보지 않았습니다).이를테면 아래와 같은 경우입니다.interface Api { @PUT("/profile") Call modifyProfile(@Body Profile profile); } public class Profile {} public class NameProfile extends Profile{ String name; } public class PhoneProfile extends Profile{ String phone; } // using case api.modifyProfile(new NameProfile("Steve")); 허나 아래와 같은 상황이 펼쳐집니다.// expect {"name":"Steve"} // actual {} 해당 문제는 Converter-Jackson 의 이슈이기 때문에 위와 같은 상황이 예상된다면 별도의 Converter.Factory 를 선언하여 사용하시기 바랍니다.OkHttpClient 생성 이슈Okhttp 에 여러가지 기능이 추가되었습니다. 그중 잔디가 사용 중인 목록입니다.okhttp-logging-interceptorauthenticatorCutome SSL이런 이유 때문에 OkHttpClient 를 직접 생성하여 사용 하고 있습니다.처음에는 OkHttpClient 를 모든 API 호출시 새로 생성하도록 하였습니다. 헌데 TestCode 가 200회가 넘어가면 File IO 를 너무 많이 사용했다는 오류가 계속적으로 발생하였습니다.이 오류가 단순히 File IO 가 많아서 라는 메세지 때문에 처음에는 Database 에 대한 오류인 줄 알고 Memory Cache 작업과 테스트코드 개선작업을 하였으나 정상 동작이 되지 않았습니다. (테스트 코드 1회에 평균 2번의 API 통신과 2회의 DB 처리를 합니다.)그 와중에 기존의 테스트 코드는 정상 동작하는 것을 보고 Retrofit2 작업을 진행한 branch 만의 문제임을 깨달았습니다.현재는 OkhttpClient.Builder 를 통해 생성한 1개의 OkhttpClient 만을 재사용하도록 변경하였습니다.Network Retry 시 동작 변경Retrofit2 는 Call 객체를 이용하여 동일한 정보로 재요청을 할 수 있도록 지원하고 있습니다. 하지만 이에 대한 제약이 하나 있습니다. 이미 Network IO 가 끝난 경우 Retrofit2 는 Call 객체를 복사하여 재사용할 것을 가이드 하고 있습니다. 그래서 재요청시 다음과 같이 코드를 작성하셔야 합니다.Call call = action0.call(); if (!call.isExecuted()) { return call.execute(); } else { return call.clone().execute(); } OkHttp3 의존성Okhttp 를 사용하는 타 라이브러리가 있다면 Okhttp3 의존성을 가지고 있기 때문에 이에 유념하셔야 합니다.3. 정리Retrofit1 -> Retrofit2 로 변경하는 과정에서 다양한 이슈를 발견하였습니다.Return Value 수정Exception 처리 강화Annotation 수정Request-Response Converter 수정OkhttpClient 재사용 정의재요청 처리에 대한 validation 추가OkHttp3 의존성Retrofit2 로 변경에 있어서 가장 큰 핵심은 Call 이라는 객체라고 할 수 있다는 것입니다.이 객체는 Request 에 대한 동작 제어(cancel, retry 등), Request-Response 의 독립성 보장, 그에 따라 각각의 정보에 대한 접근 등을 보장하게 됩니다.Retrofit2 는 그외에도 Okhttp3 와 다양한 플러그인 지원하고 있습니다. 요청-응답에 필요한 Body 의 변환툴 (Converter-xxx), EndPoint 에서 접근하는 Call 객체에 대한 다양한 툴 (CallAdapter-xxx)현재 Retrofit1 에서 잘 동작하고 있고 의도대로 흐름제어를 하고 있다면 Retrofit2 로 옮겨갈 이유는 없습니다. 하지만 변경을 하고자 한다면 이러한 영향도가 있을 것임을 공유해드렸습니다.참고하면 좋은 Slidehttps://speakerdeck.com/jakewharton/simple-http-with-retrofit-2-droidcon-nyc-2015Jake Wharton’ Retrofit2Presentation 영상#토스랩 #잔디 #JANDI #개발 #개발자 #인사이트 #경험공유

기업문화 엿볼 때, 더팀스

로그인

/