스토리 홈

인터뷰

피드

뉴스

조회수 940

비트윈의 HBase 스키마 해부 - VCNC Engineering Blog

비트윈에서는 HBase를 메인 데이터베이스로 이용하고 있습니다. 유저 및 커플에 대한 정보와 커플들이 주고받은 메시지, 업로드한 사진 정보, 메모, 기념일, 캘린더 등 서비스에서 만들어지는 다양한 데이터를 HBase에 저장합니다. HBase는 일반적인 NoSQL과 마찬가지로 스키마를 미리 정의하지 않습니다. 대신 주어진 API를 이용해 데이터를 넣기만 하면 그대로 저장되는 성질을 가지고 있습니다. 이런 점은 데이터의 구조가 바뀔 때 별다른 스키마 변경이 필요 없다는 등의 장점으로 설명되곤 하지만, 개발을 쉽게 하기 위해서는 데이터를 저장하는데 어느 정도의 규칙이 필요합니다. 이 글에서는 비트윈이 데이터를 어떤 구조로 HBase에 저장하고 있는지에 대해서 이야기해 보고자 합니다.비트윈에서 HBase에 데이터를 저장하는 방법Thrift를 이용해 데이터 저장: Apache Thrift는 자체적으로 정의된 문법을 통해 데이터 구조를 정의하고 이를 직렬화/역직렬화 시킬 수 있는 기능을 제공합니다. 비트윈에서는 서버와 클라이언트가 통신하기 위해 Thrift를 이용할 뿐만 아니라 HBase에 저장할 데이터를 정의하고 데이터 저장 시 직렬화를 위해 Thrift를 이용합니다.하나의 Row에 여러 Column을 트리 형태로 저장: HBase는 Column-Oriented NoSQL로 분류되며 하나의 Row에 많은 수의 Column을 저장할 수 있습니다. 비트윈에서는 Column Qualifier를 잘 정의하여 한 Row에 여러 Column을 논리적으로 트리 형태로 저장하고 있습니다.추상화된 라이브러리를 통해 데이터에 접근: 비트윈에서는 HBase 클라이언트 라이브러리를 직접 사용하는 것이 아니라 이를 래핑한 Datastore라는 라이브러리를 구현하여 이를 이용해 HBase의 데이터에 접근합니다. GAE의 Datastore와 인터페이스가 유사하며 실제 저장된 데이터들을 부모-자식 관계로 접근할 수 있게 해줍니다.트랜잭션을 걸고 데이터에 접근: HBase는 일반적인 NoSQL과 마찬가지로 트랜잭션을 제공하지 않지만 비트윈에서는 자체적으로 제작한 트랜잭션 라이브러리인 Haeinsa를 이용하여 Multi-Row ACID 트랜잭션을 걸고 있습니다. Haeinsa 덕분에 성능 하락 없이도 데이터 무결성을 유지하고 있습니다.Secondary Index를 직접 구현: HBase에서는 데이터를 Row Key와 Column Qualifier를 사전식 순서(lexicographical order)로 정렬하여 저장하며 정렬 순서대로 Scan을 하거나 바로 임의 접근할 수 있습니다. 하지만 비트윈의 어떤 데이터들은 하나의 Key로 정렬되는 것으로는 충분하지 않고 Secondary Index가 필요한 경우가 있는데, HBase는 이런 기능을 제공하지 않고 있습니다. 비트윈에서는 Datastore 라이브러리에 구현한 Trigger을 이용하여 매우 간단한 형태의 Secondary Index를 만들었습니다.비트윈 HBase 데이터 구조 해부페이스북의 메시징 시스템에 관해 소개된 글이나, GAE의 Datastore에 저장되는 구조를 설명한 글을 통해 HBase에 어떤 구조로 데이터를 저장할지 아이디어를 얻을 수 있습니다. 비트윈에서는 이 글과는 약간 다른 방법으로 HBase에 데이터를 저장합니다. 이에 대해 자세히 알아보겠습니다.전반적인 구조비트윈에서는 데이터를 종류별로 테이블에 나누어 저장하고 있습니다. 커플과 관련된 정보는 커플 테이블에, 유저에 대한 정보는 유저 테이블에 나누어 저장합니다.각 객체와 관련된 정보는 각각의 HBase 테이블에 저장됩니다.또한, 관련된 데이터를 하나의 Row에 모아 저장합니다. 특정 커플과 관련된 사진, 메모, 사진과 메모에 달린 댓글, 기념일 등의 데이터는 해당 커플과 관련된 하나의 Row에 저장됩니다. Haeinsa를 위한 Lock Column Family를 제외하면, 데이터를 저장하기 위한 용도로는 단 하나의 Column Family만 만들어 사용하고 있습니다.각 객체의 정보와 자식 객체들은 같은 Row에 저장됩니다.또한, 데이터는 기본적으로 하나의 Column Family에 저장됩니다.이렇게 한 테이블에 같은 종류의 데이터를 모아 저장하게 되면 Region Split하는 것이 쉬워집니다. HBase는 특정 테이블을 연속된 Row들의 집합인 Region으로 나누고 이 Region들을 여러 Region 서버에 할당하는 방식으로 부하를 분산합니다. 테이블을 Region으로 나눌 때 각 Region이 받는 부하를 고려해야 하므로 각 Row가 받는 부하가 전체적으로 공평해야 Region Split 정책을 세우기가 쉽습니다. 비트윈의 경우 커플과 관련된 데이터인 사진이나 메모를 올리는 것보다는 유저와 관련된 데이터인 메시지를 추가하는 트래픽이 훨씬 많은데, 한 테이블에 커플 Row와 유저 Row가 섞여 있다면 각 Row가 받는 부하가 천차만별이 되어 Region Split 정책을 세우기가 복잡해집니다. RegionSplitPolicy를 구현하여 Region Split 정책을 잘 정의한다면 가능은 하지만 좀 더 쉬운 방법을 택했습니다.또한, 한 Row에 관련된 정보를 모아서 저장하면 성능상 이점이 있습니다. 기본적으로 한 커플에 대한 데이터들은 하나의 클라이언트 요청을 처리하는 동안 함께 접근되는 경우가 많습니다. HBase는 같은 Row에 대한 연산을 묶어 한 번에 실행시킬 수 있으므로 이 점을 잘 이용하면 성능상 이득을 얻을 수 있습니다. 비트윈의 데이터 구조처럼 특정 Row에 수많은 Column이 저장되고 같은 Row의 Column들에 함께 접근하는 경우가 많도록 설계되어 있다면 성능 향상을 기대할 수 있습니다. 특히 Haeinsa는 한 트랜잭션에 같은 Row에 대한 연산은 커밋시 한 번의 RPC로 묶어 처리하므로 RPC에 드는 비용을 최소화합니다. 실제 비트윈에서 가장 많이 일어나는 연산인 메시지 추가 연산은 그냥 HBase API를 이용하여 구현하는 것보다 Haeinsa Transaction API를 이용해 구현하는 것이 오히려 성능이 좋습니다.Column Qualifier의 구조비트윈은 커플들이 올린 사진 정보들을 저장하며, 또 사진들에 달리는 댓글 정보들도 저장합니다. 한 커플을 Root라고 생각하고 커플 밑에 달린 사진들을 커플의 자식 데이터, 또 사진 밑에 달린 댓글들을 사진의 자식 데이터라고 생각한다면, 비트윈의 데이터들을 논리적으로 트리 형태로 생각할 수 있습니다. 비트윈 개발팀은 Column Qualifier를 잘 정의하여 실제로 HBase에 저장할 때에도 데이터가 트리 형태로 저장되도록 설계하였습니다. 이렇게 트리 형태로 저장하기 위한 Key구조에 대해 자세히 알아보겠습니다.Column Qualifier를 설계할 때 성능을 위해 몇 가지 사항들을 고려해야 합니다. HBase에서는 한 Row에 여러 Column이 들어갈 수 있으며 Column들은 Column Qualifier로 정렬되어 저장됩니다. ColumnRangeFilter를 이용하면 Column에 대해 정렬 순서로 Scan연산이 가능합니다. 이 때 원하는 데이터를 순서대로 읽어야 하는 경우가 있는데 이를 위해 Scan시, 최대한 Sequential Read를 할 수 있도록 설계해야 합니다. 또한, HBase에서 데이터를 읽어올 때, 실제로 데이터를 읽어오는 단위인 Block에 대해 캐시를 하는데 이를 Block Cache라고 합니다. 실제로 같이 접근하는 경우가 빈번한 데이터들이 최대한 근접한 곳에 저장되도록 설계해야 Block Cache의 도움을 받을 수 있습니다.비트윈에서는 특정 커플의 사진이나 이벤트를 가져오는 등의 특정 타입으로 자식 데이터를 Scan해야하는 경우가 많습니다. 따라서 특정 타입의 데이터를 연속하게 저장하여 최대한 Sequential Read가 일어나도록 해야 합니다. 이 때문에 Column Qualifier가 가리키는 데이터의 타입을 맨 앞에 배치하여 같은 타입의 자식 데이터들끼리 연속하여 저장되도록 하였습니다. 만약 가리키는 데이터의 타입과 아이디가 Parent 정보 이후에 붙게 되면 사진 사이사이에 각 사진의 댓글 데이터가 끼어 저장됩니다. 이렇게 되면 사진들에 대한 데이터를 Scan시, 중간중간 저장된 댓글 데이터들 때문에 완벽한 Sequential Read가 일어나지 않게 되어 비효율적입니다.이렇게 특정 타입의 자식들을 연속하게 모아 저장하는 묶음을 컬렉션이라고 합니다. 컬렉션에는 컬렉션에 저장된 자식들의 개수나 새로운 자식을 추가할 때 발급할 아이디 등을 저장하는 Metadata가 있습니다. 이 Metadata도 특정 Column에 저장되므로 Metadata를 위한 Column Qualifier가 존재합니다. 이를 위해 Column Qualifier에는 Column Qualifier가 자칭하는 데이터가 Metadata인지 표현하는 필드가 있는데, 특이하게도 메타데이터임을 나타내는 값이 1이 아니라 0입니다. 이는 Metadata가 컬렉션의 맨 앞쪽에 위치하도록 하기 위함입니다. 컬렉션을 읽을 때 보통 맨 앞에서부터 읽는 경우가 많고, 동시에 Metadata에도 접근하는 경우가 많은데, 이 데이터가 인접하게 저장되어 있도록 하여 Block Cache 적중이 최대한 일어나도록 한 것입니다.Datastore 인터페이스비트윈에서는 이와 같은 데이터 구조에 접근하기 위해 Datastore라는 라이브러리를 구현하여 이를 이용하고 있습니다. HBase API를 그대로 이용하는 것보다 좀 더 쉽게 데이터에 접근할 수 있습니다. GAE의 Datastore와 같은 이름인데, 실제 인터페이스도 매우 유사합니다. 이 라이브러리의 인터페이스에 대해 간단히 알아보겠습니다.Key는 Datastore에서 HBase에 저장된 특정 데이터를 지칭하기 위한 클래스입니다. 논리적으로 트리 형태로 저장된 데이터 구조를 위해 부모 자식 관계를 이용하여 만들어 집니다.Key parentKey = new Key(MType.T_RELATIONSHIP, relId); Key photoKey = new Key(parentKey, MType.T_PHOTO, photoId); // 특정 커플 밑에 달린 사진에 대한 키 Datastore는 Key를 이용해 Row Key와 Column Qualifier를 만들어 낼 수 있습니다. Datastore는 이 정보를 바탕으로 HBase에 새로운 데이터를 저장하거나 저장된 데이터에 접근할 수 있는 메서드를 제공합니다. 아래 코드에서 MUser 클래스는 Thrift로 정의하여 자동 생성된 클래스이며, Datastore에서는 이 객체를 직렬화 하여 HBase에 저장합니다.MUser user = new MUser(); user.setNickname("Alice"); user.setGender(Gender.FEMALE); user.setStatus("Hello World!"); Key userKey = new Key(MType.T_USER, userId); getDatastore().put(userKey, user); user = getDatastore().get(userKey); getDatastore().delete(userKey); 또한, Datastore는 Key를 범위로 하여 Scan연산이 할 수 있도록 인터페이스를 제공합니다. Java에서 제공하는 Try-with-resource문을 이용하여 ResultScanner를 반드시 닫을 수 있도록 하고 있습니다. 내부적으로 일단 특정 크기만큼 배치로 가져오고 더 필요한 경우 더 가져오는 식으로 구현되어 있습니다.try (CloseableIterable> entries = getDatastore().subSibling(fromKey, fromInclusive, toKey, toInclusive)) { for (KeyValue entry : entries) { // do something } } Secondary Index 구현 방법HBase는 데이터를 Row Key나 Column Qualifier로 정렬하여 저장합니다. 이 순서로만 Sequential Read를 할 수 있으며 Key값을 통해 특정 데이터를 바로 임의 접근할 수 있습니다. 비트윈에서는 특정 달에 해당하는 이벤트들을 읽어오거나 특정 날짜의 사진들의 리스트를 조회하는 등 id 순서가 아니라 특정 값을 가지는 데이터를 순서대로 접근해야 하는 경우가 있습니다. 이럴 때에도 효율적으로 데이터에 접근하기 위해서는 id로 정렬된 것 외에 특정 값으로 데이터를 정렬할 수 있어야 합니다. 하지만 HBase에서는 이와 같은 Secondary Index 같은 기능을 제공하지 않습니다. 비트윈 개발팀은 이에 굴하지 않고 Secondary Index를 간단한 방법으로 구현하여 사용하고 있습니다.구현을 간단히 하기 위해 Secondary Index를 다른 데이터들과 마찬가지로 특정 타입의 데이터로 취급하여 구현하였습니다. 따라서 Index에 대해서도 Column Qualifier가 발급되며, 이때, Index에 해당하는 id를 잘 정의하여 원하는 순서의 Index를 만듭니다. 이런 식으로 원하는 순서로 데이터를 정렬하여 저장할 수 있으며 이 인덱스를 통해 특정 필드의 값의 순서대로 데이터를 조회하거나 특정 값을 가지는 데이터에 바로 임의 접근할 수 있습니다. 또한, Index에 실제 데이터를 그대로 복사하여 저장하여 Clustered Index처럼 동작하도록 하거나, Reference만 저장하여 Non-Clustered Index와 같이 동작하게 할 수도 있습니다. Datastore 라이브러리에는 특정 데이터가 추가, 삭제, 수정할 때 특정 코드를 실행할 수 있도록 Trigger 기능이 구현되어 있는데, 이를 통해 Index를 업데이트합니다. 데이터의 변경하는 연산과 Index를 업데이트하는 연산이 하나의 Haeinsa 트랜잭션을 통해 원자적으로 일어나므로 데이터의 무결성이 보장됩니다.못다 한 이야기각 테이블의 특정 Row의 Column들에 대한 Column Qualifier외에도 Row에 대한 Row Key를 정의 해야 합니다. 비트윈에서는 각 Row가 표현하는 Root객체에 대한 아이디를 그대로 Row Key로 이용합니다. 새로운 Root객체가 추가될 때 발급되는 아이디는 랜덤하게 생성하여 객체가 여러 Region 서버에 잘 분산될 수 있도록 하였습니다. 만약 Row Key를 연속하게 발급한다면 특정 Region 서버로 연산이 몰리게 되어 성능 확장에 어려움이 생길 수 있습니다.데이터를 저장할 때 Thrift를 이용하고 있는데, Thrift 때문에 생기는 문제가 있습니다. 비트윈에서 서버를 업데이트할 때 서비스 중지 시간을 최소화하기 위해 롤링 업데이트를 합니다. Thrift 객체에 새로운 필드가 생기는 경우, 롤링 업데이트 중간에는 일부 서버에만 새로운 Thift가 적용되어 있을 수 있습니다. 업데이트된 서버가 새로운 필드에 값을 넣어 저장했는데, 아직 업데이트가 안 된 서버가 이 데이터를 읽은 후 데이터를 다시 저장한다면 새로운 필드에 저장된 값이 사라지게 됩니다. Google Protocol Buffer의 경우, 다시 직렬화 할 때 정의되지 않은 필드도 처리해주기 때문에 문제가 없지만, Thrift의 경우에는 그렇지 않습니다. 비트윈에서는 새로운 Thrift를 적용한 과거 버전의 서버를 먼저 배포한 후, 업데이트된 서버를 다시 롤링 업데이트를 하는 식으로 이 문제를 해결하고 있습니다.
조회수 788

