스토리 홈

인터뷰

피드

뉴스

조회수 1900

Android Studio JCenter 이용하기

 안녕하세요. 크몽개발팀 입니다.오늘 포스트 주제는 Android Studio JCenter 이용하기입니다.JCenter????  JCenter에 대해 처음 들으시는분들도 있을거같은데요.JCenter는 라이브러리들이 모여있는 저장소라고 보시면 되겠습니다.그렇다면 JCenter를 이용하여 무엇을 할까요?바로 외부 라이브러리들을 가져와서 프로젝트안에 Import 할려고 합니다. JCenter 사이트 링크 : https://bintray.com/bintray/jcenterJCenter 페이지에 접속하시면 위와 같은 페이지를 볼 수 있는데요.여기서 사용하고 싶은 라이브러리를 검색해보겠습니다.제가 검색한 라이브러리는 ImageLoder 라이브러인 'Glide'를 검색했습니다.빨간색으로 표시되있는게 제가 찾던 라이브러리 입니다.검색한 라이브러리를 클릭하면 위와 같이 상세페이지를 볼 수 있는데요.라이브러리 Github 주소 와 버젼에 대한 정보를 확인할 수 있습니다.그럼 이제 검색한 라이브러리를  Android Studio Gradle에 Import 하겠습니다. Android Studio에서 프로젝트를 생성하게 되면 위와 같이 3개의 그래들 파일을 볼 수 있는데요.자주 사용할 그래들 파일은 app폴더에 있는 그래들 파일입니다.그래들 파일을 열어보면 낯익은 코드들이 보이는데요.ADT에서는 매니페스트에서 버젼관리를 햇었는데 Studio에서는 그래들로 빠진거같습니다.그리고 빨간표시를 해둔곳이 바로 JCenter에서 검색한 라이브러리를 Import 하시면 되겠습니다.  위에 JCenter에서 찾은 라이브러리명을 입력하고 뒤에 버젼번호도 같이 입력합니다.그리고 Sync 버튼을 눌러주면 라이브러리가 Import 됩니다. External Libraries를 확인해보시면 라이브러리가 추가된걸 확인할 수 있습니다.---------------------------------------------------------------------------------------이렇게 JCenter를 이용하여 간단하게 라이브러리들을 Import를 할 수 있습니다.그리고 그래들 과 JCenter를 이용하여 라이브러리를 적용할때 가장 좋은점은'com.github.bumptech.glide:glide:3.+' 이런식으로 버젼에대한 값을 주면라이브러리 상위버젼이 나올경우 자동으로 최상위 버젼으로 라이브러리를 Import 해준다는 점입니다.이로써 라이브러리 버젼관리도 많이 편해질거 같습니다.이것으로 Android Studio JCenter 이용하기 포스트를 마치겠습니다.#크몽 #개발팀 #인턴 #인턴생활 #인사이트
조회수 1752

응답시간 분포도

애플리케이션의 성능 개선은 웹 트랜잭션의 응답시간을 분석을 통해 이뤄집니다. 와탭의 응답시간 분포도는 대규모 트랜잭션 분석이 가능한 Heatmap 형태로 제공되고 있습니다. 와탭을 사용하는 사용자는 응답시간 분포도를 통해 웹 서비스의 응답시간이 느려지는 것을 알 수 있을 뿐만 아니라 패턴 분석을 통해 느려진 원인을 예측할 수도 있습니다. 와탭의 응답시간 분포도Y 축: 트랜잭션 응답시간을 의미합니다. 10s는 트랜잭션이 시작에서 종료까지의 시간이 10초가 걸렸다는 것을 의미합니다.X 축: 트랜잭션이 종료된 시간을 의미합니다.■: 트랜잭션이 발생한 위치에 색이 칠해집니다. 청색 계열은 정상적인 트랜잭션을 의미합니다. 노랑색과 붉은 색 계열은 에러가 발생한 트랜잭션을 의미합니다. 색상의 농도는 해당 영역에 발생한 트랜잭션의 밀도를 상대적으로 표시합니다.  와탭의 응답시간 분포도는 트랜잭션의 응답시간을 시각화하는 것입니다. 웹 서비스의 트랜잭션을 시각화 할 뿐만 아니라 추적하고자 하는 영역을 드래그하여 트랜잭션의 진행상황을 추적하는 것도 가능합니다.  추적하고 싶은 트랜잭션을 드래그 하는 모습와탭의 응답시간 분포도에서 트랜잭션을 선택하면 분석 화면으로 넘어갑니다. 해당 애플리케이션 서버 정보를 통해 선택된 트랜잭션이 어느 애플리케이션 서버에서 발생했는지 알 수 있습니다.애플리케이션과 선택된 트랜잭션 정보 화면분석하고 싶은 애플리케이션 서버를 클릭하면 해당 애플리케이션 서버에서 발생한 트랜잭션 목록을 확인 할 수 있습니다. 최종적으로 APM을 통해 확인하고 싶은 내용이 트랜잭션의 디테일한 정보일 것입니다. 와탭의 APM은 트랜잭션을 시각화하고 시각화된 트랜잭션을 선택하면 선택된 트랜잭션의 목록을 애플리케이션 서버 별로 분류하여 선택할 수 있는 구조를 가지고 있습니다. 이것은 능동적으로 웹 애플리케이션을 분석할 수 있는 최적화된 흐름이라고 생각할 수 있습니다. 사용자가 응답속도 분포도를 통해 선택한 트랜잭션 목록#와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 4332

크몽 검색 기능 개선기

안녕하세요? 크몽의 백엔드 개발자로 활동하고 있는 에이든입니다. :)오늘은 크몽에 입사하고 한 달 동안 UX팀에서 진행한 검색 기능 개선에 대한 이야기를 해보려고 합니다.배경크몽에는 재능을 판매하는 프리랜서의 서비스 정보가 많이 저장되어있습니다. 판매하는 서비스 정보가 많을수록 검색 기능이 잘 되어있다면 사용자는 원하는 서비스를 빨리 찾을 수 있고, 프리랜서는 다양한 서비스를 의뢰인에게 판매할 수 있습니다.크몽에서는 사용자에게 정확한 검색으로 다양한 서비스를 제공하기 위해 노력하고 있습니다. 이번 글에서는 크몽 UX팀에서 보다 나은 검색 기능을 위해 어떠한 노력을 했는지 공유하고자 합니다.기존의 검색 기능기존의 검색 기능은 기본적인 키워드 검색 외에 별다른 기능을 제공하지 않았습니다. 그리고 스핑크스 검색엔진으로 구성되었습니다. 스핑크스는 전문 텍스트 검색 기능을 제공하며 데이터베이스와 잘 통합될 뿐만 아니라 스크립트 언어에 쉽게 접근할 수 있도록 설계되었습니다. 스핑크스의 동작 구조는 다음과 같습니다.스핑크스의 동작 구조Searchd는 클라이언트로부터 요청을 받고 스핑크스 인덱스에 대해 검색을 실행하는 역할을 합니다. 그리고 스핑크스 인덱서는 스핑크스 인덱스로 데이터를 가져오는 역할을 합니다.크몽은 이를 통해 사용자에게 검색 기능을 제공했습니다. 하지만 기존의 검색 기능은 불편한 점이 있었습니다.기존의 검색 기능의 불편한 점기존의 검색 기능은 의뢰인이 어떤 서비스를 필요로 하는지 본인이 정확하게 정의할 수 있어야 했습니다. 그게 아니라면 여러 키워드를 검색해보거나 원하는 서비스를 찾기 위해 해당 카테고리에서 서비스 전체를 둘러봐야 했습니다. 또한 많은 유료광고로 인해 사용자는 일반 서비스를 찾기가 힘든 문제가 있었습니다.기능상의 불편한 점뿐만 아니라 구현상에도 불편한 점이 있었습니다. 스핑크스에서 한글 검색을 구현하기 위해서는 복잡한 설정을 거쳐야 했으며 ngram analyzer를 통해서만 한글 형태소 분석이 가능했습니다. ngram analyzer는 음절 단위의 한국어 형태소 분석을 하므로 인덱스의 양이 많아질 뿐만 아니라 불필요한 정보까지 검색에 노출이 됩니다. 불필요한 정보가 노출되면서 종료율은 높아지고 서비스 상세페이지의 전환율이 낮아졌습니다. 또한 스핑크스는 데이터의 저장이 되지 않기 때문에 분석을 위해서는 별도의 과정이 필요했습니다.이에 크몽 개발팀은 사용자를 위한 검색 기능 보강뿐만 아니라 검색 엔진 변경이라는 결론을 내립니다.새로운 검색 기능새로운 검색 기능을 개발하기에 앞서 요구사항을 파악하고 새로운 검색 엔진에 대한 기술 탐색을 선행했습니다.프로젝트 진행 목적 및 요구사항정확한 검색 결과 제공광고 상품 제거를 통한 서비스 상세페이지로의 전환율 증대서비스 검색에 최적화된 검색 플로우무엇을 검색해야 할지 모르는 사용자를 위한 검색 가이드검색 엔진 및 한글 형태소 분석기 변경을 통해 사용자에게 정확한 검색 결과를 제공하는 게 우선순위였습니다. 그리고 광고 상품을 제거하고 사용자가 다양한 서비스를 찾을 수 있게 도와주는 기능을(자동완성검색, 연관검색어, 인기검색어) 추가했습니다. 그뿐만 아니라 서비스 검색에 최적화된 검색 플로우를 위해 UI 개선도 진행했습니다.새로운 검색 엔진새로운 검색엔진을 찾던 중 은전한닢 한글 형태소 분석기를 공식으로 지원하는 엘라스틱서치를 찾았습니다.17개 검색 엔진 순위 (출처: DB-ENGINES)17개 검색 엔진의 순위를 살펴보면 아파치 루씬 기반의 엘라스틱서치가 다른 검색 엔진보다 100점 넘게 차이 나는 압도적인 점수를 기록하고 있습니다. 위의 점수는 구글이나 빙에서 언급 횟수, 구글 트렌드, 기술적 논의 횟수, 채용 공고, 소셜 네트워크에서 언급 횟수 등으로 측정한 점수입니다. 점수 산정 방법이 객관적이지 못하지만 엘라스틱서치가 핫하다는 것에는 이견이 없었습니다. 이에 본격적으로 엘라스틱서치에 대해서 기술 탐색을 시작했으며 스핑크스와 비교도 해봤습니다.엘라스틱서치엘라스틱서치는 확장성이 뛰어난 RESTful 검색 및 분석 엔진입니다. 대용량 데이터를 빠르고 실시간으로 저장, 검색 및 분석할 수 있습니다. 기술 탐색 결과 엘라스틱서치에 저장한 데이터를 키바나를 통해서 분석하고 시각화할 수 있다는 점이 매력적이었고, 공식으로 한글 형태소 분석기를 지원하기 때문에 검색 정확도를 높일 수 있다고 생각했습니다. 한글 형태소 분석기를 이용한 엘라스틱서치의 분석 과정은 다음과 같습니다.한글 형태소 분석기를 이용한 엘라스틱서치의 분석 과정필드의 title에 블로그 검색에 엘라스틱서치를 적용해보려고 합니다. 라는 문장이 있다면 지정한 analyzer를 통해서 분석을 진행합니다. 먼저 문자 필터를 거치고 은전한닢으로 한글 형태소 분석을 수행합니다. 형태소 분석이 완료되면 [블로그, 검색, 엘라스틱, 서치, 적용, 보, 하]로 나누어집니다. 그리고 토큰 필터를 통해 [블로그, 검색, 엘라스틱, 일래스틱, elasticsearch, es, 서치, 적용, 보, 하]로 term이 만들어집니다. 이 term은 elasticsearch index에 문서 id와 함께 저장됩니다.다음은 엘라스틱서치와 스핑크스를 비교해봤습니다.엘라스틱서치 vs 스핑크스엘라스틱서치 vs 스핑크스엘라스틱서치와 스핑크스를 비교해보면 스핑크스도 충분히 좋은 검색엔진이지만 한글형태소 분석기와 키바나의 시각화, 데이터 분석 같은 장점을 활용하기 위해 엘라스틱서치를 도입하기로 했습니다.도입을 결정하고 엘라스틱서치를 구축하는 방법을 알아봤습니다.  1. 엘라스틱 클라우드를 사용하는 방법  2. AWS Elasticsearch Service를 이용해서 구축하는 방법3. EC2 인스턴스에 오픈소스 엘라스틱서치를 직접 설치해서 구축하는 방법   엘라스틱서치를 구축하는 방법에는 보통 3가지 방법이 있고 아래의 특징을 가지고 있습니다.1번은 엘라스틱에서 관리 및 교육, 컨설팅을 지원해줍니다. 그리고 한글 형태소 분석기 은전한닢을 지원합니다. 최신 버전의 엘라스틱 스택을 바로 사용할 수 있으며 모니터링 기능도 지원합니다. 라이선스 별 지원은 링크를 통해서 확인할 수 있습니다.2번은 AWS에서 제공하는 Elasticsearch Service이며, 관리형 서비스입니다. 같은 VPC에 묶여있는 인스턴스를 통해서만 접근할 수 있게 되어있으며 외부에서는 접근할 수 없습니다.(퍼블릭 액세스도 있으나 AWS에서 권장하지 않습니다.) 키바나를 사용하기 위해서는 같은 VPC의 인스턴스 웹 서버 프록시나 AWS 코그니토로 접근해야 합니다. 한글 형태소 분석기 은전한닢을 지원하지만 다른 플러그인은 지원하지 않는 경우가 많이 있습니다. AWS Elasticsearch Service에서 지원하는 플러그인 리스트는 여기에서 확인할 수 있습니다.3번은 EC2 인스턴스에 오픈소스 엘라스틱서치를 설치해서 사용하는 방법입니다. 직접 서버를 구축하는 방법이기 때문에 사용자가 어떻게 사용하느냐에 따라 달라집니다.크몽 개발팀은 가격, 관리적 측면을 고려한 결과 2번 AWS Elasticsearch Service로 구축을 진행했습니다.구현구현은 엘라스틱에서 라라벨 프레임워크에서 사용할 수 있는 엘라스틱서치 관련 라이브러리를 정리해둔 링크를 참고했습니다. 3개의 라이브러리 중 스타가 제일 많은 Plastic 라이브러리를 사용해서 구현을 시도한 적이 있었는데 몇 가지 장점이 있었지만 엘라스틱서치 5까지만 지원을 하므로 field type에 text, keyword가 존재하지 않아 매핑하는데 문제가 있었습니다. 그리고 아직 지원하지 않는 쿼리도 존재하기 때문에 결국에는 PHP 공식 엘라스틱서치 클라이언트 라이브러리인 Elasticsearch-PHP를 사용해야 되는 상황도 발생했습니다. 위에서 말한 점 때문에 Plastic 라이브러리를 걷어내고 Elasticsearch-PHP만 이용해서 개발을 진행했습니다. 엘라스틱에서 제공하는 Elasticsearch-PHP 가이드도 잘 정리되어있습니다. 더욱 자세한 구축, 구현 방법을 알고 싶으신 분들은 아래의 글에서 확인하실 수 있습니다.라라벨 프레임워크 - 엘라스틱서치 사용 경험기 : 초기 작업 수행라라벨 프레임워크 - 엘라스틱서치 사용 경험기 : 문서 관리 작업 수행결과검색 기능 개선 결과는 아래와 같습니다,1.자동완성검색자동완성검색 기능2. 연관검색어 + 검색 결과 광고 제거연관검색어 및 검색결과 광고 제거3. 키워드와 관련된 카테고리 추천키워드와 관련된 카테고리 추천4. 검색 결과가 없는 키워드에는 인기검색어 추천검색 결과가 없는 키워드에는 인기검색어 추천무엇을 검색해야 할지 모르는 사용자를 위한 검색 가이드를 만들기 위해 노력했으며, 기능 추가로 사용자의 검색 만족도와 정확도를 높이려고 노력했습니다.또한 엘라스틱서치와 한글 형태소 분석기 은전한닢을 이용해 검색 기능 개선을 통한 결과 평균 체류 시간은 20초 정도 증가했으며 종료율은 최대 22.4%, 평균 1% 정도 떨어졌습니다. 또한 서비스 상세페이지 전환율은 최대 78.3%, 평균 3% 이상 증가했습니다. 서비스 상세페이지 전환율의 상승은 사용자의 검색 만족과 검색 정확도가 상승했다고 볼 수 있습니다.정리이번 글에서는 엘라스틱서치와 한글 형태소 분석기 은전한닢을 이용해 검색 기능을 개선한 이야기를 정리해봤습니다. 검색 기능 개선 이후 서비스 상세페이지 전환율이 조금씩 상승 중입니다. 릴리즈한지 두 달 정도밖에 되지 않아 조금 더 지켜봐야 하겠지만 전환율이 조금씩 상승하고 있다는 건 좋은 신호인 거 같습니다. 다만 짧은 글을 통해서 경험을 전달하려고 하니 많은 내용을 담지 못한 것 같아 아쉽습니다. 다음에는 더욱더 깊이 있는 글을 전달할 수 있는 에이든이 되겠습니다. 감사합니다.#크몽 #개발팀 #개발자 #개발문화 #경험공유 #인사이트
조회수 4058

