스토리 홈

인터뷰

피드

뉴스

조회수 1346

EOS Smart Contract 배포

Smart Contract 배포를 위한 준비 과정은 이전글 확인 부탁드립니다.저번시간과 연계하여 이번 시간엔 스마트 컨트랙트를 배포해 보도록 하겠습니다. 지갑 key와 계정 이름등은 본 포스팅에서 그대로 사용하시면 됩니다.배포할 컨트랙트는 eosio.token 으로 eos 개발환경 세팅 시 존재하는 코드를 컴파일하여 실제 사용하는 계정에 setting 하겠습니다. 먼저 컴파일을 위해 ../eos/contracts/eosio.token 으로 이동 하겠습니다.eos/contracts/eosio.token이동 하면 위와 같은 파일들을 확인 하실 수 있습니다.hpp : cpp 파일에서 사용하는 변수, 상수, 함수를 담는 헤더파일cpp : contract 함수를 구현하는 소스 파일eosiocpp 를 통해 소스코드를 컴파일 해보겠습니다. eosiocpp 는 WASM 및 ABI 컴파일러 로써 블록체인에 업로드 되는 .wasm, .wast, .abi 파일을 생성합니다. 또한 기본 스켈레톤 파일을 제공합니다eosiocppwasm 컴파일wasm 파일은 아래 명령어를 사용하여 컴파일 만들 수 있습니다.$ eosiocpp -o eosio.token.wast eosio.token.cppeosiocpp 명령어를 사용하여 컴파일 하게 되면 .wast 파일과 .wasm 파일을 생성하게 됩니다. 각 확장자는 다음을 의미합니다.wast : 텍스트 파일로써 읽을 수 있는 webAssembly 파일wasm : 컴퓨터가 실제로 이해할 수 있는 webAssembly 파일abi 파일 생성$ eosiocpp -g eosio.token.abi eosio.token.cppabi 파일은 JSON과 Binary 간에 사용자 작업을 변환하는 방법에 대해 설명해주는 파일입니다. 실제로 이 JSON 파일을 통해 블록체인 위에서 개발자와 사용자간 상호작용 하는데 도와주게 됩니다.위 2과정을 통해 abi 파일 과 wast 파일을 생성하게 됩니다.compile 결과Contract 세팅하기아래 명령어를 입력하여 contract 를 set 해줍니다.$ cleos set contract hexlanthenry ../eos/build/contracts/eosio.token account : contract 를 배포할 계정이름contract-dir : 계정에 set 할 contract 가 저장된 directoryset contract 수행 결과만약 해당 계정이 RAM 을 보유하고 있지 않다면 다음과 같은 에러가 나타날 것입니다. 이를 해결하기 위해 RAM 을 구매합니다.RAM을 보유없이 contract$ cleos system buyram hexlanthenry hexlanthenry "100.0000 EOS"payer : EOS 를 지불할 계정receiver : RAM 을 사용할 계정amount : 지불할 EOS의 양 ( eos 1.1 기준 소수점4개 자리와 symbol을 무조건 넣어주어야 정상 동작 합니다)contract 확인계정에 contract가 잘 배포 되었는지 확인해 보겠습니다.$ cleos get code hexlanthenry배포한 contract 가 있을때의 code hash배포한 contract 가 없을때의 code hash또한 abi 를 통해서도 확인할 수 있습니다.$ cleos get abi hexlanthenryget abi위 과정을 통해 해당 계정에 실제로 contract 가 잘 배포 되었는지 확인 할 수 있습니다.다음 시간에는 배포된 contract 를 통하여 토큰을 발행 해보고 token에 대한 balance 체크 및 transfer 하는 과정을 진행해 보도록 하겠습니다.+또한 abi를 분석하여 struct 와 action 을 어떻게 확인 하는지에 대한 자세한 방법은 다른 포스팅에서 다루도록 하겠습니다.감사합니다.#헥슬란트 #HEXLANT #블록체인 #개발자 #개발팀 #기술기업 #기술중심
조회수 3069

Apache Spark에서 컬럼 기반 저장 포맷 Parquet(파케이) 제대로 활용하기 - VCNC Engineering Blog

VCNC에서는 데이터 분석을 위해 다양한 로그를 수집, 처리하는데 대부분은 JSON 형식의 로그 파일을 그대로 압축하여 저장해두고 Apache Spark으로 처리하고 있었습니다. 이렇게 Raw data를 바로 처리하는 방식은 ETL을 통해 데이터를 전처리하여 두는 방식과 비교하면 데이터 관리비용에서 큰 장점이 있지만, 매번 불필요하게 많은 양의 데이터를 읽어들여 처리해야 하는 아쉬움도 있었습니다.이러한 아쉬움을 해결하기 위해 여러 논의 중 데이터 저장 포맷을 Parquet로 바꿔보면 여러가지 장점이 있겠다는 의견이 나왔고, 마침 Spark에서 Parquet를 잘 지원하기 때문에 저장 포맷 변경 작업을 하게 되었습니다. 결론부터 말하자면 74%의 저장 용량 이득, 10~30배의 처리 성능 이득을 얻었고 성공적인 작업이라고 평가하지만 그 과정은 간단하지만은 않았습니다. 그 과정과 이를 통해 깨달은 점을 이 글을 통해 공유해 봅니다.Parquet(파케이)에 대해Parquet(파케이)는 나무조각을 붙여넣은 마룻바닥이라는 뜻을 가지고 있습니다. 데이터를 나무조각처럼 차곡차곡 정리해서 저장한다는 의도로 지은 이름이 아닐까 생각합니다.Parquet을 구글에서 검색하면 이와 같은 마룻바닥 사진들이 많이 나옵니다.빅데이터 처리는 보통 많은 시간과 비용이 들어가므로 압축률을 높이거나, 데이터를 효율적으로 정리해서 처리하는 데이터의 크기를 1/2 혹은 1/3로 줄일 수 있다면 이는 매우 큰 이득입니다. 데이터를 이렇게 극적으로 줄일 수 있는 아이디어 중 하나가 컬럼 기반 포맷입니다. 컬럼 기반 포맷은 같은 종류의 데이터가 모여있으므로 압축률이 더 높고, 일부 컬럼만 읽어 들일 수 있어 처리량을 줄일 수 있습니다.https://www.slideshare.net/larsgeorge/parquet-data-io-philadelphia-2013Parquet(파케이)는 하둡 생태계의 어느 프로젝트에서나 사용할 수 있는 효율적인 컬럼 기반 스토리지를 표방하고 있습니다. Twitter의 “Julien Le Dem” 와 Impala 프로젝트 Lead였던 Cloudera의 “Nong Li”가 힘을 합쳐 개발한 프로젝트로 현재는 많은 프로젝트에서 Parquet를 지원하고 컬럼 기반 포맷의 업계 표준에 가깝습니다.Parquet를 적용해보니 Apache Spark에서는, 그리고 수많은 하둡 생태계의 프로젝트들에서는 Parquet를 잘 지원합니다.val data = spark.read.parquet("PATH") data.write.parquet("PATH") Spark에서는 이런 식으로 손쉽게 parquet 파일을 읽고, 쓸 수가 있습니다. 데이터를 분석하기 전에 원본이라고 할 수 있는 gzipped text json을 읽어서 Parquet 로 저장해두고 (gzipped json은 S3에서 glacier로 이동시켜버리고), 이후에는 Parquet에서 데이터를 읽어서 처리하는 것 만으로도 저장용량과 I/O 면에서 어느 정도의 이득을 얻을 수 있었습니다. 하지만 테스트 결과 저장용량에서의 이득이 gz 23 GB 에서 Parquet 18GB 로 1/3 정도의 저장용량을 기대했던 만큼의 개선이 이루어지지는 않았습니다.Parquet Deep Dive상황을 파악하기 위해 조금 더 조사를 해보기로 하였습니다. Parquet의 포맷 스팩은 Parquet 프로젝트에서 관리되고 있고, 이의 구체적인 구현체로 parquet-mr 이나 parquet-cpp 프로젝트 등에서 스펙을 구현하고 있습니다. 그리고 특별한 경우에는 Spark에서는 Spark 내부에 구현된 VectorizedParquetRecordReader 에서 Parquet 파일을 처리하기도 합니다.파일 포맷이 바뀌거나 기능이 추가되는 경우에는 쿼리엔진에서도 이를 잘 적용해주어야 합니다. 하지만 안타깝게도 Spark은 parquet-mr 1.10 버전이 나온 시점에도 1.8 버전의 오래된 버전의 parquet-mr 코드를 사용하고 있습니다. (아마 다음 릴리즈(2.4.0)에는 1.10 버전이 적용될 것으로 보이지만)Parquet 의 메인 개발자 중에는 Impala 프로젝트의 lead도 있기 때문에, Impala에는 비교적 빠르게 변경사항이 반영되는 것에 비하면 대조적입니다. 모든 프로젝트들이 실시간적으로 유기적으로 업데이트되는 것은 힘든 일이기 때문에 어느 정도는 받아들여야겠지만, 우리가 원하는 Parquet의 장점을 취하기 위해서는 여러 가지 옵션을 조정하거나 직접 수정을 해야 합니다.VCNC 데이터팀에서는 저장 용량과 I/O 성능을 최적화하기 위하여 Parquet의Dictionary encoding (String들을 압축할 때 dictionary를 만들어서 압축하는 방식, 길고 반복되는 String이 많다면 좋은 압축률을 기대할 수 있습니다)Column pruning (필요한 컬럼만을 읽어 들이는 기법)Predicate pushdown, row group skipping (predicate, 즉 필터를 데이터를 읽어 들인 후 적용하는 것이 아니라 저장소 레벨에서 적용하는 기법)과 같은 기능들을 사용하기를 원했고, 이를 위해 여러 조사를 진행하였습니다.저장용량 줄이기102GB의 JSON 포맷 로그를 text그대로 gzip으로 압축하면 23GB가 됩니다. dictionary encoding이 잘 적용되도록 적절한 옵션 설정을 통해 Parquet로 저장하면 6GB로, 기존 압축방식보다 저장 용량을 74%나 줄일 수 있었습니다.val ndjsonDF = spark.read.schema(_schema).json("s3a://ndjson-bucket/2018/04/05") ndjsonDF. sort("userId", "objectType", "action"). coalesce(20). write. options(Map( ("compression", "gzip"), ("parquet.enable.dictionary", "true"), ("parquet.block.size", s"${32 * 1024 * 1024}"), ("parquet.page.size", s"${2 * 1024 * 1024}"), ("parquet.dictionary.page.size", s"${8 * 1024 * 1024}"), )). parquet("s3a://parquet-bucket/2018/04/05") 비트윈의 로그 데이터는 ID가 노출되지 않도록 익명화하면서 8ptza2HqTs6ZSpvmcR7Jww 와 같이 길어지기에 이러한 항목들이 dictionary encoding을 통해 효과적으로 압축되리라 기대할 수 있었고, Parquet에서는 dictionary encoding이 기본이기에 압축률 개선에 상당히 기대하고 있었습니다.하지만 parquet-mr 의 구현에서는 dictionary의 크기가 어느 정도 커지면 그 순간부터 dictionary encoding을 쓰지 않고 plain encoding으로 fallback하게 되어 있었습니다. 비트윈에서 나온 로그들은 수많은 동시접속 사용자들의 ID 갯수가 많기 때문에 dictionary의 크기가 상당히 커지는 상태였고, 결국 dictionary encoding을 사용하지 못해 압축 효율이 좋지 못한 상태였습니다.이를 해결하기 위해, parquet.block.size를 default 값인 128MB에서 32MB로 줄이고 parquet.dictionary.page.size를 default 값 1MB에서 8MB 로 늘려서 ID가 dictionary encoding으로만 잘 저장될 수 있도록 만들었습니다.처리속도 올리기저장용량이 줄어든 것으로도 네트워크 I/O가 줄어들기 때문에 처리 속도가 상당히 올라갑니다. 하지만 컬럼 기반 저장소의 장점을 온전하게 활용하기 위해서 column pruning, predicate pushdown들이 제대로 작동하는지 점검하고 싶었습니다.소스코드를 확인하고 몇 가지 테스트를 해 본 결과, Spark에서는 Parquet의 top level field에서의 column pruning은 지원하지만 nested field들에 대해서는 column pruning을 지원하지 않았습니다. 비트윈 로그에서는 nested field들을 많이 사용하고 있었기에 약간 아쉬웠으나 top level field에서의 column pruning 만으로도 어느 정도 만족스러웠고 로그의 구조도 그대로 사용할 예정입니다.Predicate pushdown도 실행시간에 크게 영향을 줄 거라 예상했습니다. 그런데 Spark 2.2.1기준으로 column pruning의 경우와 비슷하게, top level field에 대해서만 predicate pushdown이 작동하는 것을 확인할 수 있었습니다. 이는 성능에 큰 영향을 미치기에, predicate 로 자주 사용하는 column들을 top level 로 끌어올려 저장하는 작업을 하게 되었습니다. 여기에 추가로 parquet.string.min-max-statistics 옵션을 손보고 나서야 드디어 10~30배 정도의 성능 향상을 볼 수 있었습니다.매일 15분 정도 걸리던 "의심스러운 로그인 사용자" 탐지 쿼리가 30여초만에 끝나고, cs처리를 위해 한 사람의 로그만 볼 때 5분 정도 걸리던 쿼리가 30여초만에 처리되게 되었습니다.못다 한 이야기parquet.string.min-max-statistics 옵션과 row group skipping에 관해.Parquet 같은 포맷 입장에서 string 혹은 binary 필드의 순서를 판단하기는 어렵습니다. 예를 들어 글자 á 와 e 가 있을 때 어느 쪽이 더 작다고 할까요? 사전 편찬자라면 á가 더 작다고 볼 것이고, byte 표현을 보면 á는 162이고 e는 101이라 e가 더 작습니다. Parquet 같은 저장 포맷 입장에서는 binary 필드가 있다는 사실만 알고 있고, 그 필드에 무엇이 저장될지, 예를 들어 á와 e가 저장되는지, 이미지의 blob가 저장되는지는 알 수 없습니다. 그러니 순서를 어떻게 정해야 할지는 더더구나 알 수 없습니다.그래서 Parquet 내부적으로 컬럼의 min-max 값을 저장해 둘 때, 1.x 버전에서는 임의로 byte sequence를 UNSINGED 숫자로 해석해 그 컬럼의 min-max 값을 정해 저장했습니다. 이후에 이를 개선하기 위해 Ryan Blue가 PARQUET-686에서 parquet-format에 SORT_ORDER를 저장할 수 있도록 했습니다.여기에서 문제는 이전 버전과의 호환성입니다. SORT_ORDER가 없던 시절의 Parquet 파일을 읽으려 할 때, min-max 값을 사용해 row group skipping이 일어나면 query 엔진에서 올바르지 않은 결과가 나올 수 있으니, binary 필드의 min-max 값을 parquet-mr 에서 아예 반환하지 않게 되어있습니다.하지만 이는 우리가 원하는 동작이 아닙니다. 여기에 parquet.string.min-max-statistics option을 true로 설정하면, 이전처럼 binary필드의 min-max값을 리턴하게 되고 rowgroup skipping이 작동하여 쿼리 성능을 크게 올릴 수 있습니다.마치며Spark과 Parquet 모두 많은 사람이 사랑하는 훌륭한 오픈소스 프로젝트입니다. 또한 별다른 설정이나 튜닝 없이 기본 설정만으로도 잘 돌아가는 편이기 때문에 더더욱 많은 사람이 애용하는 프로젝트이기도 합니다.하지만 오픈소스는 완전하지 않습니다. 좋은 엔지니어링 팀이라면 단지 남들이 많이 쓰는 오픈소스 프로젝트들을 조합해서 사용하는 것에서 그치지 않고 핵심 원리와 내부 구조를 연구해가며 올바르게 활용해야 한다고 생각합니다. 기술의 올바른 활용을 위해 비트윈 데이터팀은 오늘도 노력하고 있습니다.
조회수 726

