스토리 홈

인터뷰

피드

뉴스

조회수 4535

개발자 직군 파헤치기 4 | 빅 데이터 엔지니어

빅 데이터 엔지니어는 무엇을 하나요?빅 데이터가 부상하면서 그와 관련된 직업군도 함께 주목받기 시작했습니다. 빅 데이터 엔지니어, 빅 데이터 애널리스트, 빅 데이터 사이언티스트 등 다양한 직업군이 생겼습니다. 오늘은 개발자 직군 중 데이터와 관련된 빅 데이터 엔지니어에 관해 이야기해 볼 것입니다. 빅 데이터 엔지니어는 무엇을 할까요? 빅 데이터 엔지니어가 무엇을 하는지 알기 위해서는 먼저 빅 데이터가 뭔지 알필요가 있겠습니다.빅 데이터는 기존 데이터베이스 관리도구의 능력을 넘어서는 대량의 정형 또는 심지어 데이터베이스 형태가 아닌 비정형의 데이터 집합조차 포함한 데이터로부터 가치를 추출하고 결과를 분석하는 기술입니다(위키 참조).빅 데이터의 특징은 방대한 데이터와 더불어 비정형 데이터까지 포함한다는 것입니다. 많은 양의 데이터와 정형화 되지 않은 데이터를 수집하는 일은 보통 일이 아닙니다. 빅 데이터를 통한 새로운 알고리즘를 만들거나 인사이트를 발견하기 위해서는 빅 데이터가 존재해야 합니다. 빅 데이터 엔지니어는 이러한 빅 데이터를 수집하고 관리하는 프로그래머입니다. 일반적인 데이터 수집과 달리 수십테라 정도의 정보를 수집 하게 됩니다. 또 그런 데이터를 어떻게 효율적으로 관리할지 고민해야합니다.데이터는 미래의 석유라고 합니다. 빅 데이터 엔지니어는 빅 데이터 분석가나 과학자들에게 이러한 석유를 가져다 주는 송유관을 설치하고 관리하는 역할을 한다고 볼 수 있습니다. 빅 데이터 활용을 위해서라면 빅 데이터 엔지니어의 역량이 반드시 필요합니다.데이터 과학자와 데이터 엔지니어는 다르다.위에서 빅 데이터 엔지니어는 데이터를 수집하고 관리하는 업무를 한다고 했습니다. 하지만 구체적으로 빅 데이터 과학자(Big Data Scientist)와 빅 데이터 엔지니어(Big Data Engineer)는 무엇이 다를까요?어떤 직업의 업무라는 것이 무 자르듯 쉽게 나눌 수 있는 것은 아니지만 확실히 그 직업만의 특징은 존재합니다. 각 직업 별로의 특징을 통해 빅 데이터 엔지니어가 빅 데이터 과학자와 어떻게 다른지 알아보도록 하겠습니다.1. 빅 데이터 엔지니어(Big Data Engineer)빅 데이터 엔지니어는 위에서도 언급 했지만, 데이터를 수집하고 관리하는 일을 합니다. 빅 데이터 엔지니어를 통해 '빅 데이터'가 만들어진다고 해도 무방하죠. 숫자나 규칙이 있는 정형 데이터는 물론이고 글자나 불규칙적인 비정형 데이터까지 수집하고 관리합니다. "그냥 데이터를 수집하고 관리하는 일인데 별거 있나?"라고 생각하실 수도 있습니다. 빅 데이터라는 개념 이전에도 데이터는 수집되었고 분석을 통해 비즈니스 문제를 해결해 왔으니까요. 그렇지만, 빅 데이터라는 개념이 부상하고 실현 가능할 수 있었던 이유는 방대한 데이터를 수집할 수 있는 퍼널(funnel) 설계과 그 데이터를 관리하고 알맞게 사용할 수 있는 시스템을 구축할 수 있었기 때문입니다.그렇기 때문에 빅 데이터 엔지니어는 프로그래밍에 아주 능숙해야합니다. 빅 데이터를 수집하고 관리할 수 있는 방법을 짜야하니까요. 또한, 개별적인 정보가 아닌 큰 틀에서의 정보를 다루고 통합하고 나누어 볼 수 있는 설계 능력이 따라주어야 합니다.정교하게 짜여진 빅 데이터가 아니라면 빅 데이터 과학자가 그것을 분석하고 사용하는데 상당한 자원이 들거나 최악의 경우 아예 이용하지 못하게 될 것입니다.2. 빅 데이터 과학자(Big Data Scientist)빅 데이터 엔지니어가 빅 데이터를 수집하고 관리한다면 빅 데이터 과학자는 그것을 요리하는 역할을 합니다. 데이터보고 직면한 비즈니스 문제를 해결할 새로운 인사이트를 도출해 내는 것입니다. 혹은 현재 가지고 있는 프로세스를 개선할 알고리즘을 만들어 낼 수도 있습니다.빅 데이터 과학자는 데이터를 분석할 수 있는 통계학적 지식뿐만 아니라 그 데이터를 다룰 수 있는 프로그래밍적 지식도 요구됩니다. 일반적인 데이터가 아닌 '빅' 데이터다 보니 그것을 쉽게 운용하고 자유자재로 이용하게 해줄 툴을 익혀야합니다. 또한, 빅 데이터 과학자에게 요구되는 핵심 역량 중 하나는 바로 머신러닝에 대한 지식입니다. 이 또한 프로그래밍 지식과 알고리즘 지식이 필요합니다. 빅 데이터 엔지니어가 되기 위한 Key Skills그렇다면 빅 데이터 엔지니어가 되기 위해서는 어떤 기술 스택들을 익혀야할까요? 빅 데이터 엔지니어는 데이터와 관련된 직군인만큼 데이터베이스와 관련된 기술스택들이 중요합니다.1. SQL데이터 관리를 하시는 분들이면 다들 알고 계시는 SQL입니다.  SQL은 관계형 데이터베이스 관리 시스템의 데이터를 관리하기 위해 설계된 특수 목적의 프로그래밍 언어입니다(위키참조).2. MapReduce(맵리듀스)맵리듀스는 구글에서 대용량 데이터 처리를 분산 병렬 컴퓨팅에서 처리하기 위한 목적으로 제작하여 2004년에 발표한 프레임워크입니다.(위키참조).3. Apache Hadoop(아파치 하둡)Apache Hadoop은 대규모 데이터 세트를 효율적으로 처리하는 데 사용할 수 있는 오픈 소스 소프트웨어 프로젝트입니다. 하나의 대형 컴퓨터를 사용하여 데이터를 처리 및 저장하는 대신, 하둡을 사용하면 상용 하드웨어를 함께 클러스터링하여 대량의 데이터 세트를 병렬로 분석할 수 있습니다.4. Apache Cassandra(아파치 카산드라)Apache Cassandra 자유-오픈 소스 분산형 NoSQL 데이터베이스 관리 시스템의 하나로, 단일 장애점 없이 고성능을 제공하면서 수많은 서버 간의 대용량의 데이터를 관리하기 위해 설계되었습니다. 카산드라는 여러 데이터센터에 걸쳐 클러스터를 지원하며 마스터리스(masterless) 비동기 레플리케이션을 통해 모든 클라이언트에 대한 낮은 레이턴시 운영을 허용합니다(위키참조).5. Java(자바)빅 데이터 엔지니어는 기본적으로 프로그래머이기 때문에 프로그래밍 지식있어야 합니다. 빅 데이터 엔지니어를 목표로 처음 프로그래밍을 시작한다면 자바를 추천합니다. 물론, 다른 언어를 통해 프로그래밍 실력을 쌓아도 됩니다. 그렇지만, 아파치 하둡과 아파치 카산드라가 자바를 베이스로 만들어졌기 때문에 자바를 배운다면 이 기술스택들을 습득하는데 훨씬 효율적일 것입니다.다른 포스팅에서도 항상 말씀드려왔지만 기술스택만 익힌다고 해서 그 직업을 가질 수 있는 것은 아닙니다. 기술스택은 기본이고 개발자로써의 역량이 뒷받침 되어야 시장에서 환영받는 빅 데이터 엔지니어가 될 수 있습니다.Photo by Ehud Neuhaus on Unsplash빅 데이터 엔지니어가 되기 위한 학습 콘텐츠시중에서는 완성된 단계로써 빅 데이터 엔지니어를 양성하는 프로그램은 많지 않습니다. 따라서 개인이 빅 데이터 엔지니어에게 필요한 기술 스택들을 하나씩 익혀 나가야 합니다.무료 온라인 콘텐츠도 많겠지만, 비싸지 않으면서도 잘 정제된 콘텐츠를 소개하려고 합니다. 유튜브 강좌보다는 보기 편하고 학습 환경이 잘 갖춰져 있어서 공부하기에 좋은 콘텐츠를 추천합니다.1. SQL - SQL 프로그래밍 : SQL을 무료로 학습할 수 있는 사이트(한글)2. Hadoop - 유데미 The Ultimate Hands-On Hadoop - Tame your Big Data! (영어)3. Cassandra - 유데미 From 0 to 1: The Cassandra Distributed Database (영어)데이터 엔지니어는 예전부터 있었다.오늘은 빅 데이터 엔지니어에 대해 알아보았습니다. 사실, 빅 데이터 엔지니어는 어느 날 갑자기 생겨난 직업이 아닙니다. 데이터베이스를 관리하는 프로그래머가 더 나은 기술 스택을 익히고 더 좋은 방법으로 데이터를 수집하고 관리하면서 생겨난 것입니다.세상은 빠르게 변한다고 하지만 그 안을 들여보면 서서히 발전한 것들이 다르게 네이밍(Naming) 되면서 새롭게 다가오는 것이라 생각합니다. 그렇다고 해서 그것이 변하지 않는 것이 아닙니다. 새롭게 변하는 기술들을 익히고 자신의 역량을 갈고 닦아야만 새롭게 다가오는 변화에 휩쓸리지 않고 주도할 수 있는 것 같습니다.
조회수 1015

Sublime Text 3에서 Gist 연동하기