Eclipse Memory Analyzer 소개

안드로이드 개발을 하다보면 종종 OutOfMemory(OOM)에러를 만나게 됩니다. 이전에 올렸던 포스팅에서도 이 문제로 고생을 했는데요, 메모리 누수 관련 문제는 로직 에러와는 달라서 찾기가 매우 난감한 경우가 많습니다. 이러한 메모리 누수 관련 문제를 해결하기 위한 검사 기능을 제공하는 무료 툴이 있습니다. 바로 Eclipse MAT(Memory Analyzer)(MAT)입니다.Eclipse MATMAT은 사용자로 하여금 힙 메모리의 상황을 파악하게 해주어 메모리 누수 현상과 필요없는 메모리 할당을 감지할 수 있도록 도와줍니다. 또한 자동으로 보고서를 작성하여 어떤 객체들이 메모리 누수를 일으키는지에 대한 추측을 해주는 기능을 제공합니다. MAT은 Eclipse 플러그인이기 때문에 사용하려면 Eclipse가 깔려 있어야 합니다. MAT을 설치하려면 MAT 다운로드 페이지에서 자신의 Eclipse버전에 맞는 파일을 받으시면 됩니다.How to use MATMAT을 설치하였다면 Eclipse화면에서 MAT관련 탭이 뜹니다. 탭을 클릭 하고File -> Open Heap Dump 를 누르면 힙 상황이 기록 된 hprof파일을 읽어올 수 있습니다.탭이 뜨지 않는다면Window -> Open Perspective -> Other에서 Memory Analysis 를 누르면 탭이 뜨는 것을 볼 수 있습니다.hprof 파일을 읽어오면 분석을 시작하고 결과를 Overview 화면에 보여줍니다.파이 차트의 각 부분에 마우스를 갖다 대면 옆의 Inspector 화면에 해당 객체의 정보를 보여주는 것을 볼 수 있습니다.InspectorInspector 창에서는 선택된 객체의 내용을 볼 수 있습니다. 해당 객체의 클래스명과 패키지 명 그리고 해당 객체가 가지고 있었던 변수의 내용을 살펴볼 수 있습니다.유용한 기능들MAT에서 가장 중요하게 살펴볼 기능이라고 한다면 Leak suspoect report와 Dominator tree라고 볼 수 있습니다. Leak suspect와 Dominator tree 둘 다 가장 메모리를 많이 차지하고 있는 객체에 대한 정보를 제공합니다.Leak suspectLeak suspect는 가장 큰 용량을 차지하고 있는 객체들을 좀 더 세분된 파이 도표로 보여줍니다. Problem suspect 1을 보면 현재 이 스레드 객체의 크기가 전체 힙 메모리의 크기 중 19.73%를 점유하고 있다는 것을 알 수 있습니다. 전체의 20% 가까이 차지하고 있다는 것은 이 객체를 OOM의 범인(?)이라고 생각할 근거가 됩니다. 해당 객체에 대한 더 자세한 정보를 얻고 싶다면 Details을 클릭하면 됩니다.Dominator treeDominator tree를 띄우면 현재 덤프 된 매모리 스냅 샷 중 가장 큰 용량을 차지하고 있는 객체 순으로 정렬하여 보여줍니다. Leak suspect와 비슷해 보이지만 더 구체적인 정보를 제공한다는 점이 다릅니다. 따라서 Leak suspect로 현 상황에 대한 힌트를 얻은 후 Dominator tree에서 디테일하게 살펴보는 것이 시간을 절약하는 방법입니다.상위에 있는 몇몇 객체들이 가장 의심 되는 객체들이라고 볼 수 있겠습니다. 왼쪽의 화살표를 클릭함으로써 그 객체가 참조하고 있는 다른 객체들에 대한 정보들을 볼 수 있습니다. 각 객체를 클릭하면 옆에 Inspect창의 내용이 달라지는 것을 볼 수 있습니다.실제 이 스냅 샷은 이전 포스팅의 문제를 해결하려고 떠놓은 스냅 샷인데요, 이 결과를 보고 많은 메모리가 네트워크를 통해 받아오는 스트림을 처리하고 문자열로 가공하는데에 낭비되고 있다는 생각이 들어 다른 방법으로 우회하는 방법을 썼고 결과적으로 문제를 해결 할 수 있었습니다.Android에서 MAT사용법먼저 안드로이드 기기에서 힙 덤프를 수행하여 hprof파일을 생성해야 합니다. hprof파일을 생성하기 위해서 간단하게 취할 수 있는 2가지 방법이 있습니다.1. DDMS를 이용한 추출Eclipse의 DDMS를 이용하여 힙 덤프를 추출할 수 있습니다. 아 방법을 쓰려면 앱의 메니페스트 파일에 WRITE_EXTERNAL_STORAGE 권한을 부여해야 하며, sdcard에 쓸 수 있는 권한이 있어야 합니다. 이 방법을 통해 sdcard경로에 앱 패키지명의 hprof파일이 생성됩니다.2. Heap dump method안드로이드 API에서 제공하는 메서드 중에 hprof파일을 생성하는 메서드인 dumpHprofData가 있습니다. 이 메서드는 Debug 클래스의 메서드인 것을 알 수 있는데, 이 Debug 클래스에는 앱의 상태를 점검할 수 있는 여러 유용한 메서드가 있으므로 나중에 필요하면 사용할 수 있도록 익혀두면 좋습니다.Android hporf 파일 변환앞서 설명한 방법을 적용하여 hprof파일을 추출하였어도 안드로이드에서 추출한 hprof파일은 MAT에서 받아들이는 일반적인 hprof포맷과 다르기 때문에 먼저 변환하는 과정이 필요합니다. 이러한 기능을 제공하는 것이 기본 SDK에 포함된 hprof-conv유틸입니다. 이 유틸은 SDK폴더 내의 tools폴더 안에 있는데 사용하려면 콘솔에서$ hprof-conv <안드로이드용 hprof 파일> <변환할 hprof 파일> 를 치시면 됩니다. 이제 변환된 파일을 MAT에서 열면 분석을 하실 수 있습니다.More tipEclipse Memory Analyser (MAT) - TutorialMemory Analyzer BlogJava Performance blog상기의 사이트들은 MAT과 Java의 메모리 처리에 관련된 내용을 포스팅한 사이트들입니다. 한 번 들러보면 좋은 정보를 얻을 수 있을것입니다.#스포카 #꿀팁 #개발 #개발자 #스킬스택 #스택소개 #인사이트
조회수 1415

[어반베이스 피플] 홈디자이닝 AR앱 'Urbanbase AR' 개발자 인터뷰

