스토리 홈

인터뷰

피드

뉴스

조회수 1463

A씨의 일주일

스포카 개발팀 문성원입니다. 오늘은 스포카 개발팀의 가공의 개발자 A씨의 일주일을 통해, 스포카 개발팀에서는 일주일간의 개발 일정을 어떻게 진행하는지 살펴보겠습니다. 평소 스타트업(Startup) 개발팀의 문화에 관심이 있으셨던 분들에게 도움이 되길 바랍니다.월요일오전 10시, A씨는 평소보다 조금 일찍 사무실에 도착했습니다. 매주 월요일은 스포카 전체 미팅이 있는 날이기 때문이죠. 한 주간 각자 진행한 것을 토대로 이번 주에 진행할 일을 대외적으로 공표하는 이 회의에 앞서, 스포카 개발팀은 따로 미팅을 잠깐 가집니다. 그동안 지난 주 개발 사항, 이번 주 구현 목록 등을 트렐로(Trello)를 통해 정리한 뒤, 이를 전체 미팅에서 공유합니다. A씨는 지난 주에 미쳐 다 구현하지 못했던 서버의 몇 가지 기능과 클라이언트 신버전 배포 준비를 하게 되었습니다.정신없이 회의 하고 났더니 벌써 점심시간입니다. 늘 가던 근처 식당에서 즐겁게 점심을 먹고 사무실로 올라온 A씨는 막간을 이용해 간밤에 올라온 스포카 개발 블로그의 원고를 검토합니다. 몇 가지 오탈자와 맞춤법을 지적한 뒤 모두가 지루해할 월요일 오후 1~2시경에 공개하는 것이 목표입니다.올라간 블로그 글을 확인한 뒤에, A씨는 구현해야 할 서버 기능을 살펴보기로 했습니다. 생각보단 많긴 하지만 일주일 안에는 어떻게든 끝낼 수도 있을 것 같은 분량이네요. 우선 트렐로에 올라온 카드의 명세를 토대로 작업해야 할 내용을 체크리스트(Check List)로 정리합니다. 그다음은 모두가 짐작하시듯이 열심히 일합니다. A씨는 프로니까요.어느덧 저녁 시간이 다 되었습니다. 특별히 일이 없는 이상 야근은 하지 않는 주의인 A씨지만, 오늘만큼은 저녁을 먹고 조금 더 남아있기로 합니다. 팀 내에서 진행하고 있는 스터디 때문이죠. 혼자서 읽기는 까다로웠던 책을 다 같이 읽어보니 조금은 이해가 더 되는 느낌이 드네요.화요일A씨는 오전에 작업하던 중 이상한 점을 발견합니다. 구현하기로 한 기능이 기존 기능과 모순이 되기 때문이죠. 이걸 어떻게 해결할까 고민하던 A씨는 다행히 사무실에 남아있던 엔에이블러(Enabler)팀원들과 간단하게 미팅을 합니다. 문제를 설명하고 명세를 다시 확인한 A씨는 작성한 회의록과 함께 배포합니다. 트렐로의 해당 카드에도 첨부하여 나중에 다시 볼 수 있게 하는 것은 기본입니다.뜻하지 않은 문제 때문에 오전을 날려서 기분이 나빠진 A씨지만, 다행히 좋아하는 스파게티를 먹고 기운을 내기로 했습니다. 사무실에 올라와 인터넷 뉴스와 페이스북을 잠시 보던 A씨는 암묵적으로만 정해진 점심시간이 끝나자 바로 작업을 시작합니다. A씨는 프로니까요.그런데 문제가 있습니다. 오전에 배포한 회의록을 읽어 본 다른 팀원들이 이건 다른 문제의 원인이 될 수 있다고 합니다. A씨는 새 기능 추가가 단순히 로직이 아니라 클라이언트 UI를 포함한 대규모 변경이 필요하다는 것을 깨닫습니다. A씨는 새 기능에 대한 대략적인 스케치를 발사믹 목업(Balsamiq Mockup)으로 마친 뒤 이를 다시 배포합니다. 또한, 관련된 카드에 설명도 잊지 않습니다.수요일매주 수요일 오전에 스포카 개발팀은 짧은 미팅을 합니다. 금주의 진행사항 중 변경사항이나 도움이 필요한 내용을 공유하는 자리인데요. 여기서 A씨는 어제 일을 다시 정리해서 이야기하고, 일정이 지연될 수 있음을 전달합니다. A씨에게 할당된 카드 일부를 다음 주로 미루거나, 좀 한가한 사람에게 나눠주는 형식으로 짐을 던 A씨였지만, 여전히 큰일이 되어버린 기능 변경은 무거운 짐입니다.이런 대량의 작업 때문에 고민하던 A씨에게 같은 팀 B씨가 어떤 라이브러리를 소개해줍니다. A씨는 처음 보는 라이브러리인지라 B씨가 전담해서 가르쳐주는 모양이 되었지만, 생각보다 문제 해결에 큰 도움이 될 것 같습니다. 마침 다음 주에 개발 블로그에 글을 써야 할 당번이 된 A씨는 그 라이브러리에 대해 좀 더 공부해서 쓰기로 정합니다.B씨의 도움 덕에 진행 속도가 붙은 A씨는, 금주 업무 중 하나였던 클라이언트 새 버전의 테스트를 내일부터 진행하기 위해 페이스북이나 인터넷 뉴스도 보지 않은 채 열심히 일합니다. 이런 A씨의 프로다운 모습에 하늘도 감탄했는지, 퇴근 시간인 7시 전에 작업을 끝낸 A씨는 구현된 기능들을 테스트 해 보고 팀의 다른 개발자와 공유하기 위해 github에 만들어진 스포카 서버 코드 저장소에 푸시(Push)합니다.목요일구글 플레이(Google Play)는 하루 정도면 배포가 되니 다행이지만 애플 앱스토어(Apple App Store)는 일주일 정도의 심사기간이 있기 때문에 거절(Reject)당하지 않게 철저히 준비해야 합니다. 그래서 어느 때보다 A씨는 날카로운 눈매로 클라이언트를 점검합니다. 아니나 다를까 메뉴를 이동하다 보니 화면 구성이 흐트러지는 버그가 발견되었습니다. 하지만 프로답게 A씨는 당황하지 않고 재현 조건을 확인한 뒤, 클라이언트 담당자인 C씨에게 알려줍니다. “클라이언트 관련한 버그를 찾았는데, 트렐로를 확인해보세요.”라구요. QA(Quality Assurance) 업무 역시 스포카 개발팀은 직접 처리합니다.밖에 비가 오는지라 피자를 시켜먹은 뒤, 자리에 앉아 잠깐 쉬고 있던 A씨에게 D씨가 다가와서는, “어제 푸시한 소스를 내려받다(Pull)가 충돌(Conflict)이 났는데, 어떻게 병합(Merge)해야 할지 모르겠네요.” 라며 묻습니다. A씨는 D씨와 충돌이 난 소스를 함께 검토하고 문제가 발생하지 않게끔 조정한 뒤 이를 다시 푸시해서 상황을 종료합니다.이러는 사이 C씨가 A씨가 말한 버그를 고쳤다며 다시 확인해보라고 트렐로의 관련 카드를 “테스트” 리스트로 옮깁니다. A씨는 재현된 상황에서 문제 없이 동작하는 것을 확인하고 카드를 “완료” 리스트로 다시 옮깁니다. 이제 클라이언트 앱을 심의 신청하고 어제 구현한 서버 쪽 코드의 개선사항이 있는지 살펴봅니다. 서버는 클라이언트가 앱스토어나 플레이에 준비되는 것을 확인한 뒤, DotCloud에서 제공하는 배포 스크립트를 통해 손쉽게 버전업할 수 있기 때문에 시간이 좀 남아 있습니다. 현재로선 특별히 더 손댈 부분이 없다는 걸 확인한 A씨는 오늘도 즐겁게 퇴근합니다.금요일월요일과 마찬가지로 오늘도 A씨는 평소보다 조금 서둘러서 사무실에 도착했습니다. 오늘은 사내 전체적으로 한 주간 있었던 업무 내용을 간략하게 보고하는 자리가 있습니다. A씨는 이번 주에 맡은 서버 개발이 이러저러해서 이렇고 저렇게 바뀌었다고 설명한 뒤, 앱스토어에 신청되었다는 사실을 공지합니다. 전체 보고가 끝난 뒤엔 개발팀은 따로 남아서 약간 자세하게 금주 작업을 공유하면서 트렐로의 “완료” 상태에 있는 카드들을 정리하는 시간을 갖습니다.점심을 먹고 나서, 이번 주에 더는 급한 일정이 없다는 것을 확인한 A씨는 개발 블로그에 쓸 글을 정리하기 시작합니다. 수요일에 B씨가 알려 준 라이브러리의 사용 방법은 대강 배웠지만, 그것을 남에게 설명할 수 있을 만큼 자세히 알지는 못했기 때문에 A씨는 한동안 공식 문서와 예제 코드들과 씨름합니다. 그래도 어느새 옆에서 거들기 시작한 B씨 덕에 글은 생각보다 순조롭게 마무리되었습니다. 이제 다음 주 월요일까지 퇴고해서 블로그에 공개하기만 하면 되죠.생각보다 오늘 업무를 끝낸 A씨는 친구들과 약속이 있는 홍대로 가기 위해, 7시 정시에 사무실을 떠납니다.#스포카 #개발 #개발자 #개발팀 #개발자의일주일 #개발자의일상 #인사이트 #경험공유
조회수 1748

Docker Hub 이벤트를 Slack으로 받기