HBase Meetup - 비트윈에서 HBase를 사용하는 방법 - VCNC Engineering Blog

비트윈에서는 서비스 초기부터 HBase를 주요 데이터베이스로 사용하였으며 사용자 로그를 분석하는 데에도 HBase를 사용하고 있습니다. 지난 주 금요일(11월 15일)에 HBase를 만든 Michael Stack 씨가 한국을 방문하게 되어 ZDNet 송경석 팀장님의 주최 하에 HBase Meetup Seoul 모임을 가졌습니다. 그 자리에서 VCNC에서 비트윈을 운영하면서 HBase를 사용했던 경험들이나 HBase 트랜잭션 라이브러리인 Haeinsa에 대해 간단히 소개해 드리는 발표 기회를 가질 수 있었습니다. 이 글에서 발표한 내용에 대해 간단히 소개하고자 합니다.비트윈 서비스에 HBase를 사용하는 이유비트윈에서 가장 많이 사용되는 기능 중 하나가 채팅이며, 채팅은 상대적으로 복잡한 데이터 구조나 연산이 필요하지 않기 때문에 HBase 의 단순한 schema 구조가 큰 문제가 되지 않습니다. 특히 쓰기 연산이 다른 기능보다 많이 일어나기 때문에 높은 쓰기 연산 성능이 필요합니다. 그래서 메세징이 중심이 되는 서비스는 높은 확장성(Scalability)과 쓰기 성능을 가진 HBase가 유리하며 비슷한 이유로 라인이나 페이스북 메신저에서도 HBase를 사용하는 것이라고 짐작할 수 있습니다.로그 분석에도 HBase를 사용합니다비트윈은 사용자 로그 분석을 통해서 좀 더 나은 비트윈이 되기 위해서 노력하고 있습니다. 비트윈 사용자가 남기는 로그의 양이 하루에 3억건이 넘기 때문에 RDBMS에 저장하여 쿼리로 분석하기는 힘듭니다. 그래서 로그 분석을 위해 분산 데이터 처리 프레임워크인 Hadoop MapReduce를 이용하며 로그들은 MapReduce와 호환성이 좋은 HBase에 저장하고 있습니다. 또한 이렇게 MapReduce 작업들을 통해 정제된 분석 결과를 MySQL에 저장한 후에 다양한 쿼리와 시각화 도구들로 custom dashboard를 만들어 운영하고 있습니다. 이를 바탕으로 저희 Biz development팀(사업개발팀)이나 Data-driven팀(데이터 분석팀)이 손쉽게 insight를 얻어낼 수 있도록 돕고 있습니다.HBase를 사용하면서 삽질 했던 경험HBase를 사용하면서 처음에는 잘못 사용하고 있었던 점이 많았고 차근차근 고쳐나갔습니다. Region Split과 Major Compaction을 수동으로 직접 하는 등 다양한 최적화를 통해 처음보다 훨씬 잘 쓰고 있습니다. HBase 설정 최적화에 대한 이야기는 이전에 올렸던 블로그 글에서도 간단히 소개한 적이 있으니 확인해보시기 바랍니다.HBase 트랜잭션 라이브러리 해인사Haeinsa는 HBase에서 Multi-Row 트랜잭션을 제공하기 위한 라이브러리입니다. 오픈소스로 공개되어 있으며 Deview에서도 발표를 했었습니다. HBase에 아무런 변형도 가하지 않았기 때문에 기존에 사용하던 HBase 클러스터에 쉽게 적용할 수 있습니다. 비트윈에 실제로 적용되어 하루 3억 건 이상의 트랜잭션을 처리하고 있으며 다른 많은 NoSQL 기반 트랜잭션 라이브러리보다 높은 확장성과 좋은 성능을 가지고 있습니다.발표에서 사용했던 슬라이드를 첨부하였으니 도움이 되었으면 합니다.<iframe class="speakerdeck-iframe" frameborder="0" src="//speakerdeck.com/player/2b8092b02ff90131ef414aa7d272d735?" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" style="border: 0px; background: padding-box rgba(0, 0, 0, 0.1); margin: 0px; padding: 0px; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.2) 0px 5px 40px; width: 750px; height: 563px;">
조회수 2779

Python 기반의 웹서비스 개발 환경 구축 방법