어반베이스 AR을 사용하여 원하는 가구 및 가전제품을 미리 배치해볼 수 있다는 사실, 알고 계시죠? 최근 가구, 가전, 화장품, 의류 등 다양한 업계에서 AR을 활용해 고객들에게 새로운 경험을 제공하고 있으며 이러한 서비스들은 점점 증가하고 있습니다. 미래에는 AR을 활용한 쇼핑 플랫폼들이 점차 대중화 될 것이고, AR 쇼핑 플랫폼을 설계하는 전문가에 대한 수요도 늘어날 것으로 예상됩니다.서울산업진흥원은 미래 경쟁력 있는 신직업 40개를 선정했는데, 선정한 미래직업 중 'AR 쇼핑 플랫폼 설계자'가 포함되었고, '어반베이스 AR'의 담당 개발자 우석님이 인터뷰를 진행하게 되었습니다.홈디자이닝 AR앱 'Urbanbase AR'의 개발자Q. 일하면서 보람을 느끼는 순간은 언제인가요? 사람들은 작은 물건 하나를 구입할 때도 성능과 디자인 등을 꼼꼼히 살핍니다. 몇 번이나 구매를 망설이기도 하고요. 살아가는 집, 그 공간을 꾸미는 데는 얼 마나 많은 시간과 노력이 필요할까요? 가구와 인테리어 소품을 일일이 쇼핑하지 않고도 스마트폰 안에서 내가 원하는 상품들로 내 방을 미리 꾸며볼 수 있는 셀프인테리어 앱을 설계하는 것이 저의 일입니다. VR, AR 기술을 통해 가 구 배치, 벽지 교체, 인테리어 등을 미리 경험해보고 구매할 수 있기에, 시간과 비용은 줄어들고 만족도는 올라가게 됩니다. 제가 만든 가상의 공간이 누군가에게 편안하고 안락한 삶을 선사해주는 것을 볼 때 제 일에 보람을 느낍니다.Q. AR 쇼핑 플랫폼 설계자가 신직업으로서 가지는 경쟁력은 무엇일까요? 지금 이 순간에도 수많은 기업에서 무수히 많은 제품이 개발, 생산되고 있습 니다. 제품 정보나 장점을 소비자에게 보다 정확하게 전달해 반품율을 줄이 고 판매율을 높이는 것은 모든 기업이 바라는 점이죠. 그 대안이 될 수 있는 것이 AR 쇼핑인 만큼 AR 쇼핑 플랫폼 설계자에 대한 니즈는 빠르게 증가할 것입니다. AR은 커머스뿐 아니라 건설, 교통, 의료, 부동산, 인테리어 등 현대 산업 전체에 적용 가능한 기술이죠. 이는 AR 쇼핑 플랫폼 설계자로 쌓은 경험과 경력을 바탕으로 다양한 분야에 진출할 수 있다는 의미이기도 합니다. Q. AR 쇼핑 플랫폼 설계자에게 가장 필요한 자질은 무엇이라고 생각하시나요? AR 쇼핑 플랫폼 설계자는 크게 본다면 프로그래머 직군에 속합니다. 그렇기에 컴퓨터공학에 대한 소양이나 정보처리기사 자격증 등을 미리 준비해 두는 것이 좋습니다. 또한 AR 플랫폼은 주로 모바일 환경에서 제공되기 때문에 안드로이드 혹은 iOS 플랫폼에 대한 이해가 필수적입니다. 여기에 3D 그래픽에 대한 개념을 알고 있으면 업무를 수행하는 데 큰 도움이 됩니다. AR 쇼핑 플랫폼 설계자는 많은 가능성을 가진 유망 직종이지만, 이제 막 출 발한 분야이기에 상대적으로 참고할 수 있는 레퍼런스가 많지 않습니다. 그렇기 때문에 누군가가 만들어 놓은 길을 따라가기보다는 치열하게 연구하고 도전하는 자세가 필요합니다. Q. AR 쇼핑 플랫폼 설계자를 꿈꾸는 이들에게 조언 한마디 부탁드립니다.AR 기술을 습득하고 활용하기 위해서는 여러 가지 기본 지식들이 뒷받침돼야 합니다. AR 기술을 온라인에 접목하려면 쇼핑 플랫폼은 물론 관련 상품에 대한 지식도 필수적이고요. 이러한 지식들은 하루아침에 습득할 수 없는 것들입니다. 그렇기에 너무 조급해하지 말고 하나씩 내 것으로 만드는 자세 가 중요합니다. 시공간에 구애받지 않는 ‘가상의 세계’를 만들어내는 일은 분명 신나는 일입니다. 실패를 두려워하지 않는 개척자 마인드를 가진 사람이라면 충분히 즐기면서 일할 수 있으니, 꼭 도전해보세요.사진 출처 및 인터뷰 전문https://blog.naver.com/urbanbaseinc 
조회수 1767

TDD(파이썬) : 테스트 잘하고 계신가요?

Overview반복적인 테스트에 지쳐가고 있던 무렵, TDD방법론을 접하게 되었습니다. TDD(Test Driven Development)는 테스트 주도적인 개발로 소스코드 작업 전에 테스트 코드를 먼저 작성해 소스수정에 대한 부담을 덜고 디버깅 시간을 줄일 수 있습니다. TDD 장점소스코드의 품질이 높다.재설계 및 디버깅 시간이 절감된다.TDD 단점단기적 코드일 경우 생산성이 떨어진다.실제 코드보다 테스트 케이스가 더 커질 수 있다.파이썬에서 TDD가 필요한 이유1) 파이썬에는 정적 타입 검사 기능이 없다. (Python 3.6 에서는 정적 타입 선언 가능)2) 동적언어이기 때문에 TDD를 하기에 적합하다.3) 파이썬은 간결성과 단순함으로 생산성이 높은 반면 런타임 오류가 발생할 수도 있다.4) 파이썬을 신뢰할 수 있는 유일한 방법은 테스트를 하는 것이다.파이썬 테스트 모듈 unittest이번 글에서는 unittest를 사용해 단위 테스트를 해보겠습니다. unittest는 이미 내장되어 있어 따로 설치하지 않아도 되는 표준 라이브러리입니다. 사용방법1) import unittest 2) unittest.TestCase 상속받는 하위 클래스 생성3) TestCase.assert 메소드를 사용하여 테스트 코드를 간략화4) unittest.main() 실행그럼 간단한 예제로 단위 테스트를 해보겠습니다.1.사칙연산 함수를 추가합니다.def add(a, b):     return a + b   def substract(a, b):     return a - b   def division(a, b):     return a / b   def multiply(a, b):     return a * b 2. unittest.TestCase 상속받아 테스트 클래스를 생성합니다. 아래는 각각의 함수 결과값을 비교해 텍스트를 출력하는 코드입니다.import unittest class TddTest(unittest.TestCase): def testAdd(self):         result = lib_calc.add(10, 20)         if result == 30:             print('testAdd OK')      def testSubstract(self):         result = lib_calc.substract(20, 30)          if result > 0:             boolval = True         else:             boolval = False if boolval == False:             print('testSubstract Error')      def testDivision(self):         try:             lib_calc.division(4, 0)         except Exception as e:             print(e)      def testMultiply(self):         result = lib_calc.multiply(10, 9)          if result < 100>             print('testMultiply Error') if __name__ == '__main__':     unittest.main() 3.결과: 해당 조건에 만족해 작성한 텍스트가 출력됩니다.이번에는 unittest에서 지원하는 TestCase.assert 메소드를 사용해 간략하게 소스를 수정해보겠습니다.TestCase.assert 메소드1) assertEqual(A, B, Msg) - A, B가 같은지 테스트2) assertNotEqual(A, B, Msg) - A, B가 다른지 테스트3) assertTrue(A, Msg) - A가 True인지 테스트4) assertFalse(A, Msg) - A가 False인지 테스트5) assertIs(A, B, Msg) - A, B가 동일한 객체인지 테스트6) assertIsNot(A, B, Msg) - A, B가 동일하지 않는 객체인지 테스트7) assertIsNone(A, Msg) - A가 None인지 테스트8) assertIsNotNone(A, Msg) - A가 Not None인지 테스트9) assertRaises(ZeroDivisionError, myCalc.add, 4, 0) - 특정 에러 확인1. TestCase.assert 메소드 사용TestCase.assert 메소드를 사용하여 에러를 발생시켜 보겠습니다.import unittest class TddTest(unittest.TestCase): def testAdd(self):         result = lib_calc.add(10, 20)          # 결과 값이 일치 여부 확인         self.assertEqual(result, 31)      def testSubstract(self):         result = lib_calc.substract(20, 10)          if result > 10:             boolval = True         else:             boolval = False # 결과 값이 True 여부 확인         self.assertTrue(boolval)      def testDivision(self):         # 결과 값이 ZeroDivisionError 예외 발생 여부 확인         self.assertRaises(ZeroDivisionError, lib_calc.division, 4, 1)      def testMultiply(self):         nonechk = True result = lib_calc.multiply(10, 9)          if result > 100:             nonechk = None # 결과 값이 None 여부 확인         self.assertIsNone(nonechk) if __name__ == '__main__':     unittest.main() 2. 결과1) 테스트가 실패해도 다른 테스트에 영향을 미치지 않음2) 실패한 위치와 이유를 알 수 있음다음으로 setUp(), tearDown() 메소드를 사용하여 반복적인 테스트 메소드 실행 전, 실행 후의 동작을 처리해보겠습니다.TestCase 메소드1) setUp() - TestCase클래스의 매 테스트 메소드가 실행 전 동작2) tearDown() - 매 테스트 메소드가 실행 후 동작 1. setUp(), tearDown() 메소드 사용- setUp() 메소드로 전역 변수에 값을 지정- tearDown() 메소드로 “ 결과 값 : ” 텍스트 출력import unittest class TddTest(unittest.TestCase): aa = 0     bb = 0     result = 0 # 매 테스트 메소드 실행 전 동작     def setUp(self):        self.aa = 10        self.bb = 20 def testAdd(self):         self.result = lib_calc.add(self.aa, self.bb)          # 결과 값이 일치 여부 확인         self.assertEqual(self.result, 31)      def testSubstract(self):         self.result = lib_calc.substract(self.aa, self.bb)          if self.result > 10:             boolval = True         else:             boolval = False # 결과 값이 True 여부 확인         self.assertTrue(boolval)      def testDivision(self):         # 결과 값이 ZeroDivisionError 예외 발생 여부 확인         self.assertRaises(ZeroDivisionError, lib_calc.division, 4, 1)      def testMultiply(self):         nonechk = True self.result = lib_calc.multiply(10, 9)          if self.result > 100:             nonechk = None # 결과 값이 None 여부 확인         self.assertIsNone(nonechk)      # 매 테스트 메소드 실행 후 동작     def tearDown(self):         print(' 결과 값 : ' + str(self.result))   if __name__ == '__main__':     unittest.main() 2. 결과- setUp() 메소드로 지정한 값으로 테스트를 수행 - tearDown() 메소드로 각각의 테스트 메소드 마다 “ 결과 값 : ” 텍스트 출력실행 명령어 여러 옵션을 사용하여 실행 결과를 출력해보겠습니다.실행 명령어python -m unittest discover [option]1. -v : 상세 결과 2. -f : 첫 번째 실패 또는 오류시 중단3. -s : 시작할 디렉토리4. -p : 테스트 파일과 일치하는 패턴5. -t : 프로젝트의 최상위 디렉토리1. 상세 결과테스트 메소드명 및 해당 클래스명 출력 2. 첫 번째 실패 또는 오류시 중단첫 번째 테스트에서 오류 발생하여 중단3. 여러 옵션 실행현재경로 디렉토리 안에 tdd_test*.py 패턴에 속하는 모든 파일의 상세 결과Conclusion지금까지 파이썬에서 unittest 모듈을 이용한 테스트 코드를 작성했습니다. 처음에는 귀찮고 번거롭지만 테스트 코드를 먼저 작성하는 습관을 길러보세요. 분명 높은 품질의 소스코드를 만들 수 있을 겁니다!참고Python 테스트 시작하기파이썬 TDD 101글곽정섭 과장 | R&D 개발1팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발자 #개발팀 #인사이트 #경험공유 #파이썬 #Python
조회수 896

[Tech Blog] How we pipe data