비트윈이 사용자를 분석하는 방법 - VCNC Engineering Blog

 빅데이터분석이 최근 이슈가 되면서 관심이 많으실 것 같습니다. 비트윈팀도 데이터 분석 참 좋아하는데요, 저희도 한번 해보았습니다. 이번 포스팅에서는 비트윈팀의 데이터 분석 노하우를 아낌없이 공유해드립니다.왜 사용자의 데이터를 분석해야하는가요?비트윈같은 서비스는 초기 단계에는 앱을 기획하고 만들어낸 팀에 아이디어에 의해 계속해서 발전하고, 유지됩니다. 하지만 기능이 점점 다양해지고 사용자가 점점 많아지면서 사용자들의 앱 사용패턴을 점점 예측하기 어려워집니다. 게다가 비트윈은 해외 진출을 구상 중이었는데, 개인 혹은 팀의 아이디어만으로 해외에서의 사용패턴을 정확히 알기는 어려웠습니다.이런 시점에 필요한 것이 사용자 분석입니다.사용자들의 사용패턴을 분석해 보는 방법은 여러 가지가 있습니다. 초기에 해볼 수 있는 가장 직관적이고 쉬운 것은 비트윈을 사용하는 자기 자신의 사용 패턴을 돌아보고 분석해보는 것입니다. 또 친구들이나 익명 사용자들의 사용패턴을 물어보거나, 관찰하는 방법들이 있습니다. 이런 방법은 매우 효과적이고 많은 아이디어를 주지만 여러 가지 한계점이 있습니다. 지역적, 시간적인 한계 등이 그것입니다.그래서 택할 수 있는 방법이 실제로 사용자들의 행동을 컴퓨터로 수집해서 분석하는 것입니다. 말 그대로 '데이터 분석'을 하게 되는 것입니다.무엇을 분석할지 알아야 합니다데이터로 분석할 수 있는 것은 무궁무진합니다만, 먼저 데이터가 있어야합니다. 비트윈과 같이 서버와 통신하는 앱은 사용자들이 서버에 요청을 할 때마다 엑세스 로그를 남기게 됩니다. 이 엑세스 로그는 사용자들의 사용패턴을 고스란히 담고 있어, 소중한 데이터가 됩니다.엑세스 로그 분석은 전혀 어렵지 않습니다. 엑세스 로그에서 특정 행동에 해당하는 내용을 세는 것만으로도 여러 가지 유의미한 값을 얻어낼 수 있습니다. 하루 동안의 로그를 한줄씩 읽어서 메시지에 관련된 로그를 카운트하면 그날의 메시지 전송 건수를 얻을 수 있는 것입니다. (참 쉽죠?)엑세스로그에서 가입, 메시지, 사진, 메모 등 기본적인 내용에 해당하는 것들을 카운트하는 것만으로도 꽤 자세하게 앱 전체 사용자들의 전반적인 사용통계를 얻어낼 수 있습니다. 이제 해당 데이터를 엑셀에 넣어서 차트를 그려보면, 사용 통계에 대한 그럴싸한 차트가 그려집니다.엑세스 로그 분석에 성공했다면 좀 더 다양한 분석을 해볼 수 있을 텐데요, 사용자별 행동패턴 분석이나, 나라별, 혹은 아이폰, 안드로이드 디바이스별 분석 등 다양한 분석을 시도해볼 수 있습니다. 분석을 하기 전에 중요한 것은 무엇이 궁금한지, 어떻게 궁금한 데이터를 모을지 아이디어를 먼저 내는 것입니다. 여러 예제들을 찾아보며 공부해보면, 금방 좋은 아이디어를 얻으실 수 있을 겁니다.물론 여기서 중요한것은 개인정보나 사생활의 보호입니다. 로그가 유출되었을때의 보안 문제 뿐 아니라, 데이터 분석팀에게조차 개인정보가 노출된다면 곤란합니다. 이 문제에 저희가 어떻게 대처하고 있는지는 글 뒷부분에 자세히 알려드리겠습니다.특정 기술에 구애받지 말고 다양하게 구현해봅시다처음에는 로그 파일을 돌며 간단한 string을 검사하는 스크립트와 엑셀로도 충분했지만, 점점 복잡한 분석을 할수록 다양한 기술이 필요해집니다. 비트윈 사용자 분석도 점점 다양해지고 복잡해지면서 여러 가지 기술들을 사용하고 있습니다.비트윈 사용자 분석은 처음에는 6줄짜리 간단한 shell script에서 시작되었습니다.cat 2011-10-31.log | grep /messages | grep POST | wc -l cat 2011-10-31.log | grep /photos | grep POST | wc -l cat 2011-10-31.log | grep /memos | grep POST | wc -l cat 2011-10-31.log | grep /like | grep POST | wc -l cat 2011-10-31.log | grep SIGN | wc -l cat 2011-10-31.log | grep REL | grep POST | wc -l 이런 스크립트를 만들어서 결과를 이메일로 공유하거나, 엑셀로 만들어 놓곤 했습니다.여기에 비트윈 분석은 조금 더 발전하여, 로그파일을 쿼리하여 Map Reduce 작업이 가능한 Hive를 사용하고, PHP로 통계 웹사이트를 만들어 차트를 그리기 시작했습니다. 이 방식은 처음에는 매우 편리했지만 차츰 쿼리만으로 원하는 결과를 얻기가 힘든 다소 복잡한 분석이 필요해지기 시작했습니다.현재는 모든 로그를 분산 데이터베이스인 HBase에 Date Key와 User Key로 넣고, 코드 생산성이 좋은 Scala로 직접 Map Reduce코드를 작성해서 데이터들을 분석하고 있습니다. 그래서 충분히 scalable하면서도 꽤 편리하게 이용할 수 있는 데이터베이스를 활용하고, Scala의 좋은 expression을 활용하여 짧고 유지보수나 확장이 쉬운 코드로 분석을 수행하면서도 Java와 호환되는 Scala의 특성을 이용하여 Map Reduce 코드 작성을 효과적으로 하고 있습니다. 이렇게 분석한 데이터는 MySQL에 넣어서 2차로 가공하고, Scala Web Framework인 Play Framework을 이용하여 분석 사이트를 구축하고 D3 Chart를 이용해서 Visualize하고 있습니다. 이렇게 함으로써 편리한 MySQL 쿼리 사용의 장점을 취하고 멋진 차트를 효과적으로 그려낼 수 있습니다.좋은 Visualization은 멋질 뿐만 아니라 손쉽게 아이디어를 공유할 수 있게 해줍니다.앞으로는 더 빠른 성능을 위해 Hive를 더 잘 사용해보거나, Elastic Search같은 index engine들을 사용해 볼 계획도 가지고 있습니다. 또한 End point들에서 직접 성능을 측정하여 중앙으로 모아서 분석해보려는 생각도 가지고 있습니다.기술을 선택함에 있어서 정답은 없는 거 같습니다. 널리쓰이는 MySQL같이 scalability가 좀 떨어지지만, 다양한 쿼리로 높은 생산성을 낼 수 있는 데이터베이스도 있고, HBase같이 scalability가 좋지만, 데이터를 저장하는 형태에 제한이 있어 생산성이 조금 떨어지는 데이터베이스도 있습니다. 저희는 앞서 소개드렸듯이 이 두 가지를 모두 혼용하여 사용하고 있습니다. 각자가 마주한 상황에 맞게, 또 각자가 익숙한 기술에 맞게 설계하고, 사용해보면 됩니다.개인정보 보호는 철저하게빅데이터 분석이 개인정보를 침해하는 빅 브라더가 될 수 있다는 우려들이 나오고 있습니다. 300만이 넘는 커플들의 비밀스러운 일기를 담고 있는 비트윈 서비스는 당연하게도 모든 업무를 진행하는 데 있어 보안과 개인정보를 최우선으로 하고 있습니다. 데이터 분석에서도 분석할 수 있는 내용을 상당히 제한받더라도, 예외 없이 그 원칙을 지키고 있습니다.비트윈의 API서버는 AWS클라우드에서 운영되고 있는데, 사용료가 상당히 비싸기 때문에 큰 컴퓨팅 파워를 사용해야 하는 데이터분석까지 AWS에서 하기엔 좀 부담이 되었습니다. 그래서 PC급 컴퓨터 여러 대를 구입하여 사무실 구석에 쌓아놓고 사용하고 있습니다.하지만 문제는 보안이었습니다. AWS의 비트윈 API서버는 다중으로 보안이 유지되고 있지만, 사무실에 있는 서버에 사용자들의 개인정보를 담아둘 수는 없는 일이었습니다. SECO*이 사무실을 지켜주고 있긴 하지만 보안회사에 고객들의 소중한 개인정보를 맡기고 안심할 수는 없으니까요. 그리고 설사 보안 문제가 잘 해결된다고 해도, 분석을 수행하는 비트윈 데이터분석팀원에 개인정보 혹은 사생활이 노출된다면 그 또한 문제라고 생각하였습니다.그래서 저희가 생각해낸 방법은 '익명화'입니다. Access Log들을 저장할 때 사용자의 아이디를 전부 단방향 salted-hash하여 누구인지 알 수 없게 만들었습니다. (물론 salt key는 데이터 분석팀은 알 수 없습니다.) 그리고 애초에 Access Log에는 '어떤 사람'이 '50글자짜리 메시지를 보냈다' 라던가, '사진을 올렸다' 정도만 기록이 되기 때문에, 이를 통계적으로 분석하는 것은 유의미하지만, 사적인 정보를 담고 있지는 않습니다.익명화되어 처리되고 있는 로그는 개인정보는 거의 담고 있지 않으면서도, 유익한 분석 결과를 만들어줍니다.이런식으로 운영을 한다면 데이터 분석팀에서도 사적인 정보(예: 메시지 내용)에 대해서는 접근할 수 없기 때문에, 회원들의 소중한 개인정보와 사생활을 지킬 수 있습니다. 어떤 분석을 수행할 때 언제나 비트윈팀은 언제나 보안과 사생활 보호의 원칙을 지킬 수 있는 범위에서만 진행하고 있습니다.아이디어의 공유, 그리고 액션아이템이 무엇보다도 중요합니다데이터 분석의 목표가 무엇인지, 왜 해야 하는지 생각해보면, 무엇을 해야 하는지 알 수 있습니다. 바로 분석으로부터 얻은 아이디어를 공유하고 액션아이템을 정하고 실천하는 것입니다.데이터를 visualization하는것이 중요한 이유가 여기에 있습니다. 보기 좋은 떡이 먹기도 좋다는 말이 있듯이, 데이터도 먹기 좋아야 합니다. 여러 사람이 쉽게 이해할 수 있어야 아이디어를 공유하고 의사결정을 내리기가 수월하기 때문입니다.민트&베리 사용량 분석. 연인들이 쓰는 앱이라 사랑표현이 인기가 많군요. 디자인팀이 이런 자료를 참고하여 이후 디자인 아이디어를 내는 데 도움이 되면 좋겠죠?비트윈팀은 매번 데이터 분석 미팅을 진행하고 나면 액션아이템을 정하고 실천합니다. 저희가 어떤 식으로 의사결정을 내리고 행동하는지에 대해서는 비트윈 팀블로그의 VCNC는 데이터분석에 기반해 어떤 결정을 내렸나 포스팅을 보시면 도움이 되실 것 같네요.맺으며이번 포스팅에서는 비트윈팀이 어떻게 무엇을 분석하는지 간단하게 다뤄봤습니다. 의견이나 참견 모두 환영이니 댓글 많이 남겨주세요! 다음번 포스팅엔 기술적인 부분에 대해 좀 더 자세하게 다뤄보도록 하겠습니다.
조회수 2288

리브랜딩을 생각하다.