안녕하세요. 스포카 크리에이터팀의 프로그래밍 인턴을 맡고 있는 __박종규, 정성재, 고아라__입니다. 저희 세 명은 각각 다른 OS 환경에서 웹서비스를 개발하였는데 이번 포스팅에서는 OS별로 개발 환경을 구축하는 과정을 설명하겠습니다.PythonPython(파이썬)은 비영리의 Python 소프트웨어 재단이 관리하는 개방형, 공동체 기반 개발 모델을 가지고 있습니다. Python은 C파이썬 구현이 사실상의 표준이며 동적 타이핑 범용 프로그래밍 언어로, 펄 및 루비와 자주 비교됩니다. Python은 순수한 프로그래밍 언어의 기능 외에도 다른 언어로 쓰인 모듈들을 연결하는 Glue language로써 자주 이용됩니다. 실제 Python은 많은 상용 응용 프로그램에서 스크립트 언어로 채용되고 있습니다. 또한, 유니코드 문자열을 지원하여 다양한 언어의 문자 처리에도 능합니다. 현대의 Python은 여전히 인터프리터 언어처럼 동작하나 사용자가 모르는 사이에 스스로 Python 소스 코드를 컴파일하여 바이트 코드를 만들어 냄으로써 다음에 수행할 때에는 빠른 속도를 보여줍니다.Windows에서 Python 2.x 설치 방법Linux와 Mac OS에서 Python은 기본적으로 설치되어 있기 때문에 터미널 창에서 Python 명령만으로 쉽게 실행할 수 있지만 Windows에서는 Python을 따로 설치해주어야 합니다.Python 공식 사이트해당 사이트에 들어가서 Quick Links (2.7.3) – Windows Installer 선택하여 python-2.7.3.msi 다운로드 후 실행하여 설치합니다. 특별히 원하는 버전이 있을 때에는 DOWNLOAD – Releases에서 버전별로 설치파일을 다운로드 할 수 있습니다. Python의 기본 설치 경로는 C:\Python27 이며 설치 완료 후, 환경변수를 등록해야 합니다. 환경변수를 등록하는 방법은 다음과 같습니다.내컴퓨터(마우스 오른쪽 버튼 클릭) – 속성(시스템 등록 정보) – 고급 – 환경 변수 클릭시스템 변수 – Path 선택 후 편집 클릭변수 값에 맨 뒤에 C:\Python27;C:\Python27\Scripts; 입력 후, 확인 버튼을 눌러 시스템에 적용변수 값은 각각 ; (세미콜론) 으로 구분Python의 패키지 설치 방법시작 메뉴 – 실행 – CMD 로 커맨드 창을 실행 시킨 후에 Python이 설치된 디렉터리로 이동합니다.cd C:\Python27\Scripts 그 다음 easy_install pip 명령으로 pip를 설치해줍니다. pip는 PyPI(Python Package Index)에 등록된 패키지들을 설치하고 관리할 수 있는 패키지 관리 시스템입니다.$ easy_install pip 다음은 pip 명령의 사용법입니다.pip install packageName 명령 : 최신버전으로 설치pip install packageName==0.x.x 명령 : 0.x.x버전으로 설치패키지 설치 경로 : C:\Python27\Lib\site-packagespip uninstall packageName 명령 : package 제거pip freeze 명령 : 현재 환경에 설치된 package 이름과 버전 목록 PostgreSQLPostgreSQL는 California 대학 Berkeley computer science 학부에서 개발한 POSTGRES, Version 4.2 를 기반으로 한 오브젝트 RDB 관리 시스템(ORDBMS)입니다. 또한, PostgreSQL은 BSD 허가권으로 배포되며 오픈소스 개발자 및 관련 회사들이 개발에 참여하고 있습니다. 따라서 누구라도 사용, 수정, 배포할 수 있으며 목적과 관계없이 무료로 이용할 수 있습니다.각 운영체제 별 PostgreSQL 설치 방법WindowsWindows에서 PostgreSQL을 설치하기 위해 해당 사이트로 접속합니다.PostgreSQL 공식 사이트해당 사이트의 Download탭을 선택하여 Downloads 페이지로 이동합니다. 그 다음 Binary packages 에서 Windows를 선택하여 Windows installers 페이지로 이동합니다. One click installer 에서 Download 선택 후 이 페이지 로 이동하여 해당하는 OS 버전으로 선택하여 다운로드 후 설치합니다.Linux (ubuntu 12.04 LTS)Linux(리눅스)에서 PostgreSQL은 여러 가지 방법으로 설치 할 수 있습니다. 패키지로 설치하는 방법은 터미널 창에서 아래와 같은 명령어를 입력하시면 됩니다.$ sudo apt-get install postgresql-X.X(버전명) 다른방법으로 설치하는 방법은 아래 주소로 들어가시면 자세히 나와 있습니다.PostgreSQL 공식 사이트추가로 PostgreSQL을 편하게 이용하고 싶은 사용자는 pgadmin3이라는 PostgreSQL의 GUI 프로그램을 설치하시면 됩니다. 설치 방법은 터미널 창에서 아래와 같은 명령어를 입력하시면 됩니다.$ sudo apt-get install pgadmin3 Max OS ( MAC OS X Mountain Lion 10.8.2)Mac OS에서 PostgreSQL은 Homebrew를 이용하여 설치하도록 하겠습니다. Homebrew는 Mac OS의 패키지 관리자 프로그램입니다. PostgreSQL은 Homebrew 이외에도 PostgreSQL 다운로드 사이트, Homebrew와 비슷한 기능을 하는 MacPorts 등을 이용해서도 다운받을 수 있습니다. 하지만 PostgreSQL 이외의 다른 프로그램을 설치하기에도 패키지 관리자가 유용하기 때문에 저는 Homebrew를 이용하도록 하겠습니다. 일단, Homebrew 패키지를 컴파일 하기 위해서 xCode가 설치되어 있어야 합니다. 앱스토어에서 xCode를 검색하여 받도록 합니다.xCode 설치를 완료했으면 메뉴에서 __xCode탭 - Preferences - Downloads - Command Line Tools__를 다운받습니다. 그럼 이제 Homebrew 패키지를 컴파일할 수 있게 되었습니다.이제 터미널을 실행시키고 다음 명령을 입력하면 Homebrew가 설치됩니다.$ ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)" Homebrew가 이미 설치되어있다면 업데이트할 사항이 없는지 확인해보고 업데이트를 시켜주세요.$ brew update이제 Homebrew 설치를 완료했으니 간단하게 PostgreSQL을 설치할 수 있습니다.$ brew install postgresql 설치된 버전을 $ psql –ver 명령으로 확인해 보니 PostgreSQL 9.1.4 버전이 설치되어 있었습니다.psycopg2psycopg2는 Python library의 한 종류로써 하는 역할은 Python에서 PostgreSQL를 활용하게 해주는 library입니다. 설치 방법은 터미널 창에서 아래와 같은 명령어를 입력하시면 됩니다.$ pip install psycopg2 * 참고 ubuntu/debian 사용하시는 분 중에서 설치가 안 되시는 분들은 psycopg2를 설치하시기전에 python-dev라는 패키지 파일을 설치하시면 psycopg2를 설치 하실 수 있습니다. 설치 방법은 터미널 창에서 아래와 같은 명령어를 입력하시면 됩니다.$ sudo apt-get install python-dev FlaskFlask는 Python용 Micro Framework이며, Jinja2 template engine과 Werkzerg WSGI toolkit에 의존합니다. Flask에는 기본적으로 많은 환경설정 값들이 존재합니다. 규칙에 따라 템플릿 파일과 CSS, JavaScript, Images 등의 파일들은 templates과 static 이라는 하위 디렉터리에 각각 보관해야 합니다. 기본적으로 Flask는 다른 라이브러리에는 존재하는 Database abstraction layer, Form validation 등의 기능을 포함하지 않지만, 기능을 추가할 수 있는 확장성을 제공합니다. 이미 수많은 라이브러리들이 Database integration, Form validation, Upload handling, Various open authentication technologies등을 제공합니다. SQLAlchemy나 다른 DB Tool을 이용하여 고급 패턴을 구현할 수 있으며, Flask를 이용해보면 다양한 기능을 확장할 수 있다는 것을 알 수 있을 것입니다.Flask 설치 방법Flask를 설치하려면 터미널 창에서 다음 명령어를 입력하면 됩니다. (windows의 경우 cmd창) $ sudo pip install flask SQLAlchemySQLAlchemy는 Oracle, DB2, MySQL, PostgreSQL, SQLite와 같은 관계형 데이터베이스에 강력하고 유연한 인터페이스를 제공하는 Python SQL Toolkit이자 Object Relation Mapper(ORM)입니다. 여기서 ORM은 객체를 관계형 DB 테이블에 매핑해주는 역할을 하는데 SQLAlchemy는 객체를 매핑하기 위해 특정 클래스를 상속받지 않아도 되기 때문에 높은 수준의 라이브러리라고 할 수 있습니다.앞선 단계까지의 설치가 완료되었다면 SQLAlchemy의 설치법 역시 pip 명령을 쓰면 되므로 간단합니다. 윈도우는 커맨드창을 실행시키고, 리눅스와 MAC OS의 경우 터미널을 실행시켜 다음 명령을 입력합니다. 저는 SQLAlchemy 0.7.2 버전을 설치했습니다.$ pip install SQLAlcheymy==0.7.2Permission denied라는 문구가 뜨면 권한이 없는 것이므로 관리자 계정으로 설치를 해주어야 합니다. 관리자 계정은 $ sudo su로 로그인하거나 명령 앞에 sudo를 붙이면 됩니다.$ sudo pip install SQLAlchemy==0.7.2 여기에서 ==0.7.2는 설치할 SQLAlchemy의 버전을 뜻하며 버전을 명시하지 않으면 최신 버전으로 깔립니다.Flask-SQLAlchemyFlask-SQLAlchemy는 SQLAlchemy를 더욱 뒷받침할 수 있는 Flask의 확장으로 SQLAlchemy 0.6 이상의 버전을 필요로합니다. Flask-SQLAlchemy 역시 pip 명령으로 설치할 수 있으며 저는 Flask-SQLAlchemy 0.15 버전을 설치했습니다.$ sudo pip install Flask-SQLAlchemy==0.15 마치며지금까지 Windows, Linux, Mac OS에서 Python, PostgreSQL을 이용한 웹서비스 개발 환경 구축 방법에 대해 알아보았습니다. 이 글을 통해서 처음 접한 사람들도 특정 OS에 구애받지 않고 쉽게 웹서비스 개발 환경을 구축하는 데에 도움이 되었으면 좋겠습니다.출처Python 위키백과pip 위키백과 Flask 홈페이지PostgreSQL plusPostgreSQL 위키백과 Essential SQLAlchemy, O REILLY, 2008Flask-SQLAlchemy 홈페이지#스포카 #개발 #개발팀 #개발자 #파이썬 #Python #개발환경 #업무환경 #꿀팁 #조언 #인사이트
조회수 5796

유용한 Javascript UI Component 라이브러리 소개

웹 애플리케이션을 개발할 때 기능적으로는 무관하지만, 사용자에게 인터렉티브하고 심미적으로 예쁜 디자인을 제공하고 싶은 경험이 있을 것입니다. 하지만 막상 직접 구현을 하는 것은 생각보다 시간이 오래 걸리고, 구현하더라도 양질의 UI가 나오지 않는 경우들이 있습니다. 그래서 이번 글에서는 쉽고 빠르게 양질의 UI를 제공해주는 라이브러리를 소개해 드리려고 합니다.Spin.js작업을 완료하거나 페이지가 넘어갈 때 아무런 말도 없이 그냥 기다리는 경우가 있습니다. 이럴 경우 사용자에게 현재 기다리는 중이라는 것을 표현하는 것이 좋습니다. 이러한 기능을 제공해주는 라이브러리가 바로 Spin.js입니다.Spin.js는 위의 그림과 같이 로딩 중이나 무언가를 진행 중이라는 것을 알려주는 사용하기 쉬운 Javascript 라이브러리입니다. 이미지 없이 사용되어 매우 가볍게 사용할 수 있습니다. 그리고 사용할 때 쉽게 설정하여 사용할 수 있으며 대다수 브라우저를 지원합니다.Spin.js / DownloadDatatables많은 양의 정보를 쉽게 볼 수 있도록 테이블로 정리해야되는 경우가 있습니다. 그러나 많은 양의 정보를 처리할 때 쉽게 원하는 정보를 찾을 수 있어야 하고 정보가 쉽게 정렬이 될 수 있어야 합니다. 이러한 기능을 제공해주는 라이브러리가 바로 Datatables입니다.Datatables는 위의 그림과 같이 테이블을 동적인 테이블을 만들어주는 JQuery Javascript 라이브러리입니다. 다양하게 정렬할 수 있도록 테이블을 만들수 있으며, 따로 정보를 찾아주는 기능을 만들어주지 않아도 검색을 할 수 있는 기능을 제공하고, 정보를 편하게 볼 수 있도록 구성을 제공합니다. 그리고 DOM, Ajax, Server-Side Processing으로 쉽게 정보를 Datatables로 만들 수 있습니다.DatatablesCurtain.js긴 내용으로 된 하나의 페이지를 섹션별로 효과적으로 내용을 전환해야 되는 경우가 있습니다. 그러나 사용자에게 혼란을 주지 않으면서 전환 효과를 만들어 내야 합니다. 이러한 기능을 제공해주는 라이브러리가 바로 Curtain.js입니다.Curtain.js는 위의 그림과 같이 마치 커튼이 걷히는 것처럼 내용 전환 효과를 주는 JQueryJavascript 라이브러리입니다. 각 내용을 화면에 고정하고 스크롤이나 키보드를 통해 화면을 전환하여 트렌디하면서 인터렉티브한 느낌을 쉽게 제공할 수 있습니다.Curtain.js / DownloadTurn.js위의 Curtain.js가 세로형태의 전환 효과를 내는 것이었다면 가로형태의 전환 효과를 내야 하는 경우가 있습니다. 이러한 기능을 제공해주는 라이브러리가 바로 Turn.js입니다.Turn.js는 위의 그림과 같이 책장을 넘기는 듯한 내용 전환 효과를 주는 JQuery Javascript 라이브러리입니다. 하나에 페이지를 섹션별로 나눠서 키보드를 통해 화면을 전환하여 책장을 넘기는 느낌을 제공해 스마트폰이나 태블릿에서 책을 읽는 듯한 느낌을 쉽게 제공할 수 있습니다.Turn.js / DownloadGlfx.js이미지를 따로 수정해서 올리는 것이 아니라 웹에서 바로 밝기를 조정하거나 다양한 효과를 주고 싶은 때도 있습니다. 이러한 기능을 제공해주는 라이브러리가 바로 Glfx.js입니다.Glfx.js는 위의 그림과 같이 다양한 효과를 주는 WebGL기반의 Javascript 라이브러리입니다. 이미지에 Blur 효과, 세피아, 밝기 조절, 모자이크처리 등 다양한 효과를 다양한 설정을 통해 쉽게 사용 할 수 있습니다. 그러나 WebGL 기반으로 되어 있어서 WebGL을 지원하는 브라우저만 가능합니다.Glfx.js / DownloadJQuery Tag-it태그를 넣을 때 쉽게 수정 가능하게 하고 자동완성기능을 넣고 싶은 때도 있습니다. 이러한 기능을 제공해주는 라이브러리가 바로 JQuery Tag-it입니다.JQuery Tag-it은 위의 그림과 같이 태그에 대한 JQuery Javascript 라이브러리입니다. 쉽게 태그를 넣고 지울 수 있으며 태그에 대해 자동완성 기능을 지원합니다. 그리고 각 태그에 대해 이벤트를 줄 수 있어서 매우 유용하게 사용하실 수 있습니다.JQuery Tag-it / DownloadTinycon새 글의 개수나 접속자 수에 대한 정보를 사용자에게 알리고 싶은 때도 있습니다. 이럴 경우 브라우저 탭에 정보를 제공하는 경우가 있습니다. 이러한 기능을 제공해주는 라이브러리가 바로 Tinycon입니다.Tinycon는 위의 그림과 같이 파비콘에 동적인 숫자를 통해 정보를 알리는 Javascript 라이브러리입니다. 매우 쉽게 사용할 수 있으며, 설정을 통해 어떤 내용을 숫자로 표현할 것인지를 쉽게 사용자화 할 수 있습니다. 파비콘에 경우 브라우저 탭에 항상 보이기 때문에 아주 유용하게 사용할 수 있을 것 같습니다. 그러나 현재 크롬, 파이어폭스, 오페라 브라우저만이 지원 가능합니다.Tinycon / Download3D GALLERY사진이나 슬라이드 탭을 보여주기 위해 갤러리 공간을 만듭니다. 그래서 좀 더 효과적으로 보여주기 위해 다양한 효과를 넣는 경우가 있습니다. 이러한 기능을 제공해주는 라이브러리가 바로 3D GALLERY입니다.3D GALLERY는 위의 그림과 같이 내용을 3D로 나열해 보여주는 JQuery Javascript 라이브러리입니다. 간단한 설정으로 3D로 배치하고 움직이도록 할 수 있습니다. 그리고 자동으로 내용을 넘어가게 할 수도 있고 다양하게 바뀌는 효과를 줄 수 있습니다.3D GALLERY / Demo글을 마치면서이번 글에서는 UI Component Javascript 라이브러리들에 대해 알아봤습니다. 위의 라이브러리로 좀 더 쉽고 빠르게 양질의 웹 애플리케이션을 개발할 수 있었으면 좋겠습니다.#스포카 #개발자 #디자이너 #협업 #Javascript #라이브러리 #꿀팁 #유용한정보
조회수 1046