버즈빌에서는 미국과 일본을 비롯한 전 세계 30개국에서 1,700만 이상의 유저의 행동에 대한 데이터를 수집하고 있습니다. 이 데이터에는 유저들이 잠금화면에서 어떤 Action을 수행하는지부터 잠금화면에 어떤 광고가 노출되고 유저들이 어떤 광고를 클릭 하는 지 등의 정보들이 포함되는데요. 이러한 데이터는 여러 종류의 다른 소스로부터 오고 각기 다른 종류의 DB (MySQL, DynamoDB, Redis, S3 등등) 에 저장됩니다. 하지만 데이터를 분석하고 활용하기 위해서는 이렇게 흩어져서 저장된 데이터들을 한 곳으로 모으는게 필수적입니다. 그래서 저희 팀에서는 이렇게 다양한 소스로 부터 발생해서 다양한 DB에 저장된 데이터를 어떤 과정을 통해 한 곳으로 모을 것인가에 대해서 고민하게 되었습니다. 그리고 고민 끝에 각각의 DB에 저장된 데이터를 하나의 큰 데이터 스토리지에 모을 수 있는 ‘데이터 파이프라인’을 구축하는 계획을 세우게 되었습니다. 하지만 다양한 소스로부터 수집된 수많은 데이터들을 잘 유지해가며 하나의 큰 DB에 모을 수 있는 데이터 파이프라인을 구축하는 것이 쉽지 않았는데요. 이 포스팅을 통해서 버즈빌에서는 어떻게 각각의 데이터들을 수집하고 저장하는지 또 이런 데이터들을 통합하기 위한 파이프라인을 어떻게 구축했는지 공유하고자 합니다. 본격적인 이야기에 앞서 현재 버즈빌에서 모든 데이터가 모이는 데이터 스토리지로 사용 중인 RedShift에 대해 이야기하고 싶습니다. 개인적으로는 정말 쓰면 쓸수록 감탄이 나오는 데이터 스토리지라고 생각합니다. Redshift는 AWS에서 관리하는 SQL기반의 열기반 스토리지(SQL based columnar data warehouse)이며 복잡하고 대규모의 데이터 분석에 적합합니다. 고객들로부터 생성된 수많은 종류의 데이터를 기반으로 다양한 인사이트를 얻고자 하는 많은 기업들(Yelp, Coursera, Pinterest 등)이 사용하고 있는 솔루션 이기도 합니다. 버즈빌에서는 여러가지 특징을 고려하여 Redshift를 도입하게 되었는데요. 그 이유는 아래와 같습니다.  Performance Performance Performance.     Column 기반 스토리지 -> 필요한 Column에만 접근한다.   Join이나 aggregation이 많은 복잡한 쿼리도 쉽게 계산할 수 있다.   분산 저장 방식 (Distributed Storage)   Date Ingestion이 빠르다. (Ingest first, index and clean later)     Horizontal Scalability   sharding이나 clustering에 추가적인 complexity가 필요하지 않다. 데이터가 원래 노드에 저장되기 때문에 horizontal scaling을 위해서는 그냥 추가적인 노드만 붙이면 된다. 다른 AWS서비스들과 쉽게 연동이 가능하다. (장점 이자 단점)    하지만 몇 개의 아쉬운 점들도 있습니다. :  다른 RDBMS와 달리 Mutilple indice를 지원하지 않는다.  1 Distribution Key and 1 Sort Key   MySQL이나 다른 RDBMS처럼 uniqueness나 foreign key constraint를 걸 수 없다.     모은 데이터를 어떤 방식으로 Redshift로 옮겨야 할까요? 버즈빌이 구축한 데이터 파이프 라인은 크게 3갈래의 메인 루트가 있습니다.   1) Athena Preprocessing Batch job을 통해서 (잠금화면 활동, 광고 할당) Why? 전처리 작업(Preprocessing)이 필요한 가장 큰 이유는 들어오는 데이터의 어마어마한 크기 때문입니다. 또 어떤 데이터들은 너무 raw하기 때문에 애널리스트나 데이터 사이언티스트가 분석에 활용할 수 있는 형태로 바꾸기위해 전처리가 필요하기도 합니다. 버즈빌에서는 이런 데이터들을 처리하기 위해서 AWS Athena를 사용하고 있습니다. Athena는 과금 방식이 Athena 쿼리로 읽은 데이터의 사이즈를 기반으로 하기 때문에 다른 EMR이나 MapReduce solution들을 사용했을때보다 상대적으로 적은 비용으로 활용할 수 있다는 장점이 있습니다. How?  먼저 S3로 데이터를 보냅니다. 그 후, Athena를 활용하여 데이터를 가공/처리합니다. 가공된 데이터를 읽어서 Redshift로 보냅니다. (COPY command 활용)  Pros?  서버를 따로 가질 필요가 없습니다. (EMR 클러스터나 서버를 관리할 필요가 없음) 경제적입니다. (S3에서 1TB를 읽을때마다 $5 정도의 비용)  Cons?  사용량이 몰리는 시간대 (12:00 AM UTC)에는 일부 쿼리가 실패할 수 있습니다. -> 중요하고 필수적인 데이터는 Athena가 아닌 다른 방법을 통해 처리하는것이 적합합니다. PRESTO DB의 기능을 (아직은) 온전히 활용할 수 없습니다.     2) Firehose를 통해서 (Impression, Clicks, Device, Events) Why? Kinesis Firehose는 Redshift, Elasticsearch, S3와 같은 최종 목적지까지 다양한 데이터들을 안정적으로 옮길 수 있는 파이프라인을 제공할 뿐 아니라 Fluentd와 매끄럽게 잘 연동된다는 점에서 굉장히 뛰어난 서비스 입니다. Fluentd는 서버로부터 firehose까지 데이터가 안정적이고 꾸준하게 전달 될 수 있도록 도와줍니다.  따라서 firehose와 fluentd의 연동을 통해서 따로 두개의 파이프라인 ( SERVER -> S3, S3 -> Redshift) 을 관리할 필요 없이 데이터 소스부터 최종 저장소까지 이어지는 하나의 파이프 라인만 관리할 수 있게 됩니다. How?  (https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html)  적절한 data format과 원하는 ingestion period를 설정하여 Firehose delivery stream을 만듭니다.   conf["user_activity"] = { "DataTableName": "user_activity", "DataTableColumns": "user_id, app_id, activity_type, timestamp", "CopyOptions": "FORMAT AS JSON "s3://buzzvil-firehose/sample/user_activity/jsonpaths/user_activity_log-0001.jsonpaths" gzip TIMEFORMAT AS "YYYY-MM-DDTHH:MI:SS" ACCEPTINVCHARS TRUNCATECOLUMNS COMPUPDATE OFF STATUPDATE OFF", "jsonpaths_file": "buzzvil-firehose/sample/user_activity/jsonpaths/user_activity_log-0001.jsonpaths", } configuration = { "RoleARN": "arn:aws:iam::xxxxxxxxxxxx:role/firehose_delivery_role", "ClusterJDBCURL": "jdbc:redshift://buzzvil.xxxxxxxxx.us-west-2.redshift.amazonaws.com:5439/sample_db", "CopyCommand": { "DataTableName": sample_table, "DataTableColumns": conf[type]["DataTableColumns"], "CopyOptions": conf[type]["CopyOptions"], }, "Username": db_user, "Password": db_password, "S3Configuration": { "RoleARN": "arn:aws:iam::xxxxxxxxxxxx:role/firehose_delivery_role", "BucketARN": "arn:aws:s3:::firehose_bucket", "Prefix": "buzzvil/user_activity/", "BufferingHints": { "SizeInMBs": 64, "IntervalInSeconds": 60 }, "CompressionFormat": "GZIP", "EncryptionConfiguration": { "NoEncryptionConfig": "NoEncryption", } } }  2. Fluentd docker containers을 각각의 서버에서 세팅하고 실행합니다.  @type tail path /var/log/containers/buzzad/impression.json pos_file /var/log/containers/td-agent/impression-json.pos format none tag firehose.impression @type kinesis_firehose region us-west-2 delivery_stream_name "prod-buzzad-impression-stream" flush_interval 1s data_key message  3. Firehose에서 데이터를 잘 모아서 Redshift 문제없이 보내고 있는지 모니터링 합니다.  Pros?  빠르고 안정적인 데이터 전송이 가능합니다. 모니터링이 편합니다.  Cons?  Schema가 자동으로 바뀌지 않습니다.( Redshift의 Schema를 수동으로 일일히 변경해주어야 합니다.)     3) MySQL Asynchronous Loads를 통해 (Ads, Contents, Ad Provider, Ad Publishers) Why? 여러대의 RDS MySQL DB로부터오는 데이터간의 sync를 맞춰가며 Redshift로 데이터를 복제하기 위해서는 3가지의 테크닉을 활용해야만 합니다. (이 방법은 소개하고 있는 세 메인 루트 중에서 가장 매력도가 떨어지는 방법입니다..) How?  FULL_COPY  MySQL 테이블 전체를 복사해서 SQL insert를 통해서 Redshift에 복사합니다.     INCREMENTAL_COPY  이전에 복사한 가장 마지막 Primary key부터 시작해서 새로생긴 row들을 읽어서 Redshift로 복사합니다.     UPDATE_LATEST_COPY  이전에 복사한 가장 마지막 타임스탬프부터 시작해서 새로 생성되거나 업데이트된 row들을 Redshift로 복사합니다.(중복된 값은 삭제).    Pros?  데이터의 특징에 맞게 잘 조정된 방법입니다. binary log를 통한 Replication보다 훨씬 다루기 쉽습니다.  Cons?  MySQL을 잘 조정하기 위해 여러대의 서버나 lambda를 다루어야만 합니다. -> Redshift sync task를 위해서 안정적인 schema altering을 할 수 있을 만큼 Redshift의 ORM이 발전된 상황은 아닙니다..    어떤 데이터를 다루는지에 따라서 위에서 소개한 3가지 방법 중 어떤 방법을 활용해야할지가 달라진다고 할 수 있습니다. 예를 들어 Transactianl log 같은 데이터들의 경우에는 firehose를 통해 전달하는 방법이나 먼저 aggregate하는 과정을 거친 후에 Redshift에 저장하는 식으로 처리를 해야 합니다. 그리고 MySQL에 저장된 fact table같은 데이터들은 CDC (change data capture) sync method를 통해서 Redshift에 데이터를 전달하고 동기화를 하는 과정이 필요합니다. 버즈빌에서는 위에서 소개해드린 3가지 방법을 적절히 조합해가면서 BD 매니저나 애널리스트들이 서비스간 플랫폼간의 데이터분석을 쉽게 할 수 있는 데이터 환경을 구축하기 위해서 노력하고 있습니다.
조회수 1629

채널 데스크 프론트엔드 기술 스택

오프라인 고객 분석 솔루션 워크인사이트를 개발해 온 조이는 최근 온라인 접객 서비스 채널을 런칭했습니다. 이 글은 채널과 관련된 기술 블로그의 첫번째 글로 채널 데스크 프론트엔드(웹, 윈도우, OSX)의 기술 스택 및 개발 환경을 소개하도록 하겠습니다.React채널 개발을 처음 시작할 당시 (지금으로부터 1년 전) 에 워크인사이트 대시보드 및 기타 사내 툴에서는 AngularJS 1을 사용하고 있었습니다. 비교적 적은 코드로 복잡한 애플리케이션을 빠르게 만들 수 있는 점에는 만족했지만 퍼포먼스면에서는 아쉬운 부분이 많았습니다. 따라서 새로운 프레임워크 및 라이브러리를 리서치 했고 매우 가볍고 렌더링 퍼포먼스 면에서 AngularJS 1 대비 우위에 있던 React 를 사용하기로 결정했습니다.컴포넌트의 설계 패턴은 Redux를 만든 Dan이 제안한 Container 와 Presentational 컴포넌트를 구분하는 방식으로 설계하고 있습니다. 따라서 Container 가 data fetch 및 update 등의 액션을 실행하고 Presentational 컴포넌트들을 조합하여 렌더링을 하게 됩니다.React를 실제 1년째 사용해 본 결과 저를 비롯한 팀원들은 매우 만족하고 있습니다. 구조, 스타일, 동작을 한 컴포넌트로 묶어 재사용성이 매우 높아졌으며 React의 휴리스틱한 Dom diff algorithm 덕분에 렌더링 퍼포먼스에서도 많은 이득을 얻을 수 있었습니다.Facebook Flux Utils아키텍쳐는 페이스북이 제안한 flux 철학에 따라 설계되었습니다. flux를 구현하기 위한 기본적인 유틸리티 기능을 제공하는 Flux Utils을 사용합니다. Flux의 많은 구현체 중에 요즘 가장 인기인 Redux도 고려했었습니다. 저희가 프로젝트를 시작할 당시에 Redux는 5~6개월밖에 되지 않은 프로젝트였고 거의 Dan의 1인 프로젝트였기 때문에 향후 메인터넌스를 장담할 수 없다고 판단했습니다. 그보다는 페이스북이 만든 Flux Utils가 그런 면에서는 더 안전할 거라고 생각했던 것이죠.약 1년 정도 Flux Utils로 개발해오며 몇 가지 문제를 겪게 되었습니다. 애플리케이션이 커지면서 관리해야할 State가 많아지고 그들 사이의 의존성 관리 때문에 Store의 복잡도가 빠르게 증가했습니다. 그에 따라 테스트가 어려워지고 올바른 유닛테스트를 위해서는 테스트 코드 역시 매우 복잡해지는 문제가 있었습니다.그래서 Redux를 다시 리서치하게 되었고, 결론적으로 “단일 Store, 다수Reducer” 라는 Redux의 철학을 통해 State 관리 로직(Reducer)을 단순하고 테스트도 쉽게 유지할 수 있겠다는 생각을 하게 되었습니다. 뿐만 아니라 그 동안 설계와 관련되어 고민하고 필요한 경우 저희 스스로 개발해서 사용하던 많은 부분이 Redux의 서브 프로젝트 형태로 (redux-actions, redux-thunk, reselect 등) 개발되어 사용되고 있는 것을 발견해서 Redux로의 마이그레이션을 결정했고 현재 진행 중에 있습니다.Electron이 글의 도입부에서 이야기한 것처럼 채널 데스크는 윈도우용, OSX용 애플리케이션으로도 제공됩니다. 채널 개발 초기 당시 윈도우, OSX 각각 네이티브로 만들 리소스가 부족했기 때문에 웹 기술 기반으로 네이티브 앱을 만들 수 있는 다양한 솔루션들을 리서치했고 그 중 Electron을 선택하게 되었습니다.Electron은 제가 정말 좋아하는 제품인 Slack, Simplenote에서 사용하고 알려져 있고 국내에서는 Remember 등에서 사용하고 있습니다. 초기 개발 당시에는 안정성에 의문을 제기하는 개발자들도 많았고 저희도 여러 문제와 삽질(인증, 패키징, 이슈 레포팅의 어려움, 메모리릭 등등)을 많이 겪긴 했습니다만 개인적으로는 충분히 프로덕션에 쓸 수 있을 정도 수준이라고 생각합니다. 무엇보다 프론트엔드 개발자가 매우 적은 노력으로도 네이티브 데스크탑 앱을 만들 수 있는 장점이 다른 모든 문제점을 상쇄하고도 남습니다.언어개발 언어로는 자바스크립트 ES6를 사용합니다. 언어를 선택할 당시에도 여러 옵션이 있었는데 가능하면 실험적이지 않고 표준을 사용하는 것이 미래 유지보수에 안전하다고 판단했습니다. 또한 다른 자바스크립트 대안 언어를 사용하지 않더라도 ES6 (일부 ES7 포함) 스펙도 충분히 효율적인 개발이 가능하다고 생각했습니다.코딩 스타일은 기본적으로 Airbnb의 코딩 스타일 가이드라인을 따르며 조이의 상황과 맞지 않는 부분은 엔지니어들과 상의 후 수정해서 사용하고 있습니다. 스타일 체크는 ESLint로 자동화한 뒤 Circle CI와 붙여서 모든 풀리퀘스트에 대해 점검하고 있습니다.테스트초기 개발할 때는 테스트 코드를 별도로 붙이지 않았습니다. 고객의 요구와 기타 상황에 따라 기획과 설계가 크게 변경되기도 했고 그 때마다 기민하게 반응하기 위해서, 어느 정도 확립된 제품이 되기 이전에는 테스트 코드는 작성하지 않는 것이 좋다고 판단했습니다. 이제는 많은 부분이 확정되었고 안정성이 중요해지기 시작했으며 애플리케이션이 커지면서 자동화된 테스트는 필수가 되기 시작했기에 최근에 도입을 하고 있습니다.테스트를 위한 도구는 Jest, Enzyme 등을 사용합니다. Presentational 컴포넌트에 대한 테스트는 props에 따라 원하는 형태로 렌더링이 이루어지는지, 이벤트에 따라 콜백이 잘 실행되는지 등의 Spec 을 작성합니다. Container 컴포넌트에 대한 테스트는 각종 이벤트 및 동작을 시뮬레이션하고 그에 따라 Action이 잘 발생하는지 또는 내부 state가 잘 변경되는지를 테스트합니다. 또한 Store (또는 Reducer), Action Creator, Model, Util 등 모든 구성 요소에 대한 테스트를 붙이려고 노력하고 있습니다. 유닛 테스트가 아닌 e2e 테스트 혹은 css 스타일 테스트 등은 하지 않고 있습니다.빌드 및 배포현재 채널 데스크는 Client-side rendering을 합니다. 초기 로딩 속도가 느리다는 단점이 있어서 Server-side rendering으로의 전환도 고려하고 있습니다. 이미 Node.js 를 사용하고 있어서 Isomorphic Javascript의 형태로 어렵지 않게 전환이 가능합니다.작성된 자바스크립트는 Babel로 컴파일되고 Webpack으로 번들화됩니다. css를 포함한 각종 리소스들 역시 Webpack을 통해 처리됩니다. 웬만한 작업은 npm과 Webpack으로만 자동화하려고 했으며, Electron과 관련된 작업(패키징, 인증 등)들만 gulp를 이용해 자동화됩니다. 모든 리소스들은 Node.js + express 서버로 Serving 되고, Node.js 앱은 Docker로 빌드되어 AWS EC2로 배포됩니다.마무리이상으로 채널 데스크 프론트엔드의 기술 스택을 소개해드렸습니다. 앞으로 각 부분 별로 저희 팀이 고민해 온 문제들과 해결 방법을 공유하고자 합니다. 뛰어난 개발자 분들의 많은 관심과 피드백 부탁드립니다!
조회수 1528

8퍼센트 CTO 1년 차 회고

2015년 11월 4일에 8퍼센트에 입사했으니 이제 1년이 되었다. CTO라는 직함을 달고 보낸 지난 1년을 뒤돌아 본다.1년전 첫번째 스프린트나는 무엇을 원했던가?회고를 할 때는 목표를 기준으로 지금을 살펴봐야 한다. 일 년 전에 썼던 8퍼센트에 입사하기까지 라는 글을 다시 꺼내어 보니 당시의 나는 이런 것들을 원했다. 성공하는 회사에 다닌다.개발 조직을 책임 지고 꿈꿔왔던 이상을 실험한다.회사 경영을 경험한다.사회에 도움이 되는 일을 한다.1) 성공하는 회사에 다닌다. 입사 전이라 "성공하는 회사에 다닌다”라고 적었지만 입사를 한 이상 “회사를 성공시킨다”라는 목표로 바꿔서 생각해도 좋겠다.2015년 10월 말을 기준으로 78.4억의 누적 대출액이 현재 기준으로 480억 가량 되니 지난 1년 동안 약 400억의 돈을 투자자로부터 대출자에게로 연결했다. 나는 이 돈의 크기가 정확히 8퍼센트라는 회사의 사회적인 영향력 그리고 고객들이 회사에 갖는 신뢰의 크기라고 생각한다. 또한 회사의 성공의 척도이다.그럼 이 400억이 성공을 이야기할 때 충분한가에 답을 해야 할터인데, 아직은 많이 부족하다. 하지만 어디인지 모르는 성공이라는 것에 다가갈 확률이 일 년 전에 비해 높아졌느냐라고 묻는다면 "그렇다"라고 자신 있게 말하겠다. 그리고 나 또한 그 확률을 높이는 것에 공헌하고 있다.입사할 당시에 대표님이 내세웠던 조건 중 하나가 올해 말 기준으로 500억이었는데, 그 기준은 넘기게 되었으니 80점을 주자.2) 개발 조직을 책임 지고 꿈꿔왔던 이상을 실험한다.입사 전에는 개발 조직만 맡을 것이라고 생각했으나, 현재는 더 넓은 프로덕트를 만드는 조직을 책임지고 있다. 1년 전에 꿈꿨던 이상이라는 것은 멋지게 일하는 조직이다. 입사 초기에는 이를 위해 꽤나 많은 노력을 했다. 회사 자체가 백지상태이기도 했고 의욕도 충만했다. 하지만 시간이 지나면서 나도 모르게 안주하게 되고 더 잘하기 위한 노력에 게을러졌다. 반성하자. 그래도 일 년 동안 데모를 한 번도 빠지지 않고 34차례 진행했다. (종종 프로젝트 진척이 잘 되지 않으면 데모에서 도망가고 싶다) 그리고 주기가 끝날 때마다 프로세스 개선을 위한 회고 회의를 해왔다. 비록 그 과정에 보완할 점은 많으나 포기하지 않고 프로세스를 일 년 동안 유지한 것에 점수를 주고 싶다. 이상에는 아직 멀었으나 이 조직이 내가 많은 것들을 실험할 수 있고, 그런 설득만 할 수 있다면 그 실험에 기꺼이 동참해 줄 수 있는 조직이라는 것을 깨달았다. 80점으로 시작해서 50점까지 내려갔다가 최근에 10점 정도를 얻었다. 60점을 준다.3) 회사 경영을 경험한다. 초기에 대표님의 신뢰를 얻는데 까지 시간이 꽤 걸렸다. 지금 생각해보면 서로 간의 신뢰를 쌓는데 시간이 걸리는 것은 자연스러운 것인데, 초기에는 의욕이 앞섰다. 왜 내게 더 많은 것을 맡기지 않는지가 불만스러웠다. 대표님이 내리는 결정의 많은 부분에 의심이 들었으며 딴지를 걸었다. 하지만 지금은 대표님의 선택과 결정이 대부분 이해되고 신뢰가 간다. 그리고 대표님이 내게 많은 것을 위임하고 믿어주는 것을 느낀다. 합이 맞아간다.생각보다 회사는 시장의 시간에 쫓겨  부족한 정보를 가지고 결정을 내려야만 했다. 회사의 결정이 모든 것을 좌우한다고 생각했었지만 이제는 결정에 따른 실행이 더 중요하다는 것을 알게 되었다. 4) 사회에 도움이 되는 일을 한다. 사회에 도움이 되는 일을 하는 것은 이 회사에 입사했을 때 결정이 되었다. 회사의 성장이 사회에 미치는 긍정적인 영향과 비례한다는 생각에는 변함이 없다. 이 회사의 존재가 이미 사회에 많은 영향을 미쳤다. 그리고 대부분은 긍정적인 영향이라고 생각한다. 90점을 주겠다.일하는 것의 변화 1) 일하는 양의 변화초기 반년은 후회가 없을 정도로 최선을 다해서 살았다. (내가 인생에서 이런 말을 할 수 있는 시기가 몇 번 없다.) 내 역량의 100%를 다하며 살았다. 그 6개월을 지난 이후에는 살짝 기어를 낮췄다. 좋게 말하면 마라톤을 위한 모드로 바꿨다고도 할 수 있고 어쩌면 6개월의 달리기로 조금 지쳤는지도 모르겠다. 2) 시간 분배의 변화처음 입사했을 때에는 시간의 50%를 개발에 사용했지만 지금은 10% 밖에 사용하지 못하고 나머지 40% 를 프로젝트 관리에 사용하고 있다. 30% 정도를 팀에 쓰고 있는데 처음에는 팀의 구조를 갖추는 데 사용했다면 지금은 팀을 운영하는 데 사용한다. 대체로 자리에 앉아 있는 시간이 많이 줄었고 내외부 사람들과 커뮤니케이션하는 시간이 늘어났다. (슬랙 통계를 보니 내가 압도적인 수다쟁이더라)나는 무엇을 배웠을까? 1) B2C 사업에서의 배움 기존에 일했던 회사는 B2B 회사였다. 손에 꼽을 수 있는 고객을 만족시키면 되었고 상대적으로 그들이 원하는 것은 명확했다. 혹은 커뮤니케이션을 통해 요구사항을 명확하게 만들 수 있었다. 상대적으로 긴 호흡으로 일을 했고, 성능이 중요했다.B2C 서비스는 달랐다. 고객은 어떤 면에서는 전혀 이성적이지 않았다. 놀라운 일이었다. 하지만 대부분 우리의 서비스는 냉정하게 평가되었다. 고객의 반응은 즉각적이지만 그 반응을 옳게 해석해서 제품에 반영하는 것은 어렵구나라는 것을 느꼈다. 지금 이 순간 고객을 최대로 만족시키는 선택이 회사에 있어 항상 옳은 선택은 아니라는 것도 알았다. 내가 개발하고 있는 서비스를 사용하는 많은 사람들이 있다는 것 그리고 사회에 직접적인 영향을 미친다는 것이 제품 개발을 지속할 수 있는 큰 동기가 된다는 것을 느꼈다.2) 프로덕트 책임자로서의 배움제품을 책임지고 있는 사람으로 B2C 서비스에 필요한 많은 역량이 부족하다는 것을 알게 되었다. 그리고 나의 부족한 역량이 완성도가 떨어지는 서비스에 많은 영향을 주고 있다는 것 또한 알게 되었다. 기획자와 일하는 경험, 디자이너와 일하는 경험 모두 처음이었다. 이를 통해 같은 회사에서 하나의 제품을 만들지만 그것을 바라보는 다양한 시각이 존재한다는 것을 알게 되었다.지난 회사의 CTO를 보며 제품의 문제를 어떻게 이렇게 잘 찾아낼까 생각했었는데 나 또한 그렇게 되더라. 통찰력이 아니라 관심을 얼마나 가지는가, 얼마나 책임감을 가지고 제품을 바라보는가에 대한 차이라는 것을 알게 되었다. 많은 기술적, 비즈니스에 기반한 결정을 했고, 그 결정의 결과를 지켜보고 있다. 그것에서 배웠다.3) 프로젝트 관리자로서의 배움 프로덕트팀이 일하는 방식으로 스크럼을 도입했다. 스크럼을 할 때 ScrumBut(우리는 스크럼을 해요. 하지만 이것저것은 하지 않아요.)을 유의하라는 말을 하는데 스크럼에서 요구하는 것들 중에서 하지 못한 것들이 꽤 있다. 예를 들면 업무의 양을 측정해서 번다운 차트를 제대로 그려가며 팀의 속도를 측정하거나,  업무를 항상 우선순위 기반으로 하는 것 등이다. 처음에는 시도했었으나 몇 번의 스프린트 후에는 적당히 스크럼을 적용하고 말았다. 프로젝트를 잘 관리하기 위해서는 많은 노력이 필요하다는 것을 알면서도 필요한 만큼의 노력을 기울이지 않은 것을 반성한다. 코딩을 포함한 회사에 많은 재미있을 것들에 우선순위를 두고 재미없음을 이유로 중요한 프로젝트의 관리를 뒤로 미루었다.4) 도구의 도입에서의 배움여러 가지 도구들을 도입했다. 모든 커뮤니케이션을 슬랙을 통하도록 여러 가지를 도입했다. 아마 우리 회사만큼 슬랙을 열심히 그리고 잘 쓰는 회사가 흔치 않을 것이라 생각한다.  컨플루언스를 도입해서 문서를 쓰는 문화를 만들어 갔다. 여전히 내가 제일 많은 문서를 쓰고, 대부분 내가 위키 가드닝(문서의 내용과 구조를 재조직하는 일)을 하고 있지만 사람들이 위키를 통해서 커뮤니케이션하는 것을 자연스럽게 생각하는 것을 보면 뿌듯하다. 트렐로도 도입해서 사용하고 있다. 최근까지는 엉성하게 쓰고 있었는 데 사용 가이드라인을 잡아서 한번 공유했으니, 앞으로 팀에 녹아들 것으로 기대한다.이렇게 도구를 도입하는 과정에서 변화를 이끌어 내는 방법을 연습했다. 사람들은 스스로 필요성을 느껴야 변화를 받아들인다. 탑다운식의 강압적인 도입은 결국 실패한다. 구성원들이 도구가 업무에 도움이 되는구나 라는 것을 느낄 때까지 선구자가 많은 노력을 기울여야 한다는 것을 알게 되었다. 사람들은 자신들이 필요한 정보를 컨플루언스에서 찾을 수 있을 때 자신도 정보를 컨플루언스에 남기기 시작했다. 자신들의 요청이 트렐로를 통해서 잘 처리된다는 것을 느꼈을 때 새로운 업무를 트렐로를 통해 전달해 주었다. 5) 개발에서의 배움초반에는 영역을 가리지 않고 개발을 했었다. 인프라 쪽도 정리하고 대출 프로세스도 개발하고 다른 금융업체와 연동도 하고 그리고 개발 환경도 갖추었다. 하지만 1년이 지난 지금 이미 내가 작성했던 코드는 절반 이상 다른 분들의 더 나은 코드로 대체되었다.타 금융권과 연계해서 개발을 하면서 이쪽 동네가 얼마나 기술 변화에 뒤쳐져 있는지를 알게 되었다. 취미로만 해봤던 웹 개발을 제품 레벨로 처음 해봤다. 프런트앤드 개발의 중요성과 어려움을 알게 되었다.개발팀의 효율을 올릴 수 있는 테스팅, 코드 리뷰, CI의 사용 등을 실제로 적용해 볼 수 있었다.마지막으로 회사에 좋은 분들을 모셔오면서 내가 얼마나 부족한 개발자인지를 알게 되었다.6) 금융업에서의 배움회사의 절반인 프로덕트를 만드는 사람들은 대부분 스타트업 출신이고, 나머지 절반은 금융권 출신으로 구성되어 있다. 금알못(금융을 알지 못하는 바보)으로 출발한 내가 이제 그들의 대화에 낄 수 있는 정도는 되었다. 하지만 여전히 하루가 멀다 하고 새로운 용어와 개념을 만나고, 대화가 끝나면 용어를 검색해보기 일쑤다.금융 동네는 어떤 경우에는 모든 것에 이유가 있어 딱딱 맞아떨어지는 것처럼 보이다가도 어떤 경우에는 도대체 이해가 안 되는 경우를 만나기도 한다. 여하튼 지난 일 년 동안 새로운 분야에서 일하면서 모르던 것(정확히는 모르는지도 몰랐던 것)들을  알아가는 즐거움을 느꼈다. 다음 회사를 가게 된다면 금융이 아닌 또 다른 분야에서 일하는 게 좋겠다는 생각이 들었다. 7) 채용에서의 배움입사했을 때 개발자 2명, 기획자 1명, 디자이너 1명이던 팀은 이제 개발자 9명에 기획자 2명, 디자이너 1명인 12명 팀이 되었다. 이 중 개발자 6명과 기획자 1명을 직접 채용했다. 이 과정에서 스타트업 채용의 어려움을 알게 되었고 조그만 노하우를 얻게 되었다. 그리고 채용에 따르는 책임이라는 것도 알게 되었다.채용 글을 쓰고 페이스북에 광고를 하고 구인 사이트에 올려보고 했지만 결국 대부분의 채용이 소개로 이루어졌다. 좋은 사람은 쉽게 다른 회사에 지원하지 않는다. 채용한 사람의 30배가 넘는 이력서를 받았고 5배가 넘는 면접을 보았다. 하지만 결국 소개를 받아 채용하는 것이 거의 유일한 방법인 것 같다. 회사에 대해 꾸준히 글을 써오고 있는데 이것이 채용에 많은 도움이 되었다.프로덕트팀 구성원은 내가 직접 채용을 결정하다 보니 이효진 대표에 의해서 내 인생이 바뀐 것처럼, 내가 채용한 사람들의 인생을 바꿨다. 그들이 자신들의 능력을 발휘해서 8퍼센트에 공헌할 수 있도록 하고 회사를 성공시켜서 그들의 노력에 답해 줄 수 있어야 한다는 생각을 한다. 8) 관리자로서의 배움 지난 회사에서 5명의 팀 리더를 할 때에는 내가 개발자인가 관리자인가라고 물으면 답하기가 쉽지 않았다. 하지만 지금 내게 묻는다면 나는 관리자라고 답하겠다. 나는 내 노력 50%를 들여서 전 구성원의 효율을 10% 더 올릴 수 있는 사람이 되어야 한다. 좋은 관리자였냐라고 하면 그렇지는 못했던 것 같다. 특히 구성원들에게 제때 필요한 피드백을 하지 못한 것은 아쉽다. 쓴소리를 해야 하는 위치에 있음에도 좋은 사람으로 남고 싶어서 적절한 때 적절한 피드백을 하지 못했다. 특히 같은 팀에 있는 디자이너와 기획자에게는 미안한 마음이다. 그들의 결과물에 대한 피드백도 쉽지 않았고, 커리어에 대해 해줄 수 있는 조언도 없었다. 그저 그들이 맡고 있는 좋은 프로덕트를 통해 성장해 나가길 바랄 뿐이다. 회사에서 1년 동안 "함께"라는 것을 기업 문화에 심기 위해 노력했다. 내가 시도했던 것들 중에 어떤 것들은 문화가 되어 정착이 되었고, 어떤 것들이 도태되어 사라졌다. 그 기준은 재미였다. 사람들에게 재미를 줄 수 있었던 슬랙의 #study 채널을 통해서 함께 공부하기, 브런치 매거진을 통해 함께 글쓰기, 2주에 한 번씩 오는 특별한 점심, 함께 하는 워크샵은 문화로 살아남았고 나머지는 사라졌다.  잃은 것은 무엇인가?1) 개발자로서의 경쟁력 개발자로서 경쟁력이 떨어지고 있다. 일반적으로 개발자가 망하는 과정을 다음과 같이 이야기한다.개발을 열심히 잘 하고 있음나이가 들면서 회사에서 관리자를 하라고 함관리자를 했더니 개발할 시간이 없어서 개발 실력이 떨어짐그 회사를 나오고 났더니 찾아 주는 곳이 없음치킨집내가 이런 과정으로 가고 있는 것은 아닐까? 에 대한 불안감이 있다. 전 회사에서는 새롭게 쏟아지는 기술들을 따라가며 공부를 해왔는데, 이제는 그런 공부 대신 당장 회사에 필요한 공부를 하게 된다. 이렇게 기술적인 경쟁력을 잃어 가게 되면 앞으로 먹고사는데 문제는 없을까?라는 생각도 들고, 당장 CTO라는 자리에서 옳은 결정들을 할 수 있을까 하는 생각 또한 든다.  2) 나와 가족체중을 얻었다. 운동할 시간이 없었기보다는 운동할 마음의 여유가 없었다. (둘 다 핑계이기는 매한가지다.) 체중이 늘어나다 보니 나 자신에 대한 자신감이 좀 떨어졌다. 가족들과는 입사 전에 비해 많은 시간을 보내지 못한다. 시간을 함께 보낼 때에도 핸드폰으로 슬랙을 확인하기 일쑤였다. 그리고 육체적/정신적으로 지친 상태라 100% 마음껏 놀아주지 못했다. 총평8퍼센트에 입사하기 전 일 년보다 훨씬 더 치열하게 살았다는 것만으로도 만족할 수 있는 1년이다. 내가 원하던 자리에서 원하던 경험을 할 수 있는 기회를 갖게 된 것만으로도 8퍼센트와 이효진 대표에게 감사한다. 자신 있게 추진하던 일 중 용두사미가 되어 버린 것들은 아쉽다. 하지만 용기 있게 많은 것들을 시도한 것은 잘했다. 내가 잘하는 것과 못하는 것이 여실히 드러난 1년이었다.   다음 1년은 무엇을 목표로 해야 할까?1) 회사를 성공시키자회사의 성장과 성공에 기대고 있는 것들이 너무나 많다. 지난 1년이 잽으로 탐색으로 해보는 1라운드였다면, 앞으로의 1년은 제대로 주먹을 뻗어보고 맞아보는 2라운드가 될 것으로 기대한다.  2) 그릇의 크기를 늘이자내 그릇의 크기에 따라 좋은 프로덕트, 구성원들의 성장, 채용이 좌우된다는 것을 알게 되었다. 그리고 입사 전보다 내가 갖춰야 할 역량들이 훨씬 명확해졌다. 꾸준히 갈고닦자.3) 더 멋지게 일하는 팀을 만들자 점점 손발이 맞아 간다. 더 많은 기회를 제공하고, 더 많은 것을 위임하자. 그리고 피드백을 잘하자. 이를 위해 끊임없이 실험하자.4) 손은 항상 더럽게지난 회사 CTO 님의 가장 큰 장점이 항상 손을 더럽게 유지하는 것이었다. 다시 말해 작더라도 일부 모듈을 직접 개발하고 다른 사람들의 코드들을 충분히 이해하셨다. 나 또한 다른 많은 일들이 있더라도 하루에 한 줄의 코딩은 할 수 있도록 하고, 다른 사람의 코드를 리뷰하는 데에도 시간을 쏟아야 하겠다.다시 맞이하는 1년회고를 통해 순식간에 지나간 지난 1년이 가볍지 않았다는 것을 알게 되었다. 다행이다. 이 글을 작성하면서 1년 전에 쓴  8퍼센트 입사 날을 읽어 보았다. 그날만큼은 아니지만 가슴이 두근거린다. 여전히 8퍼센트는 내게 모험이고 도전이다. 이제 새로운 마음으로 1년 1일 째를 맞이해야겠다. 지금 기분이라면 1년 뒤 더 멋진 회고글을 쓸 수 있을 것 같다.30번째쯤 스프린트의 데일리 미팅저와 함께 하고 싶은 개발자 분은 지원해 주세요! 기다리고 있습니다.#8퍼센트 #에잇퍼센트 #CTO #기업문화 #조직문화 #팀문화 #후기 #돌아보기 #개발자
조회수 1202