블로그 같은 곳에 작성한 코드를 올리기 위해 매번 구현된 코드를 복사 붙여넣기 하여 하나하나 gist에 업로드하기는 엄청 귀찮은 일이다. 그래서 알아보았더니 서브라임 텍스트에서는 플러그인을 통해 서브라임 자체에서 바로 gist에 업로드 할 수 있었다. 엄청 간단하게 연동할 수 있음.Package Control 설치일단 서브라임 텍스트 플러그인을 설치하기 위해 Package Control을 설치해야 함.1. Sublime Text Package Control 코드 복사하기2. 서브라임 텍스트를 실행하여 control+`으로 콘솔 열기3. 복사한 내용을 붙여넣고 엔터를 눌러 설치플러그인 설치이번엔 방금 설치한 패키지 컨트롤을 이용하여 gist 플러그인을 설치해야 함.1. 서브라임에서 command+shift+p로 Command Palette 열기2. Package Control: Install Package를 선택3. gist 검색 후 설치github와 연동하기1. github에서 Settings>Personal access tokens에서 Generate new token 버튼 클릭2. Token description에 내가 알아볼 수 있게 설명을 입력한 후 Select scopes에서 gist 선택 후 Generate token 버튼을 클릭하여 생성3. 생성된 토큰을 복사4. 서브라임에서 Preferences>Package Settings>Gist>Settings-User 선택5. 열린 창에서 아래와 같이 token에 복사해놓은 키를 붙여넣고 include_users에 내 깃헙 아이디 입력 후 저장사용서브라임 텍스트에서 코드 작성 후 command+k, command+p를 누르면 하단에 gist 순서대로 설명 입력하고 엔터 제목을 입력하고 엔터를 누르면 자동으로 업로드됨.#트레바리 #개발자 #안드로이드 #앱개발 #Sublime #백엔드 #인사이트 #경험공유
조회수 1323

에이스프로젝트 추천도서 - 프론트 편

안녕하세요!기업 문화가 좋은 야구게임 개발사에이스프로젝트입니다.기획팀 편에 이어 2탄!에이스프로젝트의 대소사(?)를 책임지는 '프론트'편을 준비했습니다!프론트는 조직문화 담당자부터 인디자이너까지 다양한 인재들로 구성되어 있어요.하는 일이 다양한 만큼 추천도서의 스펙트럼도 넓었는데 그중 다섯 권을 엄선했다고 합니다.에이스프로젝트 프론트가 추천하는한 번쯤은 읽어보면 좋은 추천 도서 Best 5!1. 구글의 아침은 자유가 시작된다 - 라즐로 복[ 이미지 출처 : 예스 24 ]자유롭게 일하는데 성과도 좋은 조직문화, 구글은 어떻게 만들었을까조직문화 담당자들에게 생각할 주제를 던져주는 책2. 배민다움 - 홍성태[ 이미지 출처 : 예스 24 ]회사에 맞는 문화를 만드는 과정에 대한 정리가 잘 되어 있는 책3. 내 문장이 그렇게 이상한가요? - 김정선[ 이미지 출처 : 예스 24 ]칼럼 쓸 때 도움이 많이 됐던 글쓰기 실용서교정교열 경력 20년이 넘었다는 작가분의 내공이 느껴지는 책4. 좋은 문서 디자인 기본 원리 29 - 김은영[ 이미지 출처 : 예스 24 ]"자네는 디자이너도 아닌데 어떻게 이렇게 전달력이 좋나!"좋은 내용을 더 좋게 만들어 주는 문서 디자인 기본서5. 디자이너 사용설명서 - 박창선[ 이미지 출처 : 예스 24 ]프론트 인디자이너의 추천서!디자이너와의 원활한 협업을 원하는 모든 사람들에게 이 책을 추천합니다프론트는 인사, 채용, 회계, 홍보 등 각자의 전문 영역이 있지만 결국은 다 함께 좋은 회사를 만들기 위해 노력하는 팀입니다. 위 다섯 개의 도서는 프론트가 공통적으로 읽고 추천한 도서라고 해요 :-) 이상 "각자, 그리고 함께 조직문화를 만들어가는" 프론트의 추천도서였습니다!다음은 '그래픽팀'의 추천도서로 찾아올게요 ;)
조회수 4986

Bluetooth Low Energy(BLE) 파헤치기

1. What is BLE?스마트폰이 출시되어 대중화가 될 무렵, ‘스마트’한 개념의 밴드, 워치, 글래스 등이 출시되면서 웨어러블 디바이스 시장이 태동하기 시작했다. 그리고, 2015년 상반기, 애플워치의 등장으로 작은 생태계를 이루고 있던 웨어러블 디바이스들이 다시 한번 각광을 받게 되었다. 각기 생긴 모습은 다르지만 이들의 공통점은 스마트폰과 연동되어 작동한다는 것이었다. 과거부터 기기들간의 단거리 무선통신은 Bluetooth라는 기술이 이용되었다. Bluetooth가 공식적으로 등장한지 약 16년이라는 세월이 흘렀지만, 여전히 기기간의 무선통신에는 Bluetooth가 사용된다. 하지만, 지금 사용되는 Bluetooth는 기존과는 다른 방식이다. 바로 BLE라는 특징을 가진 Bluetooth인데, 바로 이것이 오늘날 다양한 종류의 웨어러블 디바이스들이 태어날 수 있었던 원동력이 되었다. 그렇다면 BLE라는 것이 도대체 무엇일까?그림1. BLE가 뭐지? 먹는건가?과거부터 기기들간의 무선 연결은 주로 Bluetooth라는 기술을 이용했는데, 이들은 기기간에 마스터, 슬레이브 관계를 형성하여 통신하는 Bluetooth Classic이라는 방식을 이용했다. 사람들이 이러한 기기들을 이용하면서 많이 염려했던 것은 ‘Bluetooth를 연결하면 베터리가 빨리 소모된다’, ‘사용하지 않을 때는 Bluetooth 꺼놓아야지’ 등과 같은 베터리 관련된 문제들이었다. 사실이었다. Bluetooth Classic은 다른 디바이스를 무선으로 연결을 하여 사용할 수 있는 편리함을 주었지만, 연결이 되는 동안에는 베터리를 빠르게 소모시켰기 때문에 사용하는 데에 많은 불편함이 있었다.2010년, 새로운 Bluetooth 표준으로 Bluetooth 4.0 이 채택이 된다. 기존의 Bluetooth Classic과의 가장 큰 차이는 훨씩 적은 전력을 사용하여 Classic과 비슷한 수준의 무선 통신을 할 수 있다는 점이었다. 이는 당시 Bluetooth의 최대 단점이었던 과도한 베터리를 소모 문제를 해결하는 기술이었기 때문에, Bluetooth 관련 업계에 큰 반향을 일으켰다. 이렇게 저전력을 이용하여 무선통신을 하는 특징을 Bluetooth Low Energy (이하 BLE) 라고 부르는데, Bluetooth 4.0 이후의 버전들은 이 용어로 대체되서 불리기도 한다. 최근 출시되고 있는 스마트 밴드, 워치, 글래스 등의 웨어러블 무선통신 기기들의 대부분은 이 BLE 방식을 이용하여 무선 통신을 한다.Bluetooth Smart Ready, Smart, ClassicBLE 기술이 등장하면서 Bluetooth 디바이스들은 아래와 같이 3가지로 분류 되었다.그림2. BLE 3가지 분류Bluetooth 4.0과 함께 새롭게 등장한 Bluetooth Smart Ready, Bluetooth Smart에 대해서 살펴보면,Bluetooth Smart Ready 디바이스는 Bluetooth Classic 및 저에너지 Bluetooth 무선통신 (BLE)을 지원하기 때문에 “듀얼 모드” 라디오라고 불린다. 따라서, 이들은 현재 시장에 나와 있는 수억 종의 Bluetooth 디바이스들에 대한 역방향 호환성을 가진다. 종류에는 스마트폰, 태블릿, PC, TV 그리고 셋탑박스 및 게임 콘솔 등이 있다. 이런 디바이스들은 클래식 Bluetooth 디바이스 및 Bluetooth Smart 디바이스들로부터 데이터를 받아, 이들을 유용한 정보로 변환시키는 Bluetooth 시스템의 허브라고 할 수 있다.Bluetooth Smart 디바이스 내에 있는 라디오는 “싱글모드” 라디오라 불리는데, BLE 연결만을 지원한다는 의미이다. 이들은 기존의 Bluetooth Classic 디바이스들과 호환이 되지 않고 듀얼모드 라디오를 가진 Bluetooth Smart Ready 디바이스 혹은 제조업체에 의해 호환성이 명시된 특정 Bluetooth 디바이스에만 연결이 가능하다. Bluetooth Smart 디바이스들은 ‘우리 집의 창문은 모두 잠겨 있는지’, ‘내 인슐린 농도는 얼마인지’, ‘오늘 내 몸무게는 몇 킬로그램인지’ 등과 같이 특정한 형태의 정보를 수집해, Bluetooth Smart Ready 디바이스로 보내기 위해 만들어진 디바이스이다. 종류에는 심박 모니터, 스마트 손목시계, 창문 및 현관 보안 센서, 자동차 키 체인, 그리고 혈압 팔찌 등이 있다.이 글에서는 BLE를 사용하는 디바이스들이 어떤 과정으로 서로 연결되어 통신을 하는지 그리고 이 과정들을 tracking 할 수 있는 장비인 Ubertooth 에 대해 내용을 정리해서 공유해보고자 한다.2. How they communicate?BLE를 지원하는 디바이스들은 기본적으로 Advertise(Broadcast) 과 Connection 이라는 방법으로 외부와 통신한다.Advertise Mode ( = Broadcast Mode)특정 디바이스를 지정하지 않고 주변의 모든 디바이스에게 Signal을 보낸다. 다시 말해, 주변에 디바이스가 있건 없건, 다른 디바이스가 Signal을 듣는 상태이건 아니건, 자신의 Signal을 일방적으로 보내는 것이라고 생각하면 된다. 이 때, Advertising type의 Signal을 일정 주기로 보내게 된다.Advertise 관점에서, 디바이스의 역할은 다음과 같이 구분된다.Advertiser ( = Broadcaster) : Non-Connectable Advertising Packet을 주기적으로 보내는 디바이스.Observer : Advertiser가 Advertise를 Non-Connectable Advertising Packet을 듣기 위해 주기적으로 Scanning하는 디바이스.그림3. Advertiser and ObserverAdvertise 방식은 한 번에 한 개 이상의 디바이스와 통신할 수 있는 유일한 방법이다. 주로 디바이스가 자신의 존재를 알리거나 적은 양(31Bytes 이하)의 User 데이터를 보낼 때도 사용된다. 한 번에 보내야 하는 데이터 크기가 작다면, 굳이 오버헤드가 큰 Connection 과정을 거쳐서 데이터롤 보내기 보다는, Advertise를 이용하는 것이 더 효율적이기 때문이다. 게다가 전송할 수 있는 데이터 크기 제한을 보완하기 위해 Scan Request, Scan Response을 이용해서 추가적인 데이터를 주고 받을 수 있다 (이에 대해서는 뒤에 자세히 설명한다). Advertise 방식은 말 그대로 Signal을 일방적으로 뿌리는 것이기 때문에, 보안에 취약하다.Connection Mode양방향으로 데이터를 주고받거나, Advertising Packet으로만 전달하기에는 많은 양의 데이터를 주고 받아야 하는 경우에는, Connection Mode로 통신을 한다. Advertise처럼 ‘일대다’ 방식이 아닌, ‘일대일’ 방식으로 디바이스 간에 데이터 교환이 일어난다. 디바이스간에 Channel hopping 규칙을 정해놓고 통신하기 때문에 Advertise보다 안전하다.Connection 관점에서 디바이스들의 역할은 다음과 같이 구분된다.Central (Master) : Central 디바이스는 다른 디바이스와 Connection을 맺기 위해, Connectable Advertising Signal을 주기적으로 스캔하다가, 적절한 디바이스에 연결을 요청한다. 연결이 되고 나면, Central 디바이스는 timing을 설정하고 주기적인 데이터 교환을 주도한다. 여기서 timing이란, 두 디바이스가 매번 같은 Channel에서 데이터를 주고 받기 위해 정하는 hopping 규칙이라고 생각하면 된다.Peripheral (Slave) : Peripheral 디바이스는 다른 디바이스와 Connection을 맺기 위해, Connectable Advertising Signal을 주기적으로 보낸다. 이를 수신한 Central 디바이스가 Connection Request를 보내면, 이를 수락하여 Connecion을 맺는다. Connection을 맺고 나면 Central 디바이스가 지정한 timing에 맞추어 Channel을 같이 hopping을 하면서 주기적으로 데이터를 교환한다.그림4. Central and Peripheral3. Protocol Stack디바이스들은 Bluetooth로 통신을 하기 위한 Protocol Stack을 가지고 있다. 일반적으로 네트워크 통신을 하기 위해서는, 통신을 위한 규약인 Protocol을 정의해야 되는데, 이렇게 정의된 Protocol들을 층층이 쌓아놓은 그룹이 Protocol Stack이다. Bluetooth Signal Packet을 수신하거나 송신할 때, 이 Protocol Stack을 거치면서 Packet들이 분석되거나 생성된다.그림5. Protocol Stack위 그림에서 볼 수 있듯이 Protocol Stack은 가장 아랫단부터 크게 Controller, Host, Application 로 나뉜다. 여기서는 Connection 과정에서 필요한 부분인 Physical Layer, Link Layer, Generic Access Profile(GAP), Generic Attribute Profile(GATT)에 대해서 알아볼 것이다.3.1 Physical LayerPhysical Layer에는 실제 Bluetooth Analog Signal과 통신할 수 있는 회로가 구성되어 있어서, Analog 신호를 Digital 신호로 바꾸어 주거나 Digital 신호를 Analog 신호로 바꾼다. 또한 Bluetooth에서는 2.4 GHz 밴드를 총 40개의 Channel로 나누어 통신을 한다. 40개 Channel 중 3개 Channel은 Advertising Channel 로써 각종 Advertising Packet을 비롯하여 Connection을 맺기 위해 주고 받는 Packet들의 교환에 이용된다. 나머지 37개의 Channel은 Data Channel 로써 Connection 이후의 Data Packet 교환에 이용된다.그림6. Channels3.2 Link LayerPhysical Layer의 바로 윗단에는 Link Layer이 있다. Link Layer은 하드웨어와 소프트웨어의 조합으로 구성되어 있다. 하드웨어 단에서는 높은 컴퓨팅 능력이 요구되는 작업들 (Preamble, Access Address, and Air Protocol framing, CRC generation and verification, Data whitening, Random number generation, AES encryption 등)이 처리되고, 소프트웨어 단에서는 디바이스의 연결 상태를 관리한다. 또한 통신하는데 있어서 디바이스의 Role을 정의하고 이에 따라 변경되는 State를 가지고 있다.RoleMaster : 연결을 시도하고, 연결 후에 전체 connection을 관리하는 역할.Slave : Master의 연결 요청을 받고, Master의 timing 규약을 따르는 역할.Advertiser : Advertising Packet을 보내는 역할.Scanner : Advertising Packet을 Scanning하는 역할. Scanner는 아래와 같은 2가지 Scanning 모드가 있다.Passive Scanning : Scanner는 Advertising Packet을 받고 이에 대해 따로 응답을 보내지 않는다. 따라서 해당 Packet을 보낸 Advertiser는 Scanner가 Packet을 수신했는지에 대해서 알지 못한다.Active Scanning : Advertising Packet을 받은 Scanner는 Advertiser에게 추가적인 데이터를 요구하기 위해 *Scan Request라는 것을 보낸다. 이를 받은 Advertiser는 *Scan Response로 응답한다.Scan Request, Scan Response : Advertising Packet type의 한 종류이다. 앞서, 31bytes 이하의 User data에 대해서는 Advertising Signal Packet에 넣어서 보낼 수 있다고 하였다. 하지만 31bytes보다는 크지만, Commection까지 맺어서 보내기는 오버헤드가 큰 데이터가 있을 때, Scan Request, Scan Response를 이용하면 두 번에 걸쳐서 데이터를 나눠 보낼 수 있게 된다. Advertising Packet을 받은 Scanner는 추가적인 User Data(예를 들어, Peripheral 디바이스의 이름)를 얻기 위해 Scan Request를 보내게 된다. Scan Request를 받은 Advertiser는 나머지 데이터를 Scan Response Signal에 담아서 보낸다.이들은 크게 Connection 전의 역할(Advertiser, Scanner), 후의 역할(Master, Slave)로 분류된다.StateLink Layer는 5가지 State를 가지고 있는데, 각 디바이스는 서로 연결이 되는 과정에서 이 State를 변화시킨다. 다음과 같은 5개의 State가 존재한다.Standby State : Signal Packet을 보내지도, 받지도 않는 상태.Advertising State : Advertising Packet을 보내고, 해당 Advertising Packet에 대한 상대 디바이스의 Response를 받을 수 있고 이에 응답할 수 있는 상태.Scanning State : Advertising Channel에서 Scaning하고 있는 상태.Initiating State : Advertiser의 Connectable Advertising Packet을 받고난 후 Connetion Request를 보내는 상태.Connection State : Connection 이후의 상태.아래 그림은 각각의 State를 Diagram으로 나타낸 것이다.그림7. Link Layer State3.3 Generic Access Profile (GAP)Generic Access Profile (GAP)는 서로 다른 제조사가 만든 BLE 디바이스들끼리 서로 호환되어 통신할 수 있도록 해주는 주춧돌 역할을 한다. 즉, 어떻게 디바이스간에 서로를 인지하고, Data를 Advertising하고, Connection을 맺을지에 대한 프레임워크를 제공한다. 그래서 GAP는 최상위 Control Layer라고도 불린다. Advertising Mode일 때, GAP에서 Advertising Data Payload와 Scan Response Payload를 포함할 수 있다.또한 GAP에서는 BLE 통신을 위해 Role, Mode, Procedure, Security, Additional GAP Data Format 등을 정의한다. 이들은 실제 API와 직접적으로 많은 연관이 있기 때문에 그 내용이 상당히 많지만, 여기서는 BLE Connection과 관련이 있는 Role에 대해서만 알아보겠다.RoleBroadcaster : Link Layer에서 Advertiser 역할에 상응한다. 주기적으로 Advertising Packet을 보낸다. 예를 들면, 온도센서는 온도데이터를 자신과 연결된 디바이스에게 일정주기로 보낸다.Observer : Link Layer에서 Scanner 역할에 상응한다. Broadcaster가 뿌리는 Advertising Packet에서 data를 얻는다. 온도센서로부터 온도데이터를 받아서 디스플레이에 나타내는 테블릿 컴퓨터의 역할이다.Central : Link Layer에서 Master 역할과 상응한다. Central 역할은 다른 디바이스의 Advertising Packet을 듣고 Connection을 시작할 때 시작된다. 좋은 성능의 CPU를 가지고 있는 스마트폰이나, 테블릿 컴퓨터들의 역할이다.Peripheral : Link Layer에서 Slave 역할과 상응한다. Advertising Packet을 보내서 Central 역할의 디바이스가 Connection을 시작할 수 있도록 하게끔 유도한다. 센서기능이 달린 디바이스들의 역할이다.3.4 Generic Attribute Profile (GATT)BLE Data 교환을 관리하는 GATT는 디바이스들이 Data를 발견하고, 읽고, 쓰는 것을 가능하게 하는 기초적인 Data Model과 Procedure를 정의한다. 그래서 GATT는 최상위 Data Layer라고도 불린다. 디바이스간에 low-level에서의 모든 인터렉션을 정의하는 GAP와는 달리, GATT는 오직 Data의 Format 및 전달에 대해서만 처리한다. Connection Mode일 때, GATT Service와 Characteristic을 이용하여 양방향 통신을 하게 된다. Service와 Characteristic에 대한 내용은 여기를 참고하길 바란다.GATT도 Data 처리와 관련해서 다음과 같은 역할을 정의한다.RoleClient : Server에 Data를 요청한다. 하지만 처음에는 Server에 대해서 아는 것이 없기 때문에, Service Discovery라는 것을 수행한다. 이 후, Server에서 전송된 Response, Indication, Notification을 수신할 수 있다.Server : Client에게 Request를 받으면 Response를 보낸다. 또한 Client가 사용할 수 있는 User Data를 생성하고 저장해놓는 역할을 한다.4. Packet TypeBLE 통신에서는 두 가지 종류의 패킷인 Advertising Packet, Data Packet만이 존재한다. Connection을 맺기 전에는 Advertising Packet type, 맺은 후에는 Data Packet type으로 Signal을 생성한다. Data Packet은 하나로 통일되지만, Advertising Packet은 특정 기준에 따라서 다음과 같은 성질들을 갖는다.ConnectabilityConnectable : Scanner가 Connectable Advertising Packet을 받으면, Scanner는 이를 Advertiser가 Connection을 맺고 싶어한다는 신호로 받아들인다. 그러면 Scanner는 Connection Request (이하 CONNECTREQ)를 보낼 수 있다. 해당 Connectable Signal을 보낸 Advertiser는 Scanner가 CONNECTREQ가 아닌 다른 타입의 Signal을 보내면 해당 Packet을 무시하고 다음 Channel로 이동하여 계속 Advertising을 진행한다.Non-Connectable : Non-Connectable Packet을 받은 Scanner는 CONNECT_REQ를 보낼 수 없다. 주로 Connection 목적이 아닌, Data 전달이 목적일 때 쓰인다.ScannabilityScannable : Scanner가 Scannable Advertising Packet을 받으면, Scan Request (이하 SCANREQ)를 보낼수 있다. Scannable Signal을 보낸 디바이스는 Scanner가 SCANREQ가 아닌 다른 타입의 Signal을 보내면 해당 Packet을 무시하고 버린다.Non-Scannable : Non-Scannable Signal을 받은 Scanner는 SCAN_REQ를 보낼 수 없다.DirectabilityDirected : Packet안에 해당 Signal을 보내는 디바이스의 MAC Address와 받는 디바이스의 MAC Address가 들어있다. MAC Address 이외의 데이터는 넣을 수 없다. 모든 Directed Advertising Packet은 Connectable 성질을 갖는다.Undirected : 해당 Signal을 받는 대상이 지정되어 있지 않다. Directed Advertising Packet과는 다르게, 사용자가 원하는 데이터를 넣을 수 있다.위의 내용을 종합하면, Advertising pakcet을 아래와 같이 4가지 type으로 나눌 수 있다.그림6. Advertising Packet Type5. How they really communicate?BLE 통신의 핵심은 ‘timing’이다.Before ConnectionConnection 전, 디바이스는 3개의 Advertising Channel을 이용해서 데이터를 주고 받는다고 했다. 이들은 이 3개의 Channel을 자신만의 time interval로 hopping한다. 서로의 hopping 규칙이 일치하지 않기 때문에 Channel이 서로 엇갈리는 경우가 많을 것이다. 예를 들어, Advertiser는 1번 Channel에 Advertising Packet을 보냈는데, 같은 시간에 Scanner는 3번 Channel에 대해서 Scanning을 하게 되면 데이터 전달이 되지 않는 것이다. 하지만 이러한 hopping이 빠르게 자주 일어나기 때문에, 두 디바이스가 같은 Channel에 대해 Advertising와 Scanning이 발생하는 경우도 많이 생긴다. 이 경우에 서로 데이터를 주고 받을 수 있다.After ConnectionConnection이 되면, Advertising은 종료되고 기기들은 Central, Peripheral 중 하나의 역할을 하게된다. Connection을 개시한 기기가 Central이며, Advertiser가 Peripheral이 된다. 그리고 두 디바이스는 엇갈렸던 hopping 규칙을 통일시킨다. 그렇게 함으로써, 매번 같은 채널로 동시에 hopping하면서 Signal을 주고 받을 수 있게 된다. 이는 둘 간의 Connection이 끊어질 때까지 지속된다.6. How they connect each other?디바이스간의 BLE 연결을 iPhone과 Zikto Walk와의 연결과정으로 설명하면 다음과 같다.1) Zikto Walk가 Advertising Channel을 hopping하면서 Advertising Packet을 보낸다.(Zikto Walk의 Advertising Packet 유형은 ADV_IND이다)2) iPhone Bluetooth를 켠 후, Zikto 앱에 Zikto Walk를 등록한다. iPhone은 Advertising Channel을 hopping하면서 Scan을 하다가 연결하려는 Zikto의 디바이스 이름 등의 추가적인 정보를 얻기위해 SCAN_REQ를 보낸다.3) SCANREQ를 받은 Zikto Walk는 SCANRSP를 보낸다.4) Pairing이 완료되고, Zikto Walk는 다시 Advertising Packet을 다시 일정 주기마다 보낸다.5) iPhone에서 Zikto Walk로부터 걸음 수 등의 Data를 받기 위해 Sync 버튼을 누른다. 이 버튼을 누르면 iPhone은 CONNECT_REQ를 보낸다.6) Zikto와 iPhone은 서로 Acknowledging을 시작하고, timing 정보 등을 동기화 한다.7) Connection이 완료된다.8) Connection이 완료된 후, Service Data, Characteristic Data 등에 대한 Data 교환이 일어난다.9) iPhone과 Zikto Walk간에 Data Sync가 완료되면, Connection이 해제되고, 다시 Advertising Packet을 보낸다. 이를 그림으로 표현하면 아래와 같다.그림6. Advertising Packet Type7. Ubertooth디바이스간 BLE를 이용한 통신 과정에 대해 알고나니, Bluetooth Signal Packet도 Capturing 할 수 있을 거라는 생각이 들었다. 검색을 해 본 결과, 오픈소스 Bluetooth Test tool인 Ubertooth라는 장치로 디바이스간의 BLE 통신을 tracking 할 수 있다는 사실을 알게 되었다. 가격은 100달러로 생각보다 저렴했지만 국내에서는 구매할 수가 없었다. 그렇다고 궁금한 것을 해보지도 않고 포기하는 것은 엔지니어의 마인드가 아니지 않겠는가. 직접 아마존 (www.amazon.com)에서 해외구매를 하였다. 이렇게 바다 건너 멀리서 날아온 Ubertooth를 사용했던 경험을 바탕으로, Ubertooth의 원리와 BLE 통신에 대해서 조금 더 자세히 설명을 해보고자 한다.Ubertooth는 10cm정도의 몸체와 그와 비슷한 길이의 안테나를 가지고 있는 매우 작고 귀여운 모양이다. 이것이 이름하여 Ubertooth!그림8. Ubertooth오픈소스이기 때문에 모든 소스가 공개되어 있고, 소스를 빌드하고 사용하는 방법도 Ubertooth Github 및 Ubertooth Blog에 잘 나와 있어서 사용하기가 수월했다.How it works?Ubertooth는 크게 Bluetooth Classic을 tracking하는 기능과 BLE를 tracking하는 기능으로 나뉘는데, 여기서는 BLE 통신을 tracking 하는 원리에 대해서 다루겠다.BLE는 앞에서 언급했다시피, Connection 전, 후로 통신하는 방법이 다르다. 그리고 위의 내용들을 꼼꼼히 읽은 독자라면 BLE 통신에서 가장 중요하다고 언급했던 timing 이라는 것을 기억할 것이다. timing 은 BLE 통신에서 굉장히 중요한 요소이기 때문에, 보다 더 자세하고 쉽게 설명을 해보겠다.종이컵 전화기를 사용하여 대화를 해야하는 두 사람이 있다. 종이컵 전화기는 총 40개가 놓여져 있다. 이 두 사람은 40개 전화기 중 하나를 사용해서 대화를 주고 받고, 일정시간 뒤에 다음번 전화기를 이용해야 한다. 이러한 커뮤니케이션 방식에서 소통을 하기 위해서는 한 전화기로 얼마만큼의 시간동안 통화를 할 것인지, 다음 전화기는 어떤 전화기를 사용할 것인지, 그리고 어떤 방식으로 자신들의 대화를 다른 사람들의 대화들로부터 구분할 것인지 등에 대해 알아야 할 것이다. 이것들이 위에서 말했던 timing 관련 정보이다.실제 BLE 통신에서 timing 과 관련된 정보들은 다음과 같다 : Access Adress, CRC Info, Hop Interval, Hop Increment (해당 내용들에 대한 자세한 설명은 여기를 참고하기 바란다). BLE 통신을 하는 디바이스들은 이 timing 관련 정보를 동기화하여, Connection이 맺어진 이후에 해당 규칙에 따라 Channel을 hopping하면서 데이터를 주고 받는다. Ubertooth는 바로 이 정보를 알아내어, Master, Slave와 같은 패턴으로 Channel을 hopping하면서 대화를 엿듣는다. 아까 말한 종이컵 전화기에 빗대어 말하면, 제 3자(Ubertooth)가 두 사람이 정한 대화 규칙을 알아내서, 매번 이들이 전화기를 바꿔가며 대화를 할 때 마다 해당 전화기의 대화 내용을 엿듣는 것이다. 굉장히 흥미로운 방법이 아닐 수 없다. 그렇다면 Ubertooth는 어떻게 이 정보를 알아낼까?Before Connection두 디바이스가 연결되기 전, Ubertooth가 timing 관련 정보를 알아내는 방법은 매우 간단하다. Scanner가 Advertiser에게 Connection을 맺기위해 보냈던 CONNECT_REQ을 기억하는가? 공교롭게도 해당 패킷에는 이 네 가지 정보가 전부 들어있다. Ubertooth는 그 정보를 추출해내어 저장해 두고, 그 규칙에 맞게 Channel을 hopping하면서 Signal Data를 전부 엿듣는다.그림9. Ubertooth로 Capture한 CONNECT_REQ packetAfter Connection이미 연결된 디바이스들은 CONNECT_REQ를 보낼 일이 없다. 그러면 Ubertooth는 Connection 이후의 상황에 대해서는 Signal Data를 엿듣지 못하는 것일까? 아니다. Connection 이후의 상황에 대해서 Ubertooth는 다음과 같은 방법을 이용한다.BLE Signal Packet은 Advertise Mode이든 Connection Mode이든간에 무조건 하나의 Signal Packet format만 존재하기 때문에, Packet마다 특정 정보가 존재하는 부분은 어느 Packet에서나 똑같다. 4가지 정보 중 Access Address라는 것은 모든 Signal Packet마다 존재한다. Access Address라는 것은 두 디바이스간의 Unique한 Connection을 나타내는 4bytes 크기의 Identifier로써, CONNECT_REQ를 보내는 디바이스에 의해 랜덤하게 생성된다. Ubertooth는 37개의 Data Channel을 hopping하면서 모든 Data Packet의 Access Address를 추출해내어 Look Up Table 형태로 저장해 놓는다. 그리고는 각각의 Access Address가 등장한 횟수를 세게 되는데, 가장 먼저 특정 횟수만큼 등장한 Access Address를 target으로 잡는다. 나머지 3가지 정보는 각각 추출해내는 방법 및 알고리즘이 따로 존재하는데 해당 내용도 위에 언급한 사이트에 잘 나와있다. 이렇게 해서 네 가지 정보를 알아낸 Ubertooth는 두 디바이스와 같은 패턴으로 Channel을 hopping하면서 Signal Data를 엿듣는다.그림10. Ubertooth로 Capture한 Aceess Address과 나머지 3가지 정보들이렇게 보면, Ubertooth로 모든 것을 할 수 있을 것처럼 보이지만, 몇 가지 한계점이 있기도 하다. Ubertooth가 timing 관련 정보를 얻어내는 과정에 대해 다시 한 번 생각해보길 바란다. 잘 모르겠다면, 직접 Ubertooth 구매하여 테스트를 해보는 것도 엔지니어로써 굉장히 좋은 경험이 될 것이다.8. ConclusionBLE 통신과 이를 tracking하는 Ubertooth에 대해서 알아보았다. 매우 장황한 내용처럼 보이지만 이것도 매우 압축해서 설명한 것이다. 하나하나 디테일하게 쓰기 보다는 BLE를 처음 접하는 사람이 최대한 이해하기 쉽도록 작성하는 것에 초점을 맞추었다. 위의 내용들을 바탕으로, 독자들이 BLE에 더 넒고 깊은 지식을 얻게 되었으면 하는 바램이다. 글을 읽으면서 Bluetooth Classic은 어떻게 통신하는지에 대해 궁금하신 분들도 있을거라 생각한다. 이에 대해서 간단히 언급하자면, Bluetooth Classic 통신 방식은 BLE보다 훨씬 더 복잡하다. BLE에 대해서 어느 정도 알게 되었다면, Bluetooth Classic에 도전해보는 것도 괜찮을 것이다. BLE내용과 관련해서 보충이 필요한 내용이나, 관련 경험 혹은 궁금한 점 등에 대해서 아낌없이 조이와 공유해주길 바란다.9. ReferenceAkiba, “Getting Started with Bluetooth Low Energy: Tools and Techniques for Low-Power Networking”, O’Reilly Media(2015)http://www.slideshare.net/steveyoon77/bluetooth-le-controllerhttp://www.hardcopyworld.com/ngine/aduino/index.php/archives/1132https://www.bluetooth.org/ko-kr/bluetooth-brand/smart-marks-faqshttp://trvoid.blogspot.kr/2013/05/ble.htmlhttp://blog.lacklustre.net/posts/BLEFunWithUbertooth:SniffingBluetoothSmartandCrackingItsCrypto/#조이코퍼레이션 #개발팀 #개발자 #개발환경 #업무환경 #인사이트 #경험공유
조회수 2711

스타트업 CTO의 일

최근 다음과 같은 고민이 깊어졌다."나는 잘하고 있을까?""내가 지금 해야만 하는 중요한 일은 무엇일까?""나의 역할은 어디까지고, 무엇을 위임해야 할까?""어떤 사람을 채용해야 할까?"팀의 구성원이 떠나기도 했고, 회사도 여러 가지 도전을 받고 있으며, 나 자신의 정체도 느끼는 것이 고민의 시작이다. 위 질문들의 공통된 뿌리는 “나의 일은 무엇인가?”라는 질문이다.'나의 일'이라는 것은 '스타트업 CTO의 일'이다. 하지만 모든 스타트업의 CTO가 하는 일이 나와 같지는 않다. 스타트업은 다양한 단계가 있고, 목표로 하고 있는 시장도 제각각이다. 가지고 있는 기술, 목표로 하는 기술도 다르고, 구성원 또한 제각각이기 때문이다. 하지만 어느 정도 공통점이 있을 거라 생각한다. 혹시 이 글을 어느 스타트업의 CTO가 읽으신다면 자신의 일과 비교를 해봐 주시길 부탁드린다.본격적으로 시작하기 전에 이 글은 내가 앞으로 겪을 경험에 따라 많이 바뀔 수 있음을 미리 알려둔다.CTO?Chief Technology Officer의 준말이다. 경영진 중의 한 명으로 회사에서 기술과 관련된 모든 일을 관리, 책임진다. 여기에서 '기술과 관련된 모든 일'이라는 모호한 것을  들여다보기 위해서는 CTO의 역할을 좀 더 나눠 볼 필요가 있다. 다음과 같이 나눠보고 각각에 대해서 살펴보자.Technical Leader - 최고의 엔지니어Technical Businessman - 기술조직과 사업조직의 가교Team Manager - 팀장Product Manager - 프로덕트 관리자Technical Leader보통 CTO라 하면 가장 먼저 떠올리게 되는 역할이다. 기술기업의 경우 핵심 기술역량을 보유하고 있거나, 서비스 기업의 경우 주도적으로 서비스를 개발/운영해본 경험이 있어야 한다. 다음과 같은 역할이 요구된다.1) 기술 비전과 로드맵회사의 기술 비전을 세우고, 그 비전을 달성하기 위한 로드맵을 정하고 실행해야 한다. 실행을 위해서 기술 조직에 비전을 전달하고 공감을 얻어 낼 수 있어야 한다.2) 아키텍트회사가 만드는 서비스 아키텍처를 만들고 발전시켜 나가야 한다. 동시에 이 서비스가 동작하는 인프라 아키텍처를 셋업하고 견고하게 만들어야 한다. 이를 위한 개발 스택들을 결정하고 적용해야 한다.3) 좋은 기술 코치팀이 기술적으로 성장할 수 있는 환경을 갖추고 코칭을 해야 한다. 팀의 구성원이 기술적 목표를 높게 유지할 수 있도록 해야 한다.4) 시니어 개발자시니어 개발자로 다음과 같은 역할을 해야 한다.· 팀이 현재 겪고 있는 가장 어려운 문제를 풀 수 있어야 한다.· 회사의 핵심 기술을 이해하고 높은 퍼포먼스로 제품을 만들어야 한다.· 개발 효율을 높일 수 있는 환경을 갖춰야 한다. (DevOps)· 문서화를 해야 한다.Technical Leader로서 위와 같은 일들을 잘 하게 되면· 고도화되더라도 효율이 떨어지지 않는 시스템· 높은 제품의 성능· 높은 기능적 완성도· 경쟁력 있는 기술과 그 기술을 갖춘 팀을 얻을 수 있다. 위 일들은 조직이 커지게 되면 팀의 시니어 개발자들이 점점 나누어 가지게 된다. (단, '기술 비전과 로드맵'을 제외하고) 다르게 말하면 반드시 위의 역할을 잘 나누어 가질 수 있는 사람을 시니어 개발자로 채용해야 한다.Technical Businessman대부분의 스타트업은 기술을 기반으로 시장의 문제를 해결(=사업)한다. CTO는 기술조직과 사업조직이 함께 잘 굴러가기 위한 가교 역할을 해야 한다. 이를 위해서는 회사의 사업에 대한 이해와 사업적인 센스가 필요하다.1) 기술적인 조언시장의 문제를 기술적으로 해결하고자 한다면, 기술조직에서 아이디어가 나와야 한다. CTO는 보통 가장 많은 아이디어를 사업조직에 제공해야 한다. 또한 회사가 새로운 일을 시작하고자 할 때, 그 일이 기술적으로 가능한 일인지, 어느 정도 크기의 일인지를 추정해야 한다. 비록 추정이 조금 부정확하더라도 추정이 있어야 사업적 판단을 할 수 있다. 그리고 회사에서 그 추정을 가장 잘 해야 하는 사람이 CTO다.2) 사업을 기술조직에 전파“나는 왜 이것을 개발해야 하는가?”에 대한 개발자의 질문에 답을 해주어야 한다.(정확히는 물어보기 전에 알려주어야 한다.) 이 일을 하는 사업적인 이유를 충분히 설명해 주어야 개발자는 동기를 얻고, 정해진 것 이상의 것을 만들어 낼 수 있다.3) 기술을 다른 조직에 전파회사가 가진 기술을 다른 조직에 전파해서 충분히 이해할 수 있도록 해야 한다. 그래야 기술이 아이디어를 만나 빛을 발하고 회사의 가치가 높아진다.Technical Businessman으로 위와 같은 일들을 잘하게 되면 회사가 가진 기술이 사업에서 효과적으로 사용된다. 그리고 사업을 위해 필요한 기술이 기술조직에서 발전하게 된다. 이 일들은 조직이 커지게 되면 역시 시니어 개발자와 프로젝트 관리자에 의해서 대체될 수 있다.Team Manager일반적인 팀장/조직장이다. 이 역할을 잘 수행하기 위해서는 커뮤니케이션 능력, 시간/리소스 관리 능력을 갖추어야 한다.1) 채용좋은 개발자를 채용해야 한다. 이를 위해서는 다음과 같은 기본적인 일을 해야 한다.· 채용 공고를 작성하고 올린다.· 면접을 진행하고 채용을 결정한다.· 좋은 사람을 소개받고 만난다.채용을 위해서는 장기적으로는 회사의 '기술 브랜드', '기업 문화'를 만들어 나가는 것이 도움이 된다. 물론 이런 것 보다 회사가 로켓처럼 날아가는 게 효과는 훨씬 더 좋다.2) 인력의 유지어렵게 뽑은 인력을 잘 유지해야 한다.  · 개인의 비전과 회사의 비전을 일치시키기 위해 노력한다. 다른 말로는 동기부여라고 한다.· 개인의 조직 내 성장을 돕는다.· 개인이 회사에서 만나게 되는 문제를 해결해 준다.물론 충분한 대우를 해주는 것도 중요하다.3) 자원의 산정과 확보프로젝트가 시작되기 전에 프로젝트에 필요한 인적, 물적 자원을 구체적으로 산정한다. (위의 Technical Leader가 하는 초기 결정을 위한 추정과는 다르다.) 대부분의 경우 어떤 사람이 어떤 일을 할 것인가를 결정짓는 일이다. 그리고 개발 혹은 운영에 필요한 추가적인 자원들을 준비한다. 장비가 될 수도 있고, 외부 서비스가 될 수도 있다.4) 일정의 계획과 관리일정을 계획하고, 관리한다. 다른 팀 혹은 외부와 의존성이 있는 경우 특히 이런 부분들을 잘 관리해서 일정이 차질 없이 진행이 될 수 있도록 한다. 프로젝트의 진행상황은 시각화하여 공개적으로 확인할 수 있도록 한다.5) 업무 프로세스 개선업무 프로세스를 개선해서 효율적으로 일할 수 있도록 해야 한다. 이를 위해서는프로젝트 관리 도구의 도입이슈 트래킹 시스템 도입스크럼/칸반등의 개발 방법론을 도입하고 운영등이 필요하다.3), 4), 5)는 우리가 일반적으로 프로젝트 관리자(PM)라 부르는 사람의 역할이기도 하다.이 일을 잘하게 되면회사에 필요한 인적 구성/역량을 갖춘 기술 조직을 유지할 수 있다.팀이 효율적으로 일할 수 있다.타 팀과 조화롭게 일할 수 있다.팀이 진행하는 프로젝트를 성공으로 이끌 수 있다.이 일들은 조직이 커지게 되면 중간 관리자, PM, HR 담당자가 생기면서 대체될 수 있다.Product Manager팀이 고객들이 원하는 제품을 전달하게 한다. 이 역할을 잘하기 위해서는 사업, 기술에 더해 UX에 대한 이해가 추가로 필요하다. (인터넷 서비스의 경우)1) 고객에 대한 이해고객을 보다 잘 알기 위한 노력을 해야 한다. 이를 위해서는 서비스에 관련된 지표들을 지속적으로 관찰해야 한다. 또는 인터뷰, 고객 대응 등을 통해 고객의 소리를 직접 듣는다.2) 고객의 대변자고객이 원하는 바를 명확하게 적은 스펙 문서를 작성해서 메이커에게 전달해야 한다. 또한 애매한 사항들이 있을 때 이를 최종적으로 결정해야 한다. 때로는 고객을 대신해서 제품에 대한 쓴소리를 해야 한다.3) 제품의 비전과 로드맵"우리는 어떤 제품을 만들어 갈 건가요?"라는 질문에 답을 할 수 있어야 한다. 즉, 제품의 비전을 구축해야 하고 이를 위한 구체적인 로드맵을 만들고 실행해야 한다. 이 비전을 조직에 전파하고 공감을 얻어야 한다.4) 우선순위의 결정사업, 고객의 측면에서 때로는 기술/디자인 부채를 없애기 위한 메이커의 입장에서 우선순위를 결정해야 한다.각 구성원 간의 이해관계가 부딪치는 부분이다. 효과적인 커뮤니케이션을 통해 슬기롭게 해결해 가야 한다.5) 제품의 퀄리티제품의 퀄리티를 책임진다. 직접 QA도 하고 디테일을 챙겨서, 구성원들이 높은 퀄리티를 목표로 할 수 있도록 해야 한다.이 역할을 잘하게 되면 좋은 제품을 만들어서 고객들의 호응을 이끌어 낼 수 있다. 또한 제품을 만드는 구성원들이 만족감을 얻을 수 있다. 이 역시 조직이 커짐에 따라 기획자, UX 디자이너가 일부 역할을 대체할 수 있으며 Product Manager를 뽑을 수도 있다.마치며스타트업의 CTO가 해야 하는 일은 이렇게 많다. 사실 스타트업 초기에는 위에서 말한 모든 것이 필요하지는 않다.(일단 컴퓨터를 사고, WIFI 설정도 하고..) 하지만 회사와 조직이 성장함에 따라 각각의 역할은 점점 중요해진다. 적당한 시기에 이 역할들을 위임하지 못하면 구멍이 생기기 시작하면서, 결국 여러 가지 중 하나도 제대로 챙기지 못하는 상황이 발생하게 된다. 이렇게 일을 정리하고 보니 지금의 내가 그런 상황이 아닌가 싶다.그럼 이제 내가 해야 하는 일은 동료들에게 적극적으로 도움을 요청해야 하는 것이다. 동료들도 내가 손을 내밀기를 기다리고 있을 거라 생각한다. :)  · 마지막으로 타이틀 이미지는 최근 프로덕트 그룹 워크샵에서 디자이너님의 타이포 세미나 때   제가 직접 그려 본 것입니다.#8퍼센트 #에잇퍼센트 #스타트업CTO #CTO #일상 #하루 #관리자
조회수 3140

모니터링 기본 상식 - CPU Steal Time

클라우드 서비스를 사용하시는 많은 분들이 CPU Steal Time에 대해 문의합니다. CPU Steal은 클라우드 서비스와 물리 서버의 환경차이에서 발생하는 대표적인 지표이기도 합니다. CPU Steal Time이 높아지면 CPU 부하율이 높아지기 때문에 웹 서비스에 장애를 초래하기도 합니다. 가상화를 위해 자원을 분배하는 과정에서 cpu의 자원을 빼기는 것이기 때문에 클라우드 사용자 입장에서는 억울한 감이 있는 지표이기도 합니다. 하지만 클라우드 서비스가 공유 자원을 효율적으로 사용하는 것이기에 어쩔 수 없는 부분이기도 합니다. 그럼 이 CPU Steal Time 또는 CPU Stolen Time이라고 불리는 지표에 대해 알아보도록 하겠습니다.  CPU Steal Time이 무언가요?CPU Steal time은 은 하이퍼 바이저가 다른 가상 프로세서를 서비스하는 동안 가상 CPU가 실제 CPU를 기다리는 시간을 백분율로 표시한 값입니다.가상 환경에서 동작하는 가상 시스템 (VM)은 단일 호스트에있는 다른 인스턴스와 리소스를 공유합니다. 공유하는 리소스 중 하나가 CPU주기입니다. VM이 실제 서버에있는 동일한 크기의 4 개의 VM 중 하나 인 경우 해당 CPU 사용률은 모든 CPU주기의 25 %로 제한되지 않습니다. CPU 사용 비율보다 많은 비율을 사용할 수 있습니다.CPU Steal Time은 어떻게 확인하는가?Linux top 명령을 실행하면 주요 성능 메트릭의 실시간보기를 볼 수 있습니다. 그 중 하나는 CPU를위한 것입니다.이미 경험 한 두 가지 통계는 % id (percent idle)와 % wa (percent I/O wait)입니다. % id가 낮 으면 CPU가 열심히 작동하고 있는 것이며 % id가 높으면 남은 용량이 많지 않은 것입니다. % wa가 높으면 CPU는 실행할 준비가되었지만 I / O 액세스가 완료 될 때까지 기다리고 있습니다 (디스크에 저장된 데이터베이스 테이블에서 행을 가져 오는 것과 같습니다).% st 또는 % steal time은 표시된 마지막 CPU 메트릭입니다.CPU steal time이 높으면 어떤 상황이 발생하는가.백그라운드에서 장시간 걸리는 작업의 경우, 다른 VM들과 CPU 주기를 공유하는 과정에서 조금 더 느리게 작업이 마무리 될 수 있습니다. CPU steal time은 이런 경우 작업을 중지시키는 요소로 작용하지 않습니다. 가끔은 리소스를 나누는 과정에서 작업이 더 빠르게 끝나기도 합니다. 하지만 웹앱의 경우 실시간 처리가 필요한 경우들이 있습니다. 많은 웹 응답이 이뤄져야 하는 상황에서 cpu steal time이 높아지고, 그로인해 성능이 4배이상 감소한다면 중요한 리케스트가 처리되지 못하면서 서비스에 장애가 발생할 수도 있습니다. CPU steal time이 높은 원인은?cpu steal time이 높은 원인은 둘 중 하나입니다.  더 많은 CPU 리소스를 가지고 있는 VM을 필요로 합니다. (여러분의 문제입니다.)물리버서가 과대 판매되어 가상화 장비가 공격적으로 경쟁하는 상황입니다. (여러분의 문제가 아닙니다. 아마존 나빠요.)아쉽게도 cpu 매트릭만으로 위 두가지 상황을 판별하는 것은 쉽지 않습니다. 하지만 같은 역할을 하는 복수의 호스트를 여러개 가지고 있다면 다음과 같이 분별해 볼 수 있습니다.  1. 리소스 부족의 경우위 그림처럼 모든 VM에서 %st(cpu steal time)이 높다면 시스템이 더 많은 cpu를 사용해야 한다는 것을 의미합니다. 더 높은 사양의 VM을 선택하셔야 합니다. 2. 클라우드 사업자의 과다 판매의 경우위 그림처럼 일부의 VM에서만 %st(cpu steal time)이 높다면 같은 물리 호스트에 있는 다른 VM들이 서버의 자원을 과다하게 사용하고 있을 확률이 높습니다. 물리적으로 다른 호스트로 이동하여 해결 할 수 있습니다.대처 방법을 알아보자.일반적인 경우 steal time이 20분동안 10%를 넘기는 상태에서 유지되고 있다며, VM은 정량 보다 느리게 동작하고 있을 것입니다.인스턴스를 중지하고 다른 물리 서버로 이동하세요. 그래도 steal time이 높다면 cpu 리소스를 업그레이드하세요. 그리도 steal time이 높다면 클라우드 서비스 제공자에게 문의하세요.클라우드 서비스가 과설계된것은 아닌지 알아보세요. 와탭을 사용해서 cpu steal 매트릭을 추적하세요. 최근 와탭에 들어오는 가장 많은 문의 중 하나가 cpu steal입니다. cpu steal로 인해 cpu 부하율이 80%이상으로 올라가는 경우 클라우드 서비스에 익숙하지 않은 분들은 많이 당항하게 됩니다. 이런 경우 너무 곤란해 하지 마시고 일회성 이슈인지 체크하시고 반복된다면 cpu 리소스를 업그레이드 하거나 서비스를 다른 물리서버로 이동하시기 바랍니다. 제가 가지고 있는 sample중에 cpu steal이 나온 케이스가 없지만 whatap.io는 cpu steal 값을 5초마다 저장하여 제공합니다.  관련 urlhttp://hakurei.tistory.com/67[Linux] 가상환경에서의 CPU Steal Time 개념물리 장비에다가 여러대의 가상머신을 두는 가상환경을 구축하는 경우가 많다. 가상머신이 많아지는 경우, 동일한 물리 장비에서 제공되는 환경이다보니, 특정 가상머신이 CPU를 많이 차지하게 되면, 다른 머신들도 따라서 느려지게 되는데, 이 현상을 CPU Steal이라고 한다. CPU를 많이 차지하고 있는 머신의 CPU Steal Time은 낮게 측정이되고, 같은 물리 장비에 구성된 다른 가상 머신의 경우 CPU Steal Time이 높게 측정이..hakurei.tistory.com http://www.stackdriver.com/understanding-cpu-steal-experiment/» Understanding CPU Steal – An Experimentwww.stackdriver.com http://blog.scoutapp.com/articles/2013/07/25/understanding-cpu-steal-time-when-should-you-be-worriedUnderstanding CPU Steal Time - when should you be worried?blog.scoutapp.com #와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 936

검은 머리 외국인으로서 스푼 라디오에 입사하기까지

스푼을 만드는 사람들 여섯 번째 이야기서비스 플랫폼 팀 막내이자 분위기를 담당을 맡고 있는, 6개월 차 개발자 Kyu를 소개하고자 한다.영어가 편해요? 아니면 한국어가 편해요?"일반적인 의사소통에 있어선 한국어가 편하고, 업무를 볼 땐 영어가 편해요."Q. 원래 되게 개구쟁이(?)의 이미지를 가지고 계신 줄 알았는데.."저 원래 진지한 거 진짜 싫어해요. 제가 겉보기엔 늘 장난꾸러기 같아 보이실 수도 있지만, 사실 이렇게 단 둘이 이야기를 하면 또 다른 진지하고 진정성 있는 저의 모습이 보이실 거예요. 저 지금 많이 진지해요?"(인터뷰 전에는 큐가 그저 재미있는 사람이라고 생각했는데, 인터뷰를 하고 나서 그를 다시 보았습니다..)'Kyu'라는 사람을 알고 싶습니다.Q. 본인은 어떤 사람이라고 생각하세요?Me, Myself, and I - "저는 제가 느끼는 것 그리고 원하는 것에 굉장히 집중을 하는 편이에요.제 본인 스스로에게 집중하는 양도 기준치도 꽤나 높은 편이에요. 무엇보다 스스로 혼자만의 시간을 굉장히 중요시합니다."Q. 국적이 Canadian이라 들었습니다. "네, 저는 8살 때 부모님과 함께 교육을 위해서 캐나다로 이민을 갔었어요. 그리고 캐나다에서 고등학교까지 있었고 그 후엔 미국에서 대학을 졸업했어요. 졸업 후에 한국에 취업을 하게 되어서 어느덧 한국 생활이 1년 3개월 차가 되어가고 있네요."Q. 한국에서 취업을 하게 된 계기가 있다면?"사실 처음에 제가 스타트업에 취업을 한다고 했었을 때, 주변에서 안정적인 곳이 아닌 스타트업을 선택하느냐라고 많이들 물어보셨어요. 그것도 한국에서요. 근데 저는 제가 정말 무슨 일을 하고 싶은지 잘 몰랐었어요. 목표의식과 노력 없이 공부를 하다 보니, 어느덧 졸업이 다가왔고 좌절하게 됐었어요. 정말 오랜 시간 아무것도 못했었어요. 길을 잃었다고 할까요? 그러다가, 용기를 내서 현실적으로 내가 할 수 있는 일이 무엇일까 고민 끝에 한국을 선택했어요. 한국엔 유능한 사람들이 정말 많고, 실력 있는 사람들이 열심히도 하는 곳이에요. 정말 무언가를 최선을 다해서 해본 다는 게 무엇인지 겪기 위해선 한국에서 배워보는 게 좋다고 생각했고, 실제로도 그렇다는 걸 느끼고 있어요."당신의 회사생활이 궁금합니다Q. 서비스 플랫폼 팀(서버팀)에서 하고 계신 업무는?"저는 현재 하고 있는 업무는, 정확히 말하자면 로그 데이터 수집 및 스푼 앱 내에서 발생하는 유저들의 행동 그리고 현상에 대한 데이터를 실시간으로 수집하고 조회합니다. 그리고 시간에 흐름에 따른 서비스 상태를 나타내 주는 작업을 하고 있습니다."Q. 현재 업무의 만족도는 어느 정도인가요?"업무에 대한 만족도는 높습니다. 저는 신입이고, 기본 역량이 팀원들에 비해서는 낮지만 제가 입사한 후 처음 시도한 것이 '로그 데이터 수집'인데요. 처음부터 끝까지 독립 시스템을 맡고 있다는 점이 굉장히 뿌듯합니다. 저를 그만큼 믿어주시기에 가능한 일이라고 생각합니다. 그렇다 보니 주인의식을 가지게 되고요. 앞으로 조금 더 만족도를 높이고자 한다면, 팀원들과 프로젝트를 도 함께 진행해보고 싶습니다."Q. 스푼 라디오가 큐의 첫 직장인 가요?"네, 정사원으로는 첫 직장이지만 그 전에는 인턴을 잠시 했었어요. 이건 제가 한국에서 겪은 좋지 않은 기억이지만, 인턴 생활 때, 타 스타트업에서 3개월 정도를 일을 했었는데, 임금 체불 문제가 있었어요. 당연한 부분이자 저의 권리가 지켜지지 않는 것을 보고, 다시 캐나다에 가고 싶단 생각을 했었어요. 그때 자존감도 많이 낮아지고 참 암울했던 시기였어요."Q. 한국 회사에서 느끼는 문화 차이가 있나요?"사실 제가 생각했던 것보다 워라벨이 잘 지켜지고 있어서 그 부분은 의외라고 생각이 들었어요.다만, 사람들과 함께 편하게 이야기를 하는 과정에서 문화적 차이를 느끼곤 해요. 예를 들면 Gender 부분 이라던지 등등. 의식이 조금 다르다고 느낄 때가 있어요. 하지만 한국 문화라던지, 의식의 차이를 저도 받아들이고 많이 노력하고 있어요. 누구나 의견과 관점은 다를 수 있으니까요. 잘 못되었다기 보단, 다른 사람들이구나 하고 받아들이려고 합니다."Q. 회사에서 가깝게 지내는 동료는 누구인가요?"업무를 가장 많이 함께 해서 가까운 분은 찰스, 개인적으로 제일 친하다고 느끼는 분은 샘입니다. 왜 친하다고 느끼는지는 모르겠지만 저도 모르게 자꾸 관심이 가요. 빨리 더 친해지고 싶은 생각도 들고, 그저 좋은 분이라고 느껴서입니다." (하지만 그분의 마음은 저도 몰라요.. 저만 친하다고 느낄 수도?)커피를 좋아하는 Kyu 당신의 사생활이 궁금합니다Q. 언제 가장 캐나다가 그립다거나 가고 싶어요?"일단, 미세먼지 많은 날이요.  그리고, 가끔씩 이런 마음이 들 때가 있어요. 한국에서는 쳇바퀴도는 매일 똑같은 삶을 사는 것 같다는 느낌(?) 한국에서는 아무것도 하지 않아도, 뭔가 늘 바쁜 그런 느낌이 들어요. 안정감이 없다고 해야 할까요? 한국은 소비를 통해서 스트레스를 해소하는 나라인 거 같아요. 주로 뭘 사 먹거나, 소유하거나. 근데 캐나다에서 랑 미국에선 다른 방식으로 스트레스를 풀 수 있었거든요. 공감하시려는지 모르겠어요. 저는 그렇답니다. 한국에 살다 보니 이제는 사실 오히려 이제는 외국에 나가 산다는 게 더 큰 도전이 된 느낌이기도 하고요."Q. 가장 좋아하는 캐나다 음식은?"캐나다 초밥요! 캘리포니아 롤이 캐나다 밴쿠버에서 만들어졌단 사실 알고 계시나요? 저 그거 정말 좋아합니다.."Q. 스스로를 어느 나라 사람이라고 생각하나요?"저는 국적은 캐나다이지만, 저의 정체성은 한국에서 시작되었고, 한 번도 그걸 잊은 적이 없어요. 캐나다에서도 한국 문화에 대한 관심을 늘 가지고 있었거든요. 예능이라던지, 시트콤 다 따라서 봤었으니까요. (원래 외국에 살면 더 한국 프로그램 많이 보게 된다는..) 아무쪼록, 저는 제가 한국인임을 잊어 본 적이 없어요. 비록 국적은 캐나다인이지만요. 그리고 저는 최대한 한국의 가십거리를 말하지 않아요. 왜냐면, 저는 이곳에 오래 살지 않았고 제가 기여할 수 있는 부분이 굉장히 제한적이거든요. 제가 국방의 의무를 했다거나, 투표권이 있으면 모를까 제가 감히 함부로 한국에 대해서 말하고 싶지 않아요. 무엇보다 저는 제 스스로가 어느 국가의 사람인 지보단 '나'라는 스스로에 집중하는 편이에요."(앞으로 외국인이라고 부르지 않을게요 큐..)Q. 다른 이루고 싶은 꿈이 있다면?"다음 생에 저는 래퍼가 되고 싶어요. 정말로 진지하게, 힙합과 랩이라는 문화를 존중하고 좋아합니다. 그저 취미로 시작하고 싶은 게 아니라,  정말 다시 태어나면 온전히 랩에 집중해서 좋은 래퍼가 되고 싶어요."Q. 어떤 사람과 함께 일하고 싶나요?개발자로서 이루고 싶은 비전이 확실한 사람이요. 무엇보다 소통하는 데 있어서 나이를 떠나, 마음이 열려있는 사람과 함께 일하고 싶습니다. 서로를 존중할 수 있는 그런 사람이요.탁구를 좋아하는 KyuQ. 마지막으로 하고 싶은 말이 있다면?"주변 친구들이 스푼에서 일을 시작하기 전과 후가 많이 바뀌었다고 말하는데, 저는 제 스스로에게 정말 많은 변화가 생겼다고 생각해요. 조금 더 진지하고 진중한 사람이 된 것 같고 이 긍정의 변화가 앞으로도 계속되길 바랍니다. 아! 그리고 회사에 제공되는 샐러드가 매일 아침마다 오면 좋겠어요. 저 그럼 정말 회사 지금보다 더 즐겁게 다닐 수 있습니다"P.S: 매번 다른 사람들의 인터뷰를 하고 계신 Sunny를 제가 직접 인터뷰해보고 싶어요.서비스 플랫폼팀 팀원들이 Kyu를 한마디로 표현한다면?Charles 曰:  '대장' - 대시보드 장인Sam 曰:  '거머리' - 자꾸 달라붙어서..Mark 曰: '감초 같은 사람' - 약방의 감초처럼 저희 팀 업무 전반에 없어선 안될 사람(큐가 이렇게 하라고 시켰어요) 
조회수 2254

JIRA하고 자빠졌네!?

Overview“JIRA하고, 자빠졌네!” 세종대왕은 확실히 개발자의 두뇌를 가지고 있었던 게 분명합니다. 먼 시대를 지나 오늘날 QA를 하는 저에게 응원을 해주시니 말입니다. 하지만 그는 틀렸습니다. 걱정과는 다르게 다행히 자빠지진 않았거든요. 지라(JIRA) 덕분입니다.갑자기 지라 이야기가 나와 당황하셨죠? 축하해주세요. 드디어 브랜디도 지라를 사용하게 되었답니다. (짝짝짝!) 지라 도입은 처음이라 세팅부터 쉽지 않았는데요. 이번 글은 눈물겨웠던 지라 세팅 과정과 브랜디의 이슈관리를 소개하겠습니다. 스크럼을 쓰면 좋은 점스크럼(Scrum)은 요구 사항 분석부터 하는 칸반(Kanban)보다 효율적입니다. 안드로이드와 iOS로도 나눠져 있고 업무를 짧게 반복하기 때문이죠. 스크럼에 적합한 워크플로우(Workflow)를 볼까요? 이것은 실제로 브랜디 R&D본부에서 사용하고 있기도 합니다. 스크럼에 적합한 워크플로우IN PROGRESS: 이슈나 개발 요건을 티켓으로 만들면 IN PROGRESS 상태가 됩니다. RESOLVED: 이슈나 개발 요건이 완료되면 RESOLVED 상태로 변경합니다.QA: QA가 필요한 개발 요건은 QA상태로 변경합니다.PASS: 이슈 또는 개발 요건이 수정되었거나 문제가 없다면 PASS 상태로 변경합니다.FAIL: 이슈 또는 개발 요건이 제대로 수정되지 않았거나 다른 이슈가 발생하면 FAIL 상태로 변경합니다.QA불필요: QA가 필요하지 않은 개발 요건은 QA불필요 상태로 변경합니다.DONE: 이슈를 해결했거나 개발을 완료하면 DONE 상태로 변경합니다CLOSE: 담당 팀장님이 이슈 확인 후 CLOSE 처리합니다. 예를 들어보겠습니다. 킥오프 서비스 회의를 하고, SB를 제작, 리뷰합니다. 이후에 디자인팀과 개발팀 일정을 공유하고 스크럼 마스터는 스프린트 주기를 책정하죠. 스프린트가 시작되면 개발자는 스토리 티켓을 작성하는데요. 개발이 끝나면 QA가 필요한 티켓은 테스트를 진행하고, QA가 종료되면 스프린트도 종료됩니다.Epic 티켓위의 이미지는 Epic 티켓입니다. Android, iOS, 이슈 등 모든 티켓은 Epic 안에서 관리합니다. 한 곳에서 한꺼번에 관리하기 때문에 히스토리 관리가 편하고, 진행 상황도 확인할 수 있습니다.티켓 생성개발팀의 티켓 생성입니다. 개발자는 SB를 보고 개발 티켓을 작성합니다. 개발 티켓 작성 후에 개발이 진행되며 QA 판단 여부를 체크해 QA 상태로 변경합니다. 변경된 티켓에 관한 QA가 진행되며 문제가 없으면 해당 티켓은 종료됩니다.이슈 생성다음은 이슈 생성입니다. 파악한 SB는 디자인 시안과 비교하며 개발이 된 Android, iOS 테스트 파일을 QA합니다. QA를 진행할 때 발생한 이슈는 지라 티켓으로 등록하여 이슈를 관리합니다. 모든 이슈 티켓 종료되면 해당 차수의 QA는 끝나고 마침내 상용에 배포합니다. 배포가 완료되면 필수 및 크리티컬 리그레이션 테스트가 진행됩니다. Conclusion실수는 항상 모든 것이 끝난 이후에 보이기 마련입니다. 수십 번 QA를 해도 보이지 않던 문제들이 상용에 올라간 이후부터 보이기 시작하죠. 스크럼은 이런 실수들을 가장 최소화할 수 있는 툴이 아닐까 생각합니다. 물론 아무리 좋은 툴을 써도 팀원들과 함께 뭉치는 것보다 중요한 것은 없겠죠. 다음 글은 자동화를 주제로 찾아뵙겠습니다. JIRA하고 자빠지지 않는 개발자가 됩시다!글김치영 대리 | R&D PM팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발자 #개발팀 #인사이트 #경험공유 #JIRA
조회수 2141

레진 기술 블로그 - IntersectionObserver를 이용한 이미지 동적 로딩 기능 개선

구글 크롬 51 버전부터 DOM 엘리먼트의 노출 여부를 비동기로 처리하는 IntersectionObserver API를 사용할 수 있게 되었습니다. 이 기능을 이용하면 이미지의 동적 로딩이나 광고 배너의 노출 측정 등을 효율적으로 사용할 수 있다고 구글 개발자 블로그에서 소개하고 있습니다. 이 글에서는 기존의 이미지 동적 로딩에 대한 문제점을 짚어보고 여러 예제를 통해 IntersectionObserver의 사용 방법을 익혀 기존 기능을 개선할 수 있도록 합니다. 사용한 예제들은 브라우저의 호환성을 고려하지 않고 구글 크롬을 기준으로 작성하였습니다.기존의 이미지 동적 로딩 구현이미지의 개수가 많거나 용량이 큰 페이지를 불러올 경우 쓸데없는 네트워크 비용이 증가하고 이미지를 불러오는 과정에서 서비스 속도에 문제가 발생할 소지가 있어서 이미지가 사용자에게 보일 때만 불러오는 동적 로딩 기능이 필요합니다. IntersectionObserver를 소개하기 전에 먼저 기존 라이브러리들이 이미지 동적 로딩을 어떤 방법으로 구현하고 있는지 간단하게 알아보도록 합니다.엘리먼트 가시성 판단이미지 동적 로딩에서 가장 중요한 코드는 해당 엘리먼트가 현재 화면 내에 보이는지 알아내는 것입니다. 이를 위해 엘리먼트의 크기와 위치 값을 돌려주는 Element.getBoundingClientRect 함수를 사용하는 경우가 많습니다. 아래는 이 함수를 사용한 간단한 구현 예제입니다.function isInViewport(element) { const viewportHeight = document.documentElement.clientHeight; const viewportWidth = document.documentElement.clientWidth; const rect = element.getBoundingClientRect(); if (!rect.width || !rect.height) { return false; } var top = rect.top >= 0 && rect.top < viewportHeight; var bottom = rect.bottom >= 0 && rect.bottom < viewportHeight; var left = rect.left >= 0 && rect.left < viewportWidth; var right = rect.right >= 0 && rect.right < viewportWidth; return (top || bottom) && (left || right); } 이벤트 처리위에서 구현한 isInViewport 함수는 언제 호출해야 할까요? 먼저 문서를 처음 불러왔을 때 호출해야 합니다. 그 후에는 동적 로딩이라는 단어에 맞게 사용자의 동작에 따라 보이지 않던 엘리먼트가 보이게 되는 이벤트를 감지해야 합니다. 마우스나 터치로 스크롤을 통해 문서의 위치가 바뀌거나 브라우저의 크기가 바뀔 수도 있고 모바일 기기의 화면을 돌려서 볼 수도 있습니다. 데스크톱의 경우 scroll, resize 이벤트를, 모바일의 경우 orientationchange 이벤트의 처리를 생각해야 합니다.const images = Array.from(document.querySelectorAll('img')); document.addEventListener('scroll', () => { images.forEach(image => { if (isInViewport(image)) { image.onload = () => images.splice(images.indexOf(image), 1); image.src = 'original_image_path'; } }); }); 간단하게 위 코드와 같이 구현할 수 있습니다. 물론 실제 서비스를 위해서는 수정할 점이 몇 가지 있습니다. 동적 로딩의 대상이 되는 이미지를 구분하기 위해 해당 엘리먼트에만 특정 클래스를 부여하거나 HTML5에서 지원하는 data 속성을 이용하기도 합니다. 스크롤이나 리사이즈 이벤트가 과도하게 발생하는 경우가 많으므로 throttle 또는 debounce 등을 사용해 실행 빈도를 조절할 수도 있습니다. 일부 라이브러리에서는 requestAnimationFrame을 이용해 이벤트 핸들러를 처리하기도 합니다.TADA레진코믹스에서는 이미지 동적 로딩을 위해 서비스 초기에 Unveil 라이브러리를 사용했었습니다. 그러나 적용 후 몇 가지 아쉬움이 있어 따로 TADA 라이브러리를 제작했습니다. 먼저 마크업 구조상 이미지를 태그가 아닌 다른 태그에 배경 이미지로 사용하는 경우를 지원해야 했습니다. 그리고 모바일 웹에 주로 많이 적용하는 수평 스크롤 구역에 대한 처리도 필요했습니다. 문서의 스크롤 이벤트로는 처리가 되지 않기 때문에 특정 엘리먼트를 받아 그 엘리먼트의 스크롤 이벤트 핸들러를 등록할 수 있도록 해야 했습니다. 이를 해결하기 위해 만든 라이브러리를 현재 서비스에 적용 중이지만 이 라이브러리 역시 아래와 같은 문제점들을 가지고 있습니다.</> < id>기존 이미지 동적 로딩의 문제점getBoundingClientRect 함수의 문제점위 코드에서 특정 엘리먼트가 현재 화면 내에 보이는지 검사할 때 사용하던 Element.getBoundingClientRect 함수에는 치명적인 단점이 있습니다. 이 함수를 호출할 때마다 브라우저는 엘리먼트의 크기와 위치값을 최신 정보로 알아오기 위해 문서의 일부 혹은 전체를 다시 그리게 되는 리플로우(reflow) 현상이 발생한다는 점입니다. 호출 횟수가 적을 경우에는 부담이 되지 않지만, 이 함수는 위에서 구현한 것처럼 스크롤이나 리사이즈 이벤트가 발생할 때마다 등록한 모든 엘리먼트를 순환하면서 호출하게 됩니다. 이 코드들이 하나의 메인 스레드에서 실행되기 때문에 스크롤을 할 때마다 실행 속도가 눈에 띄게 느려질 수도 있습니다.외부 도메인 문서를 사용하는 iframe최신 브라우저들은 동일 도메인 정책에 따라 iframe 내의 외부 도메인 문서에서 현재 문서에 접근하지 못 하게 막고 있습니다. 이 제한은 서비스 개발에서 겪게 되는 문제는 아니고 외부 광고 플랫폼 개발자의 입장에서 발생하는 문제입니다. 광고 이미지의 표시나 클릭 이벤트의 처리 등은 iframe 내에서 처리할 수 있지만 광고 이미지를 지연 로딩한다거나 이 광고가 사용자에게 노출이 되었는지 기록하는 등의 기능은 iframe 내에서 불가능합니다. 그래서 광고를 적용하는 서비스 개발자에게 스크립트를 제공하고 서비스 문서 내에 삽입하는 방식으로 처리하고 있습니다. 이러한 외부 광고가 여러 개라면 삽입해야 하는 코드가 늘어날 뿐만 아니라 코드 내에서 스크롤이나 리사이즈 이벤트 등을 각각 사용하기 때문에 위에서 언급한 문제점들이 배가될 수 있습니다.기타 이벤트에 대한 처리대부분의 동적 로딩 라이브러리들은 적용할 엘리먼트에 특정 클래스 또는 data 속성을 부여하면 코드를 추가 작성하지 않더라도 쉽게 사용할 수 있습니다. 하지만 화면에서 보이지 않던 엘리먼트가 갑자기 나타나는 현상은 스크롤이나 리사이즈 이벤트에서만 발생하는 것이 아닙니다. 더보기 버튼을 눌렀을 때 숨겨져 있던 엘리먼트를 노출할 수도 있고 AJAX 호출 후 엘리먼트를 생성한 후 보여줄 수도 있습니다. 이런 경우 일괄적으로 처리하기가 어렵우므로 해당 이벤트가 발생할 때 수동으로 처리하는 수밖에 없습니다.IntersectionObserver위에 나열한 문제들을 효과적으로 처리하기 위해 크롬 51/엣지 15/파이어폭스 55 버전부터 IntersectionObserver를 지원하기 시작합니다. 우리말로 번역하면 교차 감시자 정도가 될 이 기능은 등록한 엘리먼트가 보이는 영역에 나타나거나 사라질 때(용어에 충실하자면 대상 엘리먼트의 영역이 루트 엘리먼트 영역과 교차하기 시작하거나 끝났을 때) 비동기로 이벤트를 발생시켜 줍니다. 기본적인 사용법은 아래와 같습니다.const intersectionObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { // do something observer.unobserve(entry.target); } }); }); intersectionObserver.observe(element); 먼저 IntersectionObserver 생성자에 콜백 함수를 인자로 넘겨주고 생성한 인스턴스의 observe 메소드를 통해 동적으로 처리할 엘리먼트를 등록합니다. 콜백 함수는 IntersectionObserverEntry 객체 목록을 전달받으므로 순환문을 통해 각 엘리먼트에 대한 처리를 완료하고 필요한 경우 unobserve 메소드를 이용해 감시 대상에서 해제할 수 있습니다.IntersectionObserver 예제아래 예제들은 기본적으로 아래 코드를 바탕으로 작성되었습니다. 각 예제들의 최상단에 엘리먼트에 짝을 이룬 표시등을 두었고 콜백 함수가 호출될 때마다 파동 효과를 주었으며 이 때 isIntersecting 속성을 기준으로 표시등을 켜지거나 꺼지게 되어 있습니다.const io = new IntersectionObserver(entries => { entries.forEach(entry => { // isIntersecting 속성으로 해당 엘리먼트가 보이는 지 표시 }); }); Array.from(document.querySelectorAll('.box')).forEach(box => { io.observe(box); }); 스크롤 이벤트를 다루지 않더라도 엘리먼트의 가시성 여부를 isIntersecting 속성을 통해 알 수 있습니다.<iframe class="demo" data-fr-src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/basic-verticalscroll.html" width="600" height="400" frameborder="0">수평 스크롤의 경우에도 overflow 속성이 적용된 컨테이너 엘리먼트의 스크롤 이벤트를 처리하지 않더라도 상관없습니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/basic-horizontalscroll.html" width="600" height="200" frameborder="0">더보기 버튼에 대한 클릭 이벤트를 따로 등록하지 않아도 동작합니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/basic-unfold.html" width="600" height="240" frameborder="0">리사이즈 이벤트 역시 따로 처리할 필요가 없습니다. 새 창을 띄운 후 창 크기를 조절하면서 확인할 수 있습니다.위의 모든 예제들은 <iframe> 태그 안에서 실행되고 있습니다. 이처럼 작성한 코드가 외부에서 실행이 되더라도 IntersectionObserver API는 문제없이 동작합니다.IntersectionObserver 생성자 옵션rootroot 옵션에는 가시성의 판단 기준이 될 HTML 엘리먼트를 지정합니다. observe 메소드로 등록하는 엘리먼트들은 반드시 이 루트 엘리먼트의 자식이어야 합니다. 이 옵션을 지정하지 않을 경우 브라우저 화면에서 현재 보이는 영역인 뷰포트가 기본이 됩니다. 아래 예제에서 알 수 있듯이 루트 엘리먼트를 지정하면 현재 화면과는 상관없이 루트 엘리먼트와 등록한 엘리먼트들의 영역이 교차하는 지 판단하게 됩니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/option-root.html" width="600" height="400" frameborder="0">rootMargin루트 엘리먼트의 마진값을 지정할 수 있습니다. CSS에서 사용하는 형식과 같기 때문에 “10px”, “10px 20px”, “10px 20px 30px 40px” 형태가 모두 가능하며 음수값으로 지정할 수도 있습니다. 기본값은 0이고 루트 엘리먼트를 지정한 상태라면 퍼센트값을 사용할 수도 있습니다. 이 옵션을 이용하면 이미지 동적 로딩에서 해당 엘리먼트가 화면에 나타나기 전에 이미지를 불러오기 시작해 이미지 공백을 줄이는데 유용하게 이용할 수 있겠습니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/option-rootmargin.html" width="600" height="400" frameborder="0">위 예제에서는 root 옵션은 지정하지 않고 rootMargin 옵션을 각각 0, 100px, -100px, 50%로 지정했습니다. 하지만 iframe 내에서 실행을 하게 되면 이 옵션이 정상적으로 동작하지 않습니다. 프로젝트 페이지의 이슈 댓글에는 동일 도메인의 프레임 안에서는 동작하는 것으로 논의되고 있지만 뷰포트에는 해당하지 않거나 버그 또는 아직 크롬에 반영이 되지 않아 보입니다.이 예제는 새 창을 띄워 프레임을 벗어나면 정상적으로 동작합니다. 스크롤을 내리다보면 엘리먼트마다 IntersectionObserver 콜백 함수가 다른 위치에서 호출됨을 알 수 있습니다.thresholdthreshold 옵션은 엘리먼트가 콜백 함수의 호출 시점을 정하는 옵션입니다. 0과 1을 포함한 그 사이의 숫자 또는 숫자 배열을 지정할 수 있는데 이 숫자는 엘리먼트의 전체 영역 중에 현재 보이는 영역의 비율입니다. 이 비율의 경계를 넘나들 때마다 콜백 함수가 호출됩니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/option-threshold-value.html" width="600" height="400" frameborder="0">위 예제에서는 threshold 옵션을 각각 0, 0.5, 1, [0, 1]로 지정했습니다. rootMargin 예제처럼 엘리먼트마다 콜백 함수가 다른 위치에서 호출됩니다. 두 번째와 세 번째 상자는 콜백 호출 시점에 isIntersecting 값이 항상 참이기 때문에 표시등이 정상적으로 표시되지 않습니다. isIntersecting 속성을 기준으로 처리해야 할 작업이 있다면 반드시 threshold 속성에 0을 포함시켜야 정상적으로 동작합니다. threshold 속성은 아래 예제처럼 콜백 함수의 인자로 받는 IntersectionObserverEntry 객체의 intersectionRatio 속성과 같이 사용하기에 유용합니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/option-threshold-ratio.html" width="600" height="400" frameborder="0">위 예제에서는 threshold 옵션을 각각 [0, 1], [0, 0.5, 1], [0, 0.25, 0.5, 0.75, 1]로 지정하고 콜백이 호출되면 intersectionRatio 값을 기준으로 표시등의 배경 투명도를 바꾸도록 했습니다.IntersectionObserver의 활용이미지 동적 로딩지금껏 알아본 IntersectionObserver를 이용해 이미지 동적 로딩을 간단하게 구현해봅니다. 이미지 엘리먼트를 구성할 데이터가 배열로 존재한다고 가정하고 ES6에서 지원하는 템플릿 문자열을 사용해 배열을 순환하면서 이미지 목록을 생성합니다. 그 후 IntersectionObserver를 초기화하고 만들어진 엘리먼트들을 등록합니다. 콜백 함수에서는 엘리먼트가 보이는 상태일 때 이미지를 로딩하고 해당 엘리먼트를 감시 해제합니다. id="comics"> const comics = [ { alias: 'eunsoo', id: 6080299074584576, title: '은수' }, ... ]; const template = comics => ` ${comics.map(comic => ` ${comic.id}"> ${comic.alias}" class="info">${comic.title} `).join('')} `; document.getElementById('comics').innerHTML = template(comics); const io = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (!entry.isIntersecting) { return; } const target = entry.target; const id = target.dataset.id; target.querySelector('.info').style.backgroundImage = `url(https://cdn.lezhin.com/v2/comics/${id}/images/wide?width=600)`; observer.unobserve(target); }); }); Array.from(document.querySelectorAll('.comic')).forEach(el => { io.observe(el); }); 아래 예제를 실행하면서 브라우저의 개발자 도구를 열고 네트워크 탭을 살펴보면 이미지 엘리먼트가 보이기 시작할 때 불러오기 시작하는 것을 확인할 수 있습니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/demo-lazyload.html" width="600" height="400" frameborder="0">무한 스크롤IntersectionObserver 기능을 이용하면 무한 스크롤 역시 쉽게 구현할 수 있습니다. 아래 예제에서는 스크롤의 끝부분에 감시를 할 엘리먼트를 두고 그 엘리먼트가 노출이 될 때마다 콘텐츠를 추가로 불러오도록 작성하였습니다. id="items"> id="sentinel"> const count = 20; let index = 0; function loadItems() { const fragment = document.createDocumentFragment(); for (let i = index + 1; i <= index + count; ++i) { const item = document.createElement('p'); item.classList.add('item'); item.textContent = `#${i}`; fragment.appendChild(item); } document.getElementById('items').appendChild(fragment); index += count; } const io = new IntersectionObserver(entries => { entries.forEach(entry => { if (!entry.isIntersecting) { return; } loadItems(); }); }); io.observe(document.getElementById('sentinel')); loadItems(); 실행 결과를 아래 예제에서 확인할 수 있습니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/demo-infinitescroll.html" width="600" height="400" frameborder="0">마무리IntersectionObserver API는 아직 몇몇 브라우저의 최신 버전에서만 사용할 수 있지만 지원하지 않는 브라우저를 위해 Polyfill을 제공하고 있습니다.IntersectionObserver API는 웹 광고 플랫폼 제공자와 사용자 모두에게도 좋은 소식이라 봅니다. 이 API가 정착된다면 광고 노출 여부를 측정하기가 쉬워지고 서비스에 더해졌던 리소스 낭비를 줄일 수 있을 것이라 생각합니다.레진코믹스는 크롬 브라우저 사용자의 비중이 높은 편이기 때문에 빠른 시일 안에 적용해 볼 예정입니다. 이미지 동적 로딩 기능의 개선과 정주행 기능과 같이 현재 스크롤 이벤트를 과하게 사용하고 있는 코드에 대한 부담을 덜 수 있기를 기대하고 있습니다.참고자료Intersection Observer API SpecificationIntersectionObserver’s Coming into ViewIntersection Observer API
조회수 1427

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]브랜디, 오직 예쁜 옷만
조회수 1201