최근 핀다는 리뉴얼된 브랜딩과 사이트를 론칭하였습니다. 브랜드에 대한 인식과 사이트 사용성에 대한 깊은 고민이 지속되었고, 그에 대한 해결책으로 브랜드 아이덴티티와 사이트를 전면 교체하기로 결정하였습니다. 이번 글에서는 첫 번째로 새로운 브랜드 아이덴티티를 기획 및 개발하면서 느낀 점을 공유하는 시간을 가지려고 합니다.왜 리브랜딩인가  리브랜딩(Rebranding)을 진행하는 기업들은 많습니다. 그들이 리브랜딩을 진행할 때는 그 이유가 있을 것이고, 그에 따른 고민 또한 많을 것입니다. 예를 들면, 기존의 톤 앤 매너(Tone & Manner)를 유지해야 할까, 아니면 혁신적인 변화(Innovative Change)가 필요할까? 브랜드 인식(Brand Recognition)이나 기업 가치(Enterprise Value)가 하락하지 않을까? 등 다각도에서 고려해야 될 부분이 있습니다. 그래서 많은 기업들이 리브랜딩을 장기 프로젝트(Long Term Plan)로 많은 시간을 투자합니다. 그렇다면, 핀다는 이렇게 고려해야 될 사항이 많고, 고민 또한 많은 리브랜딩을 왜 결정했고, 진행했을까요?  가장 핵심적인 이유는 핀다는 ‘금융’ 특히, 핀테크(Fintech)에 속해 있는 기업이라는 것이었습니다.  즉, 금융(Finance)과 기술(Technology)를 함께 다루는 기업으로서의 적합한 브랜드 아이덴티티를 가지고 있어야 됩니다. 추상적이지만, 실제로 믿을 만한(Reliable), 정직한(Honest), Expertise(전문 지식) 등의 단어들처럼 금융 관련 기업에서 필수적으로 쓰이고 있는 단어들이 있습니다. 모든 분야를 막론하고, 기업들은 이러한 핵심 단어들을 토대로 자신들의 본질적인 핵심가치(Core Value)를 세우고, 이미지를 만들어가고 있습니다. 하지만, 기존의 아이덴티티는 금융 회사를 대표하는 얼굴로서 부족한 부분들이 있었고, 특히, 금융 관련 기업으로서 우리들이 만들고 싶은 서비스의 본질적인 핵심 가치의 부재를 메우기 위한 리브랜딩이 필수적이었습니다.핵심 가치  기존의 핀다의 핵심가치는 혼재되어있었습니다. 다양한 가치를 담고 있는 것이 브랜드를 다양한 측면에서 설명할 수 있는 방법이 될 수 있겠지만, 반면에 ‘핵심'이 없다는 생각이 들기도 합니다. 현재의 디자인팀이 형성되기 전, 금융(Finance), 마켓 플레이스(Marketplace) 그리고 추천(Recommendation)이라는 3가지 큰 축으로 핀다를 정의하려는 고민이 있었습니다. 디자인팀은 이 세 가지 단어를 연결하고 핀다를 표현하는 핵심 문장을 만들었습니다.“핀다는 금융(Finance)의 비대칭성을 해결하기 위한 마켓 플레이스(Marketplace)로서, 각각의 사용자를 대상으로 다양한 상품을 빠르고 정확하게 추천(Recommendation) 하는 서비스입니다.”물론, 로고(Logo)에 저 핵심 문장의 뜻이 한눈에 다 보이게 만드는 것이 목표는 아니었습니다. 사실, 불가능에 가깝다고 느껴졌습니다. 저희에게 브랜드 아이덴티티란 단순히 로고의 형태를 바꾸는 것이 아닌, ‘그 가치를 시각적으로 표현할 수 있는 가장 적합한 수단을 만드는 것’이었습니다. 보통은 로고를 먼저 만들고 다른 시각적 커뮤니케이션 도구(Visual Communication Tool)를 개발합니다. 하지만 핀다의 이번 리뉴얼 작업에서는 시각적 커뮤니케이션 도구를 만들고, 그에 적합한 로고를 완성하는 것을 목표로 했습니다.  기호로 표현하다  여기서 시각적 커뮤니케이션 도구(Visual Communication Tool)란, 좀 더 근본적으로 시각적 언어(Visual Language)를 뜻합니다. 소통의 도구로 문자(Letter)만 존재하지 않습니다. 우리는 보고, 듣고, 느낍니다. 그중에 시각적 언어는 ‘보는 것을 통해 그 뜻을 알다.'라고 말할 수 있습니다[1]. 굳이, 문자와 음성을 통한 커뮤니케이션이 아닌, 사진이나 무음의 영상으로 전하고 싶은 메시지를 전하는 것은 이 시대에 자연스러운 방식이 되었습니다. 여기서, 기호 체계(System of Symbol) 또한 빠질 수 없는 가장 효과적인 시각적 커뮤니케이션 도구 중 하나입니다. 빠르고 효과적인 커뮤니케이션을 위해 우리는 거의 일상의 모든 장소에서 기호 체계가 담긴 정보 디자인(Information Design)을 볼 수 있습니다. 남자 화장실과 여자 화장실을 굳이 구분하지 않아도 되듯이 말이죠.제주 오설록 티 뮤지엄  로고와 기호 체계는 형태를 집약적 단순화(Intensive simplification) 한다는 본질적 유사성(Similarity)을 가지고 있다고 판단하에, 디자인팀은 금융, 마켓 플레이스, 추천이라는 3가지 단어를 기호로 풀어낼 수 있다면, 그것을 최종적으로 로고의 형태로 가져가는 것이 가능하다고 생각하였습니다. 1년이 넘게 사용해온 로고이기 때문에 사용자의 인식에 있어서 부담이 없을 것이라는 의견이 있어, 기존 로고에서  형태를 가져오기로 하였습니다. ‘┏ ’의 형태는 기존 로고의 전체적인 틀을 만드는 골격이었고, 형태적으로도 활용도가 높다고 판단하였습니다.  다양한 조합을 시도하였고, 기존의 전통적인 기호 체계와는 다르게 독립적이 아닌, 여러 개의 기호들이 모여 하나의 의미를 만드는 방식을 선택하였습니다. 즉, 하나의 기호로는 그 뜻을 알기 힘듭니다. 반면에, 단일 기호만으로는 그 뜻을 전부 담기 힘든 단어들의 표현도 가능해졌습니다. 금융 분야와 관련된 어려운 단어들이 많이 쓰이기 때문에 그 표현의 한계치를 최대한으로 만들어 놓기 위한 결정이었습니다. 이 작업을 진행하면서 3가지의 핵심 가치 이외에도, 단순화된 기호 체계만으로 얼마든지 사용자와 커뮤니케이션이 가능할 것이라는 기대감이 생겼습니다.심볼을 없애다  핵심 가치를 기호화하면서 어느 정도 형태적 스타일를 구축한 상태에서의 첫 번째 고민은 로고에서 심볼(Symbol)를 유지할지에 대한 논의였습니다. 심볼을 사용할지 말지에 대한 그 결정에 있어서 ‘합리적인 이유(Rational Reason)’를 찾고 싶었습니다. 전 세계의 수많은 기업들은 크게 두 가지 부류로 나눌 수 있습니다. 로고에 심볼을 사용하는 기업과 사용하지 않는 기업. 그렇다면 그들도 그 결정에 있어서 어떠한 선택 기준이 있었을 것입니다. 저희의 판단 기준은 어찌 보면 단순했습니다. ‘꼭 필요한가?’입니다. 그리고 그 꼭 필요한 이유를 결국 찾지 못하였습니다. 무조건적으로 ‘남들이 다 만드니까 우리도 만들자.’라는 이유로 만들고 싶지는 않았습니다. 자연스럽게, 아마존이나 삼성 같은 기업들이 저희의 지표가 되었습니다.  ‘심볼을 쓰지 않는다.’는 결정 이후에 저희가 한 일은 FINDA의 타입 페이스(Typeface)에 기호 체계와 마찬가지로 ‘┏ ’의 형태를 녹이는 것이었습니다. ‘┏ ’은 핵심 가치를 표현하는 ‘핵심 요소'이자, 기존 로고와의 형태적 유사성을 가져올 수 있는 효과적인 수단이었습니다. 그리고, 다행스럽게도, 알파벳 ‘F’는 ‘┏ ’을 다양하게 시도해 볼  수 있는 형태를 가지고 있었습니다.  최대한 많이 ‘F’를 분할시켜 보았습니다. 처음에는 만족스러운 것들도 시간이 지남에 따라 가독성이나 완성도 면에서 떨어져 보이는 것이 느껴졌습니다. 수많은 시도 끝에 ‘유레카'를 외치는 형태적인 접근이 있었습니다.  최대한 많이 분할시키는 것에 혈안(?)이 되어있던 디자인팀에 좋은 교훈이 되었습니다. 어찌 보면, 존 마에다가 항상 강조해온 단순함(Simplicity)이 복잡함(Complexity)을 이긴다는 것을 직접적으로 느끼는 순간이기도 했습니다. 단순한 형태였지만, ‘F’전체를 ‘┏ ’의 형태로 적용할 수 있다는 것은 핀다의 기호 체계와도 가장 가깝게 접근해있습니다.컬러 입히기 형태적으로 로고를 완성한 후, 핀다의 새로운 색을 입히는 작업을 진행하였습니다. 기존의 사용하였던 색상은, 옅은 블루[#00A1D0]와 옅은 레드[#F05045]였습니다. ‘꽃이 핀다’를 상징하는 기존의 로고에서의 레드 색상은 어느 정도 합리적인 결정이었다고 생각하지만, 새로운 브랜딩 아이덴티티에서는 레드 색상의 존재에 대한 이유를 찾았을 수 없었고, 결국 쓰지 않기로 결정하였습니다. 또한, 기존의 핀다가 가지고 있는 블루 색상을 유지하면서, 깨끗하고 믿음을 줄 수 있는 톤을 가져가기 위해 좀 더 힘 있는 블루를 사용하였습니다.  블루는 브랜드를 대표하는 색상이고, 하위 색상으로 총 5개의 회색조를 선택하였습니다. 5개의 회색조는 각각의 쓰임새가 있으며, 철저히 가이드라인을 지키는 것을 목적으로 합니다.마치며  이번 리브랜딩 프로젝트를 진행하면서 느낀 점은 ‘목적을 가지고 시작하자.'입니다. 질린다. 안 이쁘다. 리소스가 남아돈다. 등의 이유로 시작하는 것은 리브랜딩의 적절한 시작점은 아닐 것입니다. 핀다의 리브랜딩에는 ‘핀테크 기업으로서의 브랜드 이미지 제고 (Brand Image Enhancement)'라는 확실한 목적이 있었습니다. 물론, 수익을 추구하는 기업의 특성상, 특히, 스타트업으로서, 오랜 기간을 리브랜딩에 투자할 시간적 여유는 없었고, 리소스로 충분하지는 않았습니다. 하지만, 핀다가 옳은 방향(Right Direction)으로 나아가고 있다는 확신은 심어준 중요한 프로젝트였습니다. 앞으로 다양한 표정을 짓는 핀다의 새로운 얼굴을 기대해주시기 바랍니다.핀다의 디자인팀 드림Design Team from Finda#핀다 #디자인 #디자이너 #브랜드 #브랜딩 #UX #UI #인사이트
조회수 578

IT 회사에서 뽑는 인재핵심은 Track record

학생, 교육자, 기업과 직접 소통하며 모든 교육을 기획하고 만들고 진행시키는 곳! 바로 엘리스 운영팀인데요. 엘리스의 실질을 만드는 운영팀에서는 어떤 생각과 방식으로 프로그래밍 교육을 만들어 갈까요? 교육의 효과는 그 내용이 아닌 방식에서 나온다는 엘리스 운영팀 리드가 직접 말합니다. IT 업계 채용에 대한 생각이 궁금하신 분들도 집중해보세요!자기소개.사회의 변화에 동력이 되도록 성장시키는 교육을 위합니다.Q. 안녕하세요! :) 자기소개 부탁드립니다.A. 자기소개 진짜 오랜만에 해봐요. 저는 워털루 대학교 컴퓨터과학과를 나왔구요. 배운 게 코딩이라고 코딩을 하다가 우연한 기회로 IT 교육 업계에서 일하게 된 지 어언 5년이 되어가는, 마음만은 신입사원인 엘리스 운영팀 매니저 유준배입니다.Q. 자바 프로그래머 출신이신 것으로 알고 있는데요, 어떻게 교육 업계에서 일하게 되셨나요?A. 루머입니다. 대학교 1학년 때 맨 처음 프로그래밍을 접했던 언어가 자바였어요. 이후로는 C++를 했기 때문에 자바는 잊고 지냈는데 엘리스에서 자바 과목을 만들 때 어시스턴트가 필요해서 여러 번 참여했을 뿐 자바 개발자였던 적은 한 번도 없어요. 전에 다니던 회사에서는 프론트엔드 단을 만드는 일을 하다가 회사를 그만두게 되면서 혼자 앱 개발을 공부했던 적이 있어요. 이때 앱을 만들어 달라는 요청이 왔는데 그게 교육회사였고 그 연으로 교육 회사에서 일하게 되었습니다. 사실 좋아하는 일을 해야 잘하는데 개발이라는, 좋아하지 않는 일을 계속할 자신이 없던 게 전향하게 된 큰 이유인 것 같아요.Q. 엘리스에서는 어떤 일을 하고 계신가요?A. 지금은 과목 제작 지원, 엘리스를 사용하는 기업들의 서포트, 팀 매니징 등 다양한 일을 하고 있어요. 제 성향 자체가 필요한 일을 찾아서 하는 걸 좋아하는데 지금 엘리스에서 하고 있는 일에는 필요가 아주 많아요. 누구도 개척한 적이 없기 때문에 맨땅에 헤딩이죠. 예를 들면 교육 콘텐츠를 만드는 일도 선생님, 교수님 등 더 잘하는 분들이 있을 텐데 그걸 엘리스 플랫폼에서 잘할 수 있느냐는 다른 문제예요. 저는 지금 누가 와도 엘리스에서 좋은 교육 서비스를 제공할 수 있도록 그 틀을 만드는 일을 하고 있어요. 어느 정도 체계가 잡혔을 때 제가 하고 싶은 일은 교육이 실질적으로 사람들에게 영향을 줄 수 있는 최대치가 어디까지인지를 체크해보는 일이에요. 예를 들면 부트캠프 같은 형태를 하나 맡아서 말이죠.Q. IT 교육을 하고자 하시는 동기가 무엇인지 궁금해요.A. 이 일이 굉장히 의미 있다고 생각해요. 그 이유는 교육이 사회 문제 해결의 최전방에 있다고 생각하기 때문이에요. 지금까지 겪은 바로 주어진 일을 잘하는 사람보다는 자기가 하고 싶은 일, 만들고 싶은 무언가가 있는 사람들이 늘 더 좋은 성과를 내고 좋은 대우를 받는 것 같아요. 그런데 학교에서의 교육이나 세상의 구조는 이런 사람보다는 주어진 일을 잘할 수 있는 사람을 만드는 시스템이라는 생각을 했어요. 주어진 틀 안에서 적응을 할 수 있는 사람들은 세상에 많고, 그 포지션들은 갈수록 줄어드는 형태예요. 실패를 하더라도 나 자신이 사회의 변화에 동력이 되는 방향이 되어야 궁극적으로는 내 가치를 높이는 방법이라고 생각해요. 단순히 어떤 내용을 가르치는 게 아니라 어떻게 배울 것인가, 어떤 습관과 마인드 셋을 가져야 하는가까지도 테스트해보고 싶고, 작더라도 몇십 명의 문제를 해결한다면 결국 비즈니스적으로도 큰 의미가 있을 거라고 생각해요.Q. 어떤 태도를 가지는 것이 내 가치를 올리는 데에 중요하다고 생각하시나요?A. 능동적으로 공부하는 태도인 것 같아요. 예를 들면 엘리스와 여러 번 협업하신 한 선생님은 개발을 시작하신 지 2년밖에 안 되셨는데요. 개발을 하면서 스스로 활동을 굉장히 많이 하신 분이에요. 능동적인 삶을 사니 개발자로서의 첫 커리어도 좋은 조건에 시작하셨고 지금은 실리콘밸리 회사로 가게 된 케이스예요. 제가 인터뷰했던 한 IT 회사에는 개발 백그라운드 0에서 시작해서 6개월 만에 취업하신 분도 계셨어요. 그분이 공부했던 내용을 빼곡히 기록한 블로그를 보고 감명을 받았어요. 엘리스 코스매니저 현곤님도 엑스트라 활동을 많이 하시죠. 그러면서 본인이 얻게 되는 깊이나 네트워크가 결국 자신의 가치를 올리는 데 있어서 매우 중요한 부분이고요. 이런 걸 알고 나니 전에 앱 개발했을 때의 제가 얼마나 우물 안 개구리였는가를 깨닫게 돼요. 만약 당시의 제가 다른 방식으로 접근했다면 좀 더 영향력 있는 개발자가 되었을 거라고 확신을 하거든요. 현재도 마찬가지이지만 점점 더 결국엔 기술력으로 모이게 될 거예요. 그 기술력을 가진 인재들의 가치가 올라갈 것이구요. 그런데 그 이상의 무엇이 필요하죠. 그게 능동적으로 공부하는 태도이고요. 프로그래밍 교육과 취업.교육자와 학생 모두의 비용을 낮추는 교육을 만듭니다.Q. 엘리스는 어떤 사회의 미션을 수행하고 있나요?프로그래밍 교육을 보다 더 적은 비용으로 제공해서 널리 확산시키는 역할이에요. 적은 비용이라는 건 시공간적 제약을 줄이는 것도, 금액을 줄이는 것도 포함돼요. 과외나 학원 같이 비싼 사교육을 MOOC 형태로 제공하거나 여러 교육 기관에게 적은 리소스로 교육을 할 수 있는 환경을 제공함으로써요. 엘리스라는 플랫폼이 있기 때문에 교육에서 중요한 피드백을 주고받는 일이 자동화돼서 선생님의 역할을 최소화할 수 있어요. 또 교육에서 필요한 휴먼터치(Human touch) 역시 튜터 서비스와 강의 영상, 플립러닝과 실습 형태로 제공하여 교육자의 비용을 줄일 수 있고요. 여러 허들을 낮추기 때문에 좋은 교육 콘텐츠를 적은 비용으로 제공할 수 있게 돼요.Q. 인터넷에 무료로 접할 수 있는 콘텐츠가 많은데 좋은 프로그래밍 교육 콘텐츠가 필요한가요?A. 무료 콘텐츠가 많다고 하지만 제대로 설계된 콘텐츠가 많냐면 그건 아니에요. 저희가 제대로 된 콘텐츠를 만듦으로써 사용자의 비용이 낮아지는 측면이 있어요. 교육의 효과가 결국엔 아웃풋이잖아요. 그 교육의 효과를 높이는 데에 드는 시간과 노력을 줄인다면 코스트 대비 아웃풋을 높이는 거죠.그리고 프로그래밍을 통해서 개발 직군으로 가는 사람의 인원은 10~20% 정도고 나머지 80~90%는 데이터를 다루는 데에 R을 사용하거나 디자이너인데 웹을 배운다든지 등의 형태일 거예요. 점점 더 이런 수요가 늘어나는데 이 분들에겐 일단 프로그래밍에 흥미를 붙이고 스스로 뭔갈 만들어보는 단계까지 가는 게 우선이 되어야 하거든요. 인터넷은 그걸 하기에는 너무 허들이 크고 불친절한 거죠.엘리스 프로그래밍 교육 콘텐츠들Q. 그렇다면 어떤 프로그래밍 교육 콘텐츠가 필요하다고 생각하시나요?A. 몰입할 수 있는 교육 콘텐츠예요. 더 빠른 피드백, 더 빠른 성취감이 있다면 그로 인해 학습 과정에 몰입이 될 수 있고, 개발자가 되고 싶은 사람도 이 교육의 혜택을 받을 수 있죠. 개발이란 건 어느 시점까지는 되게 힘들다가 그 시점이 넘어가고 내가 만들 수 있는 게 보이기 시작하면 재미있을 수 있거든요. 그런데 그 지점을 넘어가기가 어려워요. 이를 쉽게 넘어갈 수 있게 해 주고 좀 더 프로그래밍의 본질에 대해서 계속해서 재미를 알게 해주는 게 중요한 거죠.Q. 엘리스가 만드는 프로그래밍 과목은 어떤 형태인가요?A. 직접 뭔갈 만들 수 있는 가장 빠른 길을 모든 과목에서 제시하려고 해요. 일단 실습 위주잖아요. 기존 교육은 반대인 것 같아요. 커리큘럼이 있으니까 일단 배우고, 끝에 가서 무엇을 만들 수 있는 실력이 되게끔 교수 설계가 되어 있어요. 엘리스에서는 코드를 따라 치는 것에서 시작해보고, 조금씩 응용해보면서 바꿔보고, 내 실력이 쌓이면 가이드 없이 풀 수 있는 문제를 줘서 성취감이 만들어지는 교수 설계를 목표로 하고 있어요. Q. 빠른 성취를 추구하다 보면 상대적으로 내실을 다지는 데에는 소홀해지지 않을까요?A. 물론 하나의 과목으로 깊이 있는 내용까지 알게 될 수는 없지만 그 이후에 연결되는 과목들이 있어요. 궁극적으로 1에서 5까지의 과목이 연결되어 있다면 1을 최대한 빨리 끝내는 것과 동시에 5까지도 최대한 빨리 가보는 게 필요해요. 그 과정에서 깊이가 생기지 않는다고 느끼면 스스로의 노력이 더 붙어야 하는 거고요. 교육이 깜지 쓰듯이 되는 것보다는 그림을 그려놓고 그 안을 마음대로 칠하게 하는 게 훨씬 더 학습 효과가 좋다고 생각해요.Q. 분야를 막론하고 프로그래밍을 업이나 수단으로 사용하는 게 교양처럼 되고 있는 것 같아요. 개발을 배우면 좋은 이유가 있다면요?A. 융합형 인재라고 하잖아요. 말이 되는 부분이 있어요. 단순히 한 가지만 잘해서 되는 시대는 점점 지나가고 있어요. 결국엔 기계가 할 수 없는 걸 할 수 있는 사람들이 살아남을 텐데, 그랬을 때 단기적인 고용 불안을 해결하는 게 정답이 아닐 수도 있어요. 단순히 한 가지만 잘하면 언젠가는 대체되기가 굉장히 쉽다는 걸 알아야 하는 것 같아요. 퍼블리싱을 하는 디자이너, 테크 콘텐츠를 만드는 크리에이터 등 꼭 개발을 직업으로 삼지 않는다고 해도 프로그래밍을 알면 앞으로 나만의 강점으로 만들 수 있는 부분들이 분명히 있어요. 그리고 내 커리어에 도움이 될까라는 고민을 많이 하는 것보다는 관심이 간다면 일정 기간을 정해두고 많은 일을 해보라고 권하고 싶어요.Q. 지금까지 다양한 IT 기업들과 채용 관련해서 협업하셨는데요 국내 IT 기업에서 원하는 인재는 어떤 사람이라고 느끼셨나요?A. 이건 굉장히 명확해요. 자신의 성실함을 Track record로 증명할 수 있는 사람. 100% 확신을 가지고 말할 수 있어요. Track record라는 건 어떤 시험을 3개월 공부해서 몇 점 받았습니다, 이런 게 아니에요. 관련 분야에 얼마나 오랫동안 관심을 보여왔고 그걸 실제 실행으로 얼마나 옮겼는지, 더 깊게 이해하고 다른 사람과 소통하는 것을 어느 기간 동안 꾸준히 해왔는지예요. 이렇게 말하는 근거는 일단 제가 그런 사람을 원하구요. 그리고 기업 인터뷰를 다니면서 항상 동일하게 봤던 채용 조건이었던 것 같아요.이력서를 봤을 때 이 사람이 어느 시점부터 얼마나 노력을 해서 어디까지 왔다는 걸 확인하거나 아니면 그냥 실력을 확인하거나 그 둘 중 하나면 회사에서는 채용을 할 수 있어요. 블로그 쓰기, 유튜브 방송하기와 같이 능동적인 활동은 전자와 후자를 함께 보여줄 수 있는 좋은 형태죠. 넘쳐나는 에너지를 주체하지 못해 이것저것 발산하는 사람이 IT 기업에서는 베스트인 것 같아요. 팀 문화와 가치창의적인 사람들이 모여 유연성과 실행력을 추구합니다.Q. 운영팀에서 코스매니저를 구인 중인데요, 좀 생소한 분야인 것 같아요. 어떤 일을 하는 사람인가요?A. 좋은 과목을 만들기 위해 코스에 영혼을 불어넣는 사람이에요. 구체적으로 하는 일은 기획, 수요조사, 섭외, 커리큘럼 도출, 일정 관리, 피드백 등 PM과 비슷하다고 보시면 돼요. 그런데 매니징 하는 대상이 Project가 아니라 Course가 되는 거죠.다른 무엇보다도 중요한 역할은 과목 콘텐츠가 제일 잘 나오도록 만드는 것인데요. 이를 위해 논리력도 필요하고, 다양한 관계자 간에 의견을 조율할 수 있는 능력, 교육학적으로 공감 능력도 필요하죠. 또 좋은 과목을 만들기 위한 모든 것들을 주어진 제약 안에서 해나가는데 그게 원하는 대로 되지 않는 경우가 굉장히 많고 그랬을 때의 대처 방식에서 창의성이 발휘되죠. 지금 당장 과목이 제대로 나오지 않는다고 하더라도 거기에서 무엇을 배워서 나중에 어떻게 적용할 수 있는지 이해하는 사람이기도 하고요. 아직 정립되지 않은 필드이고 우리만의 특수성이 크다 보니 지휘자와 비슷해요. 교육에 관심이 있고 프로그래밍과 관련된 호기심이 많은 사람, 기획에 재미를 느끼고 직접 만든 것을 통해 사용자와 소통하는 것을 좋아하는 사람이라면 즐겁게 일할 수 있을 거예요.Q. 코스매니저로서의 커리어가 어떤 강점을 줄 수 있나요?A. IT 산업의 트렌드에 대해서 굉장히 잘 알게 될 거구요. 무엇보다 지금 프로그래밍 교육이 대세이고 앞으로 확장 가능성이 커요. 관련된 직종이 엄청 많이 늘어나고 있는데 여기서 선구자가 될 수 있어요. 업무 면에서는 개발, 디자인과 협업을 해야 하니 PM과 비슷한 역량을 개발할 수 있는데 여기에 더해서 외부 관계자와의 커뮤니케이션 능력과, Project가 아니라 콘텐츠라는 작은 그림을 디테일하게 볼 수 있는 능력이 보다 강조되죠. 다양한 이해관계를 손에 쥐고 있기 때문에 일을 함에 있어 어디에 가중치를 둬야 하는지, 예상 결과치를 돈과 시간에 대비해서 파악할 수 있게 되는데 이러한 코스트에 대한 감을 가지게 되는 것도 경쟁력 있는 강점이 될 수 있겠죠. 또 외부와 협업을 많이 하다 보니 대외적으로 강연이나 교육 등에 개인적으로도 기회를 많이 얻게 돼요. 피드백을 즉각적으로 받아볼 수 있기 때문에 린 스타트업이나 그로스 해킹을 바로바로 적용시켜볼 수 있다는 것도 매력적이고요.Q. 엘리스는 현재 어떤 팀인가요?A. 대부분의 스타트업이 그렇겠지만 정답이 있는 필드가 아니기 때문에 유연성이 되게 중요해요. 엘리스 역시 내가 하는 일이 어떻게 연결될지를 계속 유연하게 생각하면서 능동적으로 실행에 옮기는 사람들이 모여야 하는 곳이에요. 그래서 유연성과 실행력을 추구하는 조직이고요. Scrum, OKR 미팅, 주간 미팅 등 다양한 방법론을 실천하고 있어요. 이런 게 문화로 정착되기까지 많은 시행착오가 있겠지만 모두가 유연성과 실행력에 대한 공통적인 생각을 가지고 있고 이를 좀 더 표면화하려고 노력하는 단계에 있어요. 성장, 유연성, 실력, 실행력 같은 것들을 위해서 회사 차원에서도 많은 장을 만들려고 하고요. 예를 들어 운영팀에서 격주로 하는 세미나도 스스로 장을 만들고 실행해나가는 능동성을 함양하기 위한 일환이에요. 이런 장들을 통해서 회사에서 정해주는 대로 맞춰서 행동하는 게 아니라 장을 만들고 가꿔나가는 것까지도 내게 필요한 유연성과 능동성이라고 생각하는 문화가 만들어졌으면 좋겠어요.Q. 마지막으로 운영팀 리더로서, 팀 자랑 좀 해주시죠.A. 처음 시작할 때에 비해서 과목이 엄청나게 많이 발전했어요. 그게 어떻게 만들어졌냐면 그냥 팀원들이 만들었다고 생각해요. 서로가 서로에게 되게 좋은 영향들을 끼치고 있고 그게 좋은 결과물로 나와요. 그래서 지금 팀 구성에 굉장히 만족을 하고요. 다만 이분들이 성장하는 속도를 팀이 따라갈 수 있는가, 라는 게 제 이슈예요. 개개인이 계속 성장을 이룰 수 있는 환경을 만드는 게 제 역할이고, 이런 부분들을 다 같이 공유하려고 해요. 최대한 대화를 많이 해서 서로가 생각하는 것들이 최대한 일치하는 팀을 만들려고 하고요. 우리에게 어떤 어려움이 있고 어떤 요구 사항이 있고, 어떤 게 해결되어야 하는지, 팀에게 바라는 점이 무엇인지 이런 것들이 소통이 잘 되고 있어서 팀이 발전할 수 있는 근간이 되는 것 같아요. 그리고 구성원이 결국엔 팀의 발전에 이바지하는 부분이 크고요.엘리스는 ★코스매니저 구인 중! 프로그래밍 교육을 통해 기회를 만들고 확산하는 일에 영향력을 미치고 싶은 분이시라면 주저 말고 지원해주세요. :)
조회수 808