클라우드와 운영자의 불안함.

2018년은 정말 클라우드가 일반화되는 해가 될듯 합니다. 클라우드 이전 사업 소식이 이곳저곳에서 들리는 요즘입니다. 스타트업 생태계는 이미 클라우드로 넘어갔지만 올해에는 엔터프라이즈 기업에서 대규모 IT 기업들까지 모두 클라우드로 넘어가고 있습니다. 와탭이 클라우드 최적화를 목표로 하는 모니터링 서비스이다보니 클라우드로 전환하는 시점에 있는 많은 기업들을 만나는데요. 클라우드를 적용하려고 준비중이거나 최근 클라우드로 이전한 기업의 운영팀들은 현업에서 사용하는 과정에서 클라우드 안정성에 대한 불안을 토로하기도 합니다. IT 운영자들이 느끼는 클라우드에 대한 불안감IT 운영의 핵심은 안정화입니다. 클라우드 이전까지 IT 인프라는 변화를 관리하는 대상이 아니였습니다. IT 인프라는 운영중에 변화하지 않으며 초기 설계에서도 최대 부하를 견디기에 충분한 여지를 남겨서 구성하였습니다. 하지만 클라우드에서는 IT 인프라가 운영중에도 변화 가능한 요소가 되면서 IT 인프라 규모 산정에서 부터 커다란 변화가 발생합니다. 최대 부하가 아닌 최소 부하가 규모 산정 기준이 되다. 여지껏 IT 인프라의 구성 기준은 언제나 최대 부하를 견딜수 있도록 설계되어왔습니다. 하지만 IT 인프라를 클라우드로 시작한 스타트업들이 IT 인프라를 구성하는 방법은 기존의 규칙을 무시하기 시작합니다. IT 인프라를 규모를 최소 부하에 맞춰서 구성하는 것입니다. 단지 실시간으로 확장 가능한 서비스 구조와 Auto Scailing을 통해 규모를 맞춰갑니다.IT 인프라 평균 부하의 기준이 높아지다. 클라우드 이전까지 우리는 IT 인프라의 CPU 부하율을 평소 20% 아래로 유지해 왔습니다. 하지만 이 또한 변화가 생깁니다. 제가 만나는 많은 클라우드 기반 서비스 기업들이 CPU 부하율을 50%에서 70%까지 유지하고 있었습니다. 일반적은 운영관점에서 IT 서비스 운영에 익숙하지 않은 기업의 운영 미숙이라 생각할 수 있습니다. 하지만 클라우드에 익숙한 운영팀은 서비스 성능에 문제가 발생하지 않는 범위에서 인프라의 규모를 실시간으로 조절합니다. 기존의 상식으로는 매우 위험해 보이지만 클라우드를 정말 잘 쓰는 기업들은 성능과 안정성을 해치지 않으면서 인프라 자원의 여유를 최대한 줄이는 방법들을 내재화하고 있습니다. IT 인프라 장애를 해결하지 않는다.  모든 IT 인프라는 장애가 발생합니다. 인프라의 장애는 이벤트성으로 발생하지만 운영팀은 장애를 반복 해결해 나가는 과정에서 패턴을 인지하고 대처해 나갑니다. 클라우드에서도 장애는 어쩔수 없이 발생하지만 운영팀은 장애를 인지할 뿐 장애를 물리적으로 해결하지는 않습니다. 대신 클라우드를 사용하는 IT 운영팀은 빠르게 서비스 구성과 환경을 전환하여 서비스를 원활하게 동작시킵니다. 운영자들이 갖는 불안감이 현실이 되다.다시 운영자들의 불안감에 대해서 이야기 해보죠. IT 인프라의 규모를 줄이고 자원 사용률이 평소에서 50%를 넘기는 급박한 사용 환경에서 클라우드 인프라에 장애가 발생해도 할 수 있는 일이 없다는 것은 정말 큰 스트레스를 주는 일입니다. 물론 위에서 설명한 것처럼 클라우드 네이티브한 서비스라면 문제없이 돌아갈 수 있겠지만 기존 레거시를 운영하면서 클라우드로 전환한다면 IT 운영자 입장에서는 앞에 이슈들이 불안감이 아닌 현실이 됩니다. 넷플릭스 7년만에 클라우드 이전을 완료하다.넷플릭스가 클라우드 이전을 결정한것은 2007년이지만 이전을 완료한것은 2016년이였습니다. 이렇게 긴 시간은 투자한 이유에 대해 넷플릭스는 "기존 IDC 기반의 인프라가 가진 문제들을 클라우드로 가져가지 않기 위해서"라고 했지만 다른 한편으로는 클라우드에서 발생하는 문제들을 해결할 수 있는 시스템 구조를 만들기 위해서였습니다. 그렇기 때문에 넷플릭스에서는 클라우드 네이티브 방식을 택하여 사실상 모든 기술을 재구축하고 운영 방식을 근본적으로 바꿨다. 아키텍처 면에서 넷플릭스는 거대한 앱을 수백 개의 마이크로 서비스로 마이그레이션하고 NoSQL 데이터베이스를 사용하여 데이터 모델을 반정규화했다. 예산 승인, 중앙화된 릴리스 관리, 몇 주에 걸친 하드웨어 프로비저닝 주기를 도입해 지속적인 콘텐츠 전달이 가능해졌으며, 느슨하게 결합된 개발운영(DevOps) 환경에서 엔지니어링 팀이 셀프서비스 툴로 독립적인 결정을 내릴 수 있게 되면서 혁신이 가속화되었다. 이 과정에서 새로운 시스템을 여럿 구축해야 했으며, 새로운 기술도 배워야 했다. 넷플릭스가 클라우드 네이티브 기업으로 변신하는 데는 많은 시간과 노력이 필요했지만, 클라우드 마이그레이션을 통해 글로벌 TV 네트워크로서 지속적인 성장을 이뤄나갈 밑거름을 마련할 수 있었다.https://media.netflix.com/ko/company-blog/completing-the-netflix-cloud-migration결론기존의 레거시를 바탕으로 클라우드 마이그레이션을 진행하는 기업들은 클라우드에서 발생하는 다양한 운영 이슈들을 겪을 수 밖에 없습니다. 대부분 클라우드 이전 사업을 진행하는 데 있어서 이전 서비스 성능을 맞추는 데만 집중하다보니 이전 후 운영과정에서 발생하는 많은 문제들은 운영팀이 짊어지게 됩니다. 하지만 이 문제들은 개발팀과 운영팀이 함께 지속적으로 개선해 나가야 합니다. 최종적으로 클라우드 네이티브 구조가 완성되기 위해서는 시스템과 조직 문화 모두가 변화해야 합니다. 클라우드 마이그레이션은 엄청 고난한 일입니다. 만일 클라우드를 도입했는데, 아직 불안함이 있다면 아직 클라우드 마이그레이션이 끝나지 않은것입니다. #와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 1463