Docker Hub은 Docker Registry 중에 가장 돋보이지 않나 생각하는데는 다음과 같은 이유가 있다.써드파티 도구와 서비스 대부분이 Docker Hub를 우선적으로 지원한다.이미지 이름이 매우 짧다.AWS ECR: 319270577709.dkr.ecr.us-east-1.amazonaws.com/dailyhotel/myweb:1.0.1Docker Hub: dailyhotel/myweb:1.0.1단순하지만 강력한 도커 빌드 서비스를 제공한다.이 외에도 도커 허브는 장점이 많은데 도커 이미지를 도커 허브에서 빌드하거나 외부에서 docker push를 해서 도커 이미지를 레지스트리에 밀어넣으면 해당 이벤트를 Webhook로 외부에 전달해주는 기능도 그 중 하나이다. 이론적으로는 새 도커 이미지가 나올 때마다 Slack을 통해 알람을 받을 수 있다. 하지만 놀랍게도! 도커 허브는 Slack 등의 대중적인 써드 파티 서비스와의 통합 기능을 직접 지원하지 않는다. 기본적으로 도커 허브가 보내는 Webhook를 파싱해서 슬랙 등으로 보내는 서비스는 직접 구현하거나 누군가 만든 도구를 직접 설치해 사용해야 한다.구글링하면 구현체가 몇 개 나오는데 그 중 일부는 matsengrp/relay를 커스터마이징한 것이다. 다른 구현체도 있지만 matsengrp/relay가 제일 구성이 깔끔하고 커스터마이징하기 쉬웠기 때문에 이를 기반으로 더 쓸모있는 구현체를 만들기로 했다. 새로운 구현체는기존 프로젝트를 Dockerize하고소스 코드를 직접 수정하는 대신 환경변수로 설정을 제어하게 하고도커 이미지의 태그 등 중요 정보를 추가로 표시하며위트 넘치는 이미지를 추가하여 지나치게 사무적이지 않게 메시지를 구성하는데초점을 맞추었다. 그래서 나온 결과물은 다음과 같다.개인적으로는 매우 마음에 든다. Docker 이미지로 빌드했기 때문에 서비스를 띄우기도 매우 쉽다. README 문서에도 기술했듯docker run — env SLACK_URL=’https://hooks.slack.com/services/PUT/YOURS/HERE' — env RELAY_PORT=8080 — env=DEFAULT_CHANNEL=’#dev’ — env=IMAGE_URL=’https://i.giphy.com/LYDNZAzOqrez6.gif' -p 8080:8080 dailyhotel/relay이게 전부이다. IMAGE_URL 등 환경변수 대부분은 필수값도 아니어서 실제 설정은 더 간단명료하다. 도커 이미지가 간단한만큼 Kubernetes로 띄우기도 쉽다.apiVersion: v1 kind: Service metadata: name: slackrelay labels: app: slackrelay spec: ports: — name: http port: 80 targetPort: 8080 protocol: TCP selector: app: slackrelay type: LoadBalancer — - apiVersion: extensions/v1beta1 kind: Deployment metadata: name: slackrelay spec: replicas: 1 template: metadata: labels: app: slackrelay spec: containers: — name: slackrelay image: dailyhotel/relay:latest env: — name: SLACK_URL value: "https://hooks.slack.com/services/PUT/YOURS/HERE" — name: RELAY_PORT value: "8080" — name: DEFAULT_CHANNEL value: "#dev" ports: — name: slackrelay-port containerPort: 8080그래도 여전히 몇 가지 개선점이 있긴 하다. 예를 들어 슬랙의 Webhook URL 대신 API 토큰값을 설정으로 받으면 좀더 많은 기능에 접근할 수가 있다. 이러한 점은 향후 정말 필요할 때 개선해볼 생각이다.참고 자료Webhooks for automated builds는 Docker Hub가 보내는 Webhook 메시지를 기술한다. 제목만 읽으면 자동화된 빌드에만 해당하는 이야기 같지만 확인해보니 docker push로 이미지를 푸시했을 때도 동일한 메시지 포맷을 사용한다.RequestBin는 Webhooks for automated builds에서 언급한 웹 서비스인데 Webhook 개발 등에 매우 유용하다. 외부 서비스가 발송하는 HTTP 요청 메시지를 받아서 임시로 보관해준다. Webhooks for automated builds에서 기술한 메시지 포맷대로 실제로 발송되는지 확인하기에 매우 요긴했다.#데일리 #데일리호텔 #Docker #Slack #슬랙 #협업툴 #개발 #개발자 #인사이트 #꿀팁
조회수 2900

타다 클라이언트 개발기