고객 퍼널 모델 - TOMOBOFU 이론

애피타이저로 시작해서, 메인 요리와 디저트가 뒤 따르는 식사와 마찬가지로, 디지털 마케팅 영역 역시 구매자의 모든 여행 단계에서 적합한 콘텐츠를 적합한 타이밍과 타겟에 제공하고, 최적화해야 합니다. 유의미한 전환을 발생시킨 사용자 (ex 회원가입 완료자) 는 처음 전환을 하는 순간에는 구매할 준비가되지 않았습니다. ToFu, MoFu & BoFu 콘텐츠 제작 및 관련 마케팅 전략을 기획하는 것이 디지털 마케팅 광고 스킬의 핵심이지요. 오늘 디지털 마케팅 분야에서 가장 혁신적으로 주목받고 있지만, 사실은 아주 당연한 이론인 TOMOBOFU 이론에 대하여 공부해보겠습니다.ToFu, MoFu , BoFu 이게 뭔데 ?Funnel Model 이라는 개념을 아시나요 ? Funnel 이라는 말을 해석하면 깔대기 라는 의미가 나옵니다. 우리가 하나의 쇼핑몰을 운영한다고 가정할 때, [메인페이지 - 상세페이지 - 장바구니 - 결제 정보 입력 페이지 - 결제 완료 페이지] 까지의 유입량을 인포그래픽으로 나타낸 것이 바로 Funnel Model 입니다.이 중에서, 퍼널 모델의 최상단에 있는 세그먼트들을 우리는 Top of the Funnel Model 이라고 부르고, Middle of the funnel Model , Bottom of the funnel model 순으로 내려가게 됩니다. 우리는 이 세가지의 단계별 세그먼트별로 각각 다른 메시지를 적합한 타이밍에 노출시킬 필요가 있습니다. 퍼널 모델(왼쪽) 과 TOMOBOFU Segment1) TOFU : Top of the Funnel Model우리의 판매 경로 제일 위에 있음에도 불구하고, 여러분들은 잠재적으로 전환을 이끌어낼 수 있는 트래픽을 끓어들일 품질이 높은 유저들을 찾고 있을 것입니다. 전혀 의미없거나, 추가 전환으로 이어질 확률이 낮은 고객을 끌어들이기 위해 우리가 이런일을 하고 있는 것은 아니니까요. TOFU들을 위한 가장 적합한 컨텐츠는 여러분의 블로그 글이나 유의미한 글입니다. 제가 글을 쓰는 것과 마찬가지입니다. 그 시점에서 TOFU 세그먼트들은 [e-book 다운로드]나 [구독하기] 버튼과 같은 행동을 유도하는 버튼을 클릭함으로써, 주저 없이 그들의 메일주소나 핸드폰을 고품질의 컨텐츠와 맞바꾸려고 할 것입니다.ToFu 들을 위한 우리의 목표는 '그들이 필요로하는 특정 질문들에 답을 해준다던가, 그들이 가지고 있는 고민을 해결해줘야 하는 것' 입니다. 이러한 목표를 가지고 첫 단계에서의 컨텐츠를 지속적으로 배포하면, 아래에서 설명드릴, MoFu들을 위한 컨텐츠 배포를 시작할 수 있는 기회를 얻게 됩니다.2)MOFU : Middle of the Funnel ModelTofu에서 구독하기 버튼을 누르고 실제로 우리가 유도하고자 하는 행동을 마친 유저들을 비로소 '리드'라고 부를 수 있습니다. 그들은 이제 Mofu 의 단계에 들어왔습니다. Mofu들을 위한 컨텐츠는 리드의 품질이 정말 다양하기 때문에 살짝 복잡해 보일수도 있습니다.이 단계에서는 여러분의 컨텐츠는 ToFu단계에서 진행했던 것처럼, 지속적으로 그들의 니즈를 해결해주되, "결국 니즈를 해결하는 방법은 우리의 브랜드다" 라고 그들이 가지고 있는 불편한 문제들에 해결책을 제시해 주어야 합니다. Tofu 때보다 좀 더 고품질화된(업그레이드된) e-book은 이 단계에서 훌륭한 컨텐츠 형식이 될 수 있습니다.특히 한 연구에 따르면, 영상이나 퀴즈와 같은 형식의 컨텐츠는 우리 브랜드와 리드 사이의 신뢰감을 구축하는데 굉장히 강력한 영향을 미칩니다.3) BOFU : Bottom of the Funnel Model자, 이제 우리는 Tofu 단계에서 건강한 품질을 보이는 유저들을 모았고, Mofu 단계를 통해서 그들과 브랜드 커뮤니케이션을 진행하고 있습니다. Bofu 단계에서는, 우리의 제품이나 서비스를 판매할 수 있는 Sales Point를 등장시켜야 할 때 입니다.많은 산업군에서 여러분의 Bofu 단계에는 단순히 컨텐츠 만으로 구성될 수는 없습니다. 이 지점에서 우리의 리드 고객들은 브랜드와 1:1 커뮤니케이션을 하는데에 편안함을 느끼고 있을 것입니다. 무료 시험판이나 샘플과 같은 작업들은 우리의 리드 고객들에게 가장 큰 흥미를 이끌 수 있는 주요 방법론일 것입니다. 만약에 우리가 온라인 쇼핑몰을 가지고 있다면, 할인 쿠폰을 거래단계에서 사용하도록 하여 최종적으로 구매 전환을 이끌어 내야합니다.4) 리드를 만들 수 있는 콘텐츠 배포 과정 자동화 비록 제가 Tofu , Mofu , Bofu 단계를 굉장히 간단하게 설명했지만, 아시다시피 그리 간단한 것은 아닙니다. 이 단계별 콘텐츠를 배포하고 최종 구매전환을 이끌어내기까지, 그들에게 유의미한 컨텐츠도 만들어야 하고, 그들이 행동할 수 있는 유도 경로를 셋팅하는데에도 엄청난 시간이 걸리기 마련입니다.이 모든 과정을 위해 계속적으로 노력한다면 명백한 리소스 낭비가 발생할 것입니다. 한 연구에 따르면 리드 고객을 잘 만드는데 능률이 있는 회사는 50% 더 많은 리드를 생성하며, 이러한 리드 고객들은 육성되지 않은 리드보다 47%의 더 많은 구매를 발생시킵니다.비현실적이지만, 이러한 프로세스를 우리가 매일매일 수동으로 해야한다고 생각해보세요. 굉장히 힘들것입니다. 이 때가 바로 유의미한 리드 고객을 생성하기 위한 플랜의 마지막 단계인 마케팅 자동화 소프트웨어가 필요할 때입니다. 자동화 마케팅 프로세스를 구축하면 6-9개월 만에 평균적으로 10% 이상의 매출이 발생한다고 합니다.마케팅 경로 자동화는 우리가 아무 손도 대지 않고 자동으로 진행되게 한다는 것을 의미하지는 않습니다. 우리는 고객에 따라 다르게 인삿말이나 제목을 적은 메일을 보낼 수도 있으며, 우리 회사의 특정 연락처로 연락온 사람들이 있을 수도 있습니다. 리드가 전환되기 전에 생성 된 후 특정 전환을 기반으로 트리거 된 다음 회사의 구매주기에 맞춰 빈도로 예약됩니다.여러분의 TOFU , MOFU , BOFU는 어떤 사람들인가요?퍼포먼스 마케팅 에이전시, 오피노 바로가기
조회수 1435

스타트업을 시작하며... 1