Navigation Controller 자유롭게 다루기

Intro: The Navigation Controller예고했던 Navigation Controller와 TabBar Controller의 커스터마이즈 중, Navigation Controller의 구조와 간단한 커스텀 방법을 나누겠습니다. Navigation Controller(이하 내비게이션 컨트롤러)는 거의 모든 iOS 앱에서 사용된다고 해도 과언이 아닌 자주 사용되며, 간결하지만 막강한 기능을 가진 컨트롤러입니다. 앞선 글에서 소개했듯, TabBar Controller와 함께 iOS의 양대 컨트롤러라고 불러도 대부분의 iOS 개발자들이 동의하리라고 생각합니다. 이번 글에서는 내비게이션 컨트롤러를 커스텀하는 방법을 소개하겠습니다.Navigation Cotroller (출처: apple developer)목차1. Push, Pop 애니메이션 커스터마이징2. Pop 제스처 사용하기, 사용하지 않기3. Back 버튼 타이틀 숨기기4. 상단 좌우의 버튼 추가하기5. NavigationBar 숨기기, 보여주기6. What’s NEXT?1. Push, Pop 애니메이션 커스터마이징Push, Pop 트랜지션 기능은 내비게이션 컨트롤러의 핵심적인 기능입니다. Stack에 다음 View Controller를 쌓으며 디스플레이하는 것이 Push, 이전의 View Controller로 되돌아가는 것이 Pop 액션입니다. Pop 액션에는 최초에 디스플레이됐던 View Controller로 돌아가는 Pop to Root 액션이 포함되어 있습니다.<iframe width="560" height="315" src="https://www.youtube.com/embed/NqfYhI5ySKk" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="">Pop View Controller(animated)이러한 액션에는 애니메이션이 포함됩니다. 대개 기본적으로 적용된 애니메이션을 사용하면 되지만, 어떤 이유로 애니메이션을 커스텀하고 싶은 경우가 생깁니다. 이럴 때는 UINavigationController를 상속하는 커스텀 클래스를 만들어서 커스텀할 수 있습니다. 물론 Extension 형식으로 함수를 작성할 수도 있습니다.// UINavigationController를 상속하는 커스텀 클래스를 작성 class BRNavigationController: UINavigationController { // 애니메이션을 적용하는 함수를 작성 func overrideAnimation() { //여기에서 커스텀 애니메이션을 작성합니다. let transition = CATransition() transition.duration = 0.3 transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) transition.type = kCATransitionFade self.view.layer.add(transition, forKey: nil) } // popToRootViewController(animted)를 오버라이드 override func popToRootViewController(animated: Bool) -> [UIViewController]? { print("Custom Animation Triggered") if(viewControllers.last!.isKind(of: PersonalViewController.self)) { // 커스텀 애니메이션을 사용할 ViewController의 케이스를 분기한다 // 작성된 커스텀 애니메이션 트리거 self.overrideAnimation() //UINaivgationController의 Function을 그대로 반환 return super.popToRootViewController(animated: false) } else { // 다른 모든 케이스의 경우 디폴트 애니메이션을 사용 //UINavigationController의 Function을 그대로 반환 return super.popToRootViewController(animated: animated) } } } 위의 코드로 작성한 애니메이션 아래의 영상과 같이 동작합니다.<iframe width="560" height="315" src="https://www.youtube.com/embed/g_XCo1Hmnj0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="">커스텀 Pop 애니메이션이 적용된 Navigation Controller위와 같이 커스텀된 내비게이션 컨트롤러는, 단지 애니메이션을 오버라이드하는 데 그치지 않고 다양한 방식의 효율적 코드 작성을 할 수 있게 합니다. 우리가 아는 것처럼, 수퍼클래스의 위용과 유용을 마음껏 누릴 수 있습니다.2. Pop 제스처 사용하기, 사용하지 않기내비게이션 컨트롤러에서는 화면 왼쪽 끝에서 오른쪽으로 스와이프하는 Pop 제스처를 사용해 이전 View Controller로 돌아갈 수 있습니다. 하지만 종방향 스크롤이나 스와이프 이벤트를 사용하는 ViewController의 경우 어쩔 수 없이 Pop 제스처를 막아야 하는 일이 생깁니다. 이럴 때에는 해당하는 ViewController에서 다음과 같이 간단한 코드로 Pop 제스처를 방지하거나, 방지 해제할 수 있습니다.// 아래의 코드를 트리거하면 Pop 제스처를 비활성화할 수 있습니다 self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false 이 코드를 한 번 적용하면, 해당 내비게이션 컨트롤러의 Stack에 쌓인(또는 쌓일) View Controller에 일괄적으로 적용되기 때문에 반드시 다른 ViewController에서는 기본적으로 isEnabeld를 True값으로 지정하도록 코드를 구성하여 모든 ViewController에 일괄적용되는 것을 방지해야 합니다.다만 이 부분에서 중요한 것은, Back 버튼을 숨기거나 커스텀할 때 각별히 주의해야 한다는 것입니다. 제스처를 사용하는 사용자들도 있지만, 제스처의 존재 자체를 모르는 사용자들도 있기 때문에 Back 버튼은 대부분의 경우 유지하는 것이 좋습니다. 제스처를 비활성화할 때는 더더욱 유지해야 하고요.Back Button이 없다면 어떻게 뒤로 돌아갈 수 있을까요.3. Back 버튼의 타이틀 숨기기내비게이션 컨트롤러에 포함된 Navigation Bar(이하 내비게이션 바)의 Back 버튼은 자동으로 이전 ViewController의 타이틀을 보여주도록 디폴트 설정되어 있습니다. 이렇게 자동지정된 타이틀이 마음에 들지 않는다면, 간단한 트릭을 사용하여 타이틀을 없앨 수 있습니다.먼저, Back 버튼의 타이틀이 되는 이전 ViewController의 타이틀은 ViewController에서 다음과 같이 지정됩니다.// 직접 ViewController의 타이틀을 지정 viewController.title = "이것이 바로 타이틀입니다" Back Button에 '상품정보' 타이틀이 보입니다.위의 코드로 지정한 ViewController의 타이틀은 Push 액션을 통해 다음 ViewController로 넘어갔을 때 Back 버튼의 타이틀로 사용됩니다. 그래서 이 코드를 사용하지 않고, 커스텀 Label을 titleView에 넣어주는 것으로 대신할 수 있습니다.// titleView로 사용할 Label을 생성 let label = UILabel(frame: customFrame) label.text = "이것을 타이틀로 사용합니다" // viewController의 titleView를 생성한 Label로 셋업 viewController.titleView = label 짜잔- Back Button의 타이틀이 사라졌습니다!4. 상단 좌우 버튼 추가하기여러 iOS 앱들을 사용하다 보면, 내비게이션 바의 좌/우측단에 위치한 버튼들을 자주 보게 됩니다. 이 버튼들은 BarButtons(이하 내비게이션 바 버튼) 라고 불리우는 컴포넌트들입니다. 내비게이션 바 버튼들은 배열 방식으로 좌/우측에 각각 배치됩니다. 원하는 이미지와 텍스트 등으로 내비게이션 바 버튼을 생성한 후, 좌/우측의 버튼 배열 중 원하는 곳에 각각 넣어주면 디스플레이 되는 방식입니다. 다음의 코드 예제를 통해 내비게이션 바 버튼을 추가할 수 있습니다.// RightBarButtons에 추가할 UIBarButtonItem을 생성 let customButton = UIBarButtonItem(customView: customView) // Container가 될 Array를 생성 (혹은 직접 지정하는 방법도 있습니다) let rightBarButtons: [UIBarButtonItem] = [] // Array에 버튼 아이템을 추가 rightBarButtons.append(customButton) // RightBarButtonItems 배열을 셋업 viewController.navigationItem.rightBarButtonItems = rightBarButtons //LeftBarButtons에 추가할 UIBarButtonItem을 생성 let customButtonCopy = UIBarButtonItem(customView: customView) // Container가 될 Array를 생성 (혹은 직접 지정하는 방법도 있습니다) let leftBarButtons: [UIBarButtonItem] = [] // Array에 버튼 아이템을 추가 leftBarButtons.append(customButtonCopy) // LeftBarButtonItems 배열을 셋업 viewController.navigationItem.leftBarButtonItems = leftBarButtons 타이틀뷰, LeftBarButton, RightBarButton이 모두 커스텀된 브랜디의 홈5. NavigationBar 숨기기, 보여주기앱의 UI가 전체화면으로 컨텐츠를 표시해야 할 때, 또는 다른 목적에 의해서 내비게이션 바를 숨기거나 보여주어야 할 때가 있습니다. 이럴 때는 간단한 코드 트리거로 내비게이션 바를 숨기거나 보여줄 수 있습니다.// 단 한 줄의 코드로 내비게이션 바를 숨길 수 있다구요? navigationController.setNavigationBarHidden(false, animated: true) <iframe width="560" height="315" src="https://www.youtube.com/embed/ldpe-M8Uyy8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="">내비게이션바를 숨겼다가 보였다가6. What’s NEXT?현재 앱스토어에 배포된 브랜디 iOS 앱은 내비게이션 컨트롤러를 적극적으로 활용하여 작성되었습니다. 내비게이션 컨트롤러는 기본 설정으로 사용할 때에도 여전히 막강한 특징들을 많이 가지고 있기 때문에, 선택적으로 알아두어야 할 컴포넌트가 아닌 필수적으로 그 장단점과 용법을 꿰고 있어야 하는 중요한 컴포넌트입니다. 내비게이션 컨트롤러만 잘 다루어도 앱을 개발할 때 굉장히 도움을 많이 받을 수 있다는 것이죠.내비게이션 컨트롤러는 다양한 방식으로 커스터마이즈를 할 수도 있습니다. 물론 이러한 커스터마이즈는 필수사항은 아닙니다. 디자인적 요소를 적용하기 위해 커스터마이즈하는 경우가 대부분이지만, 그에 못지 않게 개발자가 프로젝트의 컴포넌트를 정규화하고 모듈화하기 위해 커스텀하는 경우도 많은 만큼 StackOverflow나 애플 개발자 문서를 참고해 다양한 커스터마이즈를 해보는 것도 재미있을 겁니다.다음 글에서는 TabBar Controller의 커스터마이즈 방식에 대해 간략하게 공유하겠습니다. iOS 루키들의 장수와 번영을 바라며, 글을 마칩니다. Live long and prosper!참고UINavigationController - UIKit | Apple Developer Documentation글이정환 과장 | R&D 개발MA팀[email protected]브랜디, 오직 예쁜 옷만
조회수 1261