안드로이드 개발자의 고민 Fragment (2)

이전 글 보기: 안드로이드 개발자의 고민: Fragment이번 글에서는 Fragment stack 관리와 Fragment 데이터 Lifecycle 관리 이슈를 줄일 수 있는 해결 방법을 찾아보겠습니다. 이전 글에서는  Fragment를 하나의 View로 관리하는 오픈소스를 검토했었습니다.하지만 검토하는 중에 기존 오픈 소스의 변경과 버전업 관리 이슈의 문제를 그냥 넘어갈 수는 없었습니다. 상용 소스에 바로 적용하기에는 리스크가 크다고 판단해 좀 더 신뢰할 수 있는 방법을 선택하기로 했는데요.요즘은 작년 6월에 Google IO 에 발표한 AndroidX의 내용을 다시 검토하고 있습니다. Deeplink를 통한 목적 화면과 Fragment 스택 관리가 중요한데, 이 기능을 도와주는 것이 AndroidX Navigation이기 때문입니다. 화면 전환을 UI 기반으로 사용하여 화면 관리를 용이하게 만들었습니다. 물론 코드 기반에 익숙한 저는 적용하는데 시간이 걸렸죠.기존의 Fragment 관리는 FragmentManager를 통하여 개발자가 직접 코드 상에서 관리했습니다. 하지만 Navigation의 경우에는 아래와 같이 직관적으로 설정할 수 있습니다.firstFragment -> secondFragment -> thirdFragment 로 화면 간의 흐름을 설정합니다. 하나의 Navigation 파일은 하나 이상의 Activity 에서 사용할 수 있습니다.이 방식은 오히려 현재 사용하는 브랜디 소스와 비슷합니다. 하나의 Activity에 ActivityFragment를 만들어서 1:1 매핑으로 화면을 Fragment를 관리하는 방식과 유사합니다. Navigation 의 세부내용은 Google Developers에서 확인할 수 있습니다.Deeplink 를 통한 Fragment Stack 관리도 간단합니다.Notification 또는 Serice 등에서 PendingIntent를 사용하여 테스트할 수 있습니다. Navigation Fragment stack 순서대로 화면을 쌓은 다음 최종 destination Fragment 로 도착합니다. 이와 같은 방법으로 Push를 통한 화면 관리를 쉽게 할 수 있습니다. 이 내용은 여기에서 자세히 확인할 수 있습니다.신속한 마무리기존 Android 에서 화면 관리가 불편했다면 Navigation으로 직관적이고 쉽게 화면을 관리할 수 있을 겁니다. 브랜디는 아직 적용할 준비 중이지만, 꼭 kotlin과 Navigation을 적용해보려 합니다. 그럼 다시 개발의 숲으로 들어가보겠습니다.글고재성 과장 | R&D 개발1팀[email protected]브랜디, 오직 예쁜 옷만
조회수 1825