기록으로 남겨보고 싶었다.사업이 성공적으로 launching되고 나서, 지금의 고민이 나중에 어떻게 증명될 수 있을까에 대한 호기심이랄까? ^^;; 새로운 서비스를 만들어가는 과정에 대한 기록을 남기는 것이 이 글의 목적이다. Brunch에 쓰기 전에 다른 곳에 남겼던 기록들을 이곳으로 옮겨왔다.Phase 0. 향수 서비스를 고민하기 시작하다.사실 지금 고민하고 있는 서비스는 어떤 특정한 problem을 해결하겠다는 접근에서 시작된 것이 아니었다. 원향(Fragrance oil)을 제조하는 회사와 business 관계가 있었고.. 4년 전 처음 그 회사(DROM fragrance)와 업무가 시작될  때부터 그 향을 어떻게 사용해 볼 수 있을까에 대한 고민을 하고 있었다. 그러던 중, Kukka 서비스를 보면서 향을 subscription 해주면 어떨까? 라는 아이디어를 떠올리고 비즈니스 모델을 생각하기 시작하였다. 향수는 지금까지 강력한 브랜드 가치를 통해 "오만한" 가격을 받고 있으며.. start-up에게 깨져본 적이 없는 영역이었다.Phase I. 서비스 모델을 구체화해 나가다..향수를 SPA업체들과 같이 트렌디하게 빨리 만들어서, 그 시점의 trend에 맞게 또한 날씨, fashon 및 occasion을 세팅하여서 한 달 정도에 사용 가능한 5ml 정도를 보내준다면 남기지 않고 잘 사용하고 버릴 수 있지 않을까?Phase II. 문제를 define 해보기 시작하다.사실 문제를 발견하고 그것을 어떻게 서비스화 할 것인가에 대한 고민이 순서에 맞다고 생각하지만, 향수라는 토픽을 정해 두고 시작하니 문제를 오히려 찾아야 하는 상황이다..  파우더 룸 같은 유명 female 카페에 가서 향수 카테고리를 뒤져보니..  남자친구나 저에게 어울리는 향이 무엇일까요? 가 problem number 1이고..   향수 소분 해서 팝니다... 연락 주세요! 가 problem number 2이고..  내가 생각하는 것은.. 향이 50ml, 100ml 이렇게 팔다 보니 너무 많이 집에 쌓아있다는 점.  나에게 어울린다고 생각하는 향수가.. 날씨, occasion 등을 모두 cover 할 수 있을까?   향수를 들고 다니기 쉽게 해서 사용하게 하면 어떨까?   브랜드 좀 있다고 하는 향수들 너무 비싼 거 아님? 공급자의 입장에서는 개발에 들인 공이 있고, 대량 생산을 해야 하기 때문에.. 양을 적게 해서 팔기 어렵다.  언제 어떤 상황에 어울리는지에 대한 story line이 없다.. Phase III. 현실 세계를 둘러보기 시작하다.향수를 만드는 공장을 방문해 보았다. 공장은 한 번의 batch를 돌리기 위한 최소한의 물량이 필요하고.. 이 공장에서는 50ml 기준이라면 불량률 15% 정도를 고려해서 3,000병 정도가 최소한의 물량이라고 한다. 물론 더 적은 양을 만들어 줄 수 있으나.. 단가가 올라갈  수밖에 없다.그리고, bottle 뚜껑은 screw 타입으로 할 것인지, 아니면 clipping type으로 할 것인지?  라벨은 자동 라벨 기를 사용할 것인지? 분사 양은 어느 정도로 할 것인지 등등 현실의 문제가 다가오기 시작한다.Phase IV. 주변의 인물들에게 의견을 구해보기 시작하다.일단은 물어보기 시작한다. 와우 좋은데.. 될 것 같은  비즈니스야!라고 하는 사람부터 음.. 미안한데 난 안 쓸 것 같아!라고 하는 사람 등등 다양한 사람들이 존재한다. 흠.. 그렇다면 이것을 받아들이겠다고 한 사람들의 의견을 모아서 작은 시장에서 시작할 것인가? 아니면 모두가 만족하는 서비스로 계속해서 수정을 할 것인가?뭐가 되든.. 소비자를 push 할 수 는 없다. 좋은 제안을 주고.. 그것에 따라오는 고객이 있다면 그 고객들을 더욱 만족시킬 수 있는 방향으로 진화하는  수밖에..Phase V. "이건 안되지 않을 이유가 없어요"를 주의하라.새로운 서비스를 기획하는 사람의 입장에서는 대부분 밝은 면 만을 볼  수밖에 없다. 어느 정도의 의견은 귀에 들어오지만, 비판적인 의견에 대해서는 귀에서 튕겨내는 것이 특징이다. 그러던 중, 한 선배에게서 "내 서비스가 안되지 않을 이유가  없어요"라고 말하는 것 같이 들린다는 의견을 들었다. 현실의 망치로 뒤통수를 맞아봐야 정신을 차리는 법이다.#파펨 #스타트업 #창업가 #창업자 #마인드셋 #인사이트
조회수 3177

창업 후 3년간 저지른 실수에 대하여

'왜 이 녀석은 일기를 블로그에 쓸까?'라고 생각할 수 있다. 내가 가장 존경하는 인물은 소프트뱅크의 창업자인 손정의 회장인데 손정의 회장은 '도저히 불가능할 것 같은 목표를 세우고 사람들 앞에 선언하라'고 하였다. 그러면 그 말을 지키기 위해 무엇이든 할 것이라고. 블로그는 내게 그런 의미다. 내가 이곳에 선언하고 많은 사람들에게 공유한 만큼, 일기보다 훨씬 더 엄격한 책임감을 갖게 된다. 다들 한 번씩 해보길 바란다. 시간은 빠르다. 이제 창업을 한 지 3년이 넘어간다. 모든 것은 2013년 3월, 군대에서 말년휴가를 나온 고교시절 단짝 친구인 경병현에게 죠스 떡볶이에서 떡볶이와 순대를 먹으면서 '창업을 하자'고 제안하면서 시작됐다. 그 제안을 군인 신분으로 받아들인 놈도 어이없지만, 우리가 제일 먼저 했던 일은 PC방에 가서 회사 로고와 이름을 만들고 페이스북 페이지를 만드는 일이었다. 지금 생각해보면 어리숙하고 순수했던 시절이지만, 얼마나 진정성이 넘치는지 말년 휴가를 나온 친구와 클럽이나 나이트클럽을 가는 게 아니라 PC방에서 밤을 새우고 다음날 오후 3시까지 그 작업을 했다. 아직도 명확하게 기억이 나는 걸 보니, 꽤 힘들면서도 즐거운 시작이었던 것 같다.사복-경병현, 군복-나우리는 경기도 안산의 실업계 고등학교에서 처음 만났다. 그 친구는 만화 그리기를 좋아하는 순수한 아이였고 가난이나 외부 환경에 무관하게 매우 행복하게 살던 친구였다. 나는 그 친구와 반대로 독기를 품고 있었는데, 이 자본주의 세상에서 제일로 여겨지는 돈이라는 걸 실컷 벌어보고 내가 단순히 돈이라는 별 것도 아닌 것에 받은 고통을 세상에 돌려받고 복수하고 싶었다. 고등학교 시절부터 매일 하버드, 옥스퍼드 대학교 등 세계 제일의 대학생이 공부하고 배우는 것들에 대해 다룬 다큐멘터리를 봤고 기업가와 관련된 영화, 마피아와 관련된 영화, 정해진 삶을 바꾸고 개척하는 주인공을 다룬 영화는 닥치는 대로 보기 시작했다. 그리고, 그 친구에게 내 사상을 마구 주입했다. 우리는 매일 집에서 같이 영화를 봤고 컵라면을 먹으면서 어떻게 세상을 바꾸는 위대한 일을 할 수 있을 지에 대해 마치 신 들린 사람처럼 설명했다. 공부를 하다가 힘이 들면 인터넷 강의를 봤고, 그래도 힘이 들면 여의도나 삼성역 근처로 가서 야간에 밝게 불이 켜진 높은 건물들을 바라보며 의지를 다지곤 했다.그렇게 3년이란 시간을 보냈기 때문에 지금의 10년이 존재하는 것 같다. 그 친구와 인연을 맺게 된지 10년이 지났고, 사업을 같이 한 지도 3년이 지났다. 집을 나와서 서로의 자취방에서 잔다고 부모님께 거짓말을 하면서 서울대입구의 조그만 방을 구해서 일을 시작했다. 이게 모든 일, 그리고 실수의 시작이다. 나는 사업을 하기 위해 사업을 택했고 어떤 아이템이나 서비스도 존재하지 않았다. 심지어, IT 기업을 하겠다고 했지만 우리 중에 코딩을 할 수 있는 사람도 없었다. 준비되지 않은 창업. 그것은 분명히 실수다. 물론, 지금에서야 인정할 수 있는 실수이긴 하지만, 앞으로 창업하고 싶은 대학생이 있다면 준비되지 않은 창업은 분명한 오류고 많은 문제를 겪을 것이란 것을 말해주고 싶다.코딩하는 나그때, 내가 선택한 길은 코딩을 배우는 일이었다. 나는 개인이 독기를 품으면 뭐든지 해낼 수 있다고 믿는데 그게 내 삶을 가로지르는 가장 중요한 가치다. 결국 독기를 품고 코딩을 한 지 한 5개월쯤 지나니 안드로이드 앱 '닥터 알람'을 출시할 수 있었다. 그리고 닥터 알람은 특유의 독특한 재미와 가치를 고객들에게 주면서 순식간에 다운로드 수 50,000이 넘어갔다. 나는 이제 우리의 역량이 시장에서 입증됐다고 생각했고 닥터 알람을 접었다. 그리고 새로운 서비스를 찾기 시작했는데, 내 친구는 SK상생혁신센터라는 입주공간에서 작업을 했고 나는 카페에서 주로 작업을 했다. 그러다 보니 커뮤니케이션 이슈가 자연스럽게 발생하게 됐는데, 이 때문에 협업 툴을 찾기 시작했다. 그런데, 대부분 협업툴은 우리가 쓰기엔 너무 어렵고 복잡했다. 그냥 포스트잇이나 링크 같은 거 공유할 수 있는 판만 있으면 좋겠다고 생각했는데 그런 게 없었다. 그래서 우리가 만들기로 결심했다. 솔직히, 얼마 안 걸릴 줄 알고 용감하게 시작했다. 그렇게 시작된 것이 비캔버스다. 비캔버스 개발을 시작한 지 어느새 2년이 됐으니 절대 쉽지 않은 일임이 분명한데, 그때는 잘 몰랐다. 그래서 사람들이 서비스가 어떻게 만들어진 건지 물어볼 때, 뭔가 멋있는 말을 해주긴 하지만 미안하게도 사실 잘 기억이 안 나서 지어낸 것이다. 너무 오랜 시간이 지났고 완전히 무식한 상태에서 시작했기 때문이다.내 실수는 나의 운과 함께 시작된다. 당시 사무실도 없고 돈도 심각하게 없던지라 마루 180이나 여러 입주시설에 인큐베이팅을 신청했는데 모두 떨어졌다. 그런데 딱 하나! 정부지원사업 '스마트 벤처창업학교'에 서류 합격한 것이다. 내 인생 처음 서류합격이었다. 너무 기뻤지만 면접 심사 때 보여줄 만한 것이 없었다. 그래서 비캔버스가 마치 돌아가는 서비스인 것처럼 애프터 이펙트로 만들어서 가져갔다. 그 이후에는 잘 기억이 나지 않지만 매우 무식하고, 아무것도 모르는데 용감했다. 처음으로, 스마트 벤처창업학교 때 썼던 사업계획서를 공개한다. 지금 쓰라고 하면 이렇게 쓸 수도 없을 것 같은데, 포스트잇으로 철학을 하겠다는 건지 매우 진지하고 용감하게 나의 무식함을 드러냈다. 스마트벤처창업학교 사업계획서. 이게 전부다. 창업을 위한 사전준비 사항을 이거 한 줄 썼다. 인간, 기계, 이상한 말들이 줄줄이 나온다. 그런데 결과가 놀라웠다. 우리가 스마트 벤처창업학교에 1등으로 입교하게 된 것이다. 그때까지는 500만 원만 있어도 무엇이든 만들고 위대한 기업이 될 수 있을 것 같았다. 그런데 1억이라는 자금이 갑자기 들어오면서 돈에 대한 개념을 다시 생각하게 됐다. 생각보다 돈은 매우 빨리 소진된다는 걸 이때 배운 것 같다.서현역 오피스텔에서 일하던 시절 경병현 이사 - 반바지입니다. (팬티 아님)스마트 벤처창업학교가 끝나서 돈이 없을 때쯤, 또다시 행운이 찾아왔다. 한화 S&C와 엔절로부터 2억 3천만 원의 투자를 유치했다. 모든 것들이 꿈만 같았다. 모든 일이 1년 안에 순식간에 일어났다. 지난 1년간의 고생이 더욱 값지게 느껴졌다. 이때부터 내 실수가 시작된다. 2억 3천만 원의 투자를 유치하고 나서도 내 기억은 작은 단칸방에서 사무실도 없이 꽁치김치찌개 통조림 먹으면서 일했던 그곳에 머물러 있었다. 나는 새로운 인력을 나와 내 친구처럼 헝그리 하게 할 수 있는 사람들로 채워 넣기 시작했다. 그들이 개발을 당장 잘하건, 성격상의 Fit이 안 맞건 상관없었다. 그냥 헝그리 하게 전투적으로 할 수 있는 사람만 모이면 무엇이든 해낼 수 있다고 믿었다. 내가 개인적으로 이제까지 믿어왔던 '독하면 무엇이든 해낸다'가 모든 사람에게 통할 것이라 생각했다. 성격이 문제가 있으면 바뀔 수 있다고 믿었고, 성과가 안나도 그것도 바뀔 수 있다고 믿었다. 1년이 흘렀다. 지금은, 이 사진속 인물 중에는 나와 경병현만이 남아있다.그렇게 우리는 매출 100원도 없는 회사임에도 매 달 천만 원 이상의 돈을 써댔다. 웃겼던 것은 그 당시에 급여를 제대로 받은 사람이 단 한 명도 없었다는 것이다. 원래 잘하던 사람을 잘하는 위치에 앉혀서 사업을 운영한 게 아니기 때문에 자연스럽게 개인 리소스의 한계가 왔고 나는 사람을 하나 둘 늘리기 시작했다. 그렇게 지출은 커져갔다. 나는 우리가 임시적인 팀이라는 것을 망각했다. 성과를 내지 않으면 소멸한다는 자연스러운 현상을 인정하지 않았다. 나는 서비스 성장보다 팀을 만들고 회사를 만드는 데 집중하기 시작했다. 뭔가 투자를 받았기 때문에 우리 회사가 대단하다고 착각한 것일까? 잘 모르겠다. 잘못된 판단을 내렸다는 것만 명확하게 알고있다. 내가 주로 했던 일은 사람들이 문제가 있을 때 설득하고 전투력을 높여주는 일이었다. 하루에 최소 4시간 이상을 사람들의 의지를 북돋고 위대한 사람들의 영상이나 글, 명언을 보여주며 혹독하게 우리를 채찍질하자고 설득하는데 시간을 쏟았다. 우리는 형제이자 가족이라고 믿었고, 그 사람들이 우리 회사에서 언젠가 나간다는 건 생각도 하기 싫었다. 기대는 커졌고, 강요도 많이 했다. 투자받은 돈을 40% 정도 썼을 때쯤 위기감이 다가왔다. 우리가 이제까지 한 게 너무 없고 마일스톤을 전혀 달성하지 못한 것을 발견했다. 그때부터 서비스에 완전히 몰입하고 다시 사람들을 채찍질하기 시작했다. 당연히 일정은 지켜지지 않았고 우리는 매주 성과를 내지 못했다. 어떤 사람들은 정말 전투적으로 열심히 했고, 어떤 사람들은 동아리 활동을 하듯 일을 했다. 전투적으로 하는 사람들은 일정을 지키는 일이 많았고 지키지 못했다고 하더라도 개인적으로 이해했다. 그런데, 그다지 일을 많이 하지도 않으면서 일정을 지키지 못하면 매우 화가 났다. 그 모든 것이 나에게 큰 스트레스를 안겨주었는데, 나와 내 친구 둘이서 할 때는 상상도 못했던 분위기였기 때문이다. '안되면 될 때까지 한다. 절대 포기하지 않고 길을 찾다보면 길은 나온다.' 이런 생각으로 살아온 우리에게는 충격적인 일이었다.나는 지금도 일은 많이 해야 한다고 믿는 사람 중 하나다. 왜냐하면 우리가 특정 분야에 숙달되지 않았기 때문에 많은 시간을 투입하는 것이 배신을 하는 일은 결코 없기 때문이다. 다만, 개인에게 그걸 강요할 수 없다는 것을 깨닫지 못했던 것이 실수라고 본다. 그리고, 사람들을 자꾸 바꾸려고 했던 이유는 내가 그 개인에게 거는 기대가 너무나도 컸기 때문이다. 어차피 우리는 10년, 20년 갈 거고 저들이 나중에 리더십을 갖게 될 텐데, 그때 리더십을 잃지 않으려면 지금 빨리 속도를 내서 능력을 키우고 성과를 내야 한다는 것이 그 이유였다. 어떤 이유로도 내 시나리오에 저 사람이 우리 회사를 나가는 것은 없었다. 내가 팀원들 개개인이 회사가 커졌을 때 가져야되는 리더쉽까지 고민을 했다니, 김칫국을 너무 빠르게 마신 셈이다.나는 단 한 사람도 회사에서 먼저 나가라고 하거나, 그것을 종용할 생각이 없었다. 우리는 가족이니까. 사업을 하면서 일본의 이나모리 가즈오, 마쓰시타 고노스케의 책을 많이 읽었는데 그들의 사업철학이 나에게 너무 심각한 영향을 줬다. 이게 많은 젊은 창업자들이 앞으로도 계속할 실수라고 본다. 여기에 내 경험으로 말미암아 실수를 공유하니, 나와 같은 실수를 덜했으면 좋겠다.1. 조금 가치가 안 맞을 것을 예상했지만 같이 가기로 했다- 사람은 결코 변하지 않는다. 처음 우려했던 이슈 그대로 마지막 모습으로 남고 떠난다.2. 어차피, 우리는 학생이 대부분이었기 때문에 일을 제대로 못했다. 그저 많이 일하는 것이 답이었다.- 제대로 하는 사람을 정확한 위치에 앉혀야 한다. 회사에서 트레이닝하려는 생각을 버렸어야 했다.3. 인원을 마구 늘렸다.- 인원은 월급이나 복지와도 같다. 늘리기는 쉽지만 한 번 늘리면 줄이기 힘들다.   사람들이 다 나가고 돌아보니, 애초에 그만큼 인원이 필요가 없었다.4. 팀은 영원할 것이고 팀원은 형제기 때문에 치고 박으면서 끝까지 가는 것이라 오판했다.- 팀은 다 같이 성과를 내지 못하면 사라지는 것이고, 팀원은 형제가 아니다. 어느 날 회사에 제시간에 아무도 나오지 않을 때, Rule을 만들어도 아무도 지키지 않을 때쯤 되서야 뭔가 잘못 돌아가고 있다는 것을 깨달을 수 있었다. 그런데, 그때는 이미 늦었다.5. 제일 중요한것. 사람들 말을 많이 무시했다. 내 인사이트가 짱이라고 착각했다.- 나는 정말 아무것도 모르는 존재기 때문에 많은 사람으로부터 배워야 한다는 걸 깨닫기 까지 오래걸렸다.이것은 내 개인의 문제에 대한 지각이다. 분노를 쉽게 하고 타협을 모르는 내 성격이 많은 문제를 발생시켰고, 인간관계에서 정말 여러번 실수했다. 이 중에는 이제 돌이킬 수 없는 관계들도 있는데, 이 부분에서 더욱 많이 배울 수 있었다.직접 경험해보지 않으면, 이런 나의 실수들이 와 닿지 않을 수도 있다. 물론 내가 팀에서 나이가 가장 어렸고 내부적으로는 형 동생을 하고 있었기 때문에 생긴 문제일 수도 있다. 그러나 결국, 트렐로 등 툴을 써서 프로젝트를 관리하고 싶을 때 2-3번 계속 이야기를 했어야 했고, 회의 자료를 준비해달라고 해도 몇 사람은 회의 때 아무것도 준비해오지 않는 일이 반복됐다. 출근 시간은 이미 존재하지도 않았고, 누군가 아프다고 안 나오겠다고 하면 딱히 할 말도 없었다. 이 약점을 깨는 방법은 간단하다. 스타트업의 특별성을 없애면 된다.대한민국 사람들이 일하는 방식 그대로 규정을 만들고 일하면 된다. 출근은 9-10시 퇴근은 7시.더 할 사람은 자기 마음대로.자기가 세운 일정은 지킨다.이렇게 해도 더 할 사람은 더 한다. 모든 것은 자율에 맡기고 그 성과만 공정하고 냉정하게 평가되면 될 일인데, 그것을 미처 깨닫지 못했다. 아마, 대학생 창업자들은 이 문제로 고민을 겪고 있을 수 있다. 누구는 시험 보러 간다고 하고, 누구는 수업을 듣는다 하고, 다시 복학을 한다 하고 스트레스의 연속일 것이 분명하다.그런데, 내가 겪어온 바로는 그런 상황에서는 그냥 뛰어들지 않는 것이 낫다. 스타트업이란 것은 팀에 대한 고민은 줄이고 서비스와 고객에 대한 고민의 시간을 늘릴 수 있을 때 성공과 가까워진다는 것을 깨달았다. 팀원과 사업 자체에 대한 고민은 백날 해봐야 서비스 어려워지면 나갈 팀원들은 나가게 되어있다. 안 나갈 사람은 애초에 고민거리도 안주는 경우가 많다. (실제로 투자를 받고 조인한 팀원은 비캔버스의 사용자였는데, Self-organized된 사람이라 딱히 내가 모티베이션을 주거나 할 시간을 들이지 않아도 됐다. 그리고 지금도 전혀 문제없이 근성있게 나아가고 있다) 이게, 내가 망각한 두 가지 공식이다. 이제, 내 뇌 깊숙이 자리 잡고 있다.팀원에 대한 고민이 줄어 온전히 서비스와 고객에 대해 고민할 수 있을 때 비로소 속도감이 붙는다매출이 없다면 지출을 줄여야 한다. 지출의 대부분 비율을 차지하는 인건비에 대해선 매달 고민해야 한다.작년을 돌아보면, 사업에 있어 왜 팀이 중요한 지에 대해 다시 감을 잡게 되는 소중하고도 비싼 수업료였다. 왜 투자자들은 팀을 보는가? 누군가는 좋은 대학, 직장을 볼 수도 있지만 사실은 그게 중요한 것이 아니다. 팀이 중요한 이유는 대부분 결성되는 팀이 막상 내부적으로는 서비스에 온전히 몰입할 수 있는 상황이 아니기 대문이다. 설득과 커뮤니케이션에 너무 많은 시간이 들어가게 되면 서비스는 뒷전일 수밖에 없다. Y Combinator의 폴 그레이엄이 대부분 성공한 창업자들에게 들은 이야기를 공유한 에세이가 있는데, 이것이 정답이라고 본다. Be Careful with CofoundersThis was the surprise mentioned by the most founders. There were two types of responses: thatyou have to be careful who you pick as a cofounder, and that you have to work hard to maintain your relationship.What people wished they'd paid more attention to when choosing cofounders was character and commitment, not ability. This was particularly true with startups that failed. The lesson:don't pick cofounders who will flake.- Paul graham (Co-founder, Y combinator)문제 생길 것 같으면 같이 일하지 말라는 게 핵심이다. 그리고 폴 그레이엄의 수많은 에세이는 이런 내용보다는 서비스와 Growth나 이에 관련된 창업자의 마인드셋 등 실제 사업 전반적인 내용에 대한 것이 대부분이다. 팀에 과도하게 매달리면 사업이 아니라 사업 놀이만 하다 끝날 확률이 매우 크다는 것을 몸으로 느꼈다.앞으로 내가 추구할 방향과 길은 이 실수들에서 비롯된다. 혹독하게 회사와 서비스를 성장시키는 데만 집중하는 것이 올바른 방향이라는 것을 깨달았다. 무언가 내부적으로 이슈가 있음에도 우리를 좋은 팀으로 포장해서 투자를 받을 생각도 하지 않을 것이다. 서비스에 대해 심각하고 밀도 있게 고민하고 회의할 수 있는 팀. 그것을 전제로 매주 다양한 시도를 통해 성장하는, 그런 그림을 그려보고 싶다. 나 또한 많이, 잘 일하지 않으면 팀에서 쓸모없는 존재가 되어버릴 수 있다. CEO라는 것은 직함일 뿐이기 때문에, 이것을 특권이라 생각하지 않고 부단히 단련하고 혹독하게 나를 채찍질하는 것을 멈추지 않겠다고 결심했다. 그리고, 사람들에게 강요하기를 멈추기로 했다. 고객이 우리를 냉정하게 바라보듯, 우리도 우리 내부의 현실을 냉정하게 바라보고 냉정하게 평가해서 회사 자체를 키워나가야만 한다. 회사는 네이비씰이 아니었다. 내가 우긴다고 되는 것이 아니었다. 내가 Motivation 할 때 큰 영향을 준 영상, 책이 누구에게나 의미 있는 것은 아니다. 결국 자기 스스로 자신만의 다양한 point에서 Motivation을 얻어야만 한다. 매주 확신과 비전, 모티베이션을 다른 사람이 계속해서 줘야만 일을 할 수 있는 사람은 언젠가 낙오하게 돼있다. 그게 내가 강요를 멈추기로 한 이유다.내가 팀원들에게 자주 말했던 것을 인용하며 글을 마치겠다.지금 이 돈 받고 이 지분 받고 일하는 이유가 무엇이냐?(뭔가 큰 명예나 부를 얻거나 원하는 삶을 살아보고 싶어서가 대부분)그렇다면, 당신이 원하는 건 항상 매일 몰아치는 잔잔한 파도가 아니라,거대한 쓰나미를 보고 싶단 건데 쓰나미는 몰아치기 전에 전조현상이라는 것이 있다. 거대한 쓰나미일수록 더 물이 많이 빠진다. 그래서 누구나 쓰나미를 본능적으로 예측할 수 있다. 그럼 우리는 지금 무슨 전조현상을 일으키고 있나? 무엇을 특별하게 하길래, 우리가 얼마나 비상식적으로 특별하길래 그런 말도 안 되는 결과를 기대할 수 있는 것인가? 우리를 바라보는 사람들은 우리의 뭘 보길래 본능적으로 성공을 예측할까?대부분 스타트업이 원하는 결과는 말도 안 되는 것이 대부분이다.그런데 대부분 말도 안 되게 뭔가 해야겠다는 생각은 안 하는 것 같다.일을 진짜 말도 안 되게 많이 하면서도 잘한다던가, 얼굴 팔리는 것 각오하고 길에서 이상한 짓을 하거나..말도 안 되는 뭔가를 해야 정말 거대한 무언가를 만날 수 있지 않을까? 이 고민을 매일 하며 잠이 든다. 그리고 매일 밤 부끄러움이 느껴진다.2014년 3월 스마트벤처창업학교 사업계획서를 쓸 때, 그때의 각오를 되살리며..
조회수 1213