CodeStar + Lambda + SAM으로 테스트 환경 구축하기

들어가기 전: 실제로 프로젝트와 팀원들과의 작업 환경을 구축한 경험을 바탕으로 작성했습니다. 한마디로 실화. Overview소스를 수정할 때마다 지속적인 테스트를 하기 위해 AWS lambda 로컬 테스트 환경, SAM을 결합해서 환경을 구축했습니다. 이번 글에서는 팀원을 추가하고 CodeCommit을 리포지토리로 사용하는 것도 소개하겠습니다. 예상 구성도테스트 환경 구축, 도저언!1. 팀원 추가하기 IAM 서비스를 이용해서 프로젝트를 같이 사용할 유저를 추가합니다. IAM에 유저를 추가하면 AWS 콘솔을 같이 사용할 수 있습니다. 사용자 추가를 클릭해 유저를 추가합니다. 팀원마다 한 개의 계정을 추가해야 합니다. 사용자 세부 정보 설정 > 엑서스 유형에서 ‘프로그램 방식 엑서스’와 ‘AWS Managrment Console 엑서스’를 체크합니다. 여기에서는 개발2팀 팀원인 강원우 과장의 계정을 생성했습니다.1) 비번은 귀찮으니 미리 세팅해둡시다. 유저 계정은 그룹을 생성해서 관리하면 편합니다. 그룹을 사용하면 보다 편리하게 계정 권한을 제어할 수 있기 때문입니다. 이번 예제에서는 그룹 이름을 codeStarGroup으로 만들었습니다. AWSCodeStarFullAcess를 정책으로 설정하고 ‘그룹생성’을 클릭해 그룹을 추가합니다. 2) codeStarGroup에 체크한 후, ‘다음: 검토’를 클릭해 진행합니다.‘사용자 만들기’를 클릭해 생성을 마무리합니다.계정 추가를 완료했습니다.사용자 이름(위의 예시에서는 kanggw)을 클릭하고, 뒤이어 ‘보안자격 증명’ 탭을 클릭합니다.콘솔 로그인 링크를 공유합시다. 링크를 입력하고 들어가면 그룹 로그인이 활성화가 되어있다는 걸 볼 수 있습니다.2. CodeStar 설정하기 프로젝트 인원을 무사히 추가했습니다. 이제 프로젝트를 만들어 봅시다. CodeStar 프로젝트 세팅 방법은 R&D본부 윤석호 이사님이 쓴 ‘애플리케이션 개발부터 배포까지, AWS CodeStar’를 참고해주세요.새 프로젝트를 생성합니다.python AWS Lambda를 선택합니다.프로젝트 이름은 ‘admin-lambda-API’로 입력하겠습니다. 그 후에 ‘다음’을 클릭합니다.‘프로젝트 생성’을 클릭합니다.우리는 Git을 이용해 로컬에서 직접 관리할 것이므로 ‘명령행 도구’를 선택한 후, ‘건너뛰기’를 클릭합니다.3분 만에 프로젝트가 생성되었습니다. 참 쉽죠?3. 프로젝트에 팀원 추가하기프로젝트를 같이 하려면 팀원을 추가해야겠죠. 팀원 추가는 codeStar 대시보드 좌측의 ‘팀’ 탭을 클릭하면 됩니다.‘팀원 추가’ 클릭IAM에서 등록한 팀원의 정보를 불러옵니다. ‘추가’를 클릭해 팀원을 추가합니다. 여기에서 중요한 사실 하나! 프로젝트의 소유자로 지정해야 소스 접근 및 코드 변경이 가능합니다.4. 코드 체크 아웃앞서 설명한 것처럼 직접 Git으로 소스를 받아야 하기 때문에 codeCommit으로 이동합니다. codeStar 대시보드 왼쪽 ‘코드’ 탭을 클릭하면 코드 내역들을 확인할 수 있습니다.‘URL 복제 > HTTPS’를 클릭해 경로를 복사합니다. 소스를 클론하기 전에 계정에 깃허용을 먼저 해주세요. IAM 돌아와서는 계정 설정을 변경해야 합니다.사용자 > kangww > 보안 자격 증명 탭 클릭 > HTTPS Git 자격 증명 > 생성Git에서 사용할 ID와 비밀번호를 받았습니다. 해당 정보를 팀원에게 전달합니다. 이제 workspace로 이동해 체크아웃을 시작합니다.git clone [복사한 경로] [id 입력] [pw 입력] clone이 완료 되었습니다. 이제 기본 프로젝트가 들어있기 때문에 바로 실행할 수 있습니다. 미리 설치된 SAM으로 실행해보겠습니다.이제 해당 경로에 이동해 SAM을 돌려서 정상적으로 구동되는지 확인해봅시다. (SAM설치 방식은 부록에서 소개합니다.) sam local start-api -p 3333 성공적으로 SAM이 구동되었습니다. (짝짝) http://localhost:3333 으로 접근해 결과를 확인할 수 있습니다. 이제 로컬에서 작업을 진행하면서 바로 바로 확인이 가능해졌습니다. 만약 동료와 함께 개발한다면 아래처럼 구동해야 자신의 IP에 접근할 수 있습니다.sam local start-api -p 3333 -host [자신의아이피] 글을 마치며CodeStar의 관리와 배포 기능은 강력합니다. 많은 부분을 알아서 해주니 고마울 뿐입니다.3) 이제 Lambda의 local 테스트 환경인 SAM을 이용해서 배포 전 과정까지 간편하게 테스트를 해보세요. 배포의 복잡함을 codeStar에서 해결하고 테스트를 하거나 개발을 할 때는 SAM을 이용해 효율적으로 업무를 진행합시다.글 쓰면서 발견한 다섯 가지1) codeDeploy > executeChangeSet 에 구동될 때 cloundFormation 이 자동 세팅 됩니다. 엄청 편합니다. API 배포가 진행되면 lambda에서 바로 수정하는 게 편합니다.2) codeCommit은 https 보다 ssh방식을 권장하며, https방식으로 하다가 꼬이면 여기를 클릭해 해결하세요.3) codeStar는 다음과 같은 추가 구성을 자동 세팅합니다.codeStar 용 S3 버킷codePipeLine용 S3 버킷cloundFormation 세팅lambda 세팅4) IDE를 cloud9을 사용하면 EC2 및 EBS가 생성되니 주의하세요. 그리고 생각보다 느립니다.5) 로컬에서 Git push를 하면 약 5분 정도 뒤에 최종적으로 배포됩니다.부록1)SAM을 설치하기 전, 여기를 클릭해 docker를 미리 설치하세요.2)SAM 설치 안내는 여기를 클릭하세요. ( npm install -g aws-sam-local )참고1)강원우 과장은 귀여운 두 달팽이, 이토와 준지의 주인이기도 하다. 2)AWSCodeStarFullAcess는 codestar 접근에 대한 권한을 부여한다.3)자동 배포까지 2~5분 정도 걸리는 게 어렵게 느껴질 수 있다.글천보성 팀장 | R&D 개발2팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발문화 #개발팀 #업무환경 #인사이트 #경험공유

기업문화 엿볼 때, 더팀스

로그인

/