[Buzzvil People] Jen Yoon, Technical Account Manager

 Buzzvil People에서는 다양한 배경과 성격 그리고 생각을 지닌 버즈빌리언들을 한 분 한 분 소개하는 시간을 갖습니다. 어떻게 버즈빌에 최고의 동료들이 모여 최고의 팀을 만들어가고 있는 지 궁금하시다면, 색색깔 다양한 버즈빌리언들 한분 한분의 이야기가 궁금하시다면, Buzzvil People을 주목해주세요.1. 간단한 자기 소개 부탁드립니다. 안녕하세요, 버즈빌에서 기술지원 업무를 담당하고 있는 Jen입니다. 본명은 윤진 (Yoon Jeen) 인데요, 입사 당시 ‘본명이 매일 불리면 일상과 회사가 구분되지 않지 않을까’라는 생각에 이름에서 한 자를 줄여 Jen으로 결정했습니다. 그런데 얼마 지나지 않아 프로덕트 팀의 윤진한 매니저가 Jin 이라는 이름으로 입사했지요. 덕분에 매일 제 이름을 제 입으로 부르고 있습니다. 버즈빌에 입사하기 전에 소셜 스타트업, 푸드 스타트업, 인테리어 O2O 스타트업 총 세 곳에서 인턴으로 근무한 경험이 있습니다. 그리고 2017년 중순 버즈빌에 입사하여만 1년 3개월 동안 BD(Business Development)팀의 전략 매니저로 일했으며, 올해 초부터 BD팀 업무와 TAM(Technical Account Manager) 업무를 겸하다가 올 10월에 정식으로 TAM 업무를 전담하게 됐습니다. 2. 어떻게 버즈빌에 오시게 되셨나요? 지인의 추천으로 버즈빌에 대해 알게 됐고, 미래에 제가 사업을 할 때 도움이 될 좋은 회사라고 판단해 입사하고자 마음먹게 됐습니다. 몇 번의 인턴 경험을 통해 세운 ‘회사를 고르는 기준’ 중 1순위는 나중에 사업을 할 때 도움이 될 만한 곳에 가자는 것이었습니다. 세부적으로는 1) 리더가 능력 있고 2) 사람들에게서 많은 것을 배울 수 있고 3) 서로의 의견을 경청하는 곳이어야 한다는 것이었어요. 지인이 버즈빌을 추천하면서 해준 말들이 이 모든 것에 너무나 아름답게 부합했답니다. 더해서 CEO인 John이 대학교 특강에 연사로 와서 해준 설명을 듣고 입사에 대한 더욱 강한 열망을 품게 됐습니다. 그래서 학기 중에 면접을 보고, 여러 우여곡절 끝에 감사하게도 합격하게 됐어요. 면접을 보는 기간 과제 때문에 엄청나게 힘들어하기도 했고, 합격하지 못할까 봐 얼마나 노심초사했는지 모르겠습니다. 뽑아주신 덕에 8학기에 교환학생을 가려 했던 계획을 내던지고 지난 8월에 졸업해 완전한 직장인이 됐답니다. 3. 버즈빌에서 어떤 업무를 담당하고 계신가요? Technical Account Manager 의 업무는 크게 3가지입니다.  연동문서 관리 – 버즈빌에서 보유하고 있는 모든 프로덕트 및 기능에 대한 문서를 관리하고 있습니다. 문서를 작성하고 적절히 연결 짓고 업데이트하고 이에 대해 내외부에 설명하는 부분까지 포함됩니다. 파트너사와 개발 미팅이 있으면 문서를 설명하기 위해 참석하기도 하고요. 내외부 이슈 해결 – 업무시간의 가장 큰 비중을 차지하는 부분은 외부 파트너의 기술 관련 이슈 해결입니다. 버즈스크린 등의 SDK를 연동한 퍼블리셔(Supply 단) 및 버즈빌이 제공하는 광고 트래킹 기능을 연동한 광고주(Demand 단)까지가 모두 파트너에 포함됩니다. 우선 연동하면서 이상이 없도록 잘 안내하고, 이후 연동이 마무리되어 출시된 이후의 이슈를 처리하며, 추가 작업이 필요할 경우 개발팀에 전달하는 것까지 모두 이에 해당합니다. 내부 프로세스 개선을 위한 요청을 관리하는 것 또한 이 업무에 포함됩니다. 프로세스 세팅 및 개선 – 위 모든 것이 수많은 커뮤니케이션을 통해 이루어지기 때문에, 효율적으로 진행될 수 있도록 유관 팀과 협력하여 프로세스를 세팅하고, 현재 비효율적인 부분을 개선해나갑니다. 그리고 세팅하는 것보다 더 중요하게 이러한 프로세스가 잘 지켜지도록 안내하는 것도 업무의 일부입니다.  얼마 전까지는 하루 대부분을 문의와 이슈를 받아 이를 해결 or 전달하고, 있었던 커뮤니케이션에 대해 기록을 남기고 유관 팀에 공유하는 것에 할애해왔어요. 버즈빌의 사업 규모가 상당해서 모든 이슈를 관리하고 프로세스를 만들고 기록까지 하다 보면 하루가 늘 빠듯하더라고요. 감사하게도 최근에 좋은 분들이 팀에 참여해주셔서, 연동문서 체계화 및 문서화 쪽에 보다 집중할 수 있는 시간이 생기고 있습니다. 업무를 하면서 가장 곤란한 순간은 ‘이게 왜 이렇게 되어있지?’ 하게 되는 때입니다. 주로 개별 적용 되어있는 부분에 대해 히스토리가 남아있지 있거나, 기능 등이 실제로 어떻게 작동하는지 또는 사용되는지 몰라서 나오는 의문들입니다. 다행히 BD팀에서 파트너사를 운영하면서 알고 있었던 히스토리와 경험이 있어서 많은 도움이 되는 것 같아요. 이를 저뿐 아니라 다른 분들이 궁금하면 언제든지 아실 수 있도록 기록을 남기는 일에 힘쓰고 있습니다. 4. 스타트업에서 혹은 광고업계에서 일하는 느낌이 어떠세요? 스타트업으로서는 모든 것을 내 손으로 빚어나가는 느낌이에요. 이건 이전 회사들에서도 많이 느꼈던 부분이네요. 물론 버즈빌은 제가 입사할 당시부터 규모가 꽤 큰 상태였고 갖춰져 있는 시스템이 많아 매우 놀랐지만, 그런데도 많은 것들을 직접 만들어나가야 하는 ‘스타트업’이에요. 그래서 할 것이 너무 많아 버겁고 힘들 때도 있지만, 결국 제가 원하는 그림을 그려나가며 최대한 완벽하게 만들어나갈 수 있어서 매일 도전적이고 스릴 넘치는 하루를 보냅니다. 저뿐 아니라 버즈빌리언 모두 각자의 자리에서 본인에게 주어진 도전들을 클리어해나가는 것 같아요. 광고업계의 스타트업으로서는 변화와 적응의 결정체랄까요. 제가 모든 업계에 종사해본 것은 아니지만, 광고업계 특성 상 변화의 속도가 더 빠른 것 같아요. 수요와 공급 쪽의 요구가 계속해서 넘쳐나고, 그 안의 플레이어들도 계속해서 나타나서 변화와 혁신이 끊이지 않는 것 같습니다. 그 와중에 플랫폼 별 정책도 변화하게 되니 그야말로 내일을 점칠 수 없는 업계인 것 같아요. 그래서 저의 업무도 매일 변화하고 새로운 상품이나 퍼블리셔에 적응하는 과정의 일부입니다. 저는 이런 역동성이 좋아서 버즈빌에서 만족하며 일하고 있어요. 버즈빌에서 일하면서 받는 느낌은, 일이 제 삶 대부분을 차지해버렸다는 점이겠네요. 하루 대부분을 회사에서 보내고 그 외의 시간에도 회사나 일 생각을 하는 것 같아요. 이것의 장단점이 있다보니 이제 워라밸도 생각하려 하고는 있지만, 여전히 제 생각의 대부분을 차지하고 있는 것이 바로 버즈빌이랍니다. 5. 이것만큼은 버즈빌이 참 좋다! 어떤 게 있으실까요? 일단 사람들이 본인 일과 다른 사람에 대한 애정을 품고 있어요. 그 덕에 무엇 하나 대충 넘기는 일 없이 다 같이 힘을 모아 일을 해낼 수 있습니다. 다들 사소한 질문에도 답을 찾기 위해 적극적으로 도와주시고, 짜증 내지 않고 웃으며 대해주세요. 그래서 크고 작은 문제를 맞닥뜨렸을 때 혼자 끙끙대는 일 없이 헤쳐나갈 수 있고, 저도 질문을 받았을 때 더 신나게 도와드릴 수 있는 것 같습니다. 두 번째로는 회사가 커뮤니케이션을 굉장히 중시한다는 점이에요. 솔직히 저는 우리나라에서 나이에 따른 꼰대질이 없는 회사는 정말 희귀할 거로 생각하는데요, 버즈빌은 그 희귀한 곳 중 하나입니다. 제가 언제 어디서든 적극적으로 의견을 낼 수 있고, 아닌 것에 대해 아니라고 말할 수 있는 회사가 얼마나 있을까요. 말만 번지르르하게 하는 것이 아니라 실제로 모두의 의견을 존중하려는 버즈빌의 문화는 버즈빌의 큰 동력 중 하나라고 생각해요. 마지막으로 사람들이 끊임없이 자기발전을 위해 노력합니다. 기본적으로 사람들의 성향이 그런 것도 있고 회사도 적극적으로 지원해줘서 더 시너지가 나는 것 같아요. 그 덕에 저도 많은 자극을 받고 더 실력 있는 사람이 될 방법은 무엇일까 고민하게 돼요. 매일매일 기분 좋은 압박감 같은 것을 느끼고 있답니다. 6. 개인적인 목표나 꿈이 있으신가요? 있다면, 버즈빌에서의 경험이 어떻게 도움이 된다고 생각하시나요? 저는 ‘기댈 수 있는 존재’가 되고 싶습니다. 누군가 힘들 때 제게 말하거나 의지해줄 때 제 존재의 의미를 느끼거든요. 개인적으로는 누군가 힘들 때 찾아올 수 있는 사람이 되고 싶어요. 한때 ‘따뜻한 사람이 되고 싶다’ 정도로 마음에 품고 살았는데, 최근에 마냥 따뜻한 것을 넘어서 누군가 찾아올 수 있는 사람이 되고 싶다고 생각이 바뀌었어요. 그리고 삶의 큰 목표로서도 마찬가지로 즐거울 때든 힘들 때든 기댈 수 있는 상품이나 서비스로 사업을 하고 싶습니다. 사실 삶에서 힘이 되는 것들이 엄청 대단한 건 아닌 것 같아요. 아침에 눈을 떠서 오늘 좋아하는 사람들과 점심 약속이 있다는 사실에 벌떡 일어나기도 하고, 아무리 새벽까지 힘들게 일하고 집에 가도 고양이가 품에 안겨있으면 피로가 사르르 녹는 것처럼요. 그래서 일확천금의 기회를 준다거나 인생을 반전시킬 만큼의 서비스는 아니라도, 잔잔한 일상 속에서나 마음이 벼랑 끝에 몰리고 지친 순간이나 머릿속에 떠오를 만한 그런 사업을 하고 싶습니다. 아무래도 관심사가 음식, 동물, 심리 이런 분야이다 보니 그 교차점에 있는 무언가를 꼭 하고 싶어요. 아침마다 고양이들에게 둘러싸여 오늘의 요리를 준비한다면 더할 나위 없이 행복할 것 같네요. 일단 버즈빌에서의 직무가 저의 이런 꿈과 관련하여 참 잘 맞는 것 같아요. 누군가가 저를 필요로 하고 불러주는 게 정말 진심으로 너무 좋답니다. 그걸 잘 처리해드리지 못할 때는 매우 힘들지만, 제 이름을 불러주실 때마다 “넵!!” 하고 대답하는 게 항상 행복하고 감사해요. 그런 점에서 현 상태만으로도 제가 되고 싶은 제 모습을 만들어나가는 데에 도움이 많이 됩니다. 두 번째로는 나중에 사업을 할 때 도움이 될 인사이트를 많이 얻어가고 있어요. 특히 사업의 확장성에 대한 것인데요, 어릴 때 단순 자영업을 꿈꾸다가 더 많은 사람에게 도움이 되면 좋지 않을까 생각해서 기업가로 꿈을 바꾸었어요. 그와 유사하게, 버즈빌에 들어와 B2B 사업을 경험하면서 파트너사가 지닌 경험과 사용자를 leveraging하여 투자하여 더 큰 확장성을 가질 수 있다는 것을 절절히 느꼈습니다. 해서 나중에 사업을 하면서 다른 주체와 협업하고 소통하는 과정에서 지금 버즈빌에서 BD매니저, 그리고 현재 TAM으로서의 경험이 아주 큰 도움이 될 거라고 확신합니다. 이에 더해서 좋은 회사란 무엇인가 고민하고, 그 고민을 통한 액션 아이템이 도출되고 실행되는 과정에 함께하는 것 또한 나중에 제 일을 할 때 큰 도움이 될 것 같습니다. 마지막으로 모든 것을 다 떠나서 너무나 좋은 사람들과 함께 웃고 이야기하고 일할 수 있다는 것 자체가 제 인생을 풍요롭게 해줍니다. 단 하루도 쉬이 넘어간 적이 없지만, 동시에 즐겁게 웃지 않았던 날도 없어요. 앞으로 버즈빌에서 제 삶이 어떻게 될지 모르지만, 여기에서 시간과 경험과 인연은 제 삶에 보석 같은 존재로 남을 것 같습니다. 