앞서 종합 모빌리티 플랫폼인 타다의 시스템 설계를 위한 많은 고민과 기술적 결정들에 대해서 서버팀에서 소개한 바 있습니다. 이번 글에서는 타다 서비스를 출시하기까지 타다 모바일 클라이언트를 개발하는 과정에서 내린 클라이언트 팀의 전략적 결정들과, 타다 클라이언트를 개발하는데 사용한 기술들을 공유합니다.시작 전 상황3달 반의 개발 기간: 타다는 VCNC가 SOCAR에 인수되면서 개발하게 된 서비스입니다. 빠르게 시장에 뛰어들어서 선점하는 것이 무엇보다 중요했기에 시간과의 싸움은 필수적이었습니다. 프로젝트는 6월에 시작되었고 1.0 출시는 추석 연휴 직전인 9월 중순으로 결정되었습니다. VCNC에서 오프라인 운영은 처음이었기 때문에 차량을 실제로 운행해보면서 사용성 경험을 테스트할 필요가 있었습니다. 그래서 8월 초에 사내 테스트용 알파 버전을 출시하기로 했습니다.클라이언트 팀 통합: 비트윈 때는 Android/iOS 팀이 나뉘어 있었습니다. 회사 인수 과정에서 발생한 조직 개편으로 인해 타다 클라이언트 개발자는 5명으로 이루어졌습니다. 전부터 다른 OS 개발도 경험하고 싶던 적극적이고 열정적인 5명의 멤버들은 과감하게 팀을 통합해서 Android/iOS을 함께 개발하기로 했습니다.3개의 앱 개발: 타다의 서비스를 위해서는 Android/iOS, 라이더/드라이버 총 4개의 앱을 제작해야 합니다. 하지만 시간과 일정을 고려했을 때 4개의 앱을 다 제작하기는 무리라고 판단을 했습니다. iOS에서는 내비게이션 앱을 사용 중에 드라이버 앱으로 손쉽게 전환하는 기능을 제공할 수 없고 내비게이션 앱으로 경로 안내를 요청하는 것도 제한적이기 때문에 iOS 드라이버 앱은 제작하지 않기로 했습니다.무에서 시작한 프로젝트: 타다는 코드 베이스가 없는 empty repository에서 시작했습니다. 언어도 바뀌었고 레거시 코드와도 엮이고 싶지 않았기 때문에 비트윈에서 어떠한 라이브러리도 가져오지 않고 전부 새로 만들기로 했습니다.클라이언트 팀의 5명의 정예 용사들. by Sam코드 아키텍처 - RIBs프로젝트가 시작되고 기획이 진행되는 동안 3주의 시간을 기반 작업에 쓰기로 했습니다. 가장 먼저 진행한 것은 코드 아키텍처 정하기입니다. 당시에 제가 SAA(Single-Activity Application)에 관심을 가지고 있었는데, 때마침 Google I/O 2018의 세션 중 Modern Android development: Android Jetpack, Kotlin, and more 에서도 비슷한 언급이 나와서 팀에 제안했고, 본격적으로 조사를 해보았습니다. 팀원들이 조사를 진행해보니 Uber, Lyft, Grab 등 굴지의 모빌리티 서비스 회사들이 전부 SAA 기반으로 앱을 개발했다는 것을 알게 되었습니다. 무거운 리소스인 지도를 중심으로 화면이 구성되기에 반복적인 지도 리소스 할당/해제를 피하기 위한 필연적인 선택으로 보입니다. 큰 기업들이 수년간 서비스를 하며 문제를 느끼고 내린 선택인 만큼 저희도 따라가기로 결정했습니다. 비트윈 때 Activity Stack으로 인해 굉장히 고통을 겪은 적이 있는지라 SAA를 원하는 공감대도 있었고요.SAA로 개발을 하기로 정한 이후에는 어떤 프레임워크를 사용해서 개발할지를 고민했습니다. 여러 개의 오픈소스를 비교할 때 Android/iOS 간의 통일된 아키텍처로 개발할 수 있는지를 가장 중점적으로 보았습니다. 대부분의 팀원이 한쪽 OS에만 익숙하기 때문에 초보임에도 빠르게 적응하고 개발하려면 비즈니스 로직을 구현하는 부분이 통일되어 있어야 한다고 생각했습니다. Uber의 RIBs는 저희의 이런 요구를 가장 잘 충족했습니다. 거기에 데이터의 scope와 전달 방식 명확해서 side-effect 없이 개발할 수 있다는 점, 그로 인해 효율적으로 협업이 가능하고 여러명이 개발한 RIB 을 레고 조립하듯 합쳐서 기능을 완성할 수 있다는 점에서 RIBs를 선택하게 되었습니다.RIBs는 아키텍처를 이해하는 것 자체가 굉장히 난해합니다. 오픈소스 상으로 공개가 되지 않은 부분들도 있어서 저희의 입맛에 맞게 변형하는 데 매우 많은 시간을 할애했습니다. RIBs와 관련한 내용은 Nate(김남현)가 Let'Swift 2018에서 발표한 RxRIBs, Multiplatform architecture with Rx 의 영상 및 발표자료를 참조하세요.추후 RIBs를 상세하게 다루는 포스팅을 해보도록 하겠습니다.서버와의 통신 프로토콜새로운 서버 API가 생길 때마다 해당 API의 명세를 문서화하고 전달하는 것은 굉장히 불편한 일입니다. 또한 문서를 작성할 때나 클라이언트에서 모델 클래스를 생성할 때 오타가 발생할 수도 있습니다. 타다에서는 서버 클라이언트 간 API 규약을 Protocol Buffer를 사용해서 단일화된 방법으로 정의하고 자동화하기로 했습니다. 모든 API의 url은 .proto 파일 이름으로 정형화되어 있고 POST body로 Params 객체를 JSON으로 serialization 해서 보내면 Result JSON이 응답으로 옵니다. 서버가 새로운 API를 개발할 때 .proto 파일만 push 하면 클라이언트에서 스크립트를 돌려서 Model 객체를 생성하고 해당 객체를 사용해서 호출만 하면 되는 아주 간단하고 편한 방식입니다.참고로 타다의 서버군에 대한 설명은 타다 시스템 아키텍처에 기술되어 있습니다.기반 작업타다는 빈 repository에서 시작한 깔끔한 프로젝트였기 때문에 Base 코드와 내부 라이브러리들을 전부 새로 개발했습니다.API Controller, gRPC Controller서버와의 통신에 필요한 모듈들을 개발했습니다. 모든 API는 Rx의 Single과 Completable로 wrapping 되어 있습니다.RIBs가장 자주 사용하는 Router 패턴들을 wrapping.Android에서 구현이 공개되어 있지 않은 ScreenStack 구현.SAA이므로 Android에서 Activity가 아닌 화면 단위의 로깅을 구현.Router의 기초적인 화면 Transition을 구현RIB 뼈대 코드용 template 파일 제작Prefs(Android)/Store(iOS)타다에서는 DB를 사용하지 않고 key-value store로만 데이터를 저장합니다. Android SharedPreference와 iOS UserDefaults의 wrapper를 만들었습니다. Object를 serialization 해서 저장하는 기능, Rx 형태의 getter, cache layer, crypto layer 등이 구현되어 있습니다.Design SupportAndroid에서 drawable을 생성하지 않고 layout.xml 상에서 border, corner-radius, masking을 쉽게 설정하기 위해서 제작했습니다.ButterKtAndroid에서 View Binding 처리를 위해 개발했습니다. 비슷한 기능을 하는 Kotter Knife, Kotlin Android Extension이 가지고 있는 lazy binding 문제를 해결하고 싶었고 가능하면 Butter Knife와 달리 apt 없이 동작하는 라이브러리를 만들고 싶었습니다. 이와 관련된 저희의 생각은 여기에 David(김진형)이 상세하게 기록해 두었습니다. 코드도 공개되어 있으니 잘 활용해 보시길 바랍니다.ToolsModel CompilerPBAndK, swift-protobuf를 수정해 .proto 파일을 저희가 원하는 형태의 kotlin data class와 swift codable struct로 변환하는 스크립트를 구현했습니다.Import ResourceUI/UX 팀에서 작업해서 Google Drive File Stream으로 공유하는 리소스를 프로젝트에 sync 하는 스크립트입니다. 타다에서는 기본적으로 벡터 포맷(Android xml, iOS pdf)을 사용하고 Android에서 벡터로 표현이 안되는 이미지들은 png를 사용합니다. 또한 애니메이션을 위한 Lottie json 파일도 사용합니다. 현재는 Android 용으로만 스크립트가 구현되어 있고 리소스를 프로젝트 내의 각각의 res 폴더에 sync 하는 기능과 svg로 전달받은 벡터 파일을 Android xml 형식으로 변환하는 기능을 포함합니다.sync Lokalise타다에서는 Lokalise로 문자열 리소스를 관리합니다. strings.xml, Localizable.strings 파일로 다운받아서 프로젝트에 sync 하는 스크립트 입니다.Code Template & Settings개발 편의를 위한 간단한 Android Studio Code Template과 코드 통일성을 위한 idea settings를 공유합니다.사용된 기술들OS 공통Firebase: Analytics, Crashlytics, Messaging, Storage 등 다양한 용도로 Firebase를 활용하고 있습니다.gRPC, ProtoBuf: 서버에서 실시간 Event를 받기 위해서 사용합니다.RIBs: 타다의 기반 아키텍처 입니다.Lottie: 애니메이션 요소를 표현하기 위해 사용합니다.Semver: 앱의 버전은 Semantic Versioning 규약을 따라 정의합니다. 버전을 파싱하고 관리하기 위해서 Nate(김남현)가 Kotlin 버전과 Swift 버전의 라이브러리를 제작하고 공개했습니다.Braze: CRM(Customer Relationship Management) 툴인 Braze는 유저를 타게팅해서 전면팝업을 띄우거나 푸시 알림을 발송하기 위해 사용합니다.TeamCity, Fastlane, Beta: CI/CD를 위해서 개발 초기에는 Jenkins를 사용했습니다. 출시 대응을 빠르게 하기 위해서 parallel build 및 우선순위 컨트롤을 하고 싶었는데 Jenkins의 Parallel build가 원하는 대로 동작하지 않아서 현재는 TeamCity로 이전했습니다. Beta를 사용해서 모든 브랜치의 빌드를 배포해서 QA 팀에서 테스트할 수 있게 했습니다. 출시용 빌드는 Android의 경우 아직은 수동 업로드를 하고 있고 iOS의 경우 Fastlane으로 배포합니다.git-flow: Git branching model로는 git-flow를 사용합니다. Branch의 종류에 따라서 TeamCity에서의 빌드 우선순위가 결정됩니다.AndroidKotlin: 당연한 선택이겠죠? 타다의 모든 소스 코드는 Fork 해서 수정한 RIBs의 클래스들을 제외하면 전부 Kotlin으로 구현되어 있습니다.AndroidX: 타다 개발을 시작하는 순간에 AndroidX가 공개되었습니다. 기존 Support Library를 사용하게 되면 언젠가는 migration 해야 할 것이기 때문에 알파 버전임에도 불구하고 처음부터 사용하기로 했습니다. ConstraintLayout, PagingLibrary, Material Component, KTX 등 다양한 Component를 사용합니다.Retrofit, OkHttp: 서버와의 HTTP 통신을 위해서 사용합니다.RxJava: 클라이언트 팀은 Rx 없이는 개발할 수 없을 정도로 적극적으로 Rx를 활용합니다.AutoDispose: Rx subscription을 dispose 하기 위해서 사용합니다. 관련해서 도움이 될만한 글을 읽어보시는 것을 추천합니다. Why Not RxLifecycle?RxBinding: View 이벤트를 Observable 형태로 바꿔주는 RxBinding은 굉장히 유용합니다.Moshi: JSON 라이브러리입니다. Kotlin data class와의 호환을 위해서 Gson 대신 선택했습니다.Glide: 이미지 로딩을 위해서 사용합니다.Detekt: Kotlin을 위한 static code analyzer 입니다. Detekt의 extension을 통해 ktlint도 활용하고 있습니다.Dagger: RIBs는 Dependency injection을 기반으로 합니다. RIBs에선 어떠한 DI system이든 사용할 수 있게 Builder가 분리되어 있습니다. RIBs에서는 Dagger로 설명이 되어 있고 저희도 마찬가지로 Dagger를 사용합니다.ThreeTen Backport: Java8의 날짜 및 시간 라이브러리인 JSR-310의 Java SE6 & 7을 위한 backport 라이브러리입니다. 문자열 파싱 및 시간 연산을 위해 사용합니다.iOSSwift: Kotlin과 마찬가지로 당연한 선택입니다. Swift4.2의 CaseIterable Swift5의 Result 등 항상 최신 버전의 Swift를 사용합니다.RxSwift: 역시나 reactive programming은 필수입니다.RxCocoa, RxGesture: iOS에서도 역시 모든 뷰 이벤트는 Rx 형태로 감지합니다.SnapKit: AutoLayout DSL을 제공하므로 코드상에서 편하게 Constraint를 조절할 수 있습니다.Moya/RxSwift, Alamofire: Http 서버와의 통신을 위해 추상화된 네트워크 라이브러리인 Moya를 사용합니다. 역시나 Rx로 wrapping 된 버전을 사용하고 있습니다.Codable: Swift4부터 제공된 프로토콜로 JSON Encoding, Decoding으로 사용중입니다.Hero: RIBs의 Router가 attach/detach 될 때의 Transition을 처리하는데 이용합니다.Kingfisher: 이미지 로딩을 위해서 사용합니다.KeychainAccess: Access Token 같은 중요 정보를 안전하게 저장하기 위해 사용합니다.Swiftlint: SwiftLint는 fastlane action으로 실행해서 code validation을 합니다.출시 후의 회고짧은 시간에 여러 개의 앱을 만들기 위해서는 시간 및 인원을 아주 효율적으로 배분해야 했습니다. 각 OS의 기존 개발자들이 먼저 프로젝트 기반을 닦는 동안 나머지는 스터디를 진행했습니다. 차량 운영 경험을 쌓는 것이 알파 테스트의 목적이었으므로 일정에 맞추기 위해 드라이버 앱도 개발해야 하는 Android로만 알파 버전을 개발했습니다. 대신에 iOS 알파 버전은 서버팀 YB(김영범)가 아주 빠르게 웹앱으로 개발해주었습니다(1.0은 Native입니다.). 알파 버전의 스펙도 호출-하차까지의 시나리오 외의 다른 부가 기능은 전부 제외했습니다.회사 구성원들이 전부 처음 도전하는 분야였기에 기획을 포함해서 모두가 지속적인 변화에 대응해야 했습니다. 특히 사내 테스트를 시작한 직후 실제 운영을 해보며 깨닫고 변경한 기획 및 UX가 상당히 많았습니다. 개발적으로는 익숙하지 않은 아키텍처인 RIBs를 이해하며 개발하는 것이 생각 이상으로 난도가 높았고 개발하는 중간에도 큰 리팩터링을 여러 번 해야 해서 힘들었습니다. 이러한 이유들로 1.0 출시도 시작 전 상황에서 언급한 것보다 2주 정도 미뤄졌습니다.실제 타다 프로젝트 타임라인하지만 저희는 성공적으로 타다를 출시했습니다! 아래는 팀 내에서 출시를 회고하며 나왔던 몇몇 의견입니다.OS 간 아키텍처가 통일되어서 한 명이 같은 기능을 두 OS 전부 개발할 때 굉장히 효율적이다. 비즈니스 로직의 경우 정말로 Swift <-> Kotlin간 언어 번역을 하면 되는 정도.결과적으로 앱 개발 순서를 굉장히 잘 정했다. 한쪽을 먼저 빠르게 개발하고 문제점을 느껴보며 정비해 나가니까 프로젝트 후반부에 빠른 속도로 기능을 개발하는 데 도움이 되었다. 큰 수정을 양쪽 OS에 하지 않아도 됐던 게 좋았다.짧은 기간 개발했음에도 앱 퀄리티가 굉장히 만족스럽다. 매 상황에서 기술적 선택, 인원 배분 등 경험에서 우러나온 아주 적절한 판단들을 했다고 생각한다.각자 독립적으로 개발하던 기능들이 쉽게 합쳐지고 큰 문제없이 잘 동작하는 하나의 앱이 되는 과정이 정말 신기했다. 아키텍처 설계에 쓴 많은 시간이 결코 아깝지 않았다.마치며아직 저희가 하고 싶고 도전해야 하는 과제들은 무궁무진합니다. 그 중 간략히 몇 가지를 소개합니다.테스트 코드 작성: 시간과의 싸움 속에서 테스트 코드 작성을 지금까지 미뤄왔습니다. RIBs의 Interactor 에 구현된 비즈니스 로직은 반드시 테스트 되어야 합니다.OS 간 구조 통일: 같은 화면임에도 OS 간 작업자가 다른 경우 많은 파편화가 일어났습니다. 1순위로 RIB tree 및 Interactor의 비즈니스 로직 통일하는 작업을 진행하고 있습니다. AlertController 같은 공통적인 컴포넌트들도 최대한 포맷을 통일하려는 작업을 지속해서 진행할 예정입니다.iOS DI: RIBs에서 Android에선 Dagger를 활용해서 쉽게 Builder 구현이 가능하지만, iOS에서는 좋은 방법이 없어서 수동으로 DI를 해결하고 있었습니다. 그래서 Uber가 개발 중인 Needle을 적용하려고 관심 있게 보고 있습니다.네트워크 에러 handling 개선: 중첩돼서 뜨는 Alert를 해결하는 것, global 하게 에러를 처리하는 좋은 구조 찾기 등의 이슈가 있습니다.String Resource 관리: 개발하면서 생성하고 아직 Lokalise에 동기화하지 않은 리소스 키를 체크해서 빌드 오류를 발생시키려고 합니다. 또한 iOS에서 "some_key".localize 형태의 extension으로 번역을 코드상에서 불러오는데 key 값 오타가 나면 런타임에서만 오류를 알 수 있습니다. 따라서 String resource를 enum 형태로 관리하려고 합니다.그 외 50여 가지나 되는 팀원들이 하고 싶은 백로그 목록이 여러분을 기다리고 있습니다. 타다가 성공적으로 런칭할 수 있었던 것은 훌륭한 팀원들이 있었기 때문입니다. 앞으로 저희와 함께 좋은 서비스를 만들어 나갈 멋진 분들의 많은 관심 바랍니다.
조회수 1679