프론트엔드 개발자라면!

Angular의 A마크를 알아본 프론트엔드 개발자님!이 글은 새로운 플랫폼을 개발하고 있는 타운컴퍼니 개발팀으로 당신을 모셔보려는 글이에요.이들이 당신과 함께 일하고 싶은 동료입니다..타운컴퍼니팀은 알고 있습니다.잘 만들어진 편리한 앱과 고객의 이탈률이 얼마나 밀접한 관계가 있는가를요.1%의 스타트업에는 1% 개발자가 필요하며 그들이 1%의 플랫폼을 만든다는 것을요.자율적이며 열정이 넘치는 팀으로 즐겁게 높은 수준의 개발을 할 수 있는 환경이죠!당신에게 즐거운 회사, 좋은 동료가 되어 줄 수 있습니다.급여는 협의 후 결정이니 원하는걸 말해봐요!좋은 동료를 얻을 수 있다면 그정도가 어렵겠어요 ; )우리는 현재 플랫폼(townus.co.kr)이 많이 부족하다는걸 알고 있어요.그래서 완전 멋있게 새롭게 만들고 있는 중입니다 :)일단 우리는 협업툴 JIRA와 Confluence, Slack을 사용하고 있어요.우리팀은 Agile 칸반을 바탕으로 테스트 주도 개발, 코드 리뷰, 페어프로그래밍으로 프로젝트를 진행하고 있죠.도메인이 잘 분석된 명세서가 Confluence에 정리되어 있고 사용자를 위한 깊은 고민이 녹아있는 디자인이 Zeplin에 올라가고 있어요.- Back-End는 Django(DRF) 기반으로 개발되고 있고, AWS, Vagrant, Docker같은 기술을 사용해요.- Front-End는 Angular 5를 사용해서 개발하고 있고, Less, RxJS, Webpack 등의 기술을 사용하고 있어요.Angular 상용 프로젝트 개발 경험이 있다면 격하게 환영하며 모십니다. 리엑티브 프로그래밍, Ionic 경험이 있다면 더 좋구요!엥 이거 완전 나 아니냐!? 라는 생각이 들었다구요? 그렇다면 얼른 지원해야지 뭐해요!무엇보다 개발을 즐기고 오픈소스활동을 좋아하는 사람이라면,종종 맛있는것도 먹으면서 많은 대화를 나눌수 있지 않을까요? :>우리 개발자는 맥주제조도 할 줄 알거든요 (겁나 맛이 좋더라구요)물론 당신에 대해 알 수 있는 Github 주소와 이력서를 보내준다면 우리가 연락하기 더 쉬울거에요!아! 참고로 보충역 산업기능요원 편입도 가능하니 문의가 필요하다면 언제든 환영이에요!타운컴퍼니팀에게 연락하고 싶다면 02–561–0950 잊지말아요,[email protected]로 메일 보내준다면 언제든 답변줄게요 :D#타운컴퍼니 #개발자 #채용 #팀빌딩 #조직문화

기업문화 엿볼 때, 더팀스

로그인

/