조회수 1233

“매일매일 새로운 도전으로 채워지는 자리”

“매일매일 새로운 도전으로 채워지는 자리” – 패스트캠퍼스에서 일하는 콘텐츠 마케터 이야기“마케팅 중 유효한 것은 콘텐츠 마케팅 뿐이다.” – 세스 고딘<보랏빛 소가 온다>를 쓴 세계적인 마케팅 구루 세스 고딘의 말처럼 콘텐츠 마케팅은 마케팅의 주류로 자리잡으며 전통적인 광고의 입지를 위협하고 있습니다. 그런데 콘텐츠 마케팅은 범주가 넓어 기업 특성에 따라 실무에서 담당하는 업무가 다양한데요. 이번 글에서는 패스트캠퍼스의 콘텐츠 마케터들은 무슨 일을 어떻게 하는지 자세히 알려드리고자 프로그래밍팀 시니어 콘텐츠 마케터 김하림님과 파이낸스팀 콘텐츠 마케터 이유나님을 모시고 인터뷰를 진행했습니다.안녕하세요 하림님 유나님, 오늘 인터뷰에 응해 주셔서 감사합니다. 간단하게 자기소개 부탁드려도 될까요? 안녕하세요, 프로그래밍팀 시니어 콘텐츠 마케터 김하림입니다. 지난주에 막 입사한 지 1년이 되었어요.안녕하세요, 저는 파이낸스팀 콘텐츠 마케터 이유나라고 합니다. 패스트캠퍼스에서 일한 지 이제 9개월 째고요. 두 분께서는 패스트캠퍼스에 합류하기 전 무슨 일을 하셨는지, 어떤 계기로 패스트캠퍼스 콘텐츠 마케터로 입사하게 되셨는지 궁금합니다. 패스트캠퍼스에 오기 전에는 웹디자인 일을 하고 있었는데, 회사 규모가 작아 세금계산서 발행부터 제안서 작성까지 회사 운영의 전과정에 참여해야 하다 보니 웹디자인에만 몰두할 수 있는 환경은 아니었어요. 전문성을 가지고 한 가지 일에 좀 더 집중하고 싶어 회사를 그만두었습니다. 그러다 채용공고를 살펴보던 중 패스트캠퍼스의 콘텐츠 매니저(지금은 콘텐츠 마케터로 직함이 바뀌었죠) 자리를 발견하게 되었고요. 제가 할 수 있는 다양한 일들을 업무 역량으로 발휘할 수 있을 것 같아 지원했어요. 저는 지금 마지막 학기를 보내고 있는 대학생이에요. 경영을 전공했고, 교육 분야에도 관심이 있어 국어교육학과를 복수전공하고 있었어요. 제가 흥미를 느낀 이 두 분야를 접목해 할 수 있는 일을 찾다 교육업에 있는 마케터 일이 저에게 딱 맞을 것 같아 지원서를 넣었던 기억이 납니다. 인턴으로 입사했다 정직원으로도 계속해서 함께하는 중이예요. 유나님께서는 인턴 기간이 종료된 후에도 이곳에서 일하고 계신데, 패스트캠퍼스를 선택하신 이유가 무엇일까요? 패스트캠퍼스에서는 인턴이라도 정직원과 같은 일을 하면서 눈치 보지 않고 자기 의견을 낼 수 있던 것이 좋았어요. 저에게는 자기발전을 계속할 수 있는지가 직업을 선택할 때 중요한 기준인데 여기에 맞고, 사회 초년생으로서 일을 배우기에도 좋은 환경인 것 같아 정직원으로 계속 일하고 있습니다. 제가 막 입사했을 때, 당시 팀장님께서 제 직무에 대해 설명해주셨던 것이 기억에 남아요. “프로덕트 매니저가 오프라인에서 기획을 하는 사람이면 콘텐츠 마케터는 온라인에서 기획을 하는 사람이다”라는 말이었는데 저희는 고객분들이 온라인에서 접하는 모든 콘텐츠를 기획·제작하고 글을 쓰는 만큼 일리가 있는 것 같아요. 기획자, 제작자, 에디터의 역량을 모두 발휘해야 하는 사람이 콘텐츠 마케터라고 생각합니다. 하림님의 말씀에 더해, 우리 회사 콘텐츠 마케터가 맡는 특별한 일 중 하나는 상세페이지를 기획 및 디자인해 고객을 설득하는 글쓰기를 한다는 것이에요. 마케터라 하면 광고 크리에이티브를 제작하는 데 업무의 초점이 맞춰져 있다는 느낌이지만, 여기서는 기획 역량까지 발휘해야 하는 점이 특징이죠. 콘텐츠 마케터로서 다양한 일을 하고 계시는데, 어느 정도 정해진 일과가 있을까요? 하루 일과를 딱 잘라서 말하긴 어렵습니다. 그때그때 담당하는 일의 중요도가 달라져서요. 우선 프로덕트 매니저 분이 새로운 강의 기획을 완성하시면 신규 상세페이지를 제작하고, 기존 강의를 업그레이드해 오시면 그에 맞게 기존 상세페이지의 내용을 수정합니다. 홍보 진행이 원활하지 않으면 팀원들과 트러블 슈팅을 통해 상세페이지나 광고 크리에이티브를 손보기도 하고 강사 인터뷰, 수강생 인터뷰 혹은 블로그 게시물이나 카드뉴스 형태의 오가닉 콘텐츠를 발행하기도 합니다. 업무 진행에 있어 큰 틀은 있겠지만 그때그때 업무의 우선순위가 달라져요. 일이 많아 야근할 때도 종종 있고요. 패스트캠퍼스 콘텐츠 마케터 직무, 입사 전 생각했던 것과 실무를 진행하는 것에 차이가 있나요? 저는 비슷한 것 같아요. 간단한 퍼블리싱, 마크업(HTML/CSS로 코딩을 하는 것)을 할 수 있는 사람으로서 이런 스킬들이 상세페이지 제작 업무에 도움이 될 거라고 생각했거든요. 입사 전 필수적으로 갖춰야 할 스킬은 아니었지만 업무를 진행하다 보니 마크업을 알아서 더 도움이 되는 게 많았어요. 그런데… 트러블 슈팅이 이렇게 많을 줄은 몰랐네요. 하하. 저는 하림님과 반대예요. 콘텐츠 마케팅이 이렇게까지 다양한 능력을 요구하는 일인 줄 전혀 몰랐어요. 업무 스킬은 물론 담당하는 강의에 대한 지식적인 부분까지도요. 깊게 파고들 필요는 없지만 얕고 넓은 지식이 필요한 일이더라고요.물론 하림님처럼 업무와 관련된 스킬을 가지고 입사하시면 실무에 확실히 도움 되는 부분이 있어요. 포토샵이나 HTML/CSS 같은 것들요. 하지만 저의 경우에는 포토샵도 못 다룰 만큼 아무것도 모르는 상태로 일을 시작했는데도 필요한 것들을 배워 가며 일할 수 있는 환경이라 괜찮았어요. 그 과정에서 성장하고 있는걸 스스로도 느낄 정도에요.지금 패스트캠퍼스에서는 프로그래밍, 데이터 사이언스, 마케팅, 외국어 등 다양한 팀에서 콘텐츠 마케터를 채용 중인데요. 팀별로 콘텐츠 마케터가 갖춰야 할 배경지식, 선호하는 스킬셋이 다를까요? 크게 차이는 없는 것 같아요. 합류하는 팀에 따라 만들게 되는 콘텐츠의 성격은 달라질 수 있지만 배경지식이 필수는 아니거든요. 프로덕트 매니저 분들이 작성하신 기획 문서를 읽고 핵심이 되는 부분을 짚어 콘텐츠로 만들어낼 수 있으면 됩니다. 이해하기 어려운 부분은 프로덕트 매니저 분들께 물어보면 어느 팀에서건 친절하게 알려주실 거예요. 맞아요. 저도 파이낸스 분야를 공부하며 콘텐츠를 만들고 있는데, 아는 게 점점 많아지고 있는 것 같아 뿌듯합니다. 콘텐츠 마케터는 끊임없이 새로운 것들을 배워야 하는 직무 같은데요. 패스트캠퍼스에서 콘텐츠 마케터로 일하며 가장 힘든 점은 무엇인지 솔직하게 말씀해 주신다면? 하나의 콘텐츠에 오랜 시간을 투입할 수 없는 점? 일주일에 새로운 상세페이지를 세 개씩 만들 때도 있다 보니 한 가지 업무만 집중해서 파고들 시간적 여유가 없어요. 특히 트러블 슈팅이 많이 발생하다 보면 업무 시간이 절대적으로 부족하죠. 유나님 말씀에 더해, 강의마다 특징을 가장 잘 보여줄 수 있는 상세페이지를 만들기 위해 고민하는 게 재밌으면서도 어려운 일 같아요. 이런 부분에 대해 어떤 도움을 드릴 수 있을까 다른 시니어 분들과 함께 고민 중이고요. 그리고 솔직히 말하자면, 일이 정말 많아요. 그게 제일 힘들죠. 업무 과다로 고생이 많으신데, 힘든 점들이 있음에도 이 일을 계속하게 만드는 원동력은 무엇인가요? 일은 많지만 업무 방식에 제한은 없어서 이것저것 새로운 시도를 해 볼 여지가 있다는 게 좋아요. 상세페이지를 수정했거나 새로운 광고 크리에이티브를 만들었는데 효율이 좋다거나, 오가닉 콘텐츠를 발행했는데 커뮤니티 등에 업로드되는 등 좋은 반응을 얻었다거나 하면 보람도 있고요. 틀에 박힌 일을 하지 않는다는 점이 재밌어요. 맞아요. 새로운 시도에 대한 제재가 없으니 할 수 있는 게 많아서 좋죠. 성과에 따른 연봉협상도 유연하게 이뤄지고요. 어떤 콘텐츠 마케터를 동료로 맞이하고 싶으신지 궁금합니다. 새로운 시도에 대한 거리낌이 없으신 분. 새로운 일이 주어졌을 때 ‘저는 이거 못하겠어요’가 아니라 ‘이것도 저것도 해 볼게요’라고 말할 수 있는 분! 팀원들과 협업을 잘할 수 있는 분. 프로덕트 매니저, 퍼포먼스 마케터의 의견을 반영해 콘텐츠를 제작하고 배포하기 때문에 커뮤니케이션 능력이 좋다면 일을 잘할 수 있을 것 같아요. 거기에 하나 더, 자신의 의견만 고집하기보다 다른 사람의 의견을 잘 받아들일 수 있는 분. 서로의 잘잘못을 따지기보다 더 나은 방향을 위해 협업하고 있다는 걸 잊지 않는 분이면 좋겠어요. 쓰는 걸 두려워하지 않는 분이면 정말 좋고요. 맞아요. 포토샵이나 워드프레스 스킬들은 모르셔도 괜찮아요. 저희가 알려드릴게요! 마지막 질문입니다. 두 분께 패스트캠퍼스란 어떤 곳일까요? 매일매일 변화무쌍한 곳. 틀에 박힌 일을 하지 않아요. 오늘, 지금입니다. 오늘이 쌓여서 내일이 되고 매일이 되는데, 그 오늘이 매일매일 새로워요.* 패스트캠퍼스 콘텐츠 마케터는? *  패스트캠퍼스 고객들이 접하게 되는 모든 접점을 컨트롤하는 역할을 담당합니다. 기획 과정에 참여하는 것은 물론 교육 콘텐츠 상세페이지를 제작하고, 매력적인 광고 크리에이티브를 만들고, 강사와 수강생들의 목소리를 전달하기도 합니다. 즉, 패스트캠퍼스에서 만들어지는 모든 콘텐츠의 외모를 결정하고 그 톤앤매너를 관리합니다.
조회수 7281