[QP크루의 항해일지] 해적선에 탄 신입 디자이너의 적응기

안녕하세요. 콘텐츠 지부 김현수입니다. 저는 4월에 해적선에 승선해서 열심히 항해하고 있는 디자이너입니다. 사실 QP에 첫 번째로 입사한 디자이너이기 때문에 어렵고 힘든 일도 있지만 그만큼 파란만장하고 재미있는 디자인 작업들을 해보고 있습니다. QP에서 진행한 크고 작은 작업들을 하나씩 소개해드리면서 공유해보고 싶었던 점들을 이야기해보려고 합니다.QP에 처음 승선한 디자이너였기 때문에 말하는 대로 이루어지고 곧바로 QP의 비주얼 아이덴티티가 돼버리는(!) 즐겁고도 책임감이 느껴지는 작업들을 해볼 수 있었습니다. 저의 제일 첫 번째 프로젝트였던 QP의 로고 만들기, 신입 크루들을 위한 웰컴키트와 스티커 제작, QP의 A부터 Z까지 담은 해적단 입문서 편찬까지 찬찬히 풀어보겠습니다.STEP 01. QP 로고 제작하기QP의 시각적 정체성을 확립하는 첫 번째 과정은 로고 제작하기였습니다. 로고는 외부에 우리를 알리는 역할을 하기도 하지만 내부 크루들의 회사에 대한 생각을 담고 소속감을 다지게 만듭니다. 그래서 로고를 제작하기 전, 크루들의 의견을 들어보기로 했습니다. 크루들은 퀀텀파이러츠의 로고에 어떤 이미지가 담겼으면 좋겠을지 자유롭게 남긴 의견들을 살펴볼까요?크루들이 주신 소중한 의견들적극적으로 의견을 전달해 주신 크루들 덕분에 디자인을 시작하는 데에 큰 도움이 될 수 있었습니다. QP 해적선이 찾고 싶은 보물 상자, 해적선을 상징하는 깃발, 배 등 다양한 답변과 이미지들이 나왔지만 여기서 일맥상통하는 지점을 찾아 힌트를 얻을 수 있었습니다. 이 힌트를 바탕으로 키워드 몇 가지를 정해 방향성을 가지고 디자인 시안을 제작해 보고자 했습니다. 첫 번째 키워드는 '해적선'입니다. 우리가 그저 표류하는 것이 아닌 거침없이 나아감을 보여줄 수 있는 해적선을 키워드로 선정했습니다. 두 번째는 '항해'입니다. QP의 해적선이 항해하는 모습이 저희의 심볼에도 표현되었으면 한다는 크루들의 의견들을 참고했습니다. 세 번째 키워드는 '방향'입니다. 어딘가로 나아가고 있는 우리의 방향성을 보여주고자 했습니다.그럼 이제 제작했던 시안들을 보여드릴게요!최종 시안을 결정하기 전까지 나온 다양한 시안들시안을 제작할 때는 틈틈이 오며 가며 크루들이 던진 시각적 모티브가 로고를 발전시키는 데에 도움이 될 수 있었습니다. 키워드에도 등장했던 해적선, 그리고 바다, 키 등 다양한 아이디어로 시안들이 완성될 수 있었습니다. 이 중에서 선정된 로고는 다음 나오는 친구입니다.최종 결정된 QP의 로고저희의 항해하는 모습과 길을 상징화했다는 의견으로 채택된 로고입니다. 로고라는 것이 아이덴티티의 시작이 되는 만큼 글에는 압축되었지만 긴 고민의 시간을 담아 완성이 되었습니다. 어떻게 보면 로고가 앞으로의 디자인 작업에서 전면으로 크게 등장하지는 않겠지만 어느 한 켠에서 우리를 알리며 존재감을 내뿜기를 바라며 마무리했습니다.+번외 이야기. QP의 롤링페이퍼입사한지 2일차 날의 이야기입니다. 갑자기 용희님이 급한 일이 있다며 저를 소환하셨습니다. 심각한 얼굴로 전한 이야기는.. 내일이 바로 세정님의 생일이라는 것이었습니다. 생일맞이 롤링페이퍼를 제작해서 전달하자는 것이었는데 이미 퇴근시간이 얼마 남지 않은 시간이었습니다. 15분 안에 롤링페이퍼를 완성해야 하는 미션이 주어진 것이죠. (용희님은 이때 "앞으로는 이렇게 데드라인이 급한 일을 전달하지 않겠다"라고 약속하셨죠.) 이렇게 만들어진 제작된 롤링페이퍼는 무사히 세정님께 전달될 수 있었고 QP의 작은 문화가 되었습니다.QP의 크고 작은 모든 이벤트들에는 롤링페이퍼가 함께 합니다.생일을 맞이하여 기쁜 QP의 아이돌 소영님STEP 02. 스티커와 웰컴키트 제작하기로고를 제작한 후 가장 손쉽게 만들 수 있는 굿즈를 먼저 제작해 웰컴키트를 구성해보기로 하였습니다. 그렇게 제작하게 된 것이 스티커입니다. 웰컴키트를 꾸밀 수 있는 타이포그래피 스티커와 로고 심볼 스티커를 제작해 회사 곳곳에 사용하기로 결정했습니다. 로고를 제작하면서 파란색이 QP의 키 컬러로 결정된 만큼 굿즈 제작에도 적극 활용해 디자인했습니다.QP의 스티커 시안들다양한 용도로 쓰일 수 있도록 3가지 시안으로 디자인을 마무리해 스티커를 제작했습니다. 제작한 후에 배포하고 실제 사용되고 있는 모습을 보니 회사 브랜딩에 작은 한 발자국을 내디딘 기분이었습니다. 또한 내부적으로도 자연스럽게 소속감을 높일 수 있게 되는 계기가 되기도 했습니다. 비록 작은 스티커로 시작했지만 이러한 굿즈가 쌓이다 보면 내부에서부터 단단하게 쌓을 브랜딩에 일환이 될 수 있겠다는 생각을 얻게 된 프로젝트였습니다.스티커를 활용하는 예스티커를 제작한 후 웰컴키트도 제작을 시작했습니다. 웰컴키트에는 우선 앞서 제작했던 스티커가 들어갑니다. 그리고 크루들이 신입 크루를 위한 환영의 말을 적은 롤링페이퍼가 들어가죠. 신입 크루들이 회사생활에 필요한 사무용품, 슬리퍼 등 필수품들 또한 준비합니다. 마지막으로 쿠폰이 들어갑니다. 살짝만 보여드리자면 점심 식대를 초과해서 지원해주는 "오늘 점심 주인공은 나야 나"쿠폰, 아직 궁금한 것이 많은 신입 크루들을 위한 "모든 바쁜 일은 제쳐두고 내 질문에 답해줘"쿠폰 등이 있습니다. 아직은 어색할 신입 크루들이 자연스럽게 크루들과 친해질 계기를 만들어 해적 생활에 적응할 수 있게 도와주죠. 신입 크루를 위한 웰컴키트STEP 03. 해적단 입문서 편찬하기웰컴키트를 제작하면서 신입 크루에게 전달할 입단 과정부터 근무에 필요한 모든 것을 적은 해적단 입문서의 필요성을 느끼게 되었습니다. 필요한 내용을 정리해 4개의 단원과 2개의 별책부록으로 나누어 편집했습니다. 2개의 별책부록은 QP에 간식이나 쉴 수 있는 곳을 소개하는 보물지도와 크루들의 자기소개가 담긴 크루 소개 페이지로 이루어져 있습니다. 이후에 내용은 주제에 따라 4단원으로 나누어져 있습니다. 첫 번째 단원은 <해적단 입단 심사>로 입사서류나 계정 생성등 입사 후 첫 번째로 해야 하는 필수 과정들에 대해 안내하고 있습니다. 두 번째 단원은 "해적 장비 안내"로 QP에서 사용하고 있는 툴들을 소개하고 어떻게 사용하는지 간략히 알려주는 단원입니다. 세 번째 단원은 "같이의 가치"파트입니다. 휴가를 어떻게 쓰는지부터 QP 크루들이 점심을 먹는 법까지 QP의 복지에 대해 소개하는 단원입니다. 마지막 단원은 해적 꿀팁으로 회의실 예약 방법이나 WIFI 정보 등 소소한 팁들을 안내하고 있습니다.입문서를 디자인할 때에는 처음부터 확실한 콘셉트를 가지고 있었습니다. 마치 해적들의 양피지를 펼쳐보는 듯한 책을 만들자는 방향으로 시작했습니다. 여타의 입사 가이드처럼 딱딱한 형식보다는 친근감 있고 재미있게 필수 정보들을 전달하자는 기획을 가지고 텍스트 작업과 디자인을 진행했습니다.해적단 입문서 내부를 살짝 보여드립니다!계속해서 키 컬러로 사용하고 있는 파란색을 포인트로 양피지 질감의 배경으로 콘셉트에 부합하는 비주얼을 만들었습니다. 다만 텍스트 양이 많다는 특성상 내지는 깔끔하게 흰 배경으로 작업을 진행했습니다. 완성된 입문서는 PDF로 새로 입사할 크루들에게 안내 메일로 배포되고 있습니다. 입사하기전 해적단 입문서를 읽으며 QP에 대한 낯섦을 조금 해소할 수 있기를 바라며 애정을 가지고 디자인 작업을 진행했는데요, 입문서를 제작하면서 저 또한 QP에 대해서 알았던 것을 정리하고 몰랐던 것을 새롭게 알아가는 시간이었습니다. QP_디자이너의_자리.jpg승선하고 처음 맡았던 작업들이 QP의 브랜딩에 관한 것이었기 때문에 디자이너로서는 책임감이 크게 느껴졌었습니다. 하지만 로고부터 시작해 회사의 아이덴티티를 다지는 작업을 하고 나니 회사 내부의 가치를 올리는 데에 일조한 것 같아 보람을 느낄 수 있었습니다. 또한 이번에 했던 프로젝트들이 회사의 문화와도 맞닿아 있는 부분이 많았기에 많은 크루들의 기대와 관심 속에 완성되었는데요, 그만큼 의견을 존중해주고 관심을 가져주는 크루들이 있었기 때문에 오히려 자유롭고 즐겁게 작업을 해볼 수 있었습니다. 이 모든 프로젝트를 함께 해주신 세정님께 특별한 감사드리며 해적단 입문서에 내용을 작성하시느라 고생하신 경모님께도 감사드립니다. 앞으로도 항해일지는 계속 이어질 예정이니 어떤 크루가 적어주실지 많이 기대 부탁드립니다!QP 크루들은 앞으로도 더 멋진 항해를 하기 위해 함께 노력하고 성장하고 있습니다. 현재 퀀텀파이러츠는 퍼포먼스 마케터, 검색광고마케터, 웹 개발자 직무의 크루를 기다리고 있습니다. QP 해적선에 승선해 함께 하고 싶다면 아래의 링크를 참고해주세요!https://blog.naver.com/haejeok_kwon/221566691682
조회수 1409