AWS Batch 사용하기

OverviewAWS Batch는 배치 컴퓨팅 작업을 효율적으로 실행할 수 있게 도와줍니다. 배치 작업량과 리소스 요청을 기반으로 최적의 리소스 수량 및 인스턴스 유형을 동적으로 프로비져닝합니다. AWS Batch에서는 별도의 관리가 필요 없기 때문에 문제 해결에 집중할 수 있습니다. 별도의 추가 비용은 없습니다. 배치 작업을 저장 또는 실행할 목적으로 생성된 AWS 리소스(인스턴스 등)에 대해서만 비용을 지불하면 됩니다. 이번 포스팅에서는 간단한 튜토리얼로 AWS Batch 사용 방법을 크게 11개의 Step으로 알아보겠습니다. 이렇게 진행하겠습니다.AWS에서 제공하는 Dockerfile, fetch&run 스크립트 및 myjob.sh 다운로드Dockerfile를 이용하여 fetch&run 스크립트를 포함한 Docker 이미지 생성생성된 Docker 이미지를 ECR(Amazon Elastic Container Registry)로 푸쉬간단한 샘플 스크립트(myjob.sh)를 S3에 업로드IAM에 S3를 접속 할 수 있는 ECS Task role 등록Compute environments 생성Job queues 생성ECR을 이용하여 Job definition 생성Submit job을 통해 S3에 저장된 작업 스크립트(myjob.sh)를 실행하기결과 확인 STEP1. AWS에서 제공하는 Dockerfile, fetch&run 스크립트 및 myjob.sh 다운로드AWS Batch helpers페이지에 접속합니다.    2. /fetch-and-run/에서 Dockerfile, fetchandrun.sh, myjob.sh 다운로드합니다.STEP2. Dockerfile을 이용하여 fetch&run 스크립트를 포함한 Docker 이미지 생성Dockerfile을 이용해서 Docker 이미지를 빌드합니다.잠시 Dockerfile의 내용을 살펴보겠습니다.FROM amazonlinux:latestDocker 공식 Repository에 있는 amazonlinux 의 lastest 버젼으로 빌드RUN yum -y install which unzip aws-cliRUN을 통해 이미지 빌드 시에 yum -y install which unzip aws-cli를 실행ADD fetch_and_run.sh /usr/local/bin/fetch_and_run.shADD를 통해 Dockerfile과 같은 디렉토리에 있는 fetch_and_run.sh를 /usr/local/bin/fetch_and_run.sh에 복사 WORKDIR /tmp컨테이너가 동작할 때 /tmp를 기본 디렉토리로 설정USER nobody컨테이너 실행 시 기본 유저 설정 ENTRYPOINT [“/usr/local/bin/fetch_and_run.sh”]컨테이너 실행 시 /usr/local/bin/fetch_and_run.sh를 call shell에 docker 명령을 통해 이미지 생성shell : docker build -t fetch_and_run . 실행하면 아래와 같은 결과가 출력됩니다.[ec2-user@AWS_BRANDI_STG fetch-and-run]$ docker build -t fetch_and_run . Sending build context to Docker daemon 8.192kB Step 1/6 : FROM amazonlinux:latest latest: Pulling from library/amazonlinux 4b92325dc37b: Pull complete Digest: sha256:9ee13e494b762db41b9db92a200f6784b78da5ac3b0f974fb1c38feb7f636474 Status: Downloaded newer image for amazonlinux:latest ---> 81bb3e78db3d Step 2/6 : RUN yum -y install which unzip aws-cli ---> Running in 1f5293a2294d Loaded plugins: ovl, priorities Resolving Dependencies --> Running transaction check ---> Package aws-cli.noarch 0:1.14.9-1.48.amzn1 will be installed --> Processing Dependency: python27-jmespath = 0.9.2 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-botocore = 1.8.13 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-rsa >= 3.1.2-4.7 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-futures >= 2.2.0 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-docutils >= 0.10 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-colorama >= 0.2.5 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-PyYAML >= 3.10 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: groff for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: /etc/mime.types for package: aws-cli-1.14.9-1.48.amzn1.noarch ---> Package unzip.x86_64 0:6.0-4.10.amzn1 will be installed ---> Package which.x86_64 0:2.19-6.10.amzn1 will be installed --> Running transaction check ---> Package groff.x86_64 0:1.22.2-8.11.amzn1 will be installed --> Processing Dependency: groff-base = 1.22.2-8.11.amzn1 for package: groff-1.22.2-8.11.amzn1.x86_64 ---> Package mailcap.noarch 0:2.1.31-2.7.amzn1 will be installed ---> Package python27-PyYAML.x86_64 0:3.10-3.10.amzn1 will be installed --> Processing Dependency: libyaml-0.so.2()(64bit) for package: python27-PyYAML-3.10-3.10.amzn1.x86_64 ---> Package python27-botocore.noarch 0:1.8.13-1.66.amzn1 will be installed --> Processing Dependency: python27-dateutil >= 2.1 for package: python27-botocore-1.8.13-1.66.amzn1.noarch ---> Package python27-colorama.noarch 0:0.2.5-1.7.amzn1 will be installed ---> Package python27-docutils.noarch 0:0.11-1.15.amzn1 will be installed --> Processing Dependency: python27-imaging for package: python27-docutils-0.11-1.15.amzn1.noarch ---> Package python27-futures.noarch 0:3.0.3-1.3.amzn1 will be installed ---> Package python27-jmespath.noarch 0:0.9.2-1.12.amzn1 will be installed --> Processing Dependency: python27-ply >= 3.4 for package: python27-jmespath-0.9.2-1.12.amzn1.noarch ---> Package python27-rsa.noarch 0:3.4.1-1.8.amzn1 will be installed --> Processing Dependency: python27-pyasn1 >= 0.1.3 for package: python27-rsa-3.4.1-1.8.amzn1.noarch --> Processing Dependency: python27-setuptools for package: python27-rsa-3.4.1-1.8.amzn1.noarch --> Running transaction check ---> Package groff-base.x86_64 0:1.22.2-8.11.amzn1 will be installed ---> Package libyaml.x86_64 0:0.1.6-6.7.amzn1 will be installed ---> Package python27-dateutil.noarch 0:2.1-1.3.amzn1 will be installed --> Processing Dependency: python27-six for package: python27-dateutil-2.1-1.3.amzn1.noarch ---> Package python27-imaging.x86_64 0:1.1.6-19.9.amzn1 will be installed --> Processing Dependency: libjpeg.so.62(LIBJPEG_6.2)(64bit) for package: python27-imaging-1.1.6-19.9.amzn1.x86_64 --> Processing Dependency: libjpeg.so.62()(64bit) for package: python27-imaging-1.1.6-19.9.amzn1.x86_64 --> Processing Dependency: libfreetype.so.6()(64bit) for package: python27-imaging-1.1.6-19.9.amzn1.x86_64 ---> Package python27-ply.noarch 0:3.4-3.12.amzn1 will be installed ---> Package python27-pyasn1.noarch 0:0.1.7-2.9.amzn1 will be installed ---> Package python27-setuptools.noarch 0:36.2.7-1.33.amzn1 will be installed --> Processing Dependency: python27-backports-ssl_match_hostname for package: python27-setuptools-36.2.7-1.33.amzn1.noarch --> Running transaction check ---> Package freetype.x86_64 0:2.3.11-15.14.amzn1 will be installed ---> Package libjpeg-turbo.x86_64 0:1.2.90-5.14.amzn1 will be installed ---> Package python27-backports-ssl_match_hostname.noarch 0:3.4.0.2-1.12.amzn1 will be installed --> Processing Dependency: python27-backports for package: python27-backports-ssl_match_hostname-3.4.0.2-1.12.amzn1.noarch ---> Package python27-six.noarch 0:1.8.0-1.23.amzn1 will be installed --> Running transaction check ---> Package python27-backports.x86_64 0:1.0-3.14.amzn1 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package                              Arch   Version            Repository                                                                           Size ================================================================================ Installing:  aws-cli                              noarch 1.14.9-1.48.amzn1  amzn-main 1.2 M  unzip                                x86_64 6.0-4.10.amzn1     amzn-main 201 k  which                                x86_64 2.19-6.10.amzn1    amzn-main  41 k  Installing for dependencies:  freetype                             x86_64 2.3.11-15.14.amzn1 amzn-main 398 k  groff                                x86_64 1.22.2-8.11.amzn1  amzn-main 1.3 M  groff-base                           x86_64 1.22.2-8.11.amzn1  amzn-main 1.1 M  libjpeg-turbo                        x86_64 1.2.90-5.14.amzn1  amzn-main 144 k  libyaml                              x86_64 0.1.6-6.7.amzn1    amzn-main  59 k  mailcap                              noarch 2.1.31-2.7.amzn1   amzn-main  27 k  python27-PyYAML                      x86_64 3.10-3.10.amzn1    amzn-main 186 k  python27-backports                   x86_64 1.0-3.14.amzn1     amzn-main 5.0 k  python27-backports-ssl_match_hostname                                       noarch 3.4.0.2-1.12.amzn1 amzn-main  12 k  python27-botocore                    noarch 1.8.13-1.66.amzn1  amzn-main 4.1 M  python27-colorama                    noarch 0.2.5-1.7.amzn1    amzn-main  23 k  python27-dateutil                    noarch 2.1-1.3.amzn1      amzn-main  92 k  python27-docutils                    noarch 0.11-1.15.amzn1    amzn-main 1.9 M  python27-futures                     noarch 3.0.3-1.3.amzn1    amzn-main  30 k  python27-imaging                     x86_64 1.1.6-19.9.amzn1   amzn-main 428 k  python27-jmespath                    noarch 0.9.2-1.12.amzn1   amzn-main  46 k  python27-ply                         noarch 3.4-3.12.amzn1     amzn-main 158 k  python27-pyasn1                      noarch 0.1.7-2.9.amzn1    amzn-main 112 k  python27-rsa                         noarch 3.4.1-1.8.amzn1    amzn-main  80 k  python27-setuptools                  noarch 36.2.7-1.33.amzn1  amzn-main 672 k  python27-six                         noarch 1.8.0-1.23.amzn1   amzn-main  31 k Transaction Summary ================================================================================ Install 3 Packages (+21 Dependent packages) Total download size: 12 M Installed size: 51 M Downloading packages: -------------------------------------------------------------------------------- Total 1.0 MB/s | 12 MB 00:12 Running transaction check Running transaction test Transaction test succeeded  Running transaction   Installing : python27-backports-1.0-3.14.amzn1.x86_64                    1/24   Installing : python27-backports-ssl_match_hostname-3.4.0.2-1.12.amzn1    2/24   Installing : python27-setuptools-36.2.7-1.33.amzn1.noarch                3/24   Installing : python27-colorama-0.2.5-1.7.amzn1.noarch                    4/24   Installing : freetype-2.3.11-15.14.amzn1.x86_64                          5/24   Installing : libyaml-0.1.6-6.7.amzn1.x86_64                              6/24   Installing : python27-PyYAML-3.10-3.10.amzn1.x86_64                      7/24   Installing : mailcap-2.1.31-2.7.amzn1.noarch                             8/24   Installing : python27-ply-3.4-3.12.amzn1.noarch                          9/24   Installing : python27-jmespath-0.9.2-1.12.amzn1.noarch                  10/24   Installing : python27-futures-3.0.3-1.3.amzn1.noarch                    11/24   Installing : python27-six-1.8.0-1.23.amzn1.noarch                       12/24   Installing : python27-dateutil-2.1-1.3.amzn1.noarch                     13/24   Installing : groff-base-1.22.2-8.11.amzn1.x86_64                        14/24   Installing : groff-1.22.2-8.11.amzn1.x86_64                             15/24   Installing : python27-pyasn1-0.1.7-2.9.amzn1.noarch                     16/24   Installing : python27-rsa-3.4.1-1.8.amzn1.noarch                        17/24   Installing : libjpeg-turbo-1.2.90-5.14.amzn1.x86_64                     18/24   Installing : python27-imaging-1.1.6-19.9.amzn1.x86_64                   19/24   Installing : python27-docutils-0.11-1.15.amzn1.noarch                   20/24   Installing : python27-botocore-1.8.13-1.66.amzn1.noarch                 21/24   Installing : aws-cli-1.14.9-1.48.amzn1.noarch                           22/24   Installing : which-2.19-6.10.amzn1.x86_64                               23/24   Installing : unzip-6.0-4.10.amzn1.x86_64                                24/24   Verifying  : libjpeg-turbo-1.2.90-5.14.amzn1.x86_64                      1/24   Verifying  : groff-1.22.2-8.11.amzn1.x86_64                              2/24   Verifying  : unzip-6.0-4.10.amzn1.x86_64                                 3/24   Verifying  : python27-pyasn1-0.1.7-2.9.amzn1.noarch                      4/24   Verifying  : groff-base-1.22.2-8.11.amzn1.x86_64                         5/24   Verifying  : aws-cli-1.14.9-1.48.amzn1.noarch                            6/24   Verifying  : python27-six-1.8.0-1.23.amzn1.noarch                        7/24   Verifying  : python27-dateutil-2.1-1.3.amzn1.noarch                      8/24   Verifying  : python27-docutils-0.11-1.15.amzn1.noarch                    9/24   Verifying  : python27-PyYAML-3.10-3.10.amzn1.x86_64                     10/24   Verifying  : python27-botocore-1.8.13-1.66.amzn1.noarch                 11/24   Verifying  : python27-futures-3.0.3-1.3.amzn1.noarch                    12/24   Verifying  : python27-ply-3.4-3.12.amzn1.noarch                         13/24   Verifying  : python27-jmespath-0.9.2-1.12.amzn1.noarch                  14/24   Verifying  : mailcap-2.1.31-2.7.amzn1.noarch                            15/24   Verifying  : python27-backports-ssl_match_hostname-3.4.0.2-1.12.amzn1   16/24   Verifying  : libyaml-0.1.6-6.7.amzn1.x86_64                             17/24   Verifying  : python27-rsa-3.4.1-1.8.amzn1.noarch                        18/24   Verifying  : freetype-2.3.11-15.14.amzn1.x86_64                         19/24   Verifying  : python27-colorama-0.2.5-1.7.amzn1.noarch                   20/24   Verifying  : python27-setuptools-36.2.7-1.33.amzn1.noarch               21/24   Verifying  : which-2.19-6.10.amzn1.x86_64                               22/24   Verifying  : python27-imaging-1.1.6-19.9.amzn1.x86_64                   23/24   Verifying  : python27-backports-1.0-3.14.amzn1.x86_64                   24/24 Installed:   aws-cli.noarch 0:1.14.9-1.48.amzn1        unzip.x86_64 0:6.0-4.10.amzn1   which.x86_64 0:2.19-6.10.amzn1   Dependency Installed:   freetype.x86_64 0:2.3.11-15.14.amzn1   groff.x86_64 0:1.22.2-8.11.amzn1   groff-base.x86_64 0:1.22.2-8.11.amzn1   libjpeg-turbo.x86_64 0:1.2.90-5.14.amzn1   libyaml.x86_64 0:0.1.6-6.7.amzn1   mailcap.noarch 0:2.1.31-2.7.amzn1   python27-PyYAML.x86_64 0:3.10-3.10.amzn1   python27-backports.x86_64 0:1.0-3.14.amzn1   python27-backports-ssl_match_hostname.noarch 0:3.4.0.2-1.12.amzn1   python27-botocore.noarch 0:1.8.13-1.66.amzn1   python27-colorama.noarch 0:0.2.5-1.7.amzn1   python27-dateutil.noarch 0:2.1-1.3.amzn1   python27-docutils.noarch 0:0.11-1.15.amzn1   python27-futures.noarch 0:3.0.3-1.3.amzn1   python27-imaging.x86_64 0:1.1.6-19.9.amzn1   python27-jmespath.noarch 0:0.9.2-1.12.amzn1   python27-ply.noarch 0:3.4-3.12.amzn1   python27-pyasn1.noarch 0:0.1.7-2.9.amzn1   python27-rsa.noarch 0:3.4.1-1.8.amzn1   python27-setuptools.noarch 0:36.2.7-1.33.amzn1   python27-six.noarch 0:1.8.0-1.23.amzn1   Complete! Removing intermediate container 1f5293a2294d  ---> 5502efa481ce Step 3/6 : ADD fetch_and_run.sh /usr/local/bin/fetch_and_run.sh  ---> 1b69173e586f Step 4/6 : WORKDIR /tmp Removing intermediate container a69678c65ee7  ---> 8a560dd25401 Step 5/6 : USER nobody  ---> Running in e063ac6e6fdb Removing intermediate container e063ac6e6fdb  ---> e5872fd44234 Step 6/6 : ENTRYPOINT ["/usr/local/bin/fetch_and_run.sh"]  ---> Running in e25af9aa5fdc Removing intermediate container e25af9aa5fdc  ---> dfca872de0be Successfully built dfca872de0be Successfully tagged awsbatch-fetch_and_run:latest docker images 명령으로 새로운 로컬 repository를 확인할 수 있습니다.shell : docker images [ec2-user@AWS_BRANDI_STG fetch-and-run]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE fetch_and_run latest dfca872de0be 2 minutes ago 253MB amazonlinux              latest              81bb3e78db3d        2 weeks ago         165MB STEP3. ECR에서 repository 생성아래는 ECR 초기 화면입니다.fetch_and_run이란 이름으로 Repository 생성합니다. 3. Repository 생성이 완료되었습니다.STEP4. ECR로 빌드된 이미지를 pushECR에 docker login후 빌드된 Docker 이미지에 태그합니다. shell : aws ecr get-login --no-include-email --region ap-northeast-2 빌드된 docker 이미지에 태그하세요.shell : docker tag fetch_and_run:latest 000000000000.dkr.ecr.ap-northeast-2.amazonaws.com/fetch_and_run:latest 태그된 docker 이미지를 ECR에 push합니다.shell: docker push 000000000000.dkr.ecr.ap-northeast-2.amazonaws.com/fetch_and_rrun:latest 아래는 ECR fetch_and_run Repository에 푸쉬된 Docker 이미지입니다.STEP5. 간단한 샘플 스크립트(myjob.sh)를 S3에 업로드아래는 간단한 myjob.sh 스크립트입니다.#!/bin/bash date echo "Args: $@" env echo "This is my simple test job!." echo "jobId: $AWS_BATCH_JOB_ID" sleep $1 date echo "bye bye!!" 위의 myjob.sh를 S3에 업로드합니다.shell : aws s3 cp myjob.sh s3:///myjob.sh STEP6. IAM에 S3를 접속할 수 있는 ECS Task role 등록Role 등록 화면에서 Elastic Container Service 선택 후, Elastic Container Service Task를 선택합니다.AmazonS3ReadOnlyAccess Policy를 선택합니다.아래 이미지는 Role에 등록 하기 전 리뷰 화면입니다.Role에 AmazonS3ReadOnlyAccess가 등록된 것을 확인합니다.STEP7. Compute environments 생성AWS Batch 콘솔에서 Compute environments를 선택하고, Create environment 선택합니다.Compute environment type은 Managed와 Unmanaged 두 가지를 선택할 수 있습니다. Managed는 AWS에서 요구사항에 맞게 자원을 관리해주는 것이고, Unmanaged는 직접 자원을 관리해야 합니다. 여기서는 Managed를 선택하겠습니다.Compute environment name을 입력합니다.Service Role을 선택합니다. 기존 Role을 사용하거나 새로운 Role을 생성할 수 있습니다. 새 Role을 생성하면 필수 역할 (AWSBatchServiceRole)이 생성됩니다.Instnace Role을 선택합니다. 기존 Role을 사용하거나 새로운 Role을 생성할 수 있습니다. 새 Role을 생성하면 필수 역할(ecsInstanceRole)이 생성됩니다.EC2 key pair에서 기존 EC2 key pair를 선택합니다. 이 key pair를 사용하여 SSH로 인스턴스에 접속할 수 있지만 이번 글의 예제에서는 선택하지 않겠습니다.Configure your compute resources Provisioning Model은 On-Demand와 Spot이 있습니다. 차이점은 Amazon EC2 스팟 인스턴스를 참고해주세요. 여기서는 On-Demand를 선택합니다.Allowed instance types에서는 시작 인스턴스 유형을 선택합니다. optimal을 선택하면 Job queue의 요구에 맞는 인스턴스 유형을 (최신 C, M, R 인스턴스 패밀리 중) 자동으로 선택합니다. 여기서는 optimal을 선택하겠습니다.Minimum vCPUs는 Job queue 요구와 상관없이 Compute environments에 유지할 vCPU 최소 개수입니다. 0을 입력해주세요.Desired vCPUs는 Compute environment에서 시작할 EC2 vCPU 개수입니다. Job queue 요구가 증가하면 필요한 vCPU를 Maximum vCPUs까지 늘리고 요구가 감소하면 vCPU 수를 Minimum vCPUs까지 줄이고 인스턴스를 제거합니다. 0을 입력해주세요.Maximum vCPUs는 Job queue 요구와 상관없이 Compute environments에서 확장할 수 있는 EC2 vCPU 최대 개수입니다. 여기서는 256을 입력합니다.Enable user-specified Ami ID는 사용자 지정 AMI를 사용하는 옵션입니다. 여기서는 사용하지 않겠습니다.Networking VPC Id 인스턴스를 시작할 VPC를 선택합니다.Subnet을 선택합니다.Security groups를 선택합니다.그리고 EC2 tags를 지정하여 생성된 인스턴스가 이름을 가질 수 있게 합니다. Key : Name, Value : AWS Batch InstanceCreate을 클릭해 Compute environment를 생성합니다.아래 이미지는 생성된 Compute environment입니다.STEP8. Job queues 생성AWS Batch 콘솔에서 Job queues - Create queue를 선택합니다.Queue name을 입력합니다.Priority는 Job queue의 우선순위를 입력합니다. 우선순위가 1인 작업은 우선순위가 5인 작업보다 먼저 일정이 예약됩니다. 여기서는 5를 입력하겠습니다.Enable Job queue가 체크되어 있어야 job을 등록할 수 있습니다.Select a compute environment에서 Job queue와 연결될 Compute environment을 선택합니다. 최대 3개의 Compute environment를 선택할 수 있습니다.생성된 Job queue, Status가 VALID면 사용 가능합니다.STEP9. ECR을 이용하여 Job definition 생성AWS Batch 콘솔에서 Job definitions - Create를 선택합니다.Job definition name을 입력하고 이전 작업에서 만들 IAM Role을 선택하세요, 그리고 ECR Repository URI를 입력합니다. 000000000000.dkr.ecr.ap-northeast-2.amazonaws.com/fetch_and_runCommand 필드는 비워둡시다.vCPUs는 컨테이너를 위해 예약할 vCPU의 수, Memory(Mib)는 컨테이너에 제공할 메모리의 제한, Job attempts는 작업이 실패할 경우 다시 시도하는 최대 횟수, Execution timeout은 실행 제한 시간, Ulimits는 컨테이너에 사용할 사용자 제한 값입니다. 여기서는 vCPUs는 1, Memory(MiB)는 512, Job Attempts는 1로 설정, Execution timeout은 기본값인 100 그리고 Limits는 설정하지 않습니다.vCPUs: 컨테이너를 위해 예약할 vCPU의 개수Memory(Mib): 컨테이너에 제공할 메모리의 제한Jop attempts: 작업이 실패할 경우 다시 시도하는 최대 횟수Execution timeout: 실행 제한 시간Ulimits: 컨테이너에 사용할 사용자 제한 값User는 기본값인 nobody로 선택 후, Create job definition을 선택합니다.Job definitions에 Job definition이 생성된 것을 확인할 수 있습니다.STEP10. Submit job을 통해 S3에 저장된 작업 스크립트(myjob.sh)를 실행하기AWS Batch 콘솔에서 Jobs를 선택합니다. Job을 실행할 Queue를 선택하고 Submit job을 선택합니다.Job run-time1)Job name을 입력합니다.2)Job definition을 선택합니다.3)실행될 Job queue를 선택합니다.Environment Job Type을 선택하는 부분에서는 Single을 선택합니다. Array 작업에 대한 자세한 내용은 어레이 작업 페이지를 참고해주세요.Job depends on은 선택하지 않습니다.자세한 내용은 작업 종속성 페이지를 참고해주세요.Environment Command에서 컨테이너에 전달할 명령을 입력합니다. 여기서는 [“myjob.sh”, “30”] 를 입력해주세요. vCPUs, Memory, Job attempts와 Execution timeout은 job definition에 설정된 값을 가져옵니다. 이 Job에 대한 설정도 가능합니다.Parameters를 통해 job을 제출할 때 기본 작업 정의 파라미터를 재정의 할 수 있습니다. Parameters에 대한 자세한 내용은 작업 정의 파라미터 페이지를 참고해주세요.Environment variables는 job의 컨테이너에 환경 변수를 지정할 수 있습니다. 여기서 주의할 점은 Key를 AWS_BATCH로 시작하면 안 된다는 것입니다. AWS Batch에 예약된 변수입니다.Key=BATCH_FILE_TYPE, Value=script Key=BATCH_FILE_S3_URL, Value=s3:///myjob.shSubmit job을 선택합니다.Job이 Submitted 된 화면입니다.Dashboard를 보시면 Runnable 상태로 대기 중인 것을 확인할 수 있습니다.STEP11. 결과 확인CloudWatch > Log Groups > /aws/batch/job에서 실행 로그를 확인할 수 있습니다.Conclusion간단한 튜토리얼로 AWS Batch를 설정하고 실행하는 방법을 알아봤습니다.(참 쉽죠?) 다음 글에서는 AWS Batch의 Array 또는 Job depends on등의 확장된 기능들을 살펴보겠습니다. 참고1) AWS Batch – 쉽고 효율적인 배치 컴퓨팅 기능 – AWS2) AWS Batch 시작하기 - AWS Batch3) Amazon ECR의 도커 기본 사항 - Amazon ECR글윤석호 이사 | 브랜디 [email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발문화 #개발팀 #업무환경 #인사이트 #경험공유
조회수 679