HTTP 404 Status Code 에 대한 고찰

뭐가 문제였나필자는 현재 HMR(가정간편식) 커머스를 다루는 모 스타트업에서 백엔드 개발자로 재직 중이다. 말이 백엔드지 최근 변화되고 있는 트렌드에 맞춰 열심히 API 작성 셔틀을 하고 있다.API 개발에 주로 사용하는 HTTP 상태 코드는 주로 200 (정상), 400 (잘못된 요청), 401 (보안 토큰 에러), 403 (권한 없음), 404 (찾을 수 없음) 정도가 있었다.문제는 여기에서 발생했는데, API를 계속 개발해 나가다 보니 API 요청 시 데이터가 없을 때 200 상태 코드에 빈 배열을 돌려주어야 하는지, 404 상태 코드를 돌려주어야 되는지 상황에 따라 다를 수 있겠다는 생각이 들었다.만약 '데이터가 없을 수도 있는 상황'과 '데이터가 없으면 안 되는 상황'에서 404 Not Found 에러 코드로 같게 응답할 경우 다음과 같은 애매한 상황이 펼쳐질 수 있다.API를 사용하는 클라이언트가 404 에러에 대한 대응을 에러로 표시할지 데이터 없음으로 표시할지 상황에 따라 다르게 정의해줘야 한다. 결과적으로 클라이언트에서 API 요청에 대한 처리가 복잡해진다.// front-endimport fetch from 'node-fetch'; function fetchUserList() {  // 유저 목록을 가져오는 API를 사용한다고 가정  return fetch('https://api.exmaple.com/users')    .then((response) => {      if (response.statusCode === 404) {        // 이 404 Http 상태 코드를 에러로 처리할 것인가? 데이터 없음으로 처리할 것인가?        // 에러일 경우 : throw new Error('Not Found');        // 데이터 없음일 경우 : return [];      } else if (response.statusCode === 200) {        return response.json();      } else {        throw new Error('Unexpected Http Status Code');      }    })    .then(result => render(successPage, result))    .catch(error => render(failurePage, error));}결국, 어떤 식으로 표시해야 명확하게 표현할 수 있을까 하여 페이스북 존잘 개발자님들에게 의견을 물었다. # 굉장히 많은 분이 의견을 주셨고 나름대로 생각을 정리할 수 있었다.결론적으로는 '데이터 없음'과 '404 Not Found'를 같은 용도로 사용하면 안 된다.그렇다면 뭘 어째야 하나위에서 나온 결론을 조금 더 자세히 풀어보면 다음 내용이다.상황에 따라 데이터가 없는 것이 정상인 상황이 있고, 데이터가 없는 것이 에러인 상황이 있다. 이를 구분 해야 한다.데이터가 없는 것이 정상일 수 있는 상황// server-sideAPI.get('/orders/date/:date', async (request, response) => {  // 특정 날짜의 주문을 검색. 특정 날짜에 주문이 없을 수도 있다.  const { date } = request.params;  const orders = await Repository.Order.findByDate(date);  // 200: OK  // 204: No Contents  response.statusCode(orders.length > 0 ? 200 : 204).json(orders);});데이터가 없는 것이 에러인 상황API.get('/orders/:orderId', async (request, response) => {  // 특정 ID의 주문을 검색. 데이터가 없으면 에러다.  const { orderId } = request.params;  const order = await Repository.Order.find(orderId);  if (order.length > 0) {    response.statusCode(200).json(order);  } else {    // 404: Not Found    response.statusCode(404).json({      message: `${orderId} is Not Found`    });  };});그렇다면 요청한 API 리소스가 없는 경우에는 어떤 에러를 보여줘야 하는가? 일반적으로는 404 Not Found 가 통상적으로 사용되지만 우리는 이미 404를 다른 용도로 사용하고 있다. 다행히도 HTTP 상태 코드에는 501 Not Implemented 이라는 좋은 친구가 있다. 이 친구를 사용할 수 있다.import { Users, Orders } from './Routes'; app.route('/users', Users);app.route('/orders' Orders);app.all('*', (request, response) => {  // 501: Not Implemented (구현되지 않음)  response.statusCode(501).json({    message: 'This Method is Not Implemented',  });})대충 이 정도면 클라이언트는 Http 상태 코드를 보고 다음 로직을 처리할 수 있을 것이다.물론 일반적으로 사용되는 상태 코드들이지만 실제 개발 진행 시에는 클라이언트를 개발하는 개발자와 미리 어떤 상황에서 어떤 상태 코드를 보낼 것인지 정해야 할 것이다.마무리API 개발 시 사용할 법 직한 응답 코드를 정리해보았다.200: OK (정상, 데이터 있음)204: No Contents (정상, 데이터 없음)301: Moved Permanently (리다이렉션)400: Bad Request (실패, 클라이언트에서 넘어온 파라미터가 이상함)401: Unauthorized (실패, 클라이언트에서 넘어온 보안 토큰이 이상함)403: Forbidden (실패, 사용자의 권한으로 리소스를 사용할 수 없음)404: Not Found (실패, 데이터가 있어야 하나 없음)410: Gone (실패, 데이터가 있었으나 삭제됨. 이건 굳이...?)500: Internal Server Error (실패, 서버 로직 문제)501: Not Implemented (실패, 없는 리소스 요청)기타 304나 502, 503 등의 상태 코드의 경우 API Application을 작성하는 개발자의 역할보다는 Server 쪽의 역할에 가깝다고 생각하여 작성하지 않음.뭔가 어렵다고 느껴진다면 다음 짤을 참고해서 쉽게 이해할 수 있다. #플레이팅 #개발 #개발자 #인사이트 #경험공유 #조언 #꿀팁 #HTTP #버그 #버그수정 #문제해결
조회수 992

코인원 크루의 채굴 현장을 포착했다! - ‘코인원 작업증명(PoW)’을 소개합니다

블록체인에서 PoW는 Proof of Work, 즉 작업증명을 말합니다. 블록체인의 암호화된 작업에 대해 참여자가 암호를 풀면, 보상을 제공받는 것이죠.오늘은 코인원의 PoW에 대해서 이야기 해보려고 합니다. '코인원 PoW'의 PoW는 블록체인을 기반으로 금융을 혁신하는 기업답게 블록체인 용어에서 차용했어요. :-)  코인원 크루들이 스스로와 동료들의 회고를 진행하고 피드백을 주고 받는 과정을 통해, 업무 개선과 성과에 대한 보상을 제공받도록 만들어진 일종의 성과관리 시스템이죠. 코인원 피플팀은 코인원 PoW 과정을 다음과 같이 설명하고 있습니다.크루들이 자신들의 업무 성과에 대해 투명하게 풀어놓는 회고를 우선적으로 진행해요. 그 후 함께 업무를 진행한 페어 그룹(pair group)끼리 서로 잘된 업무와 지원이 필요한 부분에 대해 대화를 진행하며, 이를 통해 개선점과 방법을 찾아 업무에 적용합니다.코인원 PoW의 특별한 점은, 대부분의 과정이 정성적으로 진행된다는 것에 있습니다. 물론 숫자로 보이는 결과도 중요하지만, 모든 일은 결과 못지 않게 과정도 중요하다고 판단했기 때문이에요. 그 과정에 충실함을 보인 크루들을 선별해 ‘슈퍼크루'로 지정하고 보상을 제공하는 과정도 여기에 포함됩니다. 이 변화무쌍한, 그리고 결코 쉽지 않은 크립토(crypto) 세계에서 ‘정도'를 걸어가고 있는 ‘코인원스러운' 성과관리 시스템이 아닐까 생각합니다. :-) 우선 코인원 PoW가 어떤 과정으로 진행되는지 한 번 살펴볼까요? 코인원 PoW는 아래와 같은 5가지 단계로 진행됩니다.Self mining셀프마이닝은 지난 6개월 동안 자신이 진행한 업무와 그 과정에 대해 에세이를 작성하는 단계입니다. 에세이를 작성할 때는 자신이 진행한 업무와, 업무를 진행하는 과정에서 본인이 생각하는 잘한 부분 및 아쉬웠던 점들 등에 대해서 작성합니다. ‘잘한 부분'의 경우, 성과가 좋았던 점 외에 성과는 좋지 않았어도 최선을 다한 것에 대해 상세히 작성합니다. Peer mining피어마이닝은 업무적으로 연관된 동료 크루의 셀프마이닝을 토대로 그 동료에 대한 의견을 작성하는 단계입니다. 함께 일했을 때 동료 크루의 좋았던 점, 훌륭한 점, 배워야 할 점 등을 서술하고, 앞으로 더 효율적인 협업을 위해 동료가 개선하면 좋을 것 같은 점도 함께 작성해요. Segwit세그윗 단계에서는 위 두 단계에서 도출된 자기 평가와 동료 평가를 토대로 각 셀의 리더들과 1:1 면담을 진행합니다. 이때 셀 리더들이 꼭 염두해야 하는 것은, 코인원 PoW를 통해 우리가 이끌어내고자 하는 것은 '평소의 관심과 피드백, 그리고 동반 성장'이라는 것이죠. Blue paper세그윗을 통해 최종 작성되는 것이 바로 블루페이퍼에요. 크루들의 면담을 진행한 각 셀의 리더들이 작성하죠. 이 내용은 크루들이 지난 6개월 동안 한 일에 대한 자기 자신과 동료, 그리고 셀 리더의 피드백이 담긴 한 장의 문서죠. Consensus마지막으로 컨센서스 단계에서는 최종 완성된 블루페이퍼를 바탕으로 본부별 슈퍼크루를 선정합니다. 그리고 이렇게 선정된 슈퍼크루에 대해 전체 크루가 동의 가능한지에 대한 적절성 심사가 한 번 더 진행됩니다. 현재 코인원에는 약 120명의 크루들이 일하고 있어요. 사실 모든 크루들의 정성적인 분석 과정을 진행하는 것이 쉬운 일은 아니에요. 코인원 PoW는 셀프마이닝부터 블루페이퍼 작성 및 슈퍼크루 선정까지 약 5주에 걸쳐 진행되는, 길지만 자연스러운 평가와 이를 통한 성장의 과정이라고 생각합니다.이 과정에서 코인원 피플팀 여러분들이 정말 많은 노력과 정성을 기울여주고 계시죠!그렇게 10월의 어느 날, 2018년 상반기의 코인원 PoW가 성공적으로 마무리가 됐습니다. :-)코인원의 모든 크루들이 지난 상반기의 업무에 대해 작업증명을 진행했죠! 그리고 또 다른 6개월 동안 앞으로 다시 힘차게 나아가기 위해 자신의 어떤 좋은 점을 강화하고, 어떤 점은 보완하면 될지를 나 자신, 그리고 동료 크루들과 공유하는 시간이었습니다.또, 이렇게 진행된 2018년 코인원 PoW를 통해 여섯 명의 슈퍼크루가 탄생했어요!2018 코인원 슈퍼크루를 소개합니다 :-)올 한해도 모든 크루가 각자의 분야에서 최선을 다했어요.슈퍼크루는 그 중에서도 특히 다른 크루들에게 좋은 영향을 준 크루들을 선정한 것인데요, 이 분들에게는 코인원의 특별한 추가 보상이 제공될 예정이랍니다. :-)코인원은 앞으로도 크루들이 즐겁게 일하면서 성장할 수 있는 여러가지 재밌고 유익한 도전들을 해보려고 합니다. 코인원이 크립토 세상에서 어떤 즐거운 도전들을 하고 있는지, 앞으로도 코인원 공식 블로그를 통해 지켜봐주세요! :-)#코인원 #블록체인 #기술기업 #암호화폐 #스타트업인사이트 #기업문화 #조직문화 #사내복지 #업무환경 #팀원소개
조회수 2890

JANDI CONNECT 개발기