QA 끝! ADB 설치부터 사용까지

Overview안드로이드 개발자라면 모두 ADB(Android Debug Bridge)를 사용합니다. 안드로이드 SDK에 포함되어 있는 기능인데요. 쉽게 말하면 에뮬이나 안드로이드 단말과의 연결고리, 도구를 의미합니다. 특히나 QA(Quality Assurance)를 진행할 때 ADB를 사용하면 아주 유용하고, 있어 보입니다. 이번 글에서는 ADB를 잘 모르는 QA직군들을 위해 설치 방법과 간단한 사용법을 공유하려고 합니다. SDK, ADB 설치하기앞서 ADB는 SDK에 포함된 기능이라고 했죠? 우선 여기를 클릭해 SDK를 설치해주세요. 참, 안드로이드는 JAVA가 기본 언어! JAVA도 설치하고 환경 변수도 설정해주세요!SDK를 설치했다면 plalform-tools 폴더 안의 adb.exe파일을 찾아야 합니다. 저의 설치 경로는(C:\Users\brandi_171205_02\android-sdks\platform-tools) 네요.경로를 찾았다면 JAVA 환경 변수 설정하듯 ADB도 환경변수를 설정해야 합니다. ‘내 컴퓨터 마우스 오른쪽 > 속성 클릭’해주세요.고급 시스템 설정 클릭 (개인정보라 지웠습니다.)환경변수 클릭시스템변수 영역 path클릭 > 편집 클릭윈도우10은 앞뒤로 ;를 추가하지 않아도 됩니다. ADB 경로를 추가해주세요. (C:\Users\brandi_171205_02\android-sdks\platform-tools)cmd창을 열고 ADB를 입력하고, 엔터를 눌러주세요.아래와 같이 나오면 성공!잘 따라왔나요? 그 다음은 단말기입니다. 개발자 옵션 > usb디버깅 허용 후 단말을 pc와 연결해주세요. CRM창에서 adb devices 를 입력해주세요. 이 명령어는 에뮬이나 단말 연결을 확인하는 명령어 입니다.ADB 설치를 마쳤습니다. 참 쉽죠? 지금부턴 자주 쓰는 ADB 명령어를 알려드립니다. 한 번 사용해보세요. 한 번 써봤다는 사람은 봤어도, 한 번만 썼다는 사람은 못 봤습니다.자주 쓰는 ADB 명령어단말 재시작QA진행하시면 재시작 많이 하죠? 단말초기화..!adb rebootapk설치 내컴퓨터 > 단말 > 다운로드할 필요가 없어요. 바로 설치!!adb install -r [파일명].apkapk 삭제adb uninstall [패지지명]Android버전 확인adb shell getprop ro.build.version.releaseScreenshotadb shell /system/bin/screencap -p 장치내경로동영상 녹화 QA일하면서 필수입니다. 정말 유용해요.adb shell screenrecord /sdcard/[저장할파일명].mp4텍스트 입력 로그인, 텍스트 입력 테스트 진짜 좋습니다.adb shell input text “[입력할 텍스트]”마치며ADB엔 엄~청나게 많은 명령어가 있습니다. 더 많은 정보를 알고 싶다면 adb help를 입력해보세요. 명령어 도움말이 툭 나올 겁니다. ADB가 있다면 이슈 등록과 이슈 관리 정말 편해집니다. 우선 알려드린 7번까지만 사용해보세요. 당신의 QA가 편안해질 겁니다. 지금까지 브랜디 QA 문지기, 김치영이었습니다.글김치영 대리 | R&D PM팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발자 #개발팀 #인사이트 #경험공유
조회수 396

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

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

스타일쉐어에서 이미지 분류하기 (시작 편) feat.ML

안녕하세요.스타일쉐어에서 백엔드 개발을 하고 있는 김동현입니다.작년 11월 스타일쉐어에서 뷰티에 관련된 사진들을 따로 모아서 보여줄 피드.바로 뷰티피드 라는 것을 만들었습니다. 하지만 피드를 만드는 과정이 순탄치 만은 않았는데요.그간의 과정과 얻었던 경험들을 공유하고자 합니다.들어가기에 앞서혹시 설명을 하다 보면 스타일쉐어에서만 사용되는 단어가 있을 수 있다는 생각이 들어 단어에 대한 공유를 먼저 드리고자 합니다.스타일쉐어에서는 이를 “피드”라 칭합니다.스타일쉐어에서는 이를 “스타일”이라 칭합니다.여러 가지 카테고리 중에서 왜 뷰티인가요?기존의 서비스에서는 유저들이 올리는 스타일에 대한 카테고리가 없어서 유저들이 보고 싶어 하는 스타일들을 쏙쏙 뽑아서 보여줄 수 없는 상황이었지만 “내가 보고 싶은 것들만 볼 수 있었으면 좋겠다”라는 유저들의 니즈는 계속 올라가고 있었습니다.서비스 특성상 1020 유저들이 많이 있었고 하루 동안 올라오는 스타일에 대해서 사람이 직접 카테고리를 하나하나 나눠봤을 때 가장 활발하게 대화가 이루어지고 반응이 좋고 충성도도 높은 카테고리가 바로 뷰티였습니다.뷰티만이라도 따로 보여줄 수 있도록 해보자그럼 어떻게 뷰티에 관련된 게시물들을 뽑아낼 건가요?올라오는 스타일들 중에서 뷰티라는 속성을 찾아내어 분류하는 방법으로 두 가지의 제안이 나왔습니다.1. 사람이 직접 뽑아낸다.2. 요즘 뜨고 있는 딥러닝을 이용해서 뽑아낸다.처음엔 사람이 직접 모니터링 해볼까? 라는 이야기가 나왔었습니다.당장이라도 시작 할 수 있다는 점과 높은 정확도를 가졌다는 장점이 있기 때문이였죠.하지만 주말 관계없이 4000~6000개씩 올라오는 스타일들을 상시 모니터링하고 모두 검토해야 하는 상황이 너무 막막하게 느껴졌습니다. 관련 업무를 하시는 분의 업무 만족도는 낮을 것이 당연하기도 했지만 그럴만한 인적자원이 충분하지 않았습니다.그래서 요즘 뜨고 있는 딥러닝을 이용해보자는 방향으로 일이 진행되었습니다. 게다가 요즘 딥러닝으로 Image Classification 하는데에 있어서 정확도가 사람을 넘어섰다는 이야기도 결정에 한몫을 했답니다.딥러닝으로 분류하기로 결정했다! 근데 트레이닝 셋은?딥러닝을 하시는 분들이 애용하는 사이트인 캐글만 가보아도 문제와 트레이닝 셋이 잘 정리되어있기에 개발자는 어떻게 하면 잘 예측할 수 있을까에 대한 고민만 했으면 되었었습니다. 하지만 당연하게도 실제 필드에서 처리해야 하는 문제와 그에 대한 트레이닝 셋은 존재하지 않았습니다.우선 딥러닝으로 분류하기로 결정을 하였으니 서비스에서 뷰티라는 카테고리 안에 넣을 소카테고리를 나누었고 다음과 같았습니다.* 눈 화장 관련* 입술 화장 관련* 얼굴 화장 관련* 헤어* 화장품* 발색* 네일그래도 태양 아래 새로운 것은 없다 라는 말처럼 비슷한 것들이 존재할까 하고 찾아보았으나…https://www.kaggle.com/openfoodfacts/openbeautyfactshttp://www.antitza.com/makeup-datasets.htmlㅇ…없잖아?!그렇습니다. 공개된 것은 없던 새로운 것이었습니다. 위의 소카테고리들을 모으는 방법을 모색해야 했습니다.위에서 언급했듯이 잉여 인적자원이 없었기 때문에 몇만 개의 데이터를 모을만한 데이터를 모으는 일은 저를 포함해서 개발자 2명이서 진행을 했었습니다.그래서 결국 뷰티 피드는…성.공.적.다행히도 잘 마무리되었습니다. 화자 되고 있는 딥러닝 기술을 실제로 사용해볼 수 있어서 좋았고 팀원들도 이게 되는구나, 다른 것도 해볼 수 있겠다 라는 피드백을 많이 받았고 저 또한 개발을 하면서도 이게 된다고? 하는 반응이 제일 많았던 것 같습니다. 물론 앞으로 모델을 계속 개선해나가야겠지만요.사실 딥러닝을 거의 처음 공부하는 수준에 가까웠고 초반에 우왕좌왕 하기도 많이 했었는데 믿고 기다려줬던 스타일쉐어 팀원 분들 덕분에 잘 마무리될 수 있었던 것 같습니다.분류와 트레이닝 셋에 대한 좀 더 자세한 글은 다음 포스팅 (분류 편)에서 찾아뵙겠습니다.#스타일쉐어 #개발팀 #개발자 #개발후기 #경험공유 #인사이트
조회수 1053

"안정적인 서비스 운영으로 더 나은 코인원의 가치를 고객들에게 전달합니다:D" - 플랫폼셀 김영민