숙박앱에 필요한와이즈트래커 리포트 Top 3

숙박앱은 O2O 서비스를 선도하는 사업 중 하나로 빠르게 시장을 확보하기 위한 다수의 앱이 생산되면서, 유사한 경쟁 앱 속에서 차별화 된 서비스로 고객을 잡기 위한 노력이 치열한 사업영역 이기도 합니다. 그래서 숙박 앱 운영에 도움이 될 와이즈트래커의 리포트 3가지를 소개하고자 합니다.1. 상품 카테고리 리포트숙박의 등급은 생각보다 다양합니다. 그러나 숙박 앱에서 한 화면에 보여지는 컨텐츠는 1~2개이며, 이후에는 지속적인 스크롤링으로 원하는 숙박장소를 찾기 때문에 사용자가 선호하는 컨텐츠를 상단에 효과적으로 배치하는 게 중요합니다.상품 카테고리 리포트는 각 숙박 카테고리별로 방문수(=유니크 조회수), 평균 체류시간 등 인게이지먼트 지표와 더불어 객실선택, 예약하기, 주문, 매출액 등 다양한 컨버전 지표를 함께 제공합니다. 나아가 상품 리포트를 통해서 ‘특급’이란 카테고리 중 실제 어떤 호텔이 효과가 좋았는지를 파악할 수 있습니다.이러한 데이터는 컨텐츠 배치 뿐만 아니라, 제휴 영역을 확장하는 데도 어떤 카테고리에 집중해야 할지 참고할 수 있는 유용한 데이터입니다.2. 화면 이동경로 리포트숙박 앱 UI는 매우 심플하고 직관적인 편입니다. 사용자는 예약이 앱 실행의 주 목적이기 때문에, 퍼블리셔는 보통 첫 화면에 컨텐츠를 스크롤링해서 볼 수 있도록 구성하지만 의외로 예약에 접근하는 행동패턴은 다양할 수 있습니다.샘플 데이터처럼 목적을 갖고 검색을 통해 빠르게 상품 정보를 획득하고자 하는 사용자의 비중이 많다면, 모바일 기기에 적합한 내부 검색엔진 편의성 및 결과 화면의 퀄리티가 매우 중요할 것이며 이는 예약율과 직결될 수 있습니다. 반대로 검색했는데 만족하지 못한 결과 값을 제공했다면, 높은 외부 유출 비율을 나타낼 것입니다.화면 이동경로 리포트는 이러한 다양한 사용자들의 행동패턴을 타겟별로 4가지 타입(A화면 이후, A화면 전/후, A화면 도달경로, A화면에서 B화면을 도달하는 경로)으로 분석하여 네비게이션 개선에 통찰력을 얻을 수 있는 데이터를 제공합니다.  3. 내부 검색어 리포트 숙박 앱에서 검색엔진을 사용하는 빈도는 꽤 높습니다. 앱을 실행하자마자 검색하는 사용자는 서핑을 즐겨하기보단 자신이 원하는 컨텐츠(정보)만을 빠르게 받고 싶은 성향이 있습니다. 해당 사용자에겐 효과적인 검색결과 화면을 제공하는 것이 핵심입니다.검색결과 화면은 2가지가 필히 고려돼야 합니다.1) 검색결과와 관련성 높은 결과 값 제시( 방대한 결과값은 오히려 재검색하게 하여 불편함을 제공)2) 검색결과 값이 없을 경우 대안을 제시( 빈 페이지 제시는 매우 부정적인 경험으로 기억)내부 검색어 리포트는 사용자의 검색빈도가 높은 인기 키워드를 파악할 수 있으며, 검색 실패수 지표를 통해 온전한 결과 값을 제시하지 못한 경우를 찾아 검색엔진 개선의 방향을 잡을 수 있습니다.  * WISETRACKER는 모바일 광고 성과 측정부터 In-app 이용자/컨텐츠 분석, 푸시메시지 최적화까지 지원하는 모바일 통합 분석/타겟팅 솔루션입니다. 와이즈트래커 솔루션의 무료체험을 원하실 경우 여기를 클릭해주세요.* WISETRACKER가 제공하는 무료 데이터 분석 컨설팅를 원하신다면 여기를 클릭해주세요.  #와이즈트래커 #서비스소개 #데이터분석 #데이터트래킹 #앱리포트
조회수 2956