지난 1월 말, 새해를 맞아 잔디에 새로운 기능이 업데이트되었습니다. 바로 잔디 커넥트에 관한 내용인데요, 협업에서 많이 쓰이는 몇 가지 외부 서비스를 잔디와 쉽게 연동해서 더욱 효율적인 업무 커뮤니케이션을 할 수 있게 되었습니다. 많은 고객분들이 이번 업데이트를 기다려주신 만큼, 저희 개발팀 또한 기대에 보답하고자 지난 몇 주의 스프린트 동안 열심히 준비했습니다. 이번 글에서는 커넥트 동작 방식을 설명하고 그 개발 과정에서 저희가 겪은 시행착오를 비롯한 여러 값진 경험들을 공유하고자 합니다.Integration? Webhook!연동: [기계] 기계나 장치 따위에서, 한 부분이 움직이면 다른 부분도 함께 잇따라 움직임.앞서 말한 대로 잔디 커넥트는 여러 웹 서비스들과 잔디를 연동할 수 있는 기능입니다. 서로 다른 웹 서비스를 연동하기 위해선 한 서비스 내에서 특정 이벤트가 발생 했을 때 다른 서비스로 해당 이벤트를 알려주는 연결 고리가 필요합니다. 이때 해당 연결 고리 역할을 위해 대표적으로 사용되는 기법이 웹훅(WebHook) 입니다. 웹훅은 user-defined HTTP callbacks, reverse APIs 등으로 불리는데, 간단히 설명하자면 웹 서비스에서 공개한 API가 아닌 사용자가 직접 지정한 주소(URL)로 특정 이벤트가 발생 시 HTTP Request를 보내주는 기법입니다. 예를 들어,새로운 일정이 등록된 경우(Google Calender)요청한 Pull Request가 Merge된 경우(GitHub)카드에 새로운 코멘트가 작성된 경우(Trello)이러한 이벤트가 발생했을 때 사용자가 매번 이벤트가 발생했는지 확인하지 않아도 서비스가 먼저 알려줄 수 있도록 일종의 알림을 등록하는 것이죠. 잔디 커넥트는 이와 같은 특징을 이용해서 각각의 웹 서비스에서 제공하는 웹훅을 잔디의 메시지 형태로 전달하는 기능입니다.일반적으로 웹훅은 이벤트에 대한 알림을 외부로 전달하는 것을 말합니다. 이 부분에서 중요한 것은 전달 방향인데, 서비스 내부에서 외부로 전달하기 때문에 이를 Outgoing Webhook으로 부르기도 합니다1. 같은 맥락에서 반대로 생각해보면 외부에서 서비스 내부로 특정 데이터를 전달하는 경우이니 Incoming Webhook이 됩니다. 앞서 웹훅을 reverse API라고 했는데 이를 다시 뒤집으니 결국 서비스 내부로 통신하는 제한적인 API와 같은 역할을 합니다. 굳이 용어를 구분한 이유는 API와 달리 접근하려는 서비스의 별도 인증 절차를 거치지 않고도 사용자가 생성한 웹훅의 URL을 인증 토큰으로 사용하며 약속된 Request Body 포맷만 알고 있다면 자유롭게 사용할 수 있기 때문입니다.개념 설명이 다소 길어졌지만, 이번 잔디 커넥트 기능에 대해 용어나 개념이 낯설다는 피드백이 생각보다 많았기 때문에 이번 글을 통해 더 많은 분들이 웹훅을 이해하는 데 도움이 될 수 있으면 좋겠습니다.구현에 앞서서비스를 운영한지 1년 정도 지난 시점에서 저희 내부적으로는 백엔드의 기술 스택 변경 및 각 서비스 분리에 대한 갈증이 있었습니다. 하지만 이미 서비스를 운영 중이기 때문에 안정성이 최우선시 되는 만큼 꽤 부담스러운 숙제로 미뤄둘 수밖에 없었고요. 때마침 커넥트 기능은 숙제를 시험해볼 만한 좋은 기회임에는 분명했지만, 새로운 기술 스택을 바로 서비스에 적용하기엔 오히려 개발 효율이 떨어질 것이라는 판단하에 일단 서비스 분리에만 집중하기로 했습니다.기본적으로 API와 DB를 기존 서버와 분리하고 웹훅 데이터를 저장하기 위한 큐와 해당 데이터를 처리하는 배치 서버 또한 모두 기존 서비스와 분리해서 최대한 결합도를 제거했습니다. 이런 설계 덕분에 추후 사업 전략이나 각 국가의 특성에 맞춰 커넥트 기능을 어렵지 않게 포함하거나 제외할 수 있게 되었습니다. 전반적인 저희 잔디 백엔드 아키텍쳐에 대해서는 아직 한 번도 소개 해드린 적이 없으니 다음에 따로 주제로 선정해 집중적으로 다뤄보도록 하겠습니다.동작 방식잔디 커넥트가 동작하는 방식은 기본적으로 다음과 같습니다.Incoming Webhook URL 생성 - 외부 서비스 웹훅 등록 - 웹훅 수신 - 메시지 작성 연동 대상 서비스마다 조금씩 차이가 있지만, 기본적으로 모두 위와 같은 방식으로 동작하기 때문에 단계마다 나누어 설명하겠습니다.1. Webhook URL 생성Webhook URL은 https://wh.jandi.com/connect-api/webhook/{teamId}/{webhook-token}와 같은 형태로 생성됩니다. hostname을 별도로 설정함으로써 기존 API 서버와의 분리는 물론이고, nginx의 Limiting the Request Rate 설정을 이용해서 호출되는 웹훅 요청 수를 효과적으로 제한할 수 있었습니다. webhook-token은 중복을 피하면서 각 웹훅에 대한 유효성을 검증할 수 있도록 여러 키를 조합한 md5 hash 값을 이용했습니다.이렇게 생성된 URL은 Incoming Webhook 뿐만 아니라 Google Calendar 등의 서비스에 등록하는 콜백 URL로 사용합니다.2. 외부 서비스 웹훅 등록웹훅을 등록하는 방법은 서비스에 따라 API를 이용하거나 수동으로 직접 등록할 수 있습니다. 사용자가 직접 웹훅을 등록하는 방법은 웹훅 URL만 생성해서 전달하면 등록 과정의 추가 처리가 필요 없어서 간단하지만, 서비스마다 등록하는 방법이 조금씩 다르고 다소 복잡하게 느껴지는 문제가 있습니다. 반대로 각 서비스에서 제공하는 API를 이용해 웹훅을 등록하면 사용자의 부담을 많이 줄일 수 있지만, 그만큼 내부적으로 처리해야 할 작업이 많아집니다. 그래서 구현 초기에 꽤 많은 시간을 투자할 수밖에 없었고 그 과정에서 아래와 같은 어려움을 겪었습니다.웹훅 관련 API를 사용하려면 먼저 인증을 받아야 하는데 서비스마다 제공하는 인증 방식이 조금씩 달라서 이를 통합하는 모델을 만들기가 쉽지 않았습니다. 요약하자면 기본적으로 accessToken을 사용하지만, 인증 방식에 따라 부가적으로 필요한 데이터가 서로 조금씩 다른것이죠. 가령, 구글캘린더는 만료 일시와 토큰 갱신을 위한 refreshToken 값을 별도로 갖고 있어야 합니다. 또 한가지 놓치기 쉬운 부분은 인증 폐기(revoked) 관련한 데이터 처리인데 저희가 경험한 바로는 인증이 폐기되었을 때 별도로 웹훅 알림을 주지 않기 때문에 반드시 인증의 유효성을 확인하는 추가 로직이 필요합니다.대부분의 사무실이 그렇듯이 저희 또한 공유기를 이용해 내부 네트워크를 구성하고 있습니다. 게다가 백엔드 파트는 개개인의 로컬 가상 서버에 동일한 환경을 설정해놓고 개발을 하므로2보통 경우엔 외부(public network)에서 들어오는 요청을 받을 수 없습니다. 그렇다고 매번 외부 네트워크에 있는 서버에 배포 후 테스트하기가 어려우니, 저희는 각 로컬 서버마다 고유 포트 번호를 나눠 갖고 WAN이 물린 공유기의 포트 포워딩을 알맞게 설정한 뒤에 네트워크 터널링 유틸리티인 ngrok을 이용해 내부와 연결되는 public 주소를 생성해서 외부 서비스와 문제없이 통신할 수 있었습니다.3. 웹훅 수신웹훅을 통해 들어오는 Request는 일단 정상 응답을 하는 게 좋습니다. 서비스마다 최초 웹훅 등록 시 유효한 URL인지 확인하는 테스트 요청을 하는데 이때 정상 응답을 하지 못하면 아예 등록조차 처리되지 않습니다. 또한, 정상적으로 등록된 이후 특정 이벤트에 해당하는 웹훅 요청에 대한 응답에도 주의할 필요가 있는데, 만약 에러 응답이 반복되면 일정 시간 동안 각 서비스에서 아예 해당 웹훅을 발송하지 않도록 제한이 걸려 더 이상 테스트를 진행할 수 없는 경우도 있었습니다.따라서 일단 웹훅 요청이 들어오면 teamId와 webhook-token 값으로 올바른 웹훅인지 검증한 후 서비스별 큐에 Request header와 body를 포함한 데이터를 전달한 뒤 바로 응답하고, 큐에 쌓인 데이터는 커넥트 종류별로 배치 서버가 돌면서 처리하게 됩니다. SQS를 사용함으로써 늘어나는 데이터에 대한 안정성을 확보하고 각각의 배치 서버를 독립적으로 분리해서 구현함으로써 자연스레 확장성(scalability)도 보장할 수 있게 되었습니다.4. 메시지 작성웹훅 데이터를 잔디의 메시지로 변환하는 역할은 배치 서버가 담당합니다. 서비스별로 데이터 포맷이 다르므로 해당 데이터를 파싱 및 처리하는 Worker 또한 각각 구현했습니다. 사실 커넥트 기능에서 가장 핵심적인 역할을 하는 부분인 만큼 가장 많은 공수가 드는 작업이였던 것 같습니다.서비스마다 정해놓은 웹훅 이벤트와 잔디 커넥트에서 제공하고자 하는 알림이 서로 완전히 일치하지 않아서 이를 서로 연결하는 작업연동 서비스의 문서가 잘 정리되어 있지 않아서 일일이 필요한 동작을 취하고 그에 따라 들어오는 데이터를 정리하는 작업잔디 계정 언어에 따라 메시지 L10N3을 적용하는 작업커넥트 메시지를 전달하기 위해 기존 멤버와 다른 커넥트 봇을 구현하는 작업등 요약하기 어려울 정도로 크고 작은 이슈들이 많았습니다. 그 내용이 너무 다양해서 모두 상세히 기록하긴 어렵지만, 개중에 도움이 될만한 내용을 추려서 아래 따로 정리했으니 관심 있으신 분들은 참고하시면 좋을 것 같습니다.서비스별 집중 탐구커넥트 구현 일정을 최대한 앞당기기 위해 저희는 개발자들끼리 각각의 커넥트 종류 별로 전담해서 작업하는 전략을 취했습니다. 제가 대표로 글을 작성하기는 하지만 보다 정확하고 구체적인 정보를 전달하는 것이 좋겠다는 생각에 개발을 담당하신 분들과의 짧은 인터뷰 형식을 빌려 공유하겠습니다.- Google CalendarQ. 기술적으로 난이도가 높았던 작업을 소개해달라.전반적으로 어려운 작업이 있었다기보단, 캘린더 특성상 세세하게 처리할 부분들이 많아 설계와 구현이 어쩔 수 없이 복잡해졌다. 가장 골치 아팠던 작업은 일정 알림을 타임존(Time Zone)에 따라 각각 알맞은 시간에 전달하는 작업인데, “잔디 계정의 타임존”, “구글 캘린더의 타임존”, “개별 일정의 타임존” 이렇게 3가지를 모두 고려해서 경우마다 기준이 되는 타임존을 결정하는게 엄청 까다로웠다. 심지어 구현 후 테스트를 하는 과정에서도 출력된 시간이 올바로 표시된 것인지조차 헷갈려서 디버깅하는데 한참 고생할 수 밖에 없었다.웹훅을 등록하고 관리하는 부분도 꽤 복잡했는데, 구글 답게(?) 웹훅에도 만료 기간이 존재한다는 것이 포인트다. 때문에 만료되기 전에 반드시 재등록 및 과거 웹훅 삭제 작업을 하는데, 효과적으로 처리하기 위해 “웹훅을 받을 때마다 만료 기간을 확인”, “등록된 일정이 많지 않아 웹훅을 받지 못하는 경우도 있으니 별도의 배치서버가 하루 단위로 확인” 이렇게 두 가지 로직을 넣어서 자동으로 웹훅을 유지하도록 구현했다.또한, 다른 연동 서비스와 달리 구글은 웹훅 콜백으로 들어오는 요청에 해당 이벤트에 대한 데이터를 직접 담아주지 않기 때문에 key를 가지고 한 번 더 API 호출을 통해 필요한 데이터를 가져와야 한다는 점도 주의해야 한다. 요청해야 할 API 문서는 비교적 잘 정리된 편이지만, 같은 요청에 대해서도 인자를 어떻게 보내는지에 따라 그 응답이 제각각이기 때문에 응답 값에 대해 무조건 신뢰하고 처리해서는 안 된다. 당연히 존재할 것으로 생각한 필드 값에 빈 배열이 들어와서 일정 관련된 데이터를 일부 날리고 나서야 깨달았다.. -_-Q. 가장 처리해야 할 이슈가 많았다고 알고 있는데, 그중에서도 기억에 남는 이슈가 있을 것 같다.너무 많은 이슈를 동시에 처리하다 보니 특별히 기억에 남는 이슈는 없다. 다만 아직도 왜 그랬는지 확실한 이유는 알 수 없지만, 언젠가 한 번 구글에서 웹훅을 아예 전달해주지 않았던 경우가 있었다. 과도한 요청으로 limit이 걸린 것도 아니었는데, 갑자기 웹훅이 안들어오니깐 우리로서는 어떻게 풀어볼 방법이 없었다. 그러다 나중에 확인해보니 대략 12시간쯤 지나고 나서 그동안 밀려있던 웹훅 데이터가 한 번에 밀려서 들어와 있더라. 다행히 그 이후로 지금까지 한 번도 재현되지 않는걸 보니, 혹 동일한 증상을 겪는다면 당황하지 말고 기다려 보시라.반복 일정을 다루는 것도 꽤 골치 아픈 이슈인데, 왜냐하면 일정이 있을 때 마다 웹훅 알림을 주지 않고 처음 등록된 시점에서 한 번만 정보를 알려주기 때문에 등록된 시점 이후의 일정은 내부적으로 계속 등록해줘야 한다. 기본적으로 구글 캘린더는 RFC-55454 표준을 따르지만, 실제 전달되는 데이터 중 일부는 표준과 조금 다른 부분이 있었다. 특히 반복 일정(recurrence) 관련 데이터 포맷이 조금 다르므로 캘린더 데이터를 파싱하기 위해 만약 외부 library를 사용한다면 별도의 예외처리가 필요하다. 더욱 더 까다로운 건 사실 등록된 반복 일정이 수정되거나 삭제되는 경우인데, 이때 “특정 일정만 삭제”, “지금 시점 이후의 일정 모두 수정” 등 워낙 케이스도 많고 각각을 테스트 하는 것도 쉽지 않기 때문에 작업 시간이 꽤 오래 걸렸다. (심지어 아직 확인하지 못한 드문 케이스에서는 잠재된 버그가 있을 수도…)Q. 그 밖의 도움이 될만한 노하우나 꿀팁이 있다면?구글 캘린더 API는 Webhook 보단 Push Notification 키워드를 많이 사용한다. 푸시 노티라는 게 좀 다른 카테고리에서 많이 쓰이는 용어이기도 하다 보니 코드 리뷰 등의 커뮤니케이션을 할 때 혼동이 좀 있었던 것 같다.물론 서비스 요구사항마다 다르겠지만, 잔디 같은 경우엔 요구사항에 맞춰 계속 설계를 변경 및 개선하다 보니 결과적으로 너무 복잡해져 효율이 떨어지는 코드를 작성할 수밖에 없었다. 처음부터 연동을 생각하기보다는 아예 캘린더 자체 기능을 베이스로 설계하고 데이터만 구글에서 가져온다 생각했다면 개발 생산성이 더욱 좋았을 것 같다.- TrelloQ. 기능을 구현하면서 느낀 아쉬웠던 점과 좋았던 점을 짚어달라.트렐로 공식 API 문서가 더 명확했다면 좀 더 개발이 수월했을 것이다. 문서가 RESTful하게 end-point path는 간결하게 잘 정돈되어 있지만, 각 요청 parameter에 대한 설명이나 response 데이터 등이 명확하게 정리되지 않아서 적합한 API를 찾거나 불명확함을 걷어내기 위한 테스트를 하다 보니 전반적으로 시간이 길어지고 비효율적이었던것 같다.그에 반해 트렐로에서 웹훅 이벤트를 발생시키기 위한 유저 액션들이 비교적 간단하고, 그에 따른 콜백 리퀘스트 또한 누락 없이 빠르게 잘 들어와서 그나마 쉽게 테스트를 할 수 있었다.Q. 기능 구현을 위해선 반드시 알아야 할 웹훅 이벤트 종류 및 데이터에 대한 문서는 정리가 전혀 안 되어있다고 하던데 정말인가?그렇다. 처음엔 좀 당황했지만, 그래도 방법이 없으니 일일이 경우마다 테스트해보면서 직접 정리를 하려고 했다. 하지만 각 웹훅마다 큰 구분만 있고 세세한 데이터는 너무 다양해서 깔끔하게 정리하기가 어려워 따로 공유를 위한 문서를 만들지는 못했다. 예를 들자면 트렐로에서 updateCard 라는 action type의 웹훅 데이터를 보내주는데, 그 데이터만 보고 “Card Archive”, “Description 수정/삭제”, “Due date 등록/수정”, “카드 이동” 등의 여러 가지 서로 다른 이벤트를 구분해야 한다. 근데 그 구분하는 방법이 특정 flag가 있는 게 아니라서 각 data를 모아놓고 역으로 분리하다 보니 코드를 깔끔하게 작성하기가 어려움은 물론, 추후 트렐로 측 데이터의 변동이 있을 때의 품질을 보장할 수 없는 리스크를 안고 구현할 수밖에 없었다.Q. 그 밖의 도움이 될만한 노하우나 꿀팁이 있다면?만약 트렐로와 어떤 형태로든 연동하려고 한다면, 설계 전에 모든 API에 대해 꼼꼼히 살펴보고 웹훅 이벤트 또한 직접 테스트해서 일단 전체적으로 리스트업을 정리하는 게 보다 생산성에 도움이 될 것이다. 트렐로를 잘 알고 있더라도 서비스 내부에서 “보드”, “리스트”, “카드”가 어떤 상관관계를 가지는지 미리 정리해보는 것도 좋다.사소하지만 좀 특이했던 점은 웹훅을 처음 등록할 때 해당 URL로 확인 요청을 한번 하는데, 이때 요청은 HTTP method가 POST가 아닌 HEAD로 들어온다. 그래서 반드시 동일한 URL의 HEAD 요청에 대해서도 정상 응답을 할 수 있도록 구현해야 한다.마무리잔디 커넥트를 구현하면서 특히 서비스 품질과 개발 속도 간의 밸런스에 대한 고민을 많이 했습니다. 초반에 서비스 종류별로 작업을 분리하고 각각의 방식으로 설계한 뒤 나중에 정리하는 전략이다 보니 공통으로 가져갈 수 있는 DB 모델이나 서비스 로직이 많아서 이를 통합하기 위해 반복 작업을 할 수밖에 없었는데 이 부분이 저희 내부적으로 느낀 가장 아쉬운 부분이 아니었나 생각합니다. 기능 중 많은 부분이 외부 서비스에 의존적이다 보니 생각하지도 못한 크고 작은 이슈들이 발생해서 일정 산출에도 꽤 어려움을 겪었습니다.커넥트 기능을 출시한 이후로 꽤 시간이 지났음에도 불구하고 이슈 백로그(Backlog)를 보니 아직도 개선할 부분이 많이 남아있는 듯 합니다. 그렇지만 이번에 기반이 되는 작업을 최대한 튼튼히 하기 위한 많은 시행착오를 거쳤기에, 추후 연동되는 커넥트 종류를 늘려나가는 시점5에 보다 효과적으로 개발할 수 있을 것이라 기대하면서 이번 글을 마치겠습니다.Slack API 문서 참고 ↩vagrant의 box로 서로의 로컬 개발 환경을 동일하게 유지하고 있습니다. 참고로, 현재 저희 서버 환경은 Local - Dev - Staging - Production으로 구성되어 단계별로 상황에 알맞게 배포하고 있습니다. ↩Localization의 약어. 잔디는 아시아 시장에 최적화된 서비스를 제공하고자 한국어, 일본어, 중국어 간체자(중국), 번체자(대만/홍콩), 영어 총 5가지 언어를 지원합니다. ↩아이캘린더(iCalendar)로 불리는 인터넷 캘린더의 데이터 포맷에 관한 표준. IETF 문서참고 ↩구체적인 시점은 말씀드리기 어렵지만, 더욱 좋은 사용성을 제공하고자 유저분들의 설문조사를 진행하고 있으니 많은 참여 부탁드립니다. ↩#토스랩 #잔디 #JANDI #개발후기 #일지 #인사이트
조회수 1105