하나의 서비스를 출시하고 운영하기까지의 여정을 '출산과 육아'에 비유하곤 합니다. 아이를 건강하게 낳고, 올바르게 성장할 수 있도록 하기 위한 육아법은 모든 부모들의 고민일거에요. 이는 서비스를 출시한 엔지니어들에게도 마찬가지입니다. 심혈을 기울여 서비스를 개발하고, 이후 서비스가 고객들에게 안정적으로 제공될 수 있도록 유지하고 끊임없이 개선하죠.오늘은 코인원의 서비스를 건강하게 키워나가고 있는 코인원 플랫폼셀 영민님과 이야기를 나눠봤습니다. 365일 밤낮없이 운영되는 암호화폐 거래소 서비스 운영은 어떤 모습일까요? 영민님이 이야기하는 코인원 서비스 개발부터 구축, 운영까지의 여정에 함께하시죠!Q. 영민님 반갑습니다 :-) 먼저 자기소개를 부탁드립니다!안녕하세요, 플랫폼셀의 클라우드 플랫폼 엔지니어 김영민입니다. 어느덧, 코인원에 합류한지 1년 반의 시간이 흘렀네요. 저는 코인원 한국거래소를 시작으로 해외송금 서비스 ‘크로스', 글로벌거래소 ‘CGEX’와 같은 다양한 금융 서비스 인프라 업무를 경험했습니다. 현재는 코인원 한국거래소 서비스 인프라 구축과 운영 업무를 중점적으로 담당하고 있어요. 저를 포함한 플랫폼셀의 크루들은 코인원을 지탱하고 있는 인프라를 효율적으로 운영하고 있습니다. 특히, 개발과 운영셀에 속해 있는 크루들과의 밀접한 소통으로 고객에게 더 나은 서비스의 가치를 전달할 수 있도록 하는 것이 목표입니다.  Q. 플랫폼셀은 어떻게 구성되었나요? 구체적으로 어떤 일을 하시는지도 궁금합니다. 플랫폼셀은 크게 클라우드 플랫폼 엔지니어들로 구성되어 있습니다. 세부적으로 시스템 엔지니어, 네트워크 엔지니어, 데이터 사이언티스트, 플랫폼 개발 업무로 나뉘어집니다. 플랫폼셀은 코인원 초창기 시절부터 팀명과 업무범위에 많은 변화가 있었습니다. 인프라팀, SRE(Site Reliability Engineering)팀을 거쳐 지금의 플랫폼셀이 탄생하게 되었죠. 플랫폼셀의 가장 큰 목표는 안정적인 운영을 통해 서비스의 신뢰성을 확보하는 것입니다. 이를 위해 신속하게 개발을 지원할 수 있는 플랫폼을 설계하고 구축하려고해요.플랫폼셀 크루들의 열띤 업무의 현장!Q. 플랫폼셀이 많은 변천사를 겪어온 만큼, 코인원의 서비스 구성에도 큰 변화가 있었을 것으로 예상됩니다. 그 중 가장 큰 변화는 무엇인가요?초창기 코인원 서비스의 경우, 전통적인 서비스 아키텍처인 모놀리틱(Monolitic) 아키텍처 기반의 서비스가 많았습니다. 모놀리틱 아키텍처는 로컬 환경에서 개발하기에도 편리하고 통합 시나리오 테스트를 수행하기에도 쉬운 구성입니다. 다만, 코인원의 서비스가 지속적으로 성장하고 규모가 커지면서 몇가지 한계에 부딪혔습니다.서비스 복잡도가 증가하고 트래픽이 상승하면서, 서비스 확장이나 배포 관련 업무에 인프라 작업들이 수시로 발생하게 되었어요. 무중단 배포, 효율적인 리소스 사용, 인프라 표준화를 위해 ‘마이크로서비스 아키텍처'로의 전환이 필요한 시기였습니다. 이를 위해 마이그레이션(Migration, 데이터를 추출하여 새로운 시스템 내의 지정된 형식으로 옮기는 과정) 계획을 세우고 조직의 의사결정 프로세스와 개발 문화, 배포 프로세스들을 개선해 나가기 위해 노력했죠.Q. 암호화폐 거래소 ‘코인원' 서비스를 운영하시면서 다이나믹한 에피소드들이 많을 것 같습니다.2017년 12월 말, 비트코인 전고점 시기에 도달할즈음 코인원 거래소의 서비스 트래픽이 가파르게 상승했습니다. 매일마다 두배, 세배 이상의 인프라 확장작업이 필요했어요. AWS(Amazon Web Services)에 지불했던 비용이 17년 7월 대비 12월에 20배가 늘었습니다. 6개월이라는 짧은 시간동안 이렇게 급성장한 트래픽을 경험할 수 있는 업계는 몇없을거에요!Q. 코인원을 이용하는 고객들의 거래가 더 편리해질 수 있도록 플랫폼셀에서는 어떠한 노력을 기울이고 계신가요?트래픽 급증으로 서비스 업데이트를 할 경우, 서비스 지연 그리고 점검으로 인한 중단으로 불편을 겪은 고객분들이 계실 겁니다. 코인원은 이러한 문제를 해결 하기 위해 대용량 서비스를 운영 할 수 있도록 아키텍처를 변경하는 작업을 진행했습니다. CI/CD(Continuous Integration and Continuous Delivery, 지속적 통합과 지속적 전달) 자동화, 무중단 배포 환경을 갖추면서 서비스 지연과 중단의 빈도수가 점점 줄고 있습니다. 이제는 서비스를 더 빠르게 업데이트 하고 버그나 장애를 최소화 하며 트래픽이 갑작스럽게 증가하더라도 서비스 안정성을 확보 할 수 있는 플랫폼으로 진화하고 있어요.노을지는 창가 속의 슈퍼크루 영민님!Q. 코인원의 플랫폼셀만이 갖고 있는 장점을 이야기해본다면!코인원에는 어느 스타트업보다도 연륜이 가득한 시니어 엔지니어들이 플랫폼셀을 이끌고 있습니다. 블록체인, 암호화폐 업계 뿐만 아니라 직무 경험도 많으신 분들이 곳곳에 포진되어 있어요. 코인원 기술본부만이 갖고 있는 중요한 장점이기도 하죠. 또한 플랫폼셀은 내부적인 아키텍쳐, 코드 리뷰를 거치면서 일하는 방식을 지속적으로 개선해 나가고 있습니다.추후 플랫폼셀에 합류하실 분들도 새로운 것들을 찾고 계속해서 발전시키려고 하는 분들이 함께해주셨으면 좋겠습니다! 스탠드업 미팅, 회고를 통해 소통하고, 재미있는 개발문화를 만들어가고 있으니 플랫폼셀에 많은 지원 부탁드립니다 :) (저희 해치지 않아요! ㅎㅎㅎ)Q. 영민님은 코인원에 어떻게 합류하게 되셨나요?저는 실생활에 다양한 금융서비스를 제공하는 핀테크에 관심이 많았습니다. 핀테크에 대한 관심은 이전에 몸담았던 게임산업에서부터 시작되었어요. 게임에서도 암호화폐 거래소와 유사하게 서비스 내에서 통용되는 가상의 화폐가 있습니다. 그러다보니 ‘가상의 재화가 아닌 실물화폐를 다루는 곳의 서비스는 어떻게 제공될까?’ 라는 호기심이 강해졌어요. 신기술이었던 블록체인과 암호화폐를 눈여겨보게 되었고, 지금 이렇게 코인원 크루로 함께하고 있네요! 코인원에서는 실제 현금을 다루는 곳이기 때문에 막중한 책임감으로 서비스 안정성과 보안을 함께 신경쓰고 있습니다.Q. 지난 겨울에 코인원 크루들과 함께 재미난 추억을 만드셨다고 들었어요!2018년은 코인원에서 피보탈랩스를 시작으로 새로운 것들에 많이 도전해볼 수 있는 시간이었습니다. 그 중, 다양한 직무에 계신 크루들과 함께 참가했던 ‘AWS re:Invent 2018’ 행사가 기억에 남네요. 리인벤트 기술세션에서 소개되었던 Tool들이 코인원에서 많이 사용되고 있는데, 컨퍼런스에서 새롭게 배운 것들을 적용해볼 수 있을 것 같습니다! 힙한 개발문화들도 접해보고, 다양한 국가, 회사, 직군에 계신 분들을 만나뵙게 되어 개발을 바라보는 시야 또한 넓어졌네요. 코인원 크루와 함께했던 AWS re:Invent 현장!Q. 영민님이 어떠한 미래를 꿈꾸고 계신가요?거창한 미래를 이야기하기 보단 소소한 바램을 말씀드리고 싶어요. 2019년에도 그리고 이후에도 지금 함께 일하고 있는 코인원 크루들과 더 재미나게 일하고 싶습니다. 훌륭한 동료들이 제 옆에 있다는 것만으로도 난관을 헤쳐나갈 때 큰 도움이 됩니다. 똘똘 뭉친 지금의 조직력을 바탕으로 99.999%(?)의 서비스 안정화 꿈을 이룰 거랍니다. 마지막으로, 새해에는 야근을 조금 덜하고 사랑하는 두딸들과 행복한 저녁 시간을 자주 가지려구요! (아빠 얼굴 잊은거아니지?)더 안정적인 코인원 거래소를 위해 오늘도 24시간 고군분투하고 있는 영민님. 앞으로도 코인원 플랫폼셀은 암호화폐 거래에 최적화된 플랫폼 구축을 위해 최선의 노력을 다할 예정이랍니다. 코인원 플랫폼셀 크루들이 선보일 멋진 서비스에 많은 응원과 관심 부탁드립니다.이렇게 멋진 엔지니어들과 동료가 되고 싶지 않으신가요? 현재 코인원 플랫폼셀은 함께 일할 동료 크루를 애타게 기다리고 있습니다! 많은 지원 부탁드려요 :-)
조회수 1662

결전! CodeShip Pro vs Travis-CI

데일리의 Java 백엔드 개발자는 Docker 기반의 CodeShip Pro를 애용하는데 최근에 빌드가 급격히 느려지는 문제를 겪었다. 빌드가 느려진 원인은 다양하지만 그 중 일부는 CodeShip Pro의 캐싱 방식, 더 정확히는 도커의 캐싱 방식과 관련이 있다.CodeShip Pro는 pom.xml 또는 build.gradle 을 보고 빌드에 필요한 라이브러리를 미리 가져와서 캐싱하기를 권장한다.# We're using the official Maven 3 image from the Docker Hub (https://hub.docker.com/_/maven/). # Take a look at the available versions so you can specify the Java version you want to use. FROM maven:3 # INSTALL any further tools you need here so they are cached in the docker build WORKDIR /app # Copy the pom.xml into the image to install all dependencies COPY pom.xml ./ # Run install task so all necessary dependencies are downloaded and cached in # the Docker image. We're running through the whole process but disable # testing and make sure the command doesn't fail. RUN mvn install clean --fail-never -B -DfailIfNoTests=false # Copy the whole repository into the image COPY . ./예전에는 이 방식이 문제가 안 됐는데 최근 들어 캐시 적중률이 급격히 낮아졌다. 여러 애플리케이션이 공유하는 라이브러리를 몇 개 추가했는데 그 중 하나가 빈번히 업데이트되는 게 문제다. pom.xml 파일을 자주 수정하는데 그 말인즉 COPY pom.xml ./ 줄부터 다시 빌드해야 한다는 뜻이다. 그러므로 RUN mvn install clean --fail-never -B -DfailIfNoTests=false 을 실행하는 횟수가 많고 평균 빌드시간이 장난 아니게 늘어난다.CodeShip Pro에서 이 문제를 해결하는 방법은 비교적 간단하다. pom.xml 파일을 둘로 쪼개면 된다. 자주 수정하는 `pom.xml` 파일부터 빌드하면 빌드 시간을 종전처럼 끌어내릴 수 있다.COPY pom-not-frequently-changed.xml ./ RUN mvn -f=pom-not-frequently-changed.xml install clean --fail-never -B -DfailIfNoTests=falseCOPY pom.xml ./ RUN mvn install clean --fail-never -B -DfailIfNoTests=false하지만 CodeShip Pro가 이와 유사한 문제로 여러 번 문제가 된 터라 Travis-CI로 옮기면 어떤 장단점이 있는지 확인해보았다.장점Travis-CI는 커밋과 푸시를 한 해당 브랜치 뿐 아니라 머징할 브랜치 등에서도 빌드를 돌린다.CodeShip보다 캐싱 정책을 수립하기 쉽다.캐시 적중률 문제가 덜하므로 빌드 시간이 좀더 안정적으로 유지된다.현재 머신 사양으로는 약 1분 가량 빌드가 빠르다.빌드 과정을 한 눈에 이해하기 쉽다.Cron 빌드를 지원한다. 시간이 지나면서 의존성 문제 등으로 빌드가 깨졌을 때 조기에 조치할 수 있다.단점Travis-CI는 로컬에서 CI 환경과 동일한 빌드환경을 제공하지 않는다..travis.yml 파일을 수정하고 테스트하려면 git push 를 반복해야 한다.테스트를 돌리는 리눅스 환경과 실제 서버가 작동하는 도커 리눅스 환경이 같지 않다.돈으로 더 좋은 머신을 도입할 수 없다.빌드 환경을 이전하기는 그리 어렵지 않다. 하지만 장단점이 명확하다 보니 어느 게 꼭 좋다 말하기 힘들다. 상황에 따라 결정하는 수밖에.#데일리 #데일리호텔 #개발 #개발자 #개발도구 #도입후기 #일지 #인사이트 #조언
조회수 1494