개발자 직군 파헤치기 2 | 게임 개발자

게임 개발자국내 게임 산업에서 모바일 게임의 매출액은 2011년 4235억원에서 2013년 2조3276억원으로 2년 만에 6배 가까이로 늘어났습니다.(출처:한국콘텐츠진흥원) 한국 모바일 게임은 해외에서도 인기를 끌고 있는 추세입니다. 뿐만 아니라 최근 엄청난 인기를 끌고있는 배틀그라운드는 한국 게임 산업의 가능성을 증명합니다. 배틀그라운드는 작년 한 해 7621억원의 수익을 거두면서 2017년 가장 큰 수익을 거둔 PC 게임 패키지 1위를 차지했습니다.배틀그라운드의 일러스트게임을 좋아하는 사람이라면 한번쯤은 게임 개발에 관심을 가져보았을 것입니다. 특히 프로그래밍을 하는 사람이라면 자신의 게임을 만들어보고 싶다는 생각을 해보거나, 게임 회사에서 일 하는 것을 고려해보았을 것입니다. 그러나 한편으로는 압도적인 근무 시간에 대한 부담으로 게임 개발자가 되겠다는 생각을 접게 되신 분들도 많습니다.이번 포스팅은 게임 개발자에게 필요한 역량이 무엇인지 알아보고, 게임 개발자의 두 가지 커리어 종류에 대해 설명하려고 합니다. 또한 지금 당장, 코딩을 전혀 할 줄 모르는 상태에서 게임 개발에 도전해볼 수 있는 방법 또한 소개해드리겠습니다.게임 개발자에게 필요한 역량게임을 만들기 위해서는 그래픽을 다루는 능력, 스토리와 레벨을 기획하는 능력, 3D 모델링, 그래픽 엔진을 다루는 능력 등 많은 영역들에서 전문성을 필요로 합니다. 물론 이 모든 것을 전문적으로 다루는 사람이 되기란 불가능에 가깝습니다. 그렇기 때문에 스토리라인과 컨셉 구성은 기획자가 담당하고, 기획자의 아이디어는 개발자와 그래픽 디자이너의 손을 거쳐 게임의 모습을 갖춥니다. 그래픽 디자이너가 시각적 구현을 맡는다면, 개발자는 PC나 모바일에서 게임이 실행될 수 있도록 만드는 작업을 하게되는 것입니다. 게임 개발자도 결국 개발자 직군의 일환이기 때문에 일반적으로 개발자들이 많이 다루는 언어에 대한 숙련도나 프로그래밍 능력이 필요합니다. 그러나 게임 개발자의 경우 다른 직군의 개발자에게는 필수적이지 않은 지식을 필요로 할 때가 있습니다. 아래에는 특히 게임 개발자들에게 중요한 세 가지 요소입니다. 1. 프로그래밍 언어대부분의 대규모 게임 회사들은 C++을 가장 많이 사용합니다. 모바일 게임이 대세로 더오르면서 C#을사용하는 경우가 많아진 것은 사실입니다. 그러나 PC, 모바일, 비행기 제어 프로그램까지 폭넓게 지원하는 고성능의 3D 게임을 개발하기 위해서는 여전히 C++이 최적이라는 평가를 받습니다. 주의할 점은 C/C++은 계속해서 발전하고 있는 언어라는 점입니다. 언어를 배우기 위한 서적, 인터넷 강의 등은 무궁무진하지만 중요한 것은 최신의 것을 배워야 한다는 점입니다.2. 게임 엔진게임 엔진은 간단하게 말해 게임을 개발하는 과정을 쉽게 만드는 ‘도구’입니다. 중력 같은 기본적인 물리 효과나 오브젝트 사이의 충돌 여부를 판정하는 ‘컬라이더’ 등, 개발에 필요한 기본적인 기능이 탑재되어있기 때문에 게임 엔진은 개발 과정을 획기적으로 단축시켜줍니다. 가장 많이 쓰이는 게임 엔진은 유니티와 언리얼입니다.이 글을 읽고 있을 대부분의 분들이 개발을 배우는 과정에 있다는 가정하에 학습의 용이함을 기준으로 비교해보면, 유니티의 경우 공식적으로 지원하는 교육 프로젝트의 수는 9개입니다. 그러나 공식적인 자료 외에도 한글 서적이나 온라인 강좌들은 매우 풍부합니다. 반면에 언리얼이 제공하는 공식 교육 프로젝트는 수십개입니다. 대부분이 한글 자막을 지원해줄 뿐만 아니라 다양한 주제를 경험할 수 있습니다. 언리얼의 한계라면 공식 채널 외에서 학습할 수 있는 자료나 커뮤니티가 아직까지는 많지 않다는 점입니다. 3. 수학게임 개발자에게 수학은 매우 중요하고도 기본적인 것입니다. 특히 3D 게임을 다루고 싶다면 수학적 지식과 역량은 매우 중요한 부분을 차지할 것입니다. 물론 위에서 말한 게임 엔진이 수학적인 계산이나 물리와 관련된 문제들을 해결해 줄 수는 있습니다. 그러나 게임 엔진을 활용한다 하더라도 기본적으로 그것이 어떻게 작동하는지는 이해해야 합니다. 그렇기 때문에 이산 수학, 즉 벡터, 행렬, 집합, 논리 연산 등에는 능숙할 필요가 있습니다. 게임 개발자의 커리어게임 개발자가 되기 위한 길이 게임 회사에 취직하는 것만 있는 것은 아닙니다. 최근에는 크게 성공하는 인디 게임, 즉 대규모 회사가 아닌 저예산의 1인기업 혹은 작은 팀단위로 만들어 내는 게임들의 사례가 늘어나고 있습니다. 게임 회사에 취직하는 것만큼 확실한 방법이 없다는 생각을 갖고 계신 분들, 혹은 자신만의 게임을 만드는 것에 강한 매력을 느끼시는 분들을 위해 두 가지 커리어 옵션을 비교해 보았습니다.1. 대규모 게임 회사대부분의 게임 개발자가 특정 회사에 소속되어 일을 합니다. 회사에 소속되어 있기에 안정적인 수입이 보장된다는 것이 첫번째 장점이라면, 두번째 장점은 혼자서는 절대 만들 수 없는 규모의 게임을 개발하는 데에 기여할 수 있다는 점입니다. 한 마디로 말해 완성도 있고 유명한 게임에 일조 했다는 자부심을 가질 수 있게 되는 것입니다. 또한 주니어 개발자로서 풍부한 경험을 가진 시니어 개발자를 포함해 배울 점이 많은 사람들로 구성된 팀에 소속될 수 있다는 것 또한 큰 장점입니다.한편 회사의 크기가 큰 경우에는 각 사람이 맡는 개발의 영역이 매우 세분화 되어있기 마련입니다. 자신이 느끼기에는 조금 지루하고 단순한 일이라고 생각되는 일을 맡게 될 수도 있습니다. 그러나 반대로 말하면 디자인, 기획, 마케팅 등 개발 외의 업무 등에 신경을 쓰지 않고 오직 자신의 일에 집중할 수 있는 환경이 제공되는 것이기도 합니다.2. 인디게임 개발규모가 있는 회사에 취직하는 것이 아니더라도 게임을 만들 수 있는 방법은 많습니다. 또한 안정적인 수입이 보장된 것은 아니지만, 성공하는 경우 생각는 것보다 그 수익이 큽니다. 예를 들어 트리오브라이프를 개발한 오드윈게임즈는 1년 간 20억의 매출에 도달했습니다. 단지 한 사람이 2주 동안 만든 게임, 숨바꼭질은 한 달만에 5000만원의 수익을 냈습니다. 물론, 이를 성공 신화에 불과하다고 말할 수도 있기 때문에 분명히 감수해야 하는 위험이 있는 커리어인 것이 사실입니다. 인디 게임 간에도 경쟁이 매우 치열하기 때문입니다.그럼에도 불구하고 소규모로, 혹은 혼자서 게임을 개발하는 사람들은 게임에 대한 애착을 가지고 개발 과정 전체를 아우르며 작업할 수 있다는 점에서 만족감을 느낍니다. 특히 투자 규모나 시기에 구애를 받지 않고 개성적인 게임, 만들고 싶은 게임을 만들 수 있다는 것이 장점이라고 할 수 있습니다. 지금 시작하기게임 개발을 하고 싶은데 어디서 시작해야 하는지를 막막해하고 있다면, 무조건 일단 만들어보기 시작하는 것이 중요합니다. 자신의 아이디어, 혹은 이미 있는 게임들을 가지고 점점 난이도를 높여가며 여러 프로젝트를 실행해 보는 것이 좋습니다. 이는 실력을 쌓는 데에도 도움이 되지만, 이후에 훌륭한 포트폴리오가 되기도 합니다.일단 만들어보라는 조언도 막막하신 분들을 위해 준비한 것은 무료로 사용할 수 있는 게임 개발 프로그램들입니다. 코딩을 전혀 할 줄 모르는 사람부터 완성도 있는 게임을 만들고 싶어하는 사람들까지 다양한 수준에서 접근할 수 있는 도구들을 소개해드리겠습니다.1.Flow CreatorFlow Creator는 코딩을 해본 적이 없어도 간단한 드래그앤드롭으로 게임을 만들 수 있는 웹사이트입니다. 시각적으로 논리적 구조를 짤 수 있기 때문에 어떤 언어도 배워본 적이 없어도 됩니다. 무료 버전의 경우 5개의 레벨, 50개의 개체로 제한이 되어있지만 유료 버전의 경우 앱으로 만들어 스토어에 올릴 수도 있습니다.2. StencylStencyl도 Flow Creator와 마찬가지로 프로그래밍 언어가 아니라 Stencyl의 사용법만 잘 익히면 훌륭한 게임을 만들 수 있습니다. 사용법이 Flow Creator에 비해 좀더 까다로운 것은 사실이지만 결과물의 완성도가 더 높습니다. 또한 이미 만들어져있는 코드블록 외에도 직접 코드를 작성하고 라이브러리를 불러오는 등 확장할 수 있는 가능성도 있습니다.3. Game Maker StudioGame Maker는 위의 두 가지 프로그램처럼 드랙 앤 드롭으로 만들 수 있지만, Game Maker Language(GML)이라는 자체 언어를 활용하여 만들 수도 있습니다. GML을 사용해서 게임을 만드는 것은 프로그래밍을 학습하는 데에도 도움이 될 것입니다.게임 개발자의 종류는 정말 많다.오늘 포스팅에서 언급한 게임 개발자는 일부입니다. 게임 개발자의 종류에는 온라인 게임, 모바일 게임, 콘솔 게임 등 정말 다양하고 무궁무진합니다. 여러분들이 어떤 게임 개발자가 되고 싶든 중요한 것은 게임에 대한 열정인 것 같습니다. 자신이 정말 하고 싶고 좋아하는 게임을 만든다는 것은 세상에 의미있는 프로그램을 만드는 개발자만큼이나 행복한 개발자겠지요. 다음 편에는 더 재밌는 개발자 직군으로 찾아오겠습니다.

기업문화 엿볼 때, 더팀스

로그인

/