AndroidAnnotations 과 테스트

이 포스팅은 총 4부로 이어지며 현재는 4부입니다.1부 : Android, MVC, MVVM, MVP2부 : Android 와 Annotation3부 : AndroidAnnotations 과 MVC4부 : AndroidAnnotations 과 테스트앞선 3개의 포스팅을 통해 AndroidAnnotations 과 MVC 가 view 에 관여하는 동작들이 모두 View 로 분리된 것을 확인할 수 있습니다.이러한 구조덕분에 Model 에 대한 테스트와 View 에 대한 테스트가 명확히 구분지어지게 되었습니다.Test 코드를 작성함에 있어서 View 에 대한 테스트가 다소 어려움이 있다는 것을 감안한다면 Model 에 대한 테스트만 집중할 수 있는 구조가 테스트에 대한 접근을 더욱 쉽게 해줍니다.다음은 앞선 포스팅에서 정의된 코드 중에서 Model 에 대한 테스트입니다.※ 테스트코드는 Robolectric 을 이용하여 작성하도록 하겠습니다.Model Test@RunWith(RobolectricGradleTestRunner.class) public class MainModelTest { private MainModel mainModel; @Setup public void init() { mainModel = new MainModel(Robolectric.application); } @Test public void testGetReleaseState() { // given String version = "3.19" // not yet released // when boolean isReleased = mainModel.getReleaseState(version); // then assertThat(isReleased, is(equalTo(false)); // given version = "3.18" // released // when isReleased = mainModel.getReleaseState(version); // then assertThat(isReleased, is(equalTo(true)); } }위와 같이 Model 만 별도로 테스트가 용이해졌습니다.Presenter TestPresenter 에 대한 테스트는 Model 에 대한 테스트와 다릅니다.Activity 에 커플링이 높기 때문에 해당 Activity 를 직접 바인딩해야 합니다.@RunWith(RobolectricGradleTestRunner.class) public class MainViewTest { private MainActivity mainActivity; private MainView MainView; @Setup public void init() { mainActivity = Robolectric.buildActivity(MainActivity.class).create().start().resume().get(); MainView = mainActivity.mainView; } @Test public void testGetVersionText() { // given String version = "3.19" // when MainView.versionEditText.setText(version); // then assertThat(MainView.getVersionText(), is(equalTo(version)); } }Jandi Team은 View 를 테스트하기 위해서 Presenter 와 Activity 의 패키지 Level 을 같은 Level 로 유지하고 있습니다.AndroidAnnotations 에서 DI 를 설정하기 위해서는 해당 변수나 메소드는 최소 Package Scope 로 정의해야하기에 위와 같은 형태의 Field 접근을 볼 수 있습니다.정리AndroidAnnotations 를 활용한 MVC 패턴의 전환의 또다른 이점은 이와 같이 테스트를 명확히 분리할 수 있다는 장점을 주었습니다. 물론 이 방법은 MVVM, MVP 로 구현하였을때보다 나은 형태라 할 수는 없으나 View 에 대한 테스트가 좀 더 용이해진 것이라 생각합니다.※ Activity 는 왜 테스트하지 않나요?MVP 패턴에서 Activity는 Controller 의 모습을 지니고 있습니다. 이는 Unit Test 가 아닌 Behavior 테스트에 가까운 모습이며 다른 방식으로의 테스트코드 구현이 필요하다고 생각합니다.#토스랩 #잔디 #JANDI #개발 #개발자 #개발팀 #기술스택 #일지 #후기 #꿀팁 #인사이트
조회수 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. 소통 능력과 균형 감각. 코스 매니저는 수업을 만드는 모든 단계에서 다양한 이해당사자들과 일하게 돼요. 이들과 원활하게 소통하고 의견을 공유하는 게 중요하죠. 그리고 다양한 사람들 사이에서 최고의 균형을 찾아내는 것도 중요해요. 예를 들어서 선생님의 경우 개발만 해왔고 교육이라는 것을 접해본 적이 없는 분들이 대부분이고, 학생은 프로그래밍을 처음 접하면 그 수업이 좋은 건지 아닌지 평가하기 어려워요. 때문에 코스 매니저가 이 둘 사이에 다리를 놓는 중재자의 역할을 하기 위해서는 다양한 시각에서 볼 수 있는 균형 감각이 필요하다고 생각해요.최고의 실력자들과 함께 일하며 프로덕트의 처음부터 끝까지를 만드는 경험을 통해서 사람들의 성장을 돕는 가치를 창출하고 싶으신 분이라면,>> 코스 매니저에 도전해 보세요! <<#엘리스 #코딩교육 #교육기업 #기업문화 #조직문화 #서비스소개 #팀원인터뷰 #팀원소개

기업문화 엿볼 때, 더팀스

로그인

/