원하는 정보를 5초 안에 인지할 수 있게 하자

우리나라에서 웹 서비스가 아이디어에서 출발해 출시되기까지 여러 단계를 거치게 되는데 크게는 기획, 디자인, 개발의 3단계를 거치게 된다고 볼 수 있다. 각 단계별로 세분화된 역할들이 있어도 결국은 각각 기획자, 디자이너, 개발자로 분류된다. 어니스트펀드에서는 그들이 제품개발팀을 이루고 있다.어니스트펀드 제품개발팀나는 그중 개발자로 속하고 퍼블리싱 & 프론트 개발을 하고 있다. 퍼블리싱은 디자이너가 그린 디자인된 화면을 웹페이지용 프로그래밍 언어라고 할 수 있는 HTML과 CSS로 웹 문서화하는 것이고, 프론트 개발은 HTML과 CSS로 만들어진 웹문서를 사용자의 의도/목적에 따라 기능이 동작하도록(주로 데이터 입출력, 예를 들자면 네이버 검색창의 자동 완성이나, 네이버 메인의 다음 뉴스 보기 등) 기능을 개발하는 것이다.어니스트펀드에서는 팀원들이 자신의 지식/경험을 공유하는 브런치 글을 돌아가면서 쓰고 있고 나도 함께하기로 결정하였다. 내가 가치 있게 공유할 수 있는 내용이 무엇인지를 고민하면서 나의 과거 경험들을 생각해보았다.나는 2002년 웹 디자인을 시작으로 퍼블리싱 업무를 겸하다 2004년부터 퍼블리싱 업무를 본격적으로 했고 2011년부터 스타트업에 합류하면서 기획 및 프론트 개발까지 제품 개발에 있어서 서버 개발을 제외한 사용자와 접하는 모든 업무를 두루 경험하였다. 보통 디자인 전공자들은 기획파트로 전업하는 경우가 많지만 나는 프로그래밍 언어로 코드를 작성하는 것이 재미있어 기회가 닿을 때마다 업무 영역을 넓혀왔다.따라서 기획과 디자인, 퍼블리싱, 프론트 개발에 이르는 사용자와 접점이 많은 다양한 업무를 해오면서 경험한 것을 바탕으로, 서비스를 구성하고 화면을 개발하는 데 있어 도움이 되는 유용한 내용을 공유하고자 한다.1. 많을 땐 나눠서 해결하자정보가 많다는 것은 정리 정돈할 물건이 많다는 것과 비슷하게 생각할 수 있다. 물건이 목적에 맞게 정리되지 않으면 찾기 어렵고 정리해놓더라도 쉽게 어질러질 수 있다. 정보도 마찬가지로 목적에 맞게 정리가 안되어 있을 때 이해가 어렵게 되고, 이해가 어려워서 이해를 돕기 위한 불필요한 설명이 덧붙여지다보면 더욱 이해하기 어려운 결과를 낳게 된다. 그렇게 되면 결국 설명하는 말만 늘어나고 고객의 이해는 저편에 남게 된다.웹페이지가 뜨는데 1초, 훑어보는데 3초, 원하는 정보를 캐치하는데 5초로 충분해야 한다. 사용자가 원하는 정보를 5초 안에 캐치하지 못할 정보의 양이라면 정보를 나누는 것이 좋다. 2. 제목을 생략하지 말자목적으로 나누어진 정보를 사용자가 빠르게 캐치할 수 있도록 돕는 가장 중요한 요소는 바로 제목이다. 제목은 본문을 다 읽지 않아도 내용을 어느 정도 짐작할 수 있게 한다. 따라서 훒어보는데 3초라는 의미는 한 페이지의 메뉴와 제목을 훑어보는데 필요한 시간이다. 이런 제목의 중요성 때문에 제목은 직관적이어야 하고 되도록 생략하지 말아야 한다. 생략을 할 때는 제목이 없어도 이해가 가능하며, 생략된 제목을 누구나 유추할 수 있을 경우가 아니면 제목의 생략을 피하도록 한다. 위 캡쳐화면은 네이버 메인 콘텐츠의 일부를 캡처한 이미지다. 네이버 메인 중 제목이 생략된 예는 왼쪽 하단 영역인 '주제형 캐스트'뿐이다. 다른 영역들은 '뉴스스탠드', '쇼핑' 등 제목을 생략하지 않고 노출시키고 있다. 메인 페이지처럼 목적이 다양한 페이지일수록 콘텐츠의 성격을 분명히 알 수 있게 하는 제목은 짧은 시간 안에 원하는 정보를 찾는데 도움을 준다.3. 한눈에 중요 정보를 읽을 수 있게 하자그다음으로는 정보의 배치이다. 해당 정보가 발생한 원인, 결과 등 고객이 인지하는 과정에 기반한 그룹으로 나누는 것이 좋다. 정보를 배치할 때는 개별 정보의 중요도 순서와 왼쪽에서 오른쪽, 위에서 아래로 흘러가는 흐름대로 배치고 중간에 역행하는 구성이 없는 것이 좋다. 국내 대형 인터넷 쇼핑몰의 상품 목록을 보면서 위 설명을 이해할 수 있다.정보 배치에 정답이 있는 것은 아니지만 마치 정답이 있는 것처럼 상품, 제목, 할인율, 가격, 현재 판매현황에 이르는 순서대로 나열하고 있다. 이는 선두업체를 따라 흉내 낸 것이 아니라 이와 같은 구성이 인지하기에 용이하기 때문에 모두 이와 같이 구성했다고 생각한다.   4. 어렵지 않게 보이도록 하자서비스에 대한 정보를 전달하고 나서 우리가 기대하는 바는 고객이 서비스를 이해하고 우리 서비스를 이용하게 하는 것이다. 쇼핑몰에서는 주문을 받는 것일 것이고, 어니스트펀드의 경우는 대출이나 투자를 신청하는 경우이다. 서비스를 이용하게 하려면 고객의 정보를 필수적으로 입력을 받아야 한다. 어니스트펀드의 경우는 대출 및 투자에 대한 금융서비스이기 때문에 더욱 많은 정보를 고객에게 요청한다. 고객의 정보를 웹 상에서 입력을 받을 때는 "폼"이라는 일종의 정형화된 웹페이지 구성항목을 이용하게 되는데 이것은 정형화되어있기 때문에 남들과는 다른 개성적인 방식을 이용하기는 어렵다. 금융서비스의 입력 폼이 아주 쉽지는 않다는 것을 고객들은 여러 다른 서비스를 이용하면서 어느 정도 알고 있다. 그러나 고객이 중간에 포기하지 않고 제대로 서비스 이용을 완료할 수 있도록 어렵지 않게 만들어야 하고, 언제나 경쟁사의 서비스를 확인하고 경쟁사보다는 어려워 보이지 않도록 만들어야 한다.5. 순서는 반드시 지키자순서는 여러 가지가 있다. 입력해야 할 항목이 무엇인지를 알려주는 입력항목 및 입력하는 창(=입력 필드), 입력하는데 필요한 도움말, 입력해야 할 항목들을 나열하고 전송/입력완료 버튼까지의 순서가 곧 정보의 순서이다. 이 중 쉽게 놓치는 부분은 첫 입력 필드에서 입력완료 버튼까지의 여정 중에 연관이 없는 링크나 버튼을 추가하는 경우이다. 이 순서는 디자인상으로는 잘 구분되지 않을 수 있지만, 웹코드 상으로는 100% 지켜져야 하는 순서이고 디자인과 웹코드의 순서가 일치하면 가장 좋은 결과이다.'다음'과 '네이버'의 로그인 영역을 비교해보자면 두 포탈 서비스 모두 메인 검색창에서 탭키로 아이디 입력 칸까지 이동할 수 있지만, 아이디 입력 후 비밀번호를 입력하고 로그인 버튼을 누르기까지의 탭키 이동 경로가 다르다. 다음 로그인 화면네이버 로그인 화면다   음 : 아이디 입력 -> 비밀번호 입력 -> 로그인 버튼 -> 로그인 상태 유지 순서로 이동한다.네이버 : 아이디 입력 -> 비밀번호 입력 -> 로그인 상태 유지 -> IP보안 선택여부 -> 로그인이다.탭키로 입력필드를 이동하는 경우가 곧 웹코드상에서의 각 입력 필드의 순서가 되는데, '다음'과 같은 경우는 아이디/비밀번호 입력 후 로그인에 대한 옵션을 키보드로 선택하기 위해서는 로그인 버튼을 지나쳐야 선택할 수 있다. 로그인에 대한 옵션은 로그인 버튼을 선택하기 전에 나오는 것이 더 자연스럽지 않을까? 눈에 보이는 순서도 중요하지만 각 입력필드의 논리적 우선순위를 지키는 것 또한 중요하다.6. 틀린 부분을 즉시 명확하게 알려주자고객이 언제나 우리가 기대한 값을 입력해주지는 않는다. 이 경우 너무너무 명확하게도 오류가 발생한 시점에 오류가 발생한 지점을 알려주는 것이 필요하다. 10개의 입력필드가 있는데 입력완료 버튼을 누르자마자 10개 항목 구구절절이 맞고 틀리고를 알려주는 것보다는, 오류가 발생한 시점에 알려주는 것이 훨씬 인지가 빠르다. 따라서 오류 항목을 보여주어야 하는 곳은 해당 입력필드의 다음이고 전송 버튼이나 후속 작업 이전이 되는 것이다. 위 캡쳐화면은 어니스트펀드에서 대출을 받고자 할 때 이름과 생년월일을 입력하는 부분이다. 필자는 생년월일 부분에 5월 32일이라고 없는 날짜 정보를 넣었고, 이와 같은 입력 실수는 사용자가 실수를 했다는 것을 시스템이 "정확한 정보를 입력해 주세요"라고 즉시 알려주고 있어 사용자가 입력을 실수하지 않도록 돕고 있다. 웹 페이지를 보는 고객들은 아무런 도움 없이 해당 서비스를 이해하고 이용할 수 있어야 한다. 똑같은 정보라고 하더라도 어떤 순서로 어떻게 보여주느냐에 따라서 인지와 인식은 크게 개선될 수 있다. 하물며 정보까지 가공을 하게 되면 더욱 큰 개선을 이끌어 낼 수 있다. 각자가 맡고 있는 서비스에서 5초 안에 고객이 원하는 정보를 웹 페이지 내에서 바로 인지할 수 있는지를 생각해보고 아니다면 테스트해보고 개선해보자.#어니스트펀드 #개발자 #개발팀 #UX개발 #철학 #인사이트
조회수 4840

신입 개발자를 위한 코드의 정석

Overview대학을 수석으로 졸업했지만, 정작 회사에서는 A부터 Z까지 제대로 할 줄 아는 게 없었습니다. 실수를 남발할 때마다 느꼈던 좌절감은 아직도 생생하지만 되돌아보면 그때의 삽질이 소중한 피와 살이 되었지요. 오늘은 헤매고 있는 신입 개발자를 위한 글을 쓰려고 합니다. 신입 개발자, 당신! 내 이야기를 편하게 듣고 가지 않으실래요? 남을 위한 코드, 클-린 코드“너랑 같이 일하는 사람은 어떻게 보라는 거야?” “한 명이 짠 코드인데, 어째 한 사람이 짠 것 같지가 않다..” “이게 네 스타일이냐?” 대학생이었을 땐, 대부분 혼자서 프로젝트를 진행했습니다. 다른 사람이 제 코드를 보는 일도 거의 없어서 띄어쓰기나 들여쓰기 등에 통일이 없었고, 함수의 네이밍도 전혀 고려하지 않았습니다. 이게 나쁜 습관이었다는 걸 입사하고 알게 되었죠. 이 습관을 고치려고 코딩 컨벤션(coding convention)을 지키는 것에 꽤 오랜 시간을 들여야만 했습니다. 우리는 협업을 하는 사람들입니다. 사람들이 더러운 방보다 깨끗한 방을 좋아하는 것처럼, 당신과 협업하는 개발자도 보기 어려운 코드보다 깨끗한 코드를 더 좋아합니다. 클린 코드를 작성하기 위한 세 가지 기본 원칙을 잠시 소개합니다. 클린 코드를 위한 세 가지 기본 원칙 코드를 최초로 작성한 사람이 끝까지 유지보수를 한다는 보장은 없다.이미 잘 정리된 코드는 효율성이 증가한다. 정리할 시간에 코드 한 줄을 더 분석할 수 있으니까!리팩토링은 미루었다가 한꺼번에 하는 것이 아니다. 코드를 작성하는 매순간 함께 하는 활동이다.작은 것 하나부터 습관을 들여보세요. 분명 깔끔하고 보기 좋은 코드를 만드실 수 있을 겁니다. 머지 않아 “남을 위한 코드는 곧 나를 위한 코드”라는 것도 알게 될 거고요. 책의 한 구절이 떠오르네요. “우리는 저자이다. 저자에게는 독자가 있다. 그리고 저자에게는 독자와 잘 소통해야할 책임이 있다.”⌈Clean Code⌋의 저자, Robert C. Martin 설마가 사람 잡는다, 철저한 검증만약 누군가 검증 단계에서 잊지 말아야할 것이 뭔지 묻는다면 이렇게 대답하고 싶습니다. “절대 사용자가 입력한 값을 신뢰하지 말라. 프론트엔드에서도, 백엔드에서도.” 모든 사용자가 각 항목에 맞게 올바른 정보만 입력해준다면 얼마나 좋을까요? 세상에는 다양한 사용자가 있습니다. 너무 바빠서 얼른 회원가입을 해야하는 사용자는 항목을 채우지도 않고 신청 버튼을 누를 수도 있습니다. 영어로 입력해야 하는 항목엔 한글을 입력한 사용자도 있을 겁니다. 이런 휴먼 에러(human error)뿐만 아니라 의도적으로 비정상적인 요청을 시도하는 사용자도 분명 있습니다. 이 때문에 개발자는 기능에 대해 항상 검증해야 합니다. 바로 이렇게요!그런데 프론트엔드에서 유효성 검사를 하면, 백엔드에는 유효한 값만 넘어온다고 보장할 수 없습니다. 자바스크립트는 브라우저 엔진에 따라 다르게 동작할 수도 있습니다. 또 자바스크립트에서 다루는 값들은 크롬의 개발자도구(option + command + i)를 이용하면 얼마든지 값을 변조하거나 검증을 회피할 수 있습니다. 또 불온한 시도가 아니더라도 다양한 예외 케이스들이 존재하기 때문에 백엔드에서도 무조건 검증해야 합니다.페이스북 페이지의 개발자 도구를 열었을 때 노출되는 화면입니다. 얼마나 나쁜 사람들이 많으면 경고화면까지 만들었을까요?누군가 질문할 수도 있겠군요. “프론트엔드의 검증이 의미가 없다면, 백엔드에서만 검증을 해도 되지 않을까요?” 네, 아닙니다.(단호) 많은 양의 일을 한꺼번에 하는게 힘든 것처럼 무분별한 요청이 서버에 쏟아지면 서버도 사람처럼 지치고 말 겁니다. 응답이 느려지는 등의 문제가 생길 수도 있고, 결국 사용자가 불편해질 것입니다. 그러므로 가장 좋은 검증 방식을 3단계로 정리하면 아래와 같습니다. 고수가 되는 검증 방식 3단계프론트엔드에서 먼저 값 검증을 하여 빠른 사용자 경험을 제공한다.백엔드에서 다시 한 번 더 검증을 거쳐 상황에 적절한 응답 코드를 내려준다.프론트엔드는 상황에 맞게 적절한 UX와 메시지를 보낸다. 동작 그만! 정리는 하고 코딩하자!예전에는 요구사항이 있으면 바로 키보드 위에 손부터 올렸습니다만, 그건 좋은 태도가 아니었습니다. 팀장님이 “이 경우엔 어떻게 하지?”라고 질문하면 아무 대답도 하지 못했기 때문이죠. 팀장님은 늘 “항상 먼저 생각하고 코딩하자!“라고 조언하십니다. 맞습니다. 최대한 모든 경우의 수를 머릿속에 정리하고 코딩을 시작해야 합니다. 시간이 없다는 핑계로 무작정 시작하면 분명 문제가 발생합니다. 또 구현할 기능만 몰두하지 말고, ‘이 기능이 다른 기능에 영향을 미칠 수 있을까?’를 고민하면 훨씬 좋은 코드를 만들 수 있을 겁니다. “이런 거 다 생각하고 짜면 도대체 코딩은 언제 하라고?” “얼른 선임 분들에게 코딩하는 내 모습을 보여줘야 하는데!” “당장 코드 안 짜고 있으면 노는 것처럼 보이지 않을까?” 혹시 이런 생각을 하고 계신가요? 나도 그런 생각을 했던 적이 있습니다. 하지만 요구사항을 확실하게 정리한 후, 코드를 짜는 게 더 효율적입니다. (그렇지 않으면.. ‘수정’이란 이름 아래 모든 것을 뒤엎고 처음부터 다시 시작해야할 수도 있습니다.) ‘더 나은 개발자가 되는 8가지 방법(8 Ways to Become a Better Coder)’이란 글에는 이런 내용이 있습니다. “동작하는 코드는 끝이 아니라 시작이다.” 신입 개발자는 종종 요구사항에 따라 동작하는 코드만 짜면 된다고 여길 때가 있습니다. 물론 사회생활에 적응하느라 정신 없는 와중에 그나마 자신의 코드가 요구사항대로 동작하면 무척 뿌듯할 겁니다. 하지만 동작만 한다고 절대 지나치지 말아주세요. 위에서 언급한 것처럼 깨끗한 코드가 되도록 리팩토링을 하고, 검증하고, 동작이 제대로 되는 것인지 의심하면서 꾸준히 노력해야 합니다. 마지막으로 항상 중요하게 생각하는 문장 하나를 남기고 글을 마치겠습니다.“진정으로 훌륭한 프로그래머는 적극적으로 어디가 잘못되었지를 찾는다. 자기가 놓친 결함은 결국 ‘사용자’가 발견하게 된다는 것을 알고 있기 때문이다.” Esther SchindlerConclusion지금까지 다룬 내용은 결국 같은 맥락입니다. 모든 개발조직은 좋은 품질의 소프트웨어를 개발할 줄 아는 개발자, 협업할 줄 아는 개발자를 원합니다. 누군가 “당신은 잘 지키고 있는가”라고 질문한다면, “저 또한 노력하고 있습니다.”라고 답변하고 싶습니다. 같은 자리에 머무르는 개발자가 될 것인지, 부족함을 알고 항상 배우고 나아가는 개발자가 될 것인지는 스스로의 몫이라고 생각합니다. 이 글을 끝까지 읽은 신입 개발자 당신! 같이 노력하지 않으실래요? :-) 참고 Robert C. Martin, 「Clean Code」, 케이엔피북스(2010)Esther Schindler, 8 Ways to Become a Better Corder, New Relic, 2018.03.02.유석문, 「프로그래머 철학을 만나다 - 소프트웨어를 사랑하는 기술」, 로드북(2014)임백준, 「읽기 좋은 코드가 좋은 코드다」, 한빛미디어(2012)팀장들이 꼽은 신입 PHP 개발자가 가급적 빨리 알았으면 하는 것들프론트에서”만” 유효성 검사가 문제인 경우남을 위한 코드 만들기 - 클린코드글김우경 대리 | R&D 개발1팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발문화 #개발팀 #업무환경 #인사이트 #경험공유

기업문화 엿볼 때, 더팀스

로그인

/