스토리 홈

인터뷰

피드

뉴스

조회수 1305

[Buzzvil People] Andy Kim, Software Engineer

 Buzzvil People에서는 다양한 배경과 성격 그리고 생각을 지닌 버즈빌리언들을 한 분 한 분 소개하는 시간을 갖습니다. 어떻게 버즈빌에 최고의 동료들이 모여 최고의 팀을 만들어가고 있는 지 궁금하시다면, 색색깔 다양한 버즈빌리언들 한분 한분의 이야기가 궁금하시다면, Buzzvil People을 주목해주세요.1. 간단한 자기 소개 부탁드립니다. 안녕하세요. 저는 Andy입니다. 저는 중학교부터 대학교까지 미국에서 7~8년 동안 지내며 학업을 마치고 한국으로 돌아와 버즈빌에 자리를 잡았습니다. 대학 시절에는 제약에서부터 통계, 데이터/컴퓨터 공학까지 전공을 여러 번 바꿨습니다. 개인적으로 새로운 레시피나 방법으로 요리하는 것을 좋아합니다. 개인 시간에는 주로 유튜브에서 요리 콘텐츠를 즐겨보고, 동료나 친구들과 함께 새로운 레시피에 도전해보곤 합니다. 2. 어떻게 버즈빌에 오시게 되셨나요? 대학을 졸업하고 한국으로 돌아온 후, 새로운 소프트웨어 엔지니어링 툴을 적극적으로 사용하는 IT 회사에서 일하고 싶었습니다. 구인 사이트에서 클라우드 기술과 관련된 채용공고를 찾아보다가, 버즈빌을 발견했습니다. 3. 버즈빌에서 어떤 업무를 담당하고 계신가요? 저는 데브옵스(DevOps) 팀에 소속되어 데이터 및 데브옵스 엔지니어로 일하고 있습니다. 제 주 업무는 다음과 같지만 국한되어 있지는 않습니다. – 새로운 데이터 생성 시 Data pipelines 제작 및 유지보수 – 자사에서 사용하는 Redshift 데이터 웨어하우스 유지보수 및 최적화 – 메타베이스(Metabase) 를 이용해 데이터를 다른 직원들이 사용할 수 있도록 가공 4. 스타트업에서 혹은 광고업계에서 일하는 느낌이 어떠세요? 소프트웨어 엔지니어로서 스타트업에서 근무하는 것은 샌드박스 게임을 하는 것과 비슷했습니다. 대부분의 경우, 새로운 기술이나 컨셉을 주저하지 않고 시도해볼 수 있습니다. 업무 사항에서 한발 더 나아가 더 큰 노력을 쏟아붓고자 하면, 사실상 무수히 많은 데이터 자산과 인프라에 접근할 기회도 받습니다. 5. 이것만큼은 버즈빌이 참 좋다! 어떤 게 있으실까요? 무제한으로 제공되는 신선한 커피 원두가 행복한 충격이었습니다. 커피를 내릴 때 3가지 이상의 커피 원두를 마음껏 고를 수 있는데요. 제가 속한 데브옵스 팀에서 커피타임은 매우 중요한 의식 중 하나입니다. 매일 스크럼을 커피타임과 함께 진행하고 있습니다. 돈 한 푼 사용하지 않고 즐길 수 있는 좋은 품질의 커피는 버즈빌에서 일하면서 받을 수 있는 기분 좋은 보너스 중 하나입니다. 6. 개인적인 목표나 꿈이 있으신가요? 있다면, 버즈빌에서의 경험이 어떻게 도움이 된다고 생각하시나요? 최종적으로, 제 꿈은 요식업계에 도전하는 것입니다. 아직 구체적인 계획은 없지만, 편향된 데이터나 해로운 과정의 효과를 최소화해 대중들에게 좋은 음식을 제공하는 서비스를 만들고 싶습니다. 버즈빌에서 데이터 엔지니어로서 일한 경험은 좋은 팀을 만나게 해주고, 유연하면서도 탄탄한 서비스를 만들어, 최종적으로는 사람들의 먹거리에 영향을 주는 것에 도움이 될 것으로 기대하고 있습니다.
조회수 5942

개발자 채용 시 기술검증 어떻게 할 것인가

eBrain에서 진행하는 "개발자 채용 시 기술검증 어떻게 할 것인가"라는 미니 워크숍을 다녀왔다. 항상 고민하고 있는 주제이기도 하고 개인적으로 팬심(?)을 가지고 있는 김창준님의 강의라 한시간 거리를 극복했다.  이미 창천향로님이 강의 내용을 잘 정리해 주셨다. 하지만 내 자신의 학습을 위해 강의 내용을 재해석 해서 적어 본다. 빠져든다! 1. 현재 기술력 검증의 문제점최근의 개발자 채용에 사용되는 기술력 검증 방식은 다음과 같은 것들이 있다.  온라인 코딩 테스트 (최근에 여러 가지 플랫폼도 있다)손 코딩 테스트기술 인터뷰과제 제출이 중 최근에는 주로 알고리즘에 대한 코딩 테스트가 주가 되는 것 같다. 생각보다 난이도가 있어서 재직자들이 “이런 문제면 저는 못 들어왔을 것 같아요”라고 하는 경우도 있다. 코딩 테스트에 대해 두 가지 사례를 들어 질문을 던져 본다.  삼각형 판별 문제삼각형 판별 문제는 세 좌표가 주어졌을 때 이 삼각형이 어떤 삼각형인지 (정삼각형, 이등변 삼각형, 둔각 삼각형 등)를 맞추는 것이다. 이 프로그램이 잘 동작하는지를 검증하는 것이 QA 동네의 ‘Hello World’ 문제다. 이 문제가 주어지면 초보자들은 그냥 문제를 푼다. 하지만 전문가는 문제를 풀지 않고 “이 프로그램을 누가 쓸 것인가요?”를 물어본다. 콘텍스트에 따라서 완전히 다른 테스트의 설계가 필요하기 때문이다.  코딩 테스트도 이와 비슷하다. 코딩 테스트는 단순화된 문제를 푼다. 즉 맥락이 제거된 상태에서의 문제를 푼다. 실무는 종합적인 환경에서 이뤄진다. 따라서 이 문제를 잘 푼다는 것이 실무를 잘할 수 있는 것을 의미하지 않을 수 있다.  질문) 우리의 코딩 테스트는 과연 실무에서의 실력과 높은 상관관계가 있는가?  전문성 연구개발자는 종종 전문성의 연구 대상이 되곤 한다. 이때 연구비를 이유로 주로 혼자서 빠르게 풀 수 있는 문제로 실험이 이뤄진다. 하지만 이런 식의 실험들에서 “토이 문제”가 아닌 “복잡하고 확장된 문제"를 전달했을 때 전혀 다른 결과가 도출된다는것을 알게 되었다.  복잡한 문제, 즉 실제 문제를 풀 때는 인지적 전략이 많이 바뀐다. 또한 사회적 요소도 필요하다. 이런것들을 “토이 문제”로 검증하기는 쉽지 않다. X를 테스트하면 X를 잘하는 사람을 뽑게 된다.  즉, 알고리즘 코딩 테스트를 하면 알고리즘 코딩 테스트에 능한 사람을 뽑게 된다. 질문) 실무에 최대한 가까운 상황을 제한된 면접 시간 내에 만들어 내려면 어떻게 해야 할까? 2. 개발자 채용은 어떻게 해야 할까?채용이 더 크리티컬 한 곳이 있다. 델타포스, 네이비씰과 같은 특수부대이다. 이곳에서는 사람을 어떻게 뽑을까?  작전 지역을 설정 해 두고, 보급품과 군사장비를 실제 작전 수행 환경과 같이 조성해 놓는다. 그곳에서 직접 작전을 수행하는 것을 시뮬레이션 한다.이를  교관이 직접 따라가며 기록과 채점을 한다.  개발자의 면접 시에도 최대한 실제와 비슷한 환경을 구축하는 것이 좋다. 코딩 문제처럼 맞고 틀림만 보는 것이 아니라 과정에 대한 채점이 이뤄져야 한다. 3. 효과적인 기술력 검증을 위해서는 어떻게 준비해야 하는가?1) 우리가 하는 일을 분석한다.  우리가 하는 일에 코딩만 있는 것이 아니다. 설계도 하고, 버그도 찾고, 장애 해결도 하고, 커뮤니케이션도 한다.  2) 대표 케이스들을 뽑거나 만들어 내야 한다.  예를 들어 새롭게 코드를 작성하는 것보다 기존의 기능을 파악해서 코드를 수정하는 일을 더 많이 한다면 이런 상황을 문제로 만드는 것이 좋다.  3) 대표 케이스들로 파일럿 테스트를 해본다.  우리 회사의 뛰어난 개발자 3명과 평범한 개발자 3명에게 이 문제를 풀게 해보고 이를 기준으로 채점표를 만들어야 한다. 어느 누가 평가해도 비슷하게 나오도록 해야 한다. 뛰어난 개발자의 문제 풀이 방식을 기준으로 채점 기준을 만들 수 있다. 예를 들면 다음과 채점 기준이 나올 수 있다.  질문을 5개 이상 한다.코딩하는 과정에서 반복적인 실행을 한다. 4) 면접 후에는 결과에 대한 논의가 필요하다.  특정 항목에 대해 채점 기준이 다른 경우 이에 대한 논의 과정이 필요하다. 이는 면접관의 훈련에 도움이 된다.   4. 실습실제로 면접 문제 만드는 것을 실습해 보자.1) 수강생의 제안다음과 같은 면접 문제는 어떨까요?첫날 출근을 했는데 회사 웹서비스가 죽었습니다. 어떻게 하면 좋을까요? 2) 코칭좀 더 게임스럽게 만들어 본다. 실제 토이 서버를 죽여 놓고, 쉘을 주면서 실제로 어떻게 해결 하는지 살펴본다.옆에 조언을 줄 수 있는 가상의 3년 차 팀원(NPC처럼)을 제공한다. 제한된 답변을 하도록 한다.면접자가 다음과 같은 경우면 더 높은 점수를 줄 수 있다. 실제 업무를 할 때에는 이런 상황까지 이어진다는 것을 유념하자.  문제의 원인을 밝힌 이후에 이 문제를 근본적으로 해결하기 위한 후속조치를 말한다. 개발팀 내에 이 원인과 해결에 대한 공유를 한다.  5. 질문 답변1) 필터링의 목적으로 코딩 테스트는 의미가 있나요? 간단한 문제를 던져서 못 푸는 사람을 필터링하는 것으로는 의미가 있다. 하지만 그 이상의 목적으로 사용하는 것은 조심해야 한다고 생각한다.코딩 테스트라는 과정은 특히 지원자에게 많은 비용이 드는 과정이기 때문에 조금 더 경제적인 방법들이 있다. 예를 들면 “행동 기반 인터뷰”가 있다. 과거에 있었던 행동에 대한 구체적인 질문을 던지는 것이다.또한 코딩 테스트는 지원자에게 상당히 스트레스를 주는 방법이고, 지능이 높은 사람은 오히려 스트레스에 취약하다는 연구가 있다. 따라서 코딩 테스트를 진행하더라도 스트레스를 덜 주는 방향을 고민해야 한다.  2) 블라인드 테스트(이력서를 보지 않고 면접)의 장단점? 결국 코딩 테스트에 적합한 사람을 뽑게 될 것 같다. 코딩 테스트라는 것이 훈련 과정이 필요하기 때문에 입사에 대한 갈망을 볼 수는 있겠다. 질문 시에는 실무와 관련이 깊은 질문을 하면 좋겠다. 역시나 과거의 행동에 기반한 질문이 편향이 적고 많은 정보를 얻을 수 있다. 예를 들면 “팀장이 한 달 걸릴 일을 일주일 만에 끝내라고 한 적이 있나요? 그때 어떻게 하셨나요?”와 같은 질문이다. 3) 끈기, 성실 여부를 판단할 수 있을까요? 주위에서 끈기, 성실이라는 키워드를 생각하면 떠오르는 사람이 있을 것이다. 그 사람의 구체적인 행동을 기반으로 면접 문제를 만들어내는 것이 좋다. 행동에 대한 질문을 할 때에는 과거에 대한 질문을 하는 것이 좋다. 사람은 미래에 대해서는 거짓을 이야기 하가 쉽지만 과거의 이야기를 할 때에는 과거의 상황을 조작하는 동시에 거짓말을 하기가 쉽지 않다.  4) 채용 여부는 실력에 기반하게 되는데, 결국 연봉은 연차에 따라 주게 된다. 좀 더 세밀하게 측정할 수 있는 방법이 있을까? 임시 월급을 주고, 1달 혹은 3달 뒤에 급여를 적용하는 방법이 있다. 실제 환경에서는 보다 정확하게 퍼포먼스를 측정할 수 있다.  하지만 입사할 때 연봉이 중요한 요소가 되지 않게 하는 것이 더 주요한 방법이다. 내재적 동기를 갖게 하는 것이 더 중요하다. 연봉 인상에 따른 동기는 최대 3 달이면 없어진다. 외재적 동기는 점점 내재적 동기를 감소시킨다. 그 일을 즐기지 않게 되고, 하기 싫어지고, 성과가 없어진다. 연봉 말고 다른 협상 거리를 많이 가지고 있어야 한다. 연봉이 여러 가지 조건 중 하나가 되어야 한다.  5) 현재 잘하는 사람을 기준으로 채점 기준을 만들었다면, 다른 장점이 있는 사람이 탈락되지 않을까? 만일 현재 채점기준에는 적합하지 않지만, 다른 측면에서 장점이 있는 사람이 있다면 그 측면을 반영한 채점 기준을 만들어야 한다.  채용에 대해서 틀린 선입견을 가지고 있는 경우가 많이 있다. 예를 들면 술을 잘 먹는 사람이 협력을 잘한다.라고 생각하는 것이다. 그 반례가 있는지를 생각해 보면 그런 선입견을 깨는데 도움이 된다.  6) 비개발자와 함께 면접을 할 때 합의가 힘든 경우가 있다.  회사 안에서 어떤 사람을 뽑고 싶은지 합의가 필요하다. 우리 회사에서 핵심 인재를 추린 다음에 이 사람들의 공통점을 찾아서 인재상을 만들어야 한다.  7) 전화면접 괜찮을까요? 화상면접이 더 효과적인진 않을까요? 억양이 포함되어 있는 대화는 90%의 정보를 전달할 수 있다고 본다. 그 사람의 생각을 충분히 전달받을 수 있기 때문에 화상면접이 크게 더 효과적이라고 생각하지는 않는다.  우리나라에서는 많이 하지 않지만 면접에 대한 비용이 저렴하기 때문에 전화면접이 효과적인 수단이라고 생각한다. 단, 전화면접을 하기 전에 기준이 명확해야 한다. 느낌만으로 판단을 내리는 것은 의미가 없다. 8) 사내 전문가가 없는 영역에 대한 채용을 해야 한다면? 회사 외부의 전문가 몇 분을 찾아가서 그분들의 경험을 듣는다. 그 경험들에 기반해서 면접 문제를 만든다. 도메인에 관계없는 전문성이 있는지는 검증할 수 있는 방법이 있다. 즉, 전문가의 특징이 있다. 전문가는 공부를 한다. 실력을 향상하기 위한 꾸준한 노력을 한다.전문가는 확정적이지 않고 유연하다. 9) 러닝 커브가 좋은 사람을 찾는 방법은? 소규모 회사일수록 현재는 저평가되어 있지만 성장 가능성이 있는 사람을 채용해야 한다. 사실 능력 좋은 사람이 노력도 많이 한다. 뛰어난 사람은 “의도적 수련”의 양이 많고 질이 좋다.  학습에 관련된 테스트를 할 수도 있다. 예를 들어 “새로운 언어로 작은 프로그램을 작성해 보세요. 그리고 그 과정을 타임 로그로 남겨보세요” 와 같은 문제를 보면 학습 자체에 대한 능력을 테스트할 수 있다.  10) 개발을 잘하는 친구는 리드를 안 하려고 하고, 상대적으로 부족한 친구는 리드를 하려고 합니다.  개발을 잘하는 것에 대해서 생각해 볼 필요가 있다. 보통 개발을 잘한다고 하면 코딩을 잘하는 것만 생각하지만 협력에 대한 것이 포함되어야 한다. 흔히 하는 실수가 코딩 실력만 보고 리더를 삼으려고 하는 것이다.  내가 좋아했던 상사를 생각해 보고 그 사람의 특징을 생각해 보는 것부터 시작해 보는 것이 좋겠다. 개발 트랙, 매니저 트랙으로 나눠서 이야기하는 것은 좋지 않다.   6. 후기좋은 시간이었다. 워크숍에 참여하고 나서 어떻게 실력을 검증할것인가에 대해 구체적인 방향이 잡혔다. 우리가 현재 하고 있는 것들 중에 도움이 되는것과 그렇지 않은것이 구분 되었다. 8퍼센트에 좋은 분을 모실 수 있게 하나씩 시도해 봐야겠다.#8퍼센트 #에잇퍼센트 #개발자 #워크숍 #워크샵 #채용워크숍 #채용워크샵 #후기 #참여후기
조회수 1604

비트윈 시스템 아키텍처 - VCNC Engineering Blog

VCNC는 커플을 위한 모바일 앱 비트윈을 서비스하고 있습니다. 비트윈은 사진, 메모, 채팅, 기념일 등 다양한 기능을 제공하며, 오픈 베타 테스트를 시작한 2011년 11월부터 현재까지 연인 간의 소통을 돕고 있습니다. 그동안 비트윈 시스템 아키텍처에는 많은 변화가 있었으며 다양한 결정을 하였습니다. 비트윈 아키텍처를 발전시키면서 배우게 된 여러 가지 노하우를 정리하여 공유해보고자 합니다. 그리고 저희가 앞으로 나아갈 방향을 소개하려 합니다.소프트웨어 스택Java: 비트윈 API서버는 Java로 작성되어 있습니다. 이는 처음 비트윈 서버를 만들기 시작할 때, 서버 개발자가 가장 빨리 개발해낼 수 있는 언어로 프로그래밍을 시작했기 때문입니다. 지금도 자바를 가장 잘 다루는 서버 개발자가 많으므로 여전히 유효한 선택입니다.Netty: 대부분의 API는 HTTP로 호출되며, 채팅은 모바일 네트워크상에서의 전송 속도를 위해 TCP상에서 프로토콜을 구현했습니다. 두 가지 모두 Netty를 통해 사용자 요청을 처리합니다. Netty를 선택한 것은 뛰어난 성능과 서비스 구현 시 Thrift 서비스를 통해 HTTP와 TCP 프로토콜을 한 번에 구현하기 쉽다는 점 때문이었습니다.Thrift: API서버의 모든 서비스는 Thrift 서비스로 구현됩니다. 따라서 TCP뿐만 아니라 HTTP 또한 Thrift 인터페이스를 사용합니다. HTTP를 굳이 Thrift서비스로 구현한 이유는, TCP로 메세징 전송 시 똑같은 서비스를 그대로 사용하기 위함이었습니다. 덕분에 빠른 채팅 구현 시, 이미 구현된 서비스들을 그대로 사용할 수 있었습니다. 또한, 채팅 패킷들은 패킷 경량화를 위해 snappy로 압축하여 송수신합니다. 모바일 네트워크상에서는 패킷이 작아질수록 속도 향상에 크게 도움이 됩니다.HBase: 비트윈의 대부분 트랜젝션은 채팅에서 일어납니다. 수많은 메시지 트랜젝션을 처리하기 위해 HBase를 선택했으며, 당시 서버 개발자가 가장 익숙한 데이터베이스가 HBase였습니다. 서비스 초기부터 확장성을 고려했어야 했는데, RDBMS에서 확장성에 대해 생각하는 것보다는 당장 익숙한 HBase를 선택하고 운영하면서 나오는 문제들은 차차 해결하였습니다.ZooKeeper: 커플들을 여러 서버에 밸런싱하고 이 정보를 여러 서버에서 공유하기 위해 ZooKeeper를 이용합니다. Netflix에서 공개한 오픈 소스인 Curator를 이용하여 접근합니다.AWS비트윈은 AWS의 Tokyo리전에서 운영되고 있습니다. 처음에는 네트워크 및 성능상의 이유로 국내 IDC를 고려하기도 했으나 개발자들이 IDC 운영 경험이 거의 없는 것과, IDC의 실질적인 TCO가 높다는 문제로 클라우드 서비스를 이용하기로 하였습니다. 당시 클라우드 서비스 중에 가장 안정적이라고 생각했던 AWS 를 사용하기로 결정했었고, 지금도 계속 사용하고 있습니다.EC2: 비트윈의 여러 부가적인 서비스를 위해 다양한 종류의 인스턴스를 사용 중이지만, 메인 서비스를 운용하기 위해서는 c1.xlarge와 m2.4xlarge 인스턴스를 여러 대 사용하고 있습니다.API 서버: HTTP 파싱이나 이미지 리시아징등의 연산이 이 서버에서 일어납니다. 이 연산들은 CPU 가 가장 중요한 리소스이기 때문에, c1.xlarge를 사용하기로 했습니다.Database 서버: HDFS 데이터 노드와 HBase 리전 서버들이 떠있습니다. 여러 번의 테스트를 통해 IO가 병목임을 확인하였고, 따라서 모든 데이터를 최대한 메모리에 올리는 것이 가장 저렴한 설정이라는 것을 확인하였습니다. 이런 이유 때문에 68.4GB의 메모리를 가진 m2.4xlarge를 Database 서버로 사용하고 있습니다.EBS: 처음에는 HBase상 데이터를 모두 EBS에 저장하였습니다. 하지만 일정 시간 동안 EBS의 Latency가 갑자기 증가하는 등의 불안정한 경우가 자주 발생하여 개선 방법이 필요했는데, 데이터를 ephemeral storage에만 저장하기에는 안정성이 확인되지 않은 상태였습니다. 위의 두 가지 문제를 동시에 해결하기 위해서 HDFS multiple-rack 설정을 통해서 두 개의 복제본은 ephemeral storage에 저장하고 다른 하나의 복제본은 PIOPS EBS에 저장되도록 구성하여 EBS의 문제점들로부터의 영향을 최소화하였습니다.S3: 사용자들이 올리는 사진들은 s3에 저장됩니다. 사진의 s3키는 추측이 불가능하도록 랜덤하게 만들어집니다. 어차피 하나의 사진은 두 명밖에 받아가지 않고 클라이언트 로컬에 캐싱되기 때문에 CloudFront를 사용하지는 않습니다.ELB: HTTP는 사용자 요청의 분산과 SSL적용을 위해 ELB를 사용합니다. TCP는 TLS를 위해 ELB를 사용합니다. SSL/TLS 부분은 모두 AWS의 ELB를 이용하는데, 이는 API서버의 SSL/TLS처리에 대한 부담을 덜어주기 위함입니다.CloudWatch: 각 통신사와 리전에서 비트윈 서버로의 네트워크 상태와 서버 내의 요청 처리 시간 등의 메트릭을 CloudWatch로 모니터링 하고 있습니다. 따라서 네트워크 상태나 서버에 문제가 생긴 경우, 이메일 등을 통해 즉각 알게 되어, 문제 상황에 바로 대응하고 있습니다. Netflix의 Servo를 이용하여 모니터링 됩니다.현재의 아키텍처처음 클로즈드 베타 테스트때에는 사용자 수가 정해져 있었기 때문에 하나의 인스턴스로 운영되었습니다. 하지만 처음부터 인스턴스 숫자를 늘리는 것만으로도 서비스 규모를 쉽게 확장할 수 있는 아키텍쳐를 만들기 위한 고민을 하였습니다. 오픈 베타 이후에는 발생하는 트래픽에 필요한 만큼 여러 대의 유연하게 서버를 운영하였고, 현재 채팅은 TCP 위에서 구현한 프로토콜을 이용하여 서비스하고 있습니다.HTTP 요청은 하나의 ELB를 통해 여러 서버로 분산됩니다. 일반적인 ELB+HTTP 아키텍처와 동일합니다.채팅은 TCP 연결을 맺게 되는데, 각 커플은 특정 API 서버로 샤딩되어 특정 커플에 대한 요청을 하나의 서버가 담당합니다. 비트윈에서는 커플이 샤딩의 단위가 됩니다.이를 통해, 채팅 대화 내용 입력 중인지 여부와 같이 굉장히 빈번하게 값이 바뀌는 정보를 인메모리 캐싱할 수 있게 됩니다. 이런 정보는 휘발성이고 매우 자주 바뀌는 정보이므로, HBase에 저장하는 것은 매우 비효율적입니다.Consistent Hashing을 이용하여 커플을 각 서버에 샤딩합니다. 이는 서버가 추가되거나 줄어들 때, 리밸런싱되면서 서버간 이동되는 커플들의 수를 최소화 하기 위함입니다.클라이언트는 샤딩 정보를 바탕으로 특정 서버로 TCP연결을 맺게 되는데, 이를 위해 각 서버에 ELB가 하나씩 붙습니다. 어떤 서버로 연결을 맺어야 할지는 HTTP 혹은 TCP 프로토콜을 통해 알게 됩니다.Consistent Hashing을 위한 정보는 ZooKeeper를 통해 여러 서버간 공유됩니다. 이를 통해 서버의 수가 늘어나거나 줄어들게 되는 경우, 각 서버는 자신이 담당해야 하는 샤딩에 대한 변경 정보에 대해 즉각 알게 됩니다.이런 아키텍처의 단점은 다음과 같습니다.클라이언트가 자신이 어떤 서버로 붙어야 하는지 알아야 하기 때문에 프로토콜 및 아키텍처 복잡성이 높습니다.서버가 늘어나는 경우, 순식간에 많은 사용자 연결이 맺어지게 됩니다. 따라서 새로 추가되는 ELB는 Warm-up이 필요로 하며 이 때문에 Auto-Scale이 쉽지 않습니다.HBase에 Write연산시, 여러 서버로 복제가 일어나기 때문에, HA을 위한 Multi-AZ 구성을 하기가 어렵습니다.한정된 자원으로 동작 가능한 서버를 빨리 만들어내기 위해 이처럼 디자인하였습니다.미래의 아키텍처현재 아키텍처에 단점을 보완하기 위한 해결 방법을 생각해보았습니다.Haeinsa는 HBase상에서 트렌젝션을 제공하기 위해 개발 중인 프로젝트입니다. 구현 완료 후, 기능 테스트를 통과하였고, 퍼포먼스 테스트를 진행하고 있습니다. HBase상에서 트렌젝션이 가능하게 되면, 좀 더 복잡한 기능들을 빠르게 개발할 수 있습니다. 서비스에 곧 적용될 예정입니다.Multitier Architecture를 통해 클라이언트와 서버 간에 프로토콜을 단순화시킬 수 있습니다. 이 부분은 개발 초기부터 생각하던 부분인데, 그동안 개발을 하지 못하고 있다가, 지금은 구현을 시작하고 있습니다. 커플은 특정 Application 서버에서 담당하게 되므로, 인메모리 캐싱이 가능하게 됩니다. 클라이언트는 무조건 하나의 ELB만 바라보고 요청을 보내게 되고, Presentation 서버가 사용자 요청을 올바른 Application 서버로 릴레이 하게 됩니다.Multitier Architecture를 도입하면, 더 이상 ELB Warm-up이 필요하지 않게 되므로, Auto-Scale이 가능하게 되며, 좀 더 쉬운 배포가 가능하게 됩니다.Rocky는 API 서버의 Auto-Failover와 커플에 대한 샤딩을 직접 처리하는 기능을 가진 프로젝트입니다. 현재 설계가 어느 정도 진행되어 개발 중에 있습니다. 알람이 왔을 때 서버 팀이 마음을 놓고 편히 잠을 잘 수 있는 역할을 합니다.기본적인 것은 위에서 언급한 구조와 동일하지만 몇 가지 기능이 설정을 추가하면 Multi-AZ 구성이 가능합니다.특정 커플에 대한 모든 정보는 하나의 HBase Row에 담기게 됩니다.HBase의 특정 리전에 문제가 생긴 경우, 일정 시간이 지나면 자동으로 복구되긴 하지만 잠시 동안 시스템 전체에 문제가 생기가 됩니다. 이에 대해 Pinterest에서 Clustering보다는 Sharding이 더 낫다는 글을 쓰기도 했습니다. 이에 대한 해결책은 다음과 같습니다.원래는 Consistent Hashing을 사용하여 커플들을 Application 서버에 샤딩하였습니다. 하지만 이제는 HBase에서 Row를 각 리전에 수동으로 할당하고, 같은 리전에 할당된 Row에 저장된 커플들은 같은 Application 서버에 할당하도록 합니다.이 경우에, 같은 커플들을 담당하는 Application 서버와 HBase 리전 서버는 물리적으로 같은 머신에 둡니다.이렇게 구성 하는 경우, 특정 HBase 리전이나 Application 서버에 대한 장애는 특정 샤드에 국한되게 됩니다. 이와 같이 하나의 머신에 APP과 DB를 같이 두는 구성은 구글에서도 사용하는 방법입니다.이와 같이 구성하는 경우, Multi-AZ 구성이 가능하게 됩니다.AWS에서 같은 리전에서 서로 다른 Zone간 통신은 대략 2~3ms 정도 걸린다고 합니다.Presentation의 경우, 비동기식으로 동작하기 때문에 다른 리전으로 요청을 보내도 부담이 되지 않습니다.HBase에서 Write가 일어나면 여러 복제본을 만들게 됩니다. 하나의 사용자 요청에 대해 Write가 여러번 일어나기 때문에 HBase연산의 경우에는 서로 다른 Zone간 Latency가 부담으로 작용됩니다. Haeinsa가 적용되면, 한 트렌젝션에 대해서 연산을 Batch로 전송하기 때문에 AZ간 Latency 부담이 적습니다.프리젠테이션다음은 2월에 있었던 AWS 유저 그룹 세미나에서 발표했던 자료 입니다. 비트윈 서버 아키텍처에 대해서 배포 방법을 중심으로 설명이 되어 있습니다. 비슷한 내용이 많이 있으니 살펴보시기 바랍니다.<iframe class="speakerdeck-iframe" frameborder="0" src="//speakerdeck.com/player/e4af60d05bb6013025f71231381b23b3?" 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;">
조회수 517

오픈서베이 개발팀이 일하는 법, 개발자에게 직접 들어봤습니다

김경만님은 오픈서베이의 미들레벨 안드로이드 개발자이자 오베이 시스템 PM(이하 조셉)입니다. 지인 추천으로 2명의 개발자 채용을 도운 오픈서베이 전도사기도 하죠. 이런 조셉은 지원할 때만 해도 오픈서베이가 어떤 회사인지 잘 몰랐다고 합니다. 병특 중인데 TO가 있길래 지원한 게 크죠. 그렇게 덜컥 입사한 오픈서베이를 다니며 잘 갖춰진 업무 환경, 조직 문화, 좋은 구성원에 반해버렸다고 합니다. 병특 복무를 마친 뒤에도 오픈서베이의 훌륭한 구성원으로 5년 차 개발자의 커리어를 쌓아가고 있죠. 조셉에게 오픈서베이에 반한 이유와 개발팀의 업무 문화에 대한 이야기를 들어봤습니다.            오픈서베이 김경만(조셉) 안드로이드 개발자 겸 오베이 앱 PM   조셉, 안녕하세요! 안녕하세요(웃음). 오픈서베이의 미드레벨 안드로이드 개발자 조셉입니다. 올해부터는 오베이 앱 PM으로 역할이 확대됐어요. 오베이는 오픈서베이 패널로 활동할 수 있는 설문조사 앱입니다.   세부적으로는 안드로이드 오베이 앱 개발, 오베이 회원계 시스템, 타겟팅 설문을 위한 유저 세그멘테이션 시스템을 개발·운영하고 있어요. 5년 차 개발자로 오픈서베이에는 17년 12월에 입사해서 벌써 1년 반 정도 일하고 있네요.    입사 계기가 독특하더라고요. 고백하자면 그렇죠. 전 직장에서 병특 복무 중에 이직을 결심하고 원티드에서 오픈서베이를 처음 알게 됐어요. 사실 뭐하는 회사인지도 잘 몰랐고 병특 TO가 있으니까 그때부터 찾아본 거예요.  잡플래닛을 검색해보니 ‘리서치 업계의 게임 체인저’라는 리뷰가 뜨더라고요. 실은 그 말이 정확히 무슨 의미인지도 잘 몰랐어요. 그냥 리서치란 단어가 주는 스마트하고 긍정적인 느낌이 있었는데 “그런 리서치 시장의 게임 체인저라니!”라며 면접을 본 거에요.   그럼 오픈서베이를 다니면서 긍정적인 면을 발견하신 거군요. 일단, 개발 업무 환경이 수준급이라 놀랐어요. 규모가 좀 있는 기업에서나 볼 수 있는 인텔리제이(intellij)도 너무 당연하게 구비돼 있더라고요. 이게 꽤 비싼 툴이거든요. 그래서 스타트업은 개발자 채용 공고에 인텔리제이 구매해서 사용한다고 일부러 적어놓기도 할 정도예요.  그런데 오픈서베이는 입사 때 따로 이야기해 주지 않아서 몰랐는데 떡하니 있길래 놀랐죠. whatap, jenkins, graylog 등을 이용한 배포·운영·모니터링 환경도 체계적으로 갖춰져 있었고요.  사실 이런 개발 환경을 갖춘 스타트업은 정말 흔치 않아요. 그래서 많은 개발자 꿈나무들이 큰 기대를 갖고 스타트업에 입사했다가 좌절해요. 앞에선 기술 중심의 혁신을 외치는데 그만큼의 투자가 없거나 여건이 마련돼 있지 않아서요. 여전히 많은 스타트업 개발자가 수작업으로 일일이 버그 모니터링을 하거나 업데이트 배포를 하는 경우도 많아요.  그런데 구비된 툴을 보면서 오픈서베이 개발팀은 생산성을 위한 비용 투자를 아끼지 않고 구조적인 개발 시스템에 노력하는 회사라는 인상을 받았어요. 개발 입문서 같은 데서 정석이라는 시스템을 그대로 갖추고 있으니까 제가 배운 이론을 현장에 바로 적용할 수도 있는 것도 좋았고요.   무엇보다 일에 집중할 수 있는 환경이군요.  이건 좀 개인적이긴 한데, 입사 전에 업무용 랩탑 선택권을 주는 것도 좋았어요. 사실 랩탑은 일할 때 제일 자주 많이 쓰는 도구잖아요. 업무에 가장 중요한 요소라고도 말 할 수도 있는데, 각 랩탑 사양을 정말 세부적으로 알려주고 원하는 걸 직접 선택할 수 있게 해주는 부분도 인상적이었어요.   그런데 후보 중에 제가 꼭 사고 말겠다고 생각했던 꿈의 랩탑 ‘델 XPS 15’이 있더라고요. 벌써 1년 반이나 지났는데 아직도 이 랩탑으로 일할 때는 괜히 기분이 좋아요.    “업무용 랩탑 선택권을 주는 것도 좋았어요. 사실 랩탑은 일할 때 제일 자주 많이 쓰는 도구잖아요.”   세세한 부분에서도 감동을 받으셨군요(웃음). 이렇게 디테일한 요소까지 챙기는 회사의 모습에 감동하는 거죠. 저는 오픈서베이가 3번째 직장이라서, 회사가 업무 환경에 디테일하게 신경 쓰는 게 얼마나 힘든지를 몸소 경험해서 알고 있거든요. 그런 면에서 오픈서베이는 개발 환경도 잘 갖춰져 있고, 업무를 위한 투자도 많고, 배울 사람도 많아요.   원티드에는 오픈서베이가 어떻게 소개되고 있을까요?   여건만 좋다고 다 좋은 회사는 아닐 수 있잖아요. 물론이죠. 근데 오픈서베이는 여건뿐만 아니라 성장 기회가 많아요. 의욕만 있다면 아직 주인을 찾지 못한 일들을 자신의 것으로 만들 수 있죠. 저는 주도적으로 일할 의지가 있는 구성원이 마음껏 역할을 늘려 갈 수 있는 조직이 긍정적인 면이 많다고 생각해요. 하고 싶은 사람이 그 일을 맡는 거니까요.   이런 면은 주니어나 미들레벨 개발자에게는 좋은 성장 기회가 되는 것 같아요. 제가 오베이 안드로이드 개발자에서 PM으로 역할이 확대되는 과정도 그랬어요. 처음에는 진짜 딱 개발만 했거든요. 운영 장애가 생겨도 저는 제가 개발한 요소의 코드만 아니까 다른 분야는 해결법도 모르고 제 역할도 아니니까 어쩔 줄 몰라 하며 지켜만 봤어요.  그런데 매번 아무것도 할 수 없는 상황에 놓이니까 제가 직접 문제를 해결할 수 있는 사람이 되고 싶어졌어요. 그때부터 오베이 앱 관련 코드를 다 까보면서 시스템 흐름을 파악했고, 장애가 발생했을 때 제가 해결할 수 있는 범위를 차근차근 늘려갔어요. 나중에는 노후한 시스템을 제가 만든 시스템으로 교체까지 했고요. 그러다 오픈서베이 CTO인 폴의 제안으로 올해부터 PM을 맡게 됐습니다.    조셉이 오베이 PM이 된 배경에는 그런 성장 스토리가 있었군요! 주도적으로 일하는 경험은 다른 회사에선 쉽게 얻기 힘든 기회라는 점은 정말 동의해요. 맞아요. 빠른 성장을 원하는 분에게 지금 오픈서베이는 딱 좋은 규모의 회사인 것 같아요.  정말 개발 인력이 적고 여건이 좋지 않아서 어쩔 수 없이 역할을 확대한 게 아니라, 좋은 여건과 환경에서도 빠르게 역할을 확대할 수 있는 단계에 이른 것 같아서요. 더 규모가 크고 탄탄한 회사에서는 사실 주도적으로 일하고 싶어도 환경이 따라주지 않는 경우도 많으니까요.  물론, 역량과 성취에 따라 합당한 보상을 해줘야 구성원들이 적극적이고 주도적으로 일하고 싶은 의욕이 생긴다는 생각도 하는데요. 제 경험에 비춰보면 오픈서베이는 일이 늘어나는 만큼 보상도 확실한 것 같아요(웃음).    “주도적으로 일할 의지가 있는 구성원이 마음껏 역할을 늘려 갈 수 있는 조직이 좋아요. 하고 싶은 사람이 그 일을 맡는 거니까요”     그런 좋은 경험 덕에 병특 이후에도 오픈서베이를 지켜주시는 거군요. 잘 몰랐는데 병특 복무가 끝나면 곧장 이직하는 게 훨씬 흔하다면서요?  맞아요. 더이상 그 회사에 묶여 있을 필요가 없으니 더 처우 좋은 회사를 찾아 떠나는 거죠. 저는 일부러 남았다기보다는 딱히 이직할 이유가 없어서 이직을 고려하지 않았다는 게 맞는 말인 것 같아요. 개발 업무 환경도 잘 갖춰져 있고 회사도 성장하고 있고, 무엇보다 보상 기준도 체계적이라고 생각하니까요.   보상 기준이 체계적이라고 생각하는 이유가 있나요? 개발팀에서 상하반기를 나눠서 1년에 2번씩 이뤄지는 성장진단을 해요. 단순한 연봉 협상이 아니라 정말로 제가 한 일을 돌아보면서 얼마나 성장했고 성취를 이뤘는지 상급자와 점검해보는 시간이에요. 사실 전 제 개인 블로그에 매달 1번씩 업무 성과 회고를 하거든요. 아무래도 명확한 독자가 없으니까 좀 캐주얼하게 쓰는 편이에요. 근데 회사 성장진단 문서는 내용은 같아도 독자가 다르니까 자연스럽게 자기객관화를 하면서 성과와 시행착오를 정리할 수 있는 시간이라 좋더라고요. 특히, 폴(이건노 CTO)은 이스트소프트에서 개발 조직을 오래 리딩하셔서 확실히 조언의 깊이가 달라요. 저는 아무래도 시야가 아직 넓지 않아서 개발 업무를 성능과 기술 중심으로만 대해요. 그런데 폴은 방대한 시각으로 비즈니스나 운영 관점에서 서비스가 확장될 때를 미리 계산해서 조언을 해주셔서 좋았습니다.   오픈서베이와 스타트업 얼라이언스가 함께한 ‘2018 스타트업 트렌드 리포트’를 보면, 재직자들이 스타트업에 가장 만족하는 요인은 ‘빠르고 유연한 의사결정 구조’였어요. 조셉 생각에 오픈서베이는 어떤가요? 자의적으로 해석할 여지가 많은 요소네요. 빠르고 유연한 의사결정 구조를 개발자 맘대로 하는 거라고 생각할 수 있으니까요. 그렇게 생각한다면 오픈서베이는 전혀 그런 회사는 아닌 것 같아요. 모든 의사결정은 전후 사정이나 논리적인 타당성을 따져보고 함께 결정하니까요.  대신 결정할 사안에 대한 논의는 정말 빠르고 유연하게 이뤄져요. 최고 결정권자인 하이(황희영 대표이사)와 논의가 필요하다고 생각되면 물어봐서 일정만 잡으면 얼마든지 1:1 미팅을 할 수 있어요. 대표실이 따로 있는 게 아니라 한 공간에서 같이 일하니까 몇초 걸어가서 바로 물을 수도 있고요. 대표이사와 이렇게 쉽게 이야기 나눌 수 있다는 점도 오픈서베이의 장점이죠.    “빠르고 유연한 의사결정 구조를 개발자 맘대로 하는 거라고 생각한다면, 오픈서베이는 그런 회사는 아니예요. 모든 의사결정은 전후 사정이나 논리적인 타당성을 따져보고 함께 결정하니까요.”   업무 영역을 넓힐 기회뿐만 아니라 발언 기회도 열려있다는 의미일까요? 정확해요. 개발팀에 ‘세미나’라는 제도가 있어요. 주간 회의와 별도로 팀에 공유하고 싶은 내용이 있는 구성원이 자발적으로 발표를 하는 시간이에요. 특정 프로젝트를 하면서 깨달은 점이나 노하우를 공유하는 식이죠. 저는 이런 세미나가 특히 주니어에게는 아주 좋은 발언 기회라고 생각해요.  사실 작년에 제가 ReactiveX와 Reactive System을 좋아해서 공부하고 있었어요. 당연히 오픈서베이 개발팀에도 도입하고 싶었죠. 근데 팀에 리액티브X를 다루던 분이 없어서 도입 시 이득에 대한 공감대가 없었어요. 그래서 세미나를 활용해서 , <리액티브 시스템으로 설문 서비스 구축하기>라는 주제로 두 차례 발표했어요.  당시에는 발표한다고 진짜 리액티브 시스템을 도입할 수 있을까 생각했어요. ‘필요하니 돈 내고 사자!’라며 간단히 설득할 수 있는 사안이 아니었거든요. 리액티브 시스템은 말하자면 개발 패러다임, 업무 방법론이에요. 개발 업무를 아무도 하지 않았던 새로운 방법으로 바꾸자는 얘기니까 팀 차원에서는 훨씬 복잡하고 신중한 의사결정이 필요한 사안이었죠.    조셉에게 세미나는 그런 중요한 사안을 건의할 기회의 장이었군요. 결국 도입은 성공했나요? 네(웃음). 덕분에 오베이 앱은 RxJava를 활용해 개발했어요. 이후 설문 서비스 개발을 담당하는 테리(이한별 개발자)는 리액티브한 방식으로 내부 파일 관리 시스템을 만들었어요. 정말로 저 혼자만 아니라 팀에서도 활용 가능한 개발 방법론이 된 거죠. 생각해보면 입사한 지 1년도 안 된 개발자가 팀에 새로운 업무 방법론을 도입하자는 발언권을 가질 수 있다는 점 자체가 오픈서베이 개발팀의 업무 문화와 일하는 방법을 단적으로 보여주는 예시 아닐까 싶어요.    마지막으로 오픈서베이의 예비 구성원분들께 한마디 부탁드립니다.  저는 오픈서베이를 다니면서 좋은 구성원들에게 자극을 받고 더 성장하기 위해 노력하게 된 것 같아요. 사실 제가 학창시절 때 꿈이 프로게이머였을 정도로 게임을 좋아해요. 회사 다니면서도 다른 시간 다 줄여도 게임하는 시간은 못 줄였을 정도로요.  그런데 좋은 업무 환경과 동료들, 성장 기회, 그리고 확실한 보상까지 고루 갖춘 회사에 다녀보니 더 좋은 사람이 되고 싶다는 생각이 들더라고요. 다른 동료들처럼 훌륭한 사람이 되고 싶어서 말이죠. 그래서 요즘은 그 좋아하던 게임도 접어두고 자기 계발에 몰두하고 있어요.  단순히 높은 연봉이나 좋은 복지가 아니라 함께 성장하고 싶은 예비 구성원분들의 많은 지원을 기대합니다!      “조셉과 함께 일하고 싶으시다면 지금 바로 오픈서베이 입사 지원을 해보세요”  
조회수 1046

만땅에서 스푼까지 함께 달려온 찰스를 소개합니다

스푼을 만드는 사람들 여덟 번째 이야기마이쿤의 초창기 멤버 중 한 명인 'Charles' 를 인터뷰해보았다.그래서, 영어 유치원은 보내셨나요?https://brunch.co.kr/@mirr5510/17내가(Sunny) 처음 마이쿤에 입사하게 된 계기는 바로 Neil(대표)의 브런치 글과 마이쿤 관련 인터넷 기사를 읽고 나서였다. 많은 글 둘 중에 가장 궁금하고 특이하다고 생각했던 글이 바로 '영어 유치원' 보내자 였다.영어 유치원 보내자? 무슨 말이지? 하고 클릭해서 읽어보았다. 스푼 라디오라는 서비스 전 '만땅'이라는 배터리 공유 서비스를 시작할 때 첫 팀 빌딩에 관한 이야기였다. 닐의 주변 지인, 학교 후배들에게 함께 서비스를 만들자고 제안했을 때 유부남 팀원들에게 이렇게 말씀하셨다고 한다."우리, 아이들 영어 유치원 보내자"즉, 그만큼 잘하자. 우리 같이해서 성공하자라는 의미로 이렇게 말씀을 하신 것 같다. 그래서 찰스를 인터뷰할 때 가장 먼저 물어본 질문이었다. 그래서 아이들 영어 유치원은 보내셨는지 말이다.찰스 특징: 모자 좋아함"하하하.. 이미 저희 아이들은 많이 커서 유치원은 벌써 졸업했어요. 이제 테드랑 빅터의 차례가 아닐까 싶네요"찰스가 가장 좋아하는 맥주 'Charles' 당신이 궁금합니다.Q. 본인을 한 마디로 표현한다면?'동네형 또는 오빠' 저는 어색한 걸 싫어하고, 친화력이 좋은 편이기도 하고요. 사람들과의 편한 관계를 좋아해요. 그래서 먼저 보통 말을 먼저 잘 거는 편이에요"Q. 찰스도 혹시 딸 바보세요?"네, 저는 딸 바보예요. 아빠들은 딸 바보가 된다는 건 사실인가 봐요. 딸은 일단 아들과는 정말 달라요. 되게 예쁘고요.. 되게 애교가 많고요..(이때 눈이 반짝반짝하셨습니다) 아들은 보통 엄마를 찾던데, 딸은 항상 아빠를 찾더라고요. 아! 그리고 자다가도 아빠 들어오는 소리 들리면 나와서 뽀뽀해주고 다시 자러 가요. 6살인데 아빠한테 잔소리도 하고요. 마지막으로 하나만 더 자랑해도 돼요? 오늘 5일 만에 딸 얼굴을 봤는데 (안 자고 있을 때) 아빠가 엄~청 보고 싶었다면서 일주일치 뽀뽀를 엄청 많이 해줬답니다.. 이래서 다들 딸 바보가 되나 봐요."Q. 밀가루를 정말 좋아하신다고 들었습니다 feat. 코젤 다크"제 생각에 저는 탄수화물 중독자인 것 같습니다. 탄수화물을 정말 좋아해요. 특히나 칼국수를 정말 좋아하는데요. 맑은 거 말고 찐한 국물의 칼국수 있잖아요. 그거 너무 맛있어요. 제가 추천하고 싶은 칼국수집은, 논현동 영동시장에 있는 이름이 기억이 안 나는데.. 거기 진짜 칼국수 진짜 맛있습니다."P.S: 테드가 옆에서 조용히 슬랙으로 보내주셨습니다. 바로 이 칼국수 집이라네요. '손국시' https://m.blog.naver.com/PostView.nhn?blogId=rldudal0070&logNo=220165610372&proxyReferer=https://www.google.com/당신의 회사생활이 궁금합니다Q. 마이쿤의 초장기 멤버가 되신 계기를 더 알고 싶어요"저는 마이쿤에 입사하게 된 계기가 제 인생에서 가장 큰 결정이었어요. 저는 이 전 회사에서 9년 4개월 정도 근무를 했었어요. 그러던 어느 날 Neil이 회사에 놀러 오라고 하더라고요? 그래서 놀러 갔더니 보니까 이미 Yong 도 함께 일하고 있었고, 갑자기 닐이 사업 기획서를 보여주는 거예요. 이런저런 이야기 함께 나누다가 함께 일을 하자고 제안을 하더라고요. 정말 고민 많았어요. 마침 그때 제가 이직을 생각할 때였거든요. 그렇게 고민하고 와이프와 함께 의논을 했는데 고맙게도 와이프가 저를 믿어주고 응원해주었어요. 그리고 이런 생각을 했어요. "어차피 이직할 거라면 한 번 밑바닥에서 도전해보자!" 그리고 제 손으로 서비스를 함께 만들 수 있다는 것이 가장 큰 메리트이었고요. 드디어 내가 원하는 일을 하게 되었구나 생각했었죠. 무엇보다 서비스가 잘되면 우리 아이들에게 더 나은 미래와 경험을 줄 수 있다고 믿었고요. 무엇보다 잘 되지 않아도 살아가면서 나에게 정말 좋은 경험으로 남아 미래에 발판이 될 것이라고 생각했어요. 그렇게 저는 마이쿤의 초창기 멤버가 되었어요. 무엇보다 서비스에 대한 아이디어와 매력도가 높다고 느꼈고, 닐이 "영어 유치원 보내자!"라는 말에 혹했죠"Q. 첫 서비스를 실패했을 때 떠나지 않고 남았던 이유는?"제가 처음에 입사를 하자마자 와이프가 둘째를 임신한 걸 알게 되었어요. 근데 정말 너무 바빠서 집에도 못 들어가고 일을 했었어요. 가장으로서 남편으로서도 잘하고 싶었고, 일도 잘하고 싶었는데 마음처럼 쉽지가 않더라고요. 경제적으로 힘든 부분도 있었지만, 저는 이대로 이 팀이 헤어지기엔 너무나도 아쉬워서 남는 선택을 했어요. 저희 정말 열심히 했거든요. 진짜 정말 열심히 했는데 이대로 서비스가 잘 되지 않았다는 게 아쉬웠고, 이 일로 이 팀이 해체되는 게 너무 싫었어요. 그때 우리는 모두 정말 열심히 했지만 잘하진 못했었어요. 어떻게 가야 하는지 방향도 몰랐어요. 그래서 더욱 아쉬웠죠. 팀이 해체된다 할지 언정 후회 없이 헤어지고 싶었어요. 근데 저뿐만 아니라, 모든 사람들이 동의를 했어요. 우리 이번엔 열심히 하지 말고 '잘' 하자라고. 그리고 저는 외벌이에 유부남이라 팀원들이 저를 많이 배려해줬었죠. 와이프에게 가장 고마운 점이 그때 와이프가 그랬어요. "떠날 때 떠나더라도 후회 없이 해"이 말이 정말 큰 힘이 됐던 것 같아요. 와이프에게 많이 미안하고 고맙습니다."Q. 6년 동안 함께 해올 수 있었던 원동력은?"저는 정말로 솔직하게 여태 마이쿤에서 다른 곳으로 이직을 해야겠다는 생각을 해본 적이 없어요. 첫 번째 서비스가 망하고도 자발적으로 남은 이유도 이 팀과 함께 후회 없이 가고 싶다는 마음 때문이었어요. 저는 아직도 제가 성장하고 많이 배우고 있고, 배워야 한다고 생각하거든요. 어떠한 사람들과 일하느냐가 정말 중요한 것 같아요. 무엇보다 함께 시작하여 함께 실패하고 또다시 함께 일어났다는 점과 성장했다는 점이 기쁘고 뿌듯하고 더 큰 책임감을 느끼게 해 주거든요. 하지만 언젠가 제가 회사에 도움이 되지 않는 날이 온다면 그때는 스스로 떠날 생각입니다 (웃음)"Q. 리더로서의 삶은 어떤가요?"팀에 동료가 많아지게 되고 각각 다른 성격의 동료들이 생겨났어요. 각자 다들 일을 열심하 하고 잘하지만 팀으로서 하나가 되어 한 마음으로 커 나가는 건 다른 문제라고 생각해요. 각자의 개성을 살릴 수 있는 방법이 있을까? 내가 어떻게 하면 좋은 리더가 되어 후배들을 이끌어 줄 수 있을까? 하고 고민도 많이 해보고, 함께 이야기도 해보기도 하고요. 진심을 담아서 늘 말을 해요. 제 진심이 닿아야 팀원들도 저를 더 잘 따라 줄 테니까요. 면담을 통해서 불편한 것들을 해소해주려고도 노력하고 무엇보다 저도 그 들에게 많이 배우고 있어요. 아무리 신입이라도 해도 제가 생각하지 못한 부분을 배울 수 있거든요. 각자 살아온 환경과 경험이 다르고 본인이 잘하는 것들은 다 제 각각 다르니까요. 그래서 많이 노력하고 배우려는 리더가 되려고 노력 중입니다."Q. 새로운 서비스가 성장하면서 변한 게 있다면?Sunny 曰: "지난 만 5년 동안 마이쿤의 실패 그리고 재 도전 및 성장 과정을 모두 봐오셨잖아요. 뭐가 가장 많이 달라졌을까요? 정말 많은 것들이 변했겠지만요."Charles 曰: "저는 일단 스푼이라는 서비스가 성장하면서 좋아진 점이 정말 많아진 것 같아요. 그중 가장 큰 건 회사에 점점 더 전문적이고 실력 있는 분들이 입사하셨다는 겁니다. 물론 분위기는 예전하고 같을 수 없겠지요. 그때와 지금의 인원 차가 크니까요.분위기나 문화를 그때가 똑같이 유지를 한다는 건 불가능하다고 생각해요. 서비스의 규모에 맞게 함께 성장해 나가야 하니까요. 다양한 사람과 다양한 시선으로 보고 느껴야 회사 서비스가 더 성장할 수 있거든요. 그리고 서비스가 성장해야 우리 모두에게 좋은 일인 것이고요. 새로 입사하신 분들은 굉장히 능력자가 많으세요. 그분들에게 많이 배우려고 하고 있고 있고요"찰스가 좋아하는 진라면 + 파송송 + 계란탁 당신의 사생활이 궁금합니다Q. 좋은 아빠란 어떤 아빠라고 생각하세요?"내가 생각하는 좋은 아빠란?처음에는 애들과 재미있게 잘 놀아주면 그것만으로도 좋은 아빠라고 생각을 했었어요. 알고 보니 그것만으로는 부족하더라고요. 잘 놀아주는 것은 기본이고, 아이의 시선에서 세상을 바라봐 주고, 아이와 눈높이를 맞춰 주는 자세를 가져야 하고 제일 중요한 것은 아이의 마음을 공감해줘야 한다고 생각합니다. 이렇게 해야 정말 좋은 아빠가 아닐까?라고 생각합니다. 잘 놀아주는 것은 누구보다 잘한다고 생각합니다만 아직까지도 아이의 마음을 공감해주는 부분에서는  많이 부족합니다. 저도 모르게 아이를 혼내고, 반성하고 이 패턴이 반복이에요. 한때는 뱃속에 있을 때는 건강하기만을 원했는데, 막상 세상에 나와보니 어쩔 수 없나 봅니다."Q. 자녀분들이 개발자를 꿈꾼다면 추천하시나요?“개발자는 굉장히 매력적인 직업입니다.누구나 개발자가 될 수 있고, 즐길 수 있는 지금의 문화라면 저는 아이들에게 개발자가 되는 것을 추천해주고 싶어요. 성취감이라는 걸 얻을 수 있는 직업이기에, 그런 걸 느껴보게 해주고 싶기도 하고요.나의 재능으로 나를 포함한 누군가의 삶이 달라질 수 있는 경험은 좋은 경험이라고 생각해요. 무엇보다 개발자는 스스로 만들고 싶어 하는 욕구가 있는데요. 내가 개발한 서비스나 상품을 누군가가 사용하고 좋은 피드백을 준다면 정말 보람찬 일이거든요. 물론 부정적인 피드백을 받으면 상실감을 느낄 수도 있지만, 그 과정에서 또 성장해나갈 수 있기 때문에!”Q. 나중에 개발해 보고 싶은 서비스가 있나요?"있어요. 라면 서비스요. 저는 라면을 정말 좋아하거든요, 라면 중에서도 진라면을 가장 좋아하는데 진라면에 파 넣고 마늘 넣고 콩나물 넣고! 끓여먹으면 전 일주일 내내 먹을 수 있습니다. 그래서 '우리 함께라면'이라는 라면 서비스를 해보고 싶어요. 라면에 특화된 서비스죠. 제가 그래서 예전에 회사에서 사람들 한 명 한 명한테 혹시 라면 일주일 내내 먹을 수 있냐고 물어보기도 했었어요."Q. 만약 개발을 하지 않았더라면 지금 뭐하시고 계셨을 거 같으세요?"글쎄요. 저는 원래 사실 개발자가 되려던 마음은 없었어요. 군대 제대하고 우연히 한 번 해볼까? 했는데 시작하게 되어 업이 되었네요. 저는 아마 개발자가 아니라면 지금 공무원? 하지 않았을까 싶어요. 원래 저의 옛날 성향은 뭔가 모나지 않고, 평범한 사람이었거든요. 이렇게 큰 도전을 하기 전까지는요"당신이 마이쿤에서 우리와 함께 일해야 하는 이유는요저희는 정말 많은 실패와 역경을 거쳐왔고, 쓰러질 때마다 '함께' 일어났습니다. 이제서야말로 정말 본격적으로 성장하기 위해 달려야 하는 시점이에요.  해야 할 것도 정말 많고요. 회사와 서비스가 성장하는 경험을 할 수 있다는 것은 어디서 돈 주고도 못할 경험이라고 생각합니다. 지금 이 기회에 저희와 같은 배를 타신다면, 개개인이 노력한 만큼 서비스 성장에 기여하실 수 있고 본인 스스로도 성장하는데 많은 도움이 될 것이라고 생각해요. 이미 성장한 곳에서 경험을 하는 것도 분명 가치 있는 일이지만, 나 스스로가 성장에 기여할 수 있는 회사의 구성원이 될 수 있는 건 흔한 일이 아니라고 생각합니다.서비스 플랫폼 팀원들이 Charles를 한마디로 표현한다면?Kyu 曰:  '동네형' - 사실은 동네 아저씨에 더 가깝지만 마치 동네 형인 듯 다가와주는 사람.Sam 曰:  '장군님' - 어디서 자꾸 전리품(티셔츠, 스티커 등 )을 가지고 오신다.P.S 저희 어머님께서 NewRelic 티셔츠 편하다고 너무 좋아하십니다.Mark 曰:  '언니' - 가끔 삐지시는 거 같지만 언제나 잘 챙겨준다.
조회수 1125

안드로이드 클라이언트 Reflection 극복기

비트윈 팀은 비트윈 안드로이드 클라이언트(이하 안드로이드 클라이언트)를 가볍고 반응성 좋은 애플리케이션으로 만들기 위해 노력하고 있습니다. 이 글에서는 간결하고 유지보수하기 쉬운 코드를 작성하기 위해 Reflection을 사용했었고 그로 인해 성능 이슈가 발생했던 것을 소개합니다. 또한 그 과정에서 발생한 Reflection 성능저하를 해결하기 위해 시도했던 여러 방법을 공유하도록 하겠습니다.다양한 형태의 데이터¶Java를 이용해 서비스를 개발하는 경우 POJO로 서비스에 필요한 다양한 모델 클래스들을 만들어 사용하곤 합니다. 안드로이드 클라이언트 역시 모델을 클래스 정의해 사용하고 있습니다. 하지만 서비스 내에서 데이터는 정의된 클래스 이외에도 다양한 형태로 존재합니다. 안드로이드 클라이언트에서 하나의 데이터는 아래와 같은 형태로 존재합니다.JSON: 비트윈 서비스에서 HTTP API는 JSON 형태로 요청과 응답을 주고 받고 있습니다.Thrift: TCP를 이용한 채팅 API는 Thrift를 이용하여 프로토콜을 정의해 서버와 통신을 합니다.ContentValues: 안드로이드에서는 Database 에 데이터를 저장할 때, 해당 정보는 ContentValues 형태로 변환돼야 합니다.Cursor: Database에 저장된 정보는 Cursor 형태로 접근가능 합니다.POJO: 변수와 Getter/Setter로 구성된 클래스 입니다. 비지니스 로직에서 사용됩니다.코드 전반에서 다양한 형태의 데이터가 주는 혼란을 줄이기 위해 항상 POJO로 변환한 뒤 코드를 작성하기로 했습니다.다양한 데이터를 어떻게 상호 변환할 것 인가?¶JSON 같은 경우는 Parsing 후 Object로 변환해 주는 라이브러리(Gson, Jackson JSON)가 존재하지만 다른 형태(Thrift, Cursor..)들은 만족스러운 라이브러리가 존재하지 않았습니다. 그렇다고 모든 형태에 대해 변환하는 코드를 직접 작성하면 필요한 경우 아래와 같은 코드를 매번 작성해줘야 합니다. 이와 같이 작성하는 경우 Cursor에서 원하는 데이터를 일일이 가져와야 합니다.@Overridepublic void bindView(View view, Context context, Cursor cursor) { final ViewHolder holder = getViewHolder(view); final String author = cursor.getString("author"); final String content = cursor.getString("content"); final Long timeMills = cursor.getLong("time"); final ReadStatus readStatus = ReadStatus.fromValue(cursor.getString("readStatus")); final CAttachment attachment = JSONUtils.parseAttachment(cursor.getLong("createdTime")); holder.authorTextView.setText(author); holder.contentTextView.setText(content); holder.readStatusView.setReadStatus(readStatus); ...}하지만 각 형태의 필드명(Key)이 서로 같도록 맞춰주면 각각의 Getter와 Setter를 호출해 형태를 변환해주는 Utility Class를 제작할 수 있습니다.@Overridepublic void bindView(View view, Context context, Cursor cursor) { final ViewHolder holder = getViewHolder(view); Message message = ReflectionUtils.fromCursor(cursor, Message.class); holder.authorTextView.setText(message.getAuthor()); holder.contentTextView.setText(message.getContent()); holder.readStatusView.setReadStatus(message.getReadStatus()); ...}이런 식으로 코드를 작성하면 이해하기 쉽고, 모델이 변경되는 경우에도 유지보수가 비교적 편하다는 장점이 있습니다. 따라서 필요한 데이터를 POJO로 작성하고 다양한 형태의 데이터를 POJO로 변환하기로 했습니다. 서버로부터 받은 JSON 혹은 Thrift객체는 자동으로 POJO로 변환되고 POJO는 다시 ContentValues 형태로 DB에 저장됩니다. DB에 있는 데이터를 화면에 보여줄때는 Cursor로부터 데이터를 가져와서 POJO로 변환 후 적절한 가공을 하여 View에 보여주게 됩니다.POJO 형태로 여러 데이터 변환필요Reflection 사용과 성능저하¶처음에는 Reflection을 이용해 여러 데이터를 POJO로 만들거나 POJO를 다른 형태로 변환하도록 구현했습니다. 대상 Class의 newInstance/getMethod/invoke 함수를 이용해 객체 인스턴스를 생성하고 Getter/Setter를 호출하여 값을 세팅하거나 가져오도록 했습니다. 앞서 설명한 ReflectionUtils.fromCursor(cursor, Message.class)를 예를 들면 아래와 같습니다.public T fromCursor(Cursor cursor, Class clazz) { T instance = (T) clazz.newInstance(); for (int i=0; i final String columnName = cursor.getColumnName(i); final Class<?> type = clazz.getField(columnName).getType(); final Object value = getValueFromCursor(cursor, type); final Class<?>[] parameterType = { type }; final Object[] parameter = { value }; Method m = clazz.getMethod(toSetterName(columnName), parameterType); m.invoke(instance, value); } return instance;}Reflection을 이용하면 동적으로 Class의 정보(필드, 메서드)를 조회하고 호출할 수 있기 때문에 코드를 손쉽게 작성할 수 있습니다. 하지만 Reflection은 튜토리얼 문서에서 설명된 것처럼 성능저하 문제가 있습니다. 한두 번의 Relfection 호출로 인한 성능저하는 무시할 수 있다고 해도, 필드가 많거나 필드로 Collection을 가진 클래스의 경우에는 수십 번이 넘는 Reflection이 호출될 수 있습니다. 실제로 이 때문에 안드로이드 클라이언트에서 종종 반응성이 떨어지는 경우가 발생했습니다. 특히 CursorAdapter에서 Cursor를 POJO로 변환하는 코드 때문에 ListView에서의 스크롤이 버벅이기도 했습니다.Bytecode 생성¶Reflection 성능저하를 해결하려고 처음으로 선택한 방식은 Bytecode 생성입니다. Google Guice 등의 다양한 자바 프로젝트에서도 Bytecode를 생성하는 방식으로 성능 문제를 해결합니다. 다만 안드로이드의 Dalvik VM의 경우 일반적인 JVM의 Bytecode와는 스펙이 다릅니다. 이 때문에 기존의 자바 프로젝트에서 Bytecode 생성에 사용되는 CGLib 같은 라이브러리 대신 Dexmaker를 이용하여야 했습니다.CGLib¶CGLib는 Bytecode를 직접 생성하는 대신 FastClass, FastMethod 등 펀리한 클래스를 이용할 수 있습니다. FastClass나 FastMethod를 이용하면 내부적으로 알맞게 Bytecode를 만들거나 이미 생성된 Bytecode를 이용해 비교적 빠른 속도로 객체를 만들거나 함수를 호출 할 수 있습니다.public T create() { return (T) fastClazz.newInstance();} public Object get(Object target) { result = fastMethod.invoke(target, (Object[]) null);} public void set(Object target, Object value) { Object[] params = { value }; fastMethod.invoke(target, params);}Dexmaker¶하지만 Dexmaker는 Bytecode 생성 자체에 초점이 맞춰진 라이브러리라서 FastClass나 FastMethod 같은 편리한 클래스가 존재하지 않습니다. 결국, 다음과 같이 Bytecode 생성하는 코드를 직접 한땀 한땀 작성해야 합니다.public DexMethod generateClasses(Class<?> clazz, String clazzName){ dexMaker.declare(declaringType, ..., Modifier.PUBLIC, TypeId.OBJECT, ...); TypeId<?> targetClassTypeId = TypeId.get(clazz); MethodId invokeId = declaringType.getMethod(TypeId.OBJECT, "invoke", TypeId.OBJECT, TypeId.OBJECT); Code code = dexMaker.declare(invokeId, Modifier.PUBLIC); if (isGetter == true) { Local<Object> insertedInstance = code.getParameter(0, TypeId.OBJECT); Local instance = code.newLocal(targetClassTypeId); Local returnValue = code.newLocal(TypeId.get(method.getReturnType())); Local value = code.newLocal(TypeId.OBJECT); code.cast(instance, insertedInstance); MethodId executeId = ... code.invokeVirtual(executeId, returnValue, instance); code.cast(value, returnValue); code.returnValue(value); } else { ... } // constructor Code constructor = dexMaker.declare(declaringType.getConstructor(), Modifier.PUBLIC); Local<?> thisRef = constructor.getThis(declaringType); constructor.invokeDirect(TypeId.OBJECT.getConstructor(), null, thisRef); constructor.returnVoid();}Dexmaker를 이용한 방식을 구현하여 동작까지 확인했으나, 다음과 같은 이유로 실제 적용은 하지 못했습니다.Bytecode를 메모리에 저장하는 경우, 프로세스가 종료된 이후 실행 시 Bytecode를 다시 생성해 애플리케이션의 처음 실행성능이 떨어진다.Bytecode를 스토리지에 저장하는 경우, 원본 클래스가 변경됐는지를 매번 검사하거나 업데이트마다 해당 스토리지를 지워야 한다.더 좋은 방법이 생각났다.Annotation Processor¶최종적으로 저희가 선택한 방식은 컴파일 시점에 형태변환 코드를 자동으로 생성하는 것입니다. Reflection으로 접근하지 않아 속도도 빠르고, Java코드가 미리 작성돼 관리하기도 편하기 때문입니다. POJO 클래스에 알맞은 Annotation을 달아두고, APT를 이용해 Annotation이 달린 모델 클래스에 대해 형태변환 코드를 자동으로 생성했습니다.형태 변환이 필요한 클래스에 Annotation(@GenerateAccessor)을 표시합니다.@GenerateAccessorpublic class Message { private Integer id; private String content; public Integer getId() { return id; } ...}javac에서 APT 사용 옵션과 Processor를 지정합니다. 그러면 Annotation이 표시된 클래스에 대해 Processor의 작업이 수행됩니다. Processor에서 코드를 생성할 때에는 StringBuilder 등으로 실제 코드를 일일이 작성하는 것이 아니라 Velocity라는 template 라이브러리를 이용합니다. Processor는 아래와 같은 소스코드를 생성합니다.public class Message$$Accessor implements Accessor { public kr.co.vcnc.binding.performance.Message create() { return new kr.co.vcnc.binding.performance.Message(); } public Object get(Object target, String fieldName) throws IllegalArgumentException { kr.co.vcnc.binding.performance.Message source = (kr.co.vcnc.binding.performance.Message) target; switch(fieldName.hashCode()) { case 3355: { return source.getId(); } case -1724546052: { return source.getContent(); } ... default: throw new IllegalArgumentException(...); } } public void set(Object target, String fieldName, Object value) throws IllegalArgumentException { kr.co.vcnc.binding.performance.Message source = (kr.co.vcnc.binding.performance.Message) target; switch(fieldName.hashCode()) { case 3355: { source.setId( (java.lang.Integer) value); return; } case -1724546052: { source.setContent( (java.lang.String) value); return; } ... default: throw new IllegalArgumentException(...); } }}여기서 저희가 정의한 Accessor는 객체를 만들거나 특정 필드의 값을 가져오거나 세팅하는 인터페이스로, 객체의 형태를 변환할 때 이용됩니다. get,set 메서드는 필드 이름의 hashCode 값을 이용해 해당하는 getter,setter를 호출합니다. hashCode를 이용해 switch-case문을 사용한 이유는 Map을 이용하는 것보다 성능상 이득이 있기 때문입니다. 단순 메모리 접근이 Java에서 제공하는 HashMap과 같은 자료구조 사용보다 훨씬 빠릅니다. APT를 이용해 변환코드를 자동으로 생성하면 여러 장점이 있습니다.Reflection을 사용하지 않고 Method를 직접 수행해서 빠르다.Bytecode 생성과 달리 애플리케이션 처음 실행될 때 코드 생성이 필요 없고 만들어진 코드가 APK에 포함된다.Compile 시점에 코드가 생성돼서 Model 변화가 바로 반영된다.APT를 이용한 Code생성으로 Reflection 속도저하를 해결할 수 있습니다. 이 방식은 애플리케이션 반응성이 중요하고 상대적으로 Reflection 속도저하가 큰 안드로이드 라이브러리에서 최근 많이 사용하고 있습니다. (AndroidAnnotations, ButterKnife, Dagger)성능 비교¶다음은 Reflection, Dexmaker, Code Generating(APT)를 이용해 JSONObject를 Object로 변환하는 작업을 50번 수행한 결과입니다.성능 비교 결과이처럼 최신 OS 버전일수록 Reflection의 성능저하가 다른 방법에 비해 상대적으로 더 큽니다. 반대로 Dexmaker의 생성 속도는 빨라져 APT 방식과의 성능격차는 점점 작아집니다. 하지만 역시 APT를 통한 Code 생성이 모든 환경에서 가장 좋은 성능을 보입니다.마치며¶서비스 모델을 반복적으로 정의하지 않으면서 변환하는 방법을 알아봤습니다. 그 과정에서 Reflection 의 속도저하, Dexmaker 의 단점도 설명해 드렸고 결국 APT가 좋은 해결책이라고 판단했습니다. 저희는 이 글에서 설명해 드린 방식을 추상화해 Binding이라는 라이브러리를 만들어 사용하고 있습니다. Binding은 POJO를 다양한 JSON, Cursor, ContentValues등 다양한 형태로 변환해주는 라이브러리입니다. 뛰어난 확장성으로 다양한 형태의 데이터로 변경하는 플러그인을 만들어서 사용할 수 있습니다.Message message = Bindings.for(Message.class).bind().from(AndroidSources.cursor(cursor));Message message = Bindings.for(Message.class).bind().from(JSONSources.jsonString(jsonString));String jsonString = Bindings.for(Message.class).bind(message).to(JSONTargets.jsonString());위와 같이 Java상에 존재할 수 있는 다양한 타입의 객체에 대해 일종의 데이터 Binding 기능을 수행합니다. Binding 라이브러리도 기회가 되면 소개해드리겠습니다. 윗글에서 궁금하신 점이 있으시거나 잘못된 부분이 있으면 답글을 달아주시기 바랍니다. 감사합니다.저희는 언제나 타다 및 비트윈 서비스를 함께 만들며 기술적인 문제를 함께 풀어나갈 능력있는 개발자를 모시고 있습니다. 언제든 부담없이 [email protected]로 이메일을 주시기 바랍니다!
조회수 12260

개발자가 이직에 대해 생각할 때...

‘이직’이라는 화두는 샐러리맨에게는 매우 무섭게 다가온다. 평생직장이라는 의미가 사라진 현대 시대에 있어서 직장생활 중에 많이 만나게 되는 단어이다. 더군다나, 소프트웨어 개발자들에게는 매우 일상적으로 발생한다. 그러니, 이직을 너무  두려워하지 말자. 오히려 평소에 이직에 필요한 스킬과 준비를 매우 당연하게 해야 한다.개인적으로 소프트웨어 관련 학과에서는 '이직'과 관련된 커리큘럼을 하나 만들어 두거나. 아니면, 교양과목이라도 있어야 하나 가르쳐야 한다고 생각한다.필자도 여러 기업에 입사하고 이직을 고민하는 과정을 똑같이 경험했다. 더 큰 경험으로는 기업을 창업하고 직원을 채용하고, 퇴사하는 과정도 같이 경험했다. 돌이켜 생각해 보면 직원의 입장과 중간관리자의 입장, 경영진과 최고 경영진의 입장에서의 ‘이직’을 바라보는 관점이 정말 매우 다르다.이번 이야기에서는 이런 ‘이직’의 관점을 ‘소프트웨어 개발자’의 입장에서  이야기해보자.이직이란 단어는 언제 만나게 될까? 이직이라는 단어를 머릿속에 떠올리게 되면서 당연하게 고민할 것이다. 더 좋은 조건을 제시하는 회사로 자리를 옮기거나, 또는. 현재 있는 직장에서 하는 일이 마음에 들지 않거나, 특정한 사람이나 환경 때문에도 이직이라는 단어는 언제나 떠올릴 수 있다.소프트웨어 개발자들이 이직을 고민하고  생각할 때에 어떤 부분들을 고민하고 생각해야 하는지 알아보자. 물론, 이번 이야가의 내용은 전적으로 필자의 주관적인 경험을 바탕으로 만들어진 내용들이기 때문에 매우 주관적이라는 것을 먼저 이야기해야겠다.다만, 작지 않은 경험을 적은 기업의 신입직원이었을 때부터, 벤처기업의 CEO, 중견기업의 CIO의 역할을 해보고 느낀 점 들을 몇 가지 정리하여 본 것이다.자, 이 글을 읽는 독자들은 ‘이직’을 고민하는가?혹은 이직이라는 단어에 대해서 어떻게 생각하는가?일단, 직장은 너무 쉽게 바꾸거나, 특정한 이유에 너무 집착하여, 너무 쉽게 결정하지 않기를 바란다. 일반적으로 한 회사에서 정년퇴직한다는 전설을 만난다는 것은 이제 거의 불가능에 가깝다. ( 필자역시, 딱 한사람 만났다. )소프트웨어 개발자들은 한 회사에 오래 근무할 수 있는 여건이 되는 사람들은 매우 극소수에 해당된다고 생각해야 한다. 대부분은 프로젝트가 종료되거나 의미가 없어지면서 이직에 대해서 고민을 시작 하게 된다.너무도 자주 만나게 되는 이 단어에 대해서 사람들마다 각자의 의미와 나름대로의 기준점을 잡아두는 것이 매우 좋다고 설명하겠다. 각자 자신이 걸어가야 할 로드맵이나 기본적인 원칙을 한, 두 가지쯤은 정해 두는 것이 좋다. 이 기준은 정말, 개인적인 기준들이다. 이 기준을 각자 가져야 한다.필자의 경우에는 초보때에 세웠던 원칙이 몇 가지 있었고, 나름 경험이 많아지면서  이러한 원칙들은 조금씩 그 기준을  추가하게 된다. 필자의 사례를 들어보자필자는 가장 먼저 사회생활 초년병의 시작을 병역특례로 시작하였다. 그래도. 나름 기준은 있었다. 그것은 앞으로 소프트웨어 개발일을 계속하기 위해서 내가 어떤 기준으로 회사를 찾아야 하는가에 대한 것이었다. 내가 세운 대원칙은 딱 하나였다. 하드웨어 작업을 병행하는 일을 한다는 것을 원칙으로 했다.그래서, 선택한 기업에서 처음 내게 할당된 일은 Z80으로 음성보드를 만들고, 적외선 센서로 터치스크린을 만드는 파트에서 Z80과 i8051의 크로스 어셈블리로 프로그래밍하는 일이었다. 내가 세운 큰 대원칙에는 맞는 일이었고, 일 자체에 대해서도 매우 큰 매력을 가졌다.하지만, 그 업체에서 병역특례 일을 하다가 부당한 노동현장(?)의 부조리를 맞이 하게 되면서 회사를 그만두게 됐다. 그 당시 얻은 경험 중의 하나는 ‘부조리한 노동현장’은 빨리 떠나라는 개인적인 원칙도 세웠다. 그 기준은 나중에 기업을 운영하면서도 가장 부끄러워할 경영진의 몫이라는 것을 인지하게 된 것도 가장 큰 경험이었다고 하겠다. ( 이런 경험은 차라리 초보나 신입 때에 경험하는 것이 그나마 불행 중 다행이며, 사회의 쓴맛을 제대로 보았다고 하겠다. 무료 법률상 담도 해보았고, 노무담당 문의도 해봤다. )그 후에 경력직 프로그래머로써 제대로 된 취업을 할 때에도 나름대로 원칙을 세웠다.병역특례 일을 하다가 그만두고 군대를 다녀왔을 당시에는 윈도우즈 애플리케이션의 개발이 매우 어렵던 시절이었기 때문에 나름 몸값을 요구할 수 있었다. 그래서, 프로그래밍을 하는 데 있어서 조금은 특이한 솔루션을 활용하는 경험을 하고 싶었고 그것을 중요한 원칙으로 삼았다.당시에 선택할 수 있는 기업은 3곳이었다. 하나는 용산 근처의 게임 개발사. 건대 부근의 한국전력에 소프트웨어를 개발해서 판매하던 회사, 그리고. 하나는 건축 소프트웨어 개발을 하는데 Auto-Cad의 ARX아키텍처 기반의 프로그래밍과 윈도즈 개발을 하는 일이었다.3군데의 회사에 면접이 다 통과된 이후에 고민하였다. 가장 적극적이었던 회사는 게임회사였다. 지금 기억으로도 90년대 중반에 팔레트 애니메이션을 능숙하게 조작하는 내 스킬을 보고 매우 탐을 내었던 게임업체의 사장이 기억난다. 그 먼 거리에서 인천의 집까지 나를 태워다 주면서, 같이 일하자고 차를 타고 오는 도중에 많은 이야기를 나누면서, 같이 일하자고 설득했다.하지만, 결정적으로 그 당시에 결혼을 한 필자의 입장에서는 ‘급여’가 가장 큰 걸림돌이었다. 전혀 엉뚱하게도 ‘급여’를 가장 많이 준다는 ‘회사’를 선택했다. 바로, 건축 소프트웨어 개발회사였다. ( 당연하지만, ‘급여’는 언제나 샐러리맨에게는 최고의 선택 기준이 될 것이다. )아마도, 필자가 그 당시에 급여는 매우 적지만, 그 게임업체에 들어갔다면 운명이 매우 많이 바뀌었을 것으로 생각한다. 당시, 병역특례를 하다가 군대를 다녀오면서 네트워크 프로그래밍에 대한 스킬까지 겸비한 필자가 게임업계로 들어갔으면 나름 재미있는 미래가  진행되지 않았을까 한다.하지만, 그래도 그 당시에 급여도 나름 가장 많았지만. 최고의 선택 기준은 ‘독특한 기술’에 대한 호기심이었다. 더군다나, 윈도즈 개발자로서 나름 이름을 알리기 시작하던 시기였기 때문에 필자의 선택은 옳았다고 생각한다.이때 중요한 화두는 ‘급여’와 ‘윈도즈 개발환경’, ‘독특한 콘셉트’이었다. 당시, 그 회사는 AutoCad에서 동작되는 한글 소프트웨어와 설계용 지원 유틸리티를 개발하는 업체였기 때문에, 선배 개발자들과의 경험이 매우 좋았다. 선배 개발자와 개발실장으로 계시는 분들이 20대 중반이었던 필자를 매우 아껴주었던 기억이 난다.최소한 그 계통에서 5년 이상 일을 했던 선배들이 몇 분 계셨고,  그분들에게 생각보다 많은 것을 얻을 수 있었다. 정말, 훌륭한 선배들은 언제나 초보와 신입들에게는 큰 도움이 된다.필자가 신입시절에 크게 결정한 것은 ‘장래성’도 아니고, 오히려 찾은 것은 ‘독특한 개발’을 경험할 수 있는 환경을 찾았고. 그것은 또 하나, 새로운 개발환경을 초기서부터 세팅하는 것도 포함되어 있었다.‘개발자가 이직을 결정해야 할 때’는 언제 인가하고 후배들이 가끔 질문을 해오거나 자문을 구해올 때가 있다. 그렇다면, 소프트웨어 개발자가 이직을 생각하는 때에 대해서 어떤 것을 고민해야 하고, 이직을 결정하기 위하여 중요한 사항은 어떤 것이 있을까?물론, 이직은 모든 분야에서 공통적으로 발생하는 요소이기 때문에 전부를 이야기할 수 없겠지만, 가장 좋은 이직이란 무엇인지 필자의 경험을 중심으로 이야기해보자. 다음에 나열하는 요소들은 ‘이직’을 고민하게 될 가장 큰 가능성을 가지고 있다.첫째. 자신의 전문성에 대해서 고민하기 시작할 때...보통은 자기계발에 충실한 사람의 경우에 자신이 제대로 된 전문성을 확보하고 있는지에 대해서 의문점이 생기는 시점에 '이직'을 고민하게 된다. 이 일을  계속하는 것이 미래에 ‘전문성’을 가질 수 있느냐에 대해서 의문을 가지기 시작할  때부터이다.둘째. 조직원들 간에 트러블이 발생하거나, 말도 안 되는 상사의 권위에 질렸을 때이 부분은 일반 직장과 동일하다. 아무리 전문성이 보장되고, 일이 괜찮다고 하더라도. 동료들과의 문제가 발생되는 부분은 어느 직종이나 동일하다.필자는 소프트웨어 개발일을 하면서도 벤처기업의 경영진 역할과, 중견병원그룹의 CIO생활을 하면서 다양한 직종의 사람들과 일을 해보고 인사권을 가지고 있었지만. 모두 동일하게 문제가 발생하는 것은 ‘직원들’ 간의 문제나, 중간 관리자의 전횡 등이 가장 큰 이유가 되었다.셋째. 프로젝트가 종료되었을 때에생각보다 하나의 프로젝트가 종료되면서, 소프트웨어 품질이나 개발에 대한 연속성이 제대로 이어지지 않는 경우에는 이직을 생각하게 된다.재미있고 즐거운 개발을 필자가 주창하는 이유 중의 하나가 이러한 ‘프로젝트 종료’ 시의 이직에 대한 고민을 하지 않기 위해서이다. 하지만, 대부분의 프로젝트들은 실패하거나 어려움을 겪는 경우가 다반사이기 때문에, 프로젝트가 종료될 때에 이런 충동을 느끼게 된다.이상 3가지의 기본적인 이슈들은 직장생활을 하면서 매번 만나게 되는 고민이고. 3가지의 고민이 모두 발생한다면, 당연하게 ‘이직’을 오히려 권해야 할 사항이 될 것이다.자, 이직에 대해서 고민하고, ‘이직’을 결정하였다면, ‘미련’없이 ‘이직’을 준비하자.‘이직’을 준비하는 것에 있어서 가장 중요한 것은 옮겨갈 회사를 잘 고르는 것이 가장 큰 것이다. 그리고. 퇴사를 하는 회사의 경우에는 최소한 1개월 정도의 업무 인수인계 작업은 당연하게 고려하자. 물론, 제대로 된 체계가 있는 회사는 당연하지만, 직원들의 이직 프로세스가 잘 잡혀있기 때문에 너무 걱정할 필요 없다.대부분의 조직은 누구 한 사람이 나간다고 하더라도, 그 프로젝트가 잘못되는 경우는 거의 없다. 그냥, 본인의 마음이 떠난다면 ‘이직’을 진행하는 것이 맞을 것이다.너무 걱정하지 말고 이직을 결심하고 진행하라고 조언하고 싶다.다만, 필자는 ‘이직 시에 적합한 회사’를 찾기보다는, ‘이직 시에 안 좋은 회사’를 피하는 방법을 먼저 터득하라고 조언하고 싶다.이직 시에 안 좋은 회사를 피하는 방법개발자들이 이직을 고려하고, 이직을 결심하게 되었을 때에는 신입의 입장과는 매우 다르다. 어느 정도 경력도 생겼고, 일에 대한 경험도 풍부해지고, 나이도 한두 살 더 먹었으며, 사람들과의 스킨십이나 커뮤니케이션 능력도 좋아지기 시작하는 시기가 된다.또한, 과거에는 ‘취업’과 ‘작은 목표’가 중요하였지만, 이제는 같이 일할 동료들에 대해서도 생각하게 되고, 일하는 회사의 비전이나 다른 부분들도 같이 고님할 것이다. 이런 어느 정도의 경험과 시야가 생겼을 때에 ‘이직 시에 좋지 않은 회사’를 골라내는 방법은 어떤 것들이 있을까?필자의 경험으로는  다음의 사항들을 고려하여 ‘이직’하려는 회사들을 평가했다.하나. 고급 개발자가 있는가?회사의 CTO나 개발실장이 고급 개발자이며, 그 분야의 '구루'급에 해당되는 사람인가? 존재한다면,  그분들이 회사 내부에서 '존경'받으며, '대우'를 받고 있는지 확인해보라. 그 회사에서 꾸준하게 엔지니어로 성장한다면..  그분들과 같은 대우를 받을 수 있는 인사 환경을 갖추고 있는지 확인하면 된다.대부분 허접한 회사이거나 일반 기업체에서 전산실의 역할이 부실한 경우라면 IT기술을 최고로 습득해도 계장 이상 올라갈 수 없는 곳이라면, IT기술을 중요시하는 기업이 아니라는 것이다. 이런 경우에는 '직장인'으로써의 비전만을 따지면 된다. ( 정치적인 것이 아니면, 급여, 복지일 것이다. )'개발자'로써의 삶이나 목표, 비전과는 전혀 상관없는 기업이기 때문에 일반적인 '직장생활'에 충실한 것이 좋을 것이다. 이와 관련된 처세술이나 비교자료는 인터넷에 많으니 검색해서 참조하자.둘. 개발자들이 오랫동안 근무한 사람들이 있는가?회사가 성장하고 발전하는 과정에서 사람들이 들어오고 나가는 것을 반복한다. 이런 경우에 회사에 오랫동안 근무한 개발자나 엔지니어가 존재하는지 확인해보는 것이 좋다. 대부분 경력이 올라가면 '급여'가 오르게 되고, 이렇게 경험이 풍부한 사람들이 많이 존재하는 개발 조직이나 회사가 발전 가능성이나 시장을 가지고 있는 경우가 많다.하지만, 회사는 충분하게 돈을 벌고 있지만, 회사 경력에 비해서 적은 경력의 개발자들이 2~3년 차들로 대부분 도배되어 있다면, 특정 시점에 직원들이 물갈이가 되거나, 개발자들이 죄다 못 버티고 나간 경우라는 뜻이다.'소프트웨어 개발자'들도 대부분 '직장인'에 가깝다. 이 회사가 정말 좋은 곳이고, 계속 다닐만한 가치가 있는 회사라면. 오래된 개발자들이 많이 있을 것이다. 이런 오래된 개발자가 없는 곳이라면 분명, 인사 문제나 처우에 문제가 있는 회사이다.셋. 사무실의 환경을 살펴라.큰 사무실이건 작은 사무실이건 '실제 일하는 사람들'이 사용하는 '책상'이라면 사용하는 흔적들이 있다. 공간은 있지만, 빈 책상에 사용되지 않는 물품들만 있다면. 인력파견업체가 대부분일 것이고, 처우나 사무실의 환경은 그다지 좋지 않을 것이다.대부분 팀장이고 이사이고 아웃소싱 일을 대부분 하고 있는 사람들일 것이고, 당연하지만, 근로환경도 최악이고, 월급이 때인다던 지, 프로젝트 진행이 개판이 되는 경우가 많다.넷. 신입직원 연수나 트레이닝 프로그램이 있는지 확인하라대부분, 이직 시에 이러한 것들을 고려하지 않는다. 하지만, 대부분의 중소기업이나 대기업들의 경우에 자체적인 솔루션이 있거나 나름 시장 지배력이 있는 회사의 경우에는 ‘사전에 교육’ 해야 할 내용들이 많아진다.당연하지만, 신입직원들에게 짧으면 2주, 길면 4주 이상의 트레이닝 코스가 존재하게 된다. 나름 시장 지배력이 있는 회사라면 이러한 코스가 당연하게 있다. 만일 이러한 코스가 없다면, 해당 기업은 의미 있는 솔루션을 만들거나, 의미 있는 서비스를 하고 있는 회사라고 보기 어렵다.그것은 중소기업들은 대부분 적당한 인력을 구인해서 적당하게 사용한다고 보면 된다.이처럼 소프트웨어 개발자가 이직을 생각할 때에 이러한 조건들도 있지만, 오히려 개발 경력이 3~4년 차를 넘기는 개발자에게 필자가 가장 중요하게 질문하는 것이 있다. ‘소프트웨어 개발이 적성에 맞는가?’라고 묻는다.굳이, 소프트웨어 개발이 아니더라도 자신의 자아실현이나 사회생활이 충분하게 실현되는 경우도 많다. 억지로, 소프트웨어 개발자의 길을  걸어가면서 주변을 괴롭히거나, 오히려. 안 좋은 중간 관리자가 되면서 IT업계의 원흉이 되는 것도 이 시기에 잘못 결정한 선배들이나 후배들도 많다.필자가 만난 여러 후배 개발자 중에는 소프트웨어를 설계하고 만드는 일이 그다지 적성에 맞지 않는 경우도 상당수 있었다. 또는, 저 사람은 아예 소프트웨어 개발을 하지 않았으며 좋겠다는 생각을 하게 된 사람도 있었다. 그래서, 오히려 조언을 하거나 유도를 해서 다른 일을 선택하고 그 길을 잘 걸어가는 후배들도 여럿 있다.하지만, 대한민국의 SI개발에만 있었다면 다른 직종도 가능할까?라는 질문에는 사실, 정답이 없다고  이야기한다. 갑을병정 이무기라고 불리는 먹이사슬의 과정 속에서 SI현장에서 다른 분야로 진출하는 것은 정말 어려운 일이다.대기업이나 중소기업의 SI에 입사해서, 프로젝트 관리자의 길을 걸어가는 사람이 아니라면, 매우 어려운 자리가 될 것이다. 하지만, SI나 SM의 이직 시에도 제대로 된 선택을 하면 매우 수월하고 편안한 자리로 이직을 할 수 있다.실제 후배들 중에는 많은 급여보다는 안정적인 자리를 원하는 도메인이 특화된 SM자리를 잘 차지하고 편안하게 일하는 개발자들도 간혹 발견할 수 있다. 하지만, 그런 환경이 아니라면 필사적으로 이직 시의 조건을 따져봐야 한다.최소한 ‘피해야 할 회사의 조건’을 따져봤다면, 이제는 가장 현실적인 ‘조건’을 나열하여 회사와 조직의 환경을 살펴보자. 다음의 조건들을 살펴봐라.야근수당을 받는가?2015년을 기준으로 나이 30세 초반에 연봉 3000~4000이라면 소프트웨어 개발자로서 만족하는 삶을 살 수 있을까? 하지만, 사회생활에 있어서 야근수당을 받거나 주말에 근무하면 추가 페이를 계산받는가? 냉정하게 계산하고 매일 야근과 주말근무를 하고 있다면, 실질적인 연봉은 무려 5~6000만 원을 받아야 정상이다.필자가 중견그룹의 CIO 역할을 하던 시절에 인사팀에서 가장 많은 경고와 안내를 받았던 것 중의 하나가 '야근'근무를 가능한 하지 않도록 유도하는 안내였다. 야근을 하게 되면 자연스럽게 지출되는 야근을 위한 식사와 연장근로수당, 그리고. 주말까지 일하게 되면 2배를 넘어가는 수당의 지급은 상당히 부담스러웠던 것이기 때문에, 인사팀에서는 이러한 근무를 하지 않도록 유도하는 것이 최선의 방법이었을 것이다.대부분 괜찮은 기업들은 '야근'근무를 유도하지 않는다.단지, 근무조건이 탐나는가?냉정하게 SI는 전문성이 매우 높은 분야인데, 대한민국에서는 그러하지 않고, 거의 막장에 가까운 환경을 가지고 있다. 매우 슬픈 일이다. 일본이나 미국과 같은 선진국에서 근무하는 SI 개발자들의 처우나 근무조건은 매우 좋은 조건들이고, 연봉 또한 매우 높다.제대로 된 SI분야의 경우에는 대체인원이 그렇게 많지 않고, 어느 정도 경력을 가진 개발자로 성장하기 매우 어려운 분야이기 때문에 경력자와 경험자를 매우 우대한다. 하지만, 대한민국의 SI현장은 정말 열악한 환경으로 변화하였고, 그 현장은 매우 절망스러운 곳들도 많다.대한민국의 SI가 이렇게 된 이유에 대해서는 여러 가지 이유와 근거와 설이 존재하는데, 필자가 생각하는 몇 가지 이유는 다음과 같다.하나. 대기업의 전산실에서 분리된 IT조직의 태생적 한계둘. 전산/IT를 제대로 전공으로 한 '선배'들이 실제 부재하다.셋. 대정부의 SI 관련 프로젝트가 갑을병정 프로세스만으로 진행되면서 만들어진 흑역사넷. 소프트웨어 품질을 모르는 PM/PL들이 아직 수두룩하다. ( 이론만 아는 방법론자들 투성이다. )다섯. 책임지는 소프트웨어 개발 조직과 개발인력이 그다지 SI현장에 없다.여섯. 소프트웨어 개발은 '자격증'과 아무 상관없고, 개발 경력과도 그다지 연관성이 없다.그래서, 대한민국의 SI현장은 주변에 잘 수소문하여 ‘괜찮은 곳’을 찾아가는 센스를 발휘하지 못하면, 암흙의 이직을 경험할 수 있다.물론, 이렇게 이야기하는 ‘이직’의 대부분은 ‘스타트업’이나 ‘도전적인’ 기업을 선택하는 것과는 다른 기준들이다. 대부분은 ‘조직’이라는 틀에서 움직이는 ‘작업자’들을 구인하고 그 공간이 나에게 맞는지에 대해서 잘 따져야 하는 것이다.결국, '조직'의 틀로 생각한다면, 일반 샐러리맨의 회사 선택의 기준과 그다지 차이가 없을 것이다.하지만, 소프트웨어 개발자의 세계에서 '이직'을 제대로 할 수 있는 방법은 말 그대로 '스카우트'을 받고 이동하는 것이다. 그런 대우를 받으려면, 제대로 평가된 ‘나의 인식’과 ‘나의 브랜드’가 있어야 가능하다는 것을 염두에 두자.결론적으로 '이직'을 제대로 하려면, 자신의 '브랜드'를 만들 수 있어야 한다. 그것이 핵심이다.그렇다면, 성공적인 이직을 하려면 무엇을 갖추어야 하는가? 그것은 다음의 6가지로 정리할 수 있다.하나. 자기만의 장점을 가져야 한다.둘. 자신만의 전문성을 가져야 한다.셋. 절대다수는 하지 못하는 희소성을 가져야 한다.넷. 내 경력과 전문성을 증명할 프로젝트를 가져야 한다.다섯. 포트폴리오를 구성하라여섯. 외부활동과 내 브랜드를 만들어라이 6가지 중에 2~3가지만 충족한다고 하여도, 소프트웨어 개발자는 제대로 된 대우나 평가를 받으면서 즐거운 이직을 경험할 것이다. 말 그대로 헤드헌팅이나 개발자 커뮤니티에서 당신에 대한 평가가 좋을 것이다.매우 당연한 것이지만, 준비된 사람에게는 언제나 기회가 만들어진다. 기회가 만들어지지  않는다는 것은 ‘준비가 부족하기 때문이다’라고 이야기할 수 있다.직업 이직을 권유받았는가? 아니면. 이직을 꿈꾸는가?그렇지만, 그렇게 브랜드나 명성을 얻기 전에 권유를 받았건, 상사가 괴롭혀서 떠나건, 이직에 대해서 고민하고 결심했다면 다음의 몇 가지를 고민하자.후배들에게 이야기하는 몇 가지 충고의 이야기가 있다. 이것은 정말 최소한의 기준이다.최소, 이 기준에 대해서는 고민하고 '이직'을 결심했으면 좋겠다.하나. 소프트웨어 개발자들이거나 SI현장에 있는 개발자라면 최소한 하나의 도메인이나 전문분야를 택했다면 최소 5년은 버텨야 한다.둘. 프로젝트나 포트폴리오는 5년 이하 경력은 세상이 제대로 인지하거나 인식하지 않는다.셋. 직장이 중요한 것이 아니라, 직업과 도메인이 중요하다.넷. 경력과 브랜드는 ㅇㅇ회사의 누구가 아니라. 누가 다니는 ㅇㅇ회사가 더 좋다는 평가를 받아야 한다.SI현장에 있건, SM현장에 있건, 대기업이나 중견기업은 파견 나온 개발자를 좋아한다. 어떤 분야이건 어떤 특수하거나 일반적인 분야이건 대부분은 교육이 필요하고, 경험이 필요하다. 그리고, 그 조직과 회사에 적응하는 기간이 필수적이다. 대부분 이러한 '비용'은 기업을 운영하는 입장에서는 어떻게든 최소화하기를 원한다.대부분 이런 신입 비용을 어떻게 줄이느냐가 관건이기 때문에, 대부분의 회사들은 가능한 '경험'자와 '경력자'를 선호하는 것이 매우 당연하다. 특히나, 관련된 일과 조직에 익숙한 사람이라면 회사 입장에서는 신입의 교육비용이 들어가지 않는 파견된 개발자들을 선호하게 된다.바로 업무에 투입하고 결과물을 얻을 수 있기 때문에, 이러한 파견된 개발자들을 선호할  수밖에 없다. 그래서, 보통 갑, 을의 조직들은 자신의 일을 위해서 파견 나온 SI, SM개발자들을 참 매력적으로 인식한다.특히나, 이렇게 일하는 SI, SM 개발자들은 함께 일하고, 같은 조직에서 일하는 사람들이기 때문에 눈으로 확인한 이러한 사람들을 좋아할  수밖에 없다. 당연한 것이지만, '면접'을 통해서 사람을 뽑는 것보다 직접 함께 일한 사람을 뽑는 것이기 때문에 해당 기회비용과 교육을 위한 시간 비용들이 모두 절약된다.그래서, 대부분은 고객 회사에서 이런 개발자들에게 먼저 이직을 권유하게 된다. 고객의 입장에서는 바로 실전에 투입할 수 있는 개발자를 얻을 수 있고, 권유를 받은 개발자 역시 중소기업이나 파견직에서 일하다가 더 높은 연봉과 복지제도를 제공하는 기업으로 옮겨갈 수 있는 기회를 얻는다.다만, 이러한 권유를 받는 것은 '인력파견'업체를 통해서 SI현장에 나가서 일하는 경우에는 이러한 '기회'를 얻기 어렵다. 실제, 이러한 '제의'를 받는 경우는 '고객'의 기업에 직접 나가서 일하는 경우를 의미한다고 봐야 한다.물론, 이러한 것을 중소기업 입장에서는 인력 빼가기?라고 볼 수 있다. 필자도 중소기업을 운영해봤지만, 중소기업에서 4~5년 이상 일을 하고 있는 직원이 아니라면, 이러한 이야기도 하기 힘들것이고, 실제, 중소기업의 일이라는 것이 '일을 배우고 가르치는 이유가 어느 정도 업무에 필요한 수준'까지만 가르치기 때문에, 이를 중소기업의 인력 빼가기라고 이야기하기 어렵다. 가르친 것도 없이 일만 시켰는데 무슨 ‘인력 빼가기’인가?다만, 가장 최악의 이직 회사를 피하는 방법은 정말 고려하다. 하지만, 이직을 할 때에 순간적인 선택에 의해서 정말 좋지 않은 선택을 하는 경우가 종종 있다. 하지만, 아래와 같은 회사로 이직을 하였다면, 재빠르게 '사표'를 내는 것이 가장 현명하다. 필자의 경험을 기반으로 이런 회사는 빨리 떠나야 한다고 생각한다.하나. 회사의 사무실의 인테리어가 영 허접하다현재의 소프트웨어 개발자들의 인테리어는 대부분 훌륭하다. 특히, 이제 막 시작한 스타트업의 경우라면 직원이 아니라, '동료'의 입장으로 참여하는 것이기 때문에 이 조건은 해당이 안될 것이다. 하지만, '직원'의 입장에서 그 회사에서 일을 하는 경우라면 '회사 인테리어'는 매우 중요하다.그것은 초라한 사무실에 초라한 책상에 기본적으로 제공되는 도구도 깔끔하지 않다면, 정말 간단하다. 그 회사에서 직원들에 대한 처우나 근로환경은 최악이라고 보면 된다. 아마도, 입사를 한지 한 달 후에 바로 급여나 근로형태에 대해서 불만이 생길 것이다.대부분 이런 회사의 특징은 인력파견 회사일 확률이 높다. 당연한 것이지만, 내부에 축적된 지식도, 솔루션도 없는 조직이다. 그냥, 싼 개발자를 구하고, 파견을 보낼 개발자를 구했을 것이고, 그것에 당신이 걸려들은  것뿐이다. 빨리 탈출하는 것이 현명하다.둘. 직원들의 얼굴 표정이 매일 야근한 것 같다.근무조건과 처우에 대해서는 그 회사에서 근무하는 직원들의 모습을 보면 된다, 깔끔한 복장에 자유롭고, 자신에 찬 얼굴을 하고 있는 경우라면 상관없다. 하지만, 세탁한지 며칠 된 복장에 연일 야근에 찌든 듯한 얼굴, 사무실에 난로도 제대로 안 때워서 매번 감기에 걸려있는 상태인듯한 모습이라면, 그 회사도 빨리 탈출하는 것이 현명하다.필자는 개인적으로 소프트웨어 개발자들을 제대로 처우하는 곳이라면 키보드와 마우스, 그리고. 의자는 최대한 자신이 원하는 도구를 구해주는 곳이라고 생각한다. 그리고, 최소한의 근무환경을 구성해줄 수 있어야 한다. 다만, 같이 고생하고 같이 나눌 동료가 아니라면 이런 회사는 빨리 탈출하다.셋. 오래된 선배 개발자의 경력이 얼마나 되는가?좋은 조직과 좋은 회사. 그런 곳은 좋은 회사다. 고로, 당연하게 좋은 회사는 계속 다닐만한 가치가 있기 때문에 오래된 개발자들이 존재한다. 회사 업력이 10년이 넘었다면, 10년을 다닌 개발자가 있을 것이고, 5~6년 차 개발자들이 여러 명 존재해야 한다.하지만, 회사 경력이 10년을 넘었는데도 그 회사 경력 2년 차가 팀장이고, 병특들로 모두 구성되어 있는 회사라면, '결코 좋은 회사는 아니다'.분명하게 회사의 사장에게 문제가 있거나, 똘아이 같은 개발이사가 있거나, 막 나가는 팀장이 있을 수 있다. 또는, 처우나 급여문제 등등 문제가 분명 존재할 것이다.넷. 가족과 같다는 이야기를 반복하는 사장의 이야기회사는 '이익'을 위하여 존재하는 곳이고, '돈'을 벌어야 급여가 나오는 회사이다. 회사는 '가족'이 아니다. 그리고, '사장'처럼 일하라고 반복하는 '사장'들이 가끔 있다. 그럼, 이렇게 반문해보자, '사장'같이 일하면, '그 회사'를 물려줄 것인가?아니다. 처우는 '노예'처럼 하면서 일은 '사장'처럼 하기를 원하는 것이다. 이런 회사도 떠나라. 또 이런 회사의 특징은 이렇다.'회사 사정이 어려워서...', '요즘 경기가 안 좋아서...', '다음에...', '이거 끝나면 뭔가 있을 거야...'부끄럽지만 필자도 이런 이야기들을 20대 후반 사장 시절에 반복했었다. 결론적으로 '지키지 못할 약속'을 그냥 반복할 뿐이다. 이런 이야기의 99%는 뻥이고, 그냥.  '립서비스'일뿐이다. 포상은 합리적이어야 하는 것이다. 또한, 엄청난 투자를 받는다고 해서  밀어붙인 일일 경우도 많다. 하지만, 언제나 '과실'중에 '이익'은 경영진만이 가지고 간다는 것을 잊지 말자.다섯. 인건비는 무조건 싼 개발자만 찾는 회사.간단하다. 경력 10년 차 개발, 고급 개발자가 할 수 있는 일을 하거나, 품질이 높은 일이 필요 없는 일이 대부분이다. 임금이 비싸고 경력이 풍부한 사람이 비싼 이유는 당연하게 있다. 하지만, 단지 급여가 싼 사람을 찾는 이유는 간단하다.'일'에 대한 가치를 알지도 못하고, '개발자'에게만 탓을 돌리는 사장이나 경영진일 경우에 대부분 이렇다. 경력 1년 차가 할 수 있는 일이라고만 생각하기 때문에, 경력 4~5년 차도 그에 합당한 급여를 줄 수 없는 것이다.당연한 것이지만, 실제 일은 단순 SM이기 때문에 그런 경력을 가진 개발자가 필요 없다고 인지하기 때문이다. 이런 회사들이야말로 정말 비전이 없다.여섯. 급하게 뽑는데 면접도 제대로 안보는 회사정말 엉터리 같은 인력파견업체의 경우가 이렇다. 자신들이 면접을 보는 것이 아니라, 고객사로 보내서 면접을 본다.만일 위에 언급한 6가지 내용 중에 한 개 이상으로 해당되는 회사나 조직에 있다면, ‘이직’을 고려하는 것이 정말 당연하다 하겠다. 하지만, 자신의 능력과 이직에 대한 준비가 되어 있지 않다면, 어쩔 수 없다. ‘샐러리맨’의 기본자세로 돌아가서, 내 능력에 합당한 현재의 자리에 만족하는 법을 배워야 할 것이고, 처세술이나 그 조직에서 버티기 위한 정치력을 발휘해야 할 것이다. 이러한 글들은 주변 서점에 널려있으니, 그런 책 한두권 읽어보기를 권장한다.‘이직’은 소프트웨어 개발자 생활을 하면서 계속 유혹과 한계를 경험하게 할 때마다 머릿속에 떠오를 것이다. 그때에 실수하지 않고, 좋은 판단을 하기 바라며. 가장 중요한 것은 ‘후회’ 하지 않고, 이미 결정한 것은 잊어버리는 것이 속 시원하다는 것이다.마지막으로 좋은 스타트업을 골라달라고 조언하는 경우에는 다음과 같이 답한다.스타트업은 좋은 동료가 될 생각이 있을 때에 들어가라는 것이다. 스타트업은 초기 멤버로서 합류하면서 고생도 같이 하고, 이익도 같이 나누는 동업자가 되는 것이다. 샐러리맨으로써 직장을 택하는 것과는 정말 다른 것이다.물론, 스타트업이 투자를 받고, 초기 멤버가 아닌 경우에는 위에서 언급한 내용과 별로 차이가 없다고 설명할 수 있다. 어느 규모나 별로 차이가 없었다.'이직'은 소프트웨어 개발자들에게는 매번 경험하게 된다. 그리고, 그 경험을 좋은 결과로 얻기를 바란다. 그리고, 언제나 좋은 선택이  필수이며, 인생 선배나 동료에게 좋은 조언을 구해보자.
조회수 1567

자바스크립트에대해서

안녕하세요. 크몽 개발팀입니다.오늘 저는 좀 심오한 주제를 다뤄보려고합니다.이번에 제가 다룰 주제는 ‘자바스크립트’라는 언어입니다.자바스크립트라는 언어와 자바라는 언어에 대해서 혼동을 하는 경우가 많은데요,자바와 자바스크립트는 완전히 다른언어입니다. 쉽게말해서 자바는 서버를 구축하는 부분을 주를 담당하고,자바스크립트는 화면을 구성하는 부분에서 사용되는 프로그래밍 언어라고 보시면 될 것 같습니다.(자바스크립트의 이름을 만들 당시에 자바라는 언어가 유행을 해서 자바스크립트라고 이름을 지었다고 하네요.원래 이 언어의 이름은 라이브 스크립트입니다.)물론 자바스크립트로 서버를 구축을 할 수도 있습니다.(node.js라고하는 플랫폼입니다. 자바스크립트를 이용하여 서버를 구축할 수있는 플랫폼입니다.자세한 사항은 책이나 위키피디아를 참고하시면 좋을 듯 합니다.)각설하고,아무튼 자바스크립트라는 언어에 대해서 좀더 자세히 알아보겠습니다.자바스크립트라는 언어를 알기 위해서는 일단 스크립트라는 것이 무엇인지에 대해 좀더 알아야 합니다.위키피디아에 따르면 스크립트 언어란,'응용프로그램과 독립하여 사용되고 일반적으로 응용프로그램의 언어와 다른 언어로 사용되어최종사용자가 응용프로그램의 동작을 사용자의 요구에 맞게 수행할 수 있도록 해준다.' 라고 정의하고 있습니다. 어렵지요? 쉽게 말하면 연극에서 ‘스크립트’라는 것에 서 유래 되었다고 하고, 그뜻이 연극에서의 시나리오, 각본을 의미합니다. 그 의미를 그대로 적용하면 ‘대본, 시나리오만 제공하면 알아서 작동한다.' 는 그런 뜻이지요.대충 감이 잡히셨나요?자바스크립트는 TIOBE 라는 소프트웨어 회사에서 발표한 2014년 프로그래밍 언어순위에서도 상당히 상위권에 차지를 하고있습니다.그만큼 많이 사용이 된다는 의미겠지요.매우 좋은 것처럼 보이지만 자바스크립트가 만만한 언어는 아닙니다.제가 듣기로는 ‘자바스크립트는 악마의 언어’라고 불린다고 들었습니다.그렇게 불리는 이유는 그만큼 언어가 유연하기때문입니다.조금전에 언급했듯이 연극에서의 대본과 시나리오를 프로그래머가 직접 만들어야한다는 것입니다.그만큼 프로그래밍하기 쉽지 않다는 것이겠지요.자바스크립트는 단점이 바로 장점입니다.'유연하다는 것' 때문에 사람들의 입맛에 맞게 커스터마이징을 할 수있다는 것이고웹상에 이미 프로그래머들이 만들어 놓은 많은 라이브러리가 있습니다.우리는 이걸 잘 이용하면 되겠지요?좀 더 자바스크립에 대해서 자세히 알고싶다면 ‘javascript inside’라는 책을 참고하여 공부해보시면 좋을 듯 하네요. ---------------------------------------------------------------------------------------------------저는 크몽 개발팀의 Sean이었습니다. #크몽 #개발자 #개발팀 #팀원소개 #기업문화
조회수 891

Top Five Games Made in Seoul

 Based in a country seeing huge growth in its video game sector, Korean game studios have been releasing big hits in the past few years. As seen in our previous post, the Top Ten Things to do in Seoul for Gamers, Koreans of all ages have been diving headfirst into gaming culture. Mostly focused on digital gaming like mobile and PC, the gaming industry has been growing at an annual rate of 4.3% (Statista). Although the most popular games by far are MMORPGs, we tried to diversify the list for all types of players to enjoy.  MapleStory  MapleStory - Source: maplestory.nexon.net  MapleStory has been around for years and only continues to be a huge favorite in Korea and around the world. An extremely social game, it sees players work to improve their own character’s skills while chatting, looting and even getting married to others. The 2D element gives the game an almost retro vibe, even though it has been updated many times, including the release of a sequel. Create your avatar, choose your class and find out how to fulfill your quest by defeating the Black Mage.   Ragnarok Online  Ragnark Online - Source: mmoculture.com  You guessed it, another tried and true MMORPG. Based on a comic of the same name by Lee Myung-jin, this 3D game features a constantly changing timeline that players must interact and adapt with within the specific world. The key part of the game is choosing the “job” of your character. With that choice come make-or-break strengths and weaknesses that can determine the gameplay for you. Starting at 13 but growing to 50 classes, the choice is daunting but crucial as your job can change as well. Whether you want to try out the newest sequel, the mobile version, or even watch the animated TV series, Ragnarok Online is definitely one to check out.   Blade & Soul  Blade and Soul - Source: www.bladeandsoul.com  Developed by one of the most notable studios in Korea, NCSOFT, this fantasy martial arts game was only released in Western countries 2 years ago, but had been out in Korea and Japan since 2012. A super renowned character customization system gives the game an update from the more traditional fighting style games. There are four playable races that reference the four Chinese Symbols of Azure Dragon, Vermillion Bird, Black Tortoise and White Tiger. Definitely a must for fans of combat-driven games.   ANIPANG  ANIPENG - Source: anipang-for-kakao.en.softonic.com  Finally a change of pace! ANIPANG is a mobile puzzle game, and also the first Korean game to reach 20 million downloads. Filled to the brim with squishy animal faces, this match-3 style game can be enjoyed alone or by competing with friends. Whether it’s killing time waiting for the bus or just wanting to beat that one tricky level, ANIPANG can be played anywhere at any time.   Lineage  Linage - Source: mmogames.com  Rounding out this list is Lineage, a video game series released in the 90s and still receiving sequels and spin-offs to this day. Taking you back to medieval times, this game is one of the most successful MMORPGs to date. The realistic siege warfare and constant lore updates makes it a fun and addictive way to pass the time. The mobile release of the game broke records and had fans eager to play, so don’t miss out. 
조회수 615

스마트링크 시즌2 : 은하철도 프로젝트

스마트링크 시즌2 채용공고에 보내주신 뜨거운 반응 감사합니다!! 정말 많은 분들의 열정과 관심에 분주하지만 즐거운 만남들을 여럿 가질 수 있었습니다. 그리고 드디어!! 은하철도에 함께 탑승할 5명의 동료가 최종 선발되셨습니다. 뜨거운 관심과 지원에 다시 한번 감사드리며 아쉽지만 이번에 함께하지 못한 분들도 저희가 좌석을 보다 넉넉하게 꾸리게되면 함께할 수 있는 날이 오면 좋겠습니다.여기서 잠깐!그렇다고해서 스마트링크 시즌2 채용이 완전히 완료된 것은 아닙니다. 스마트링크는 언제나 좋은 분들과 함께할 준비가 되어있습니다. 상시채용 형태로 계속 이어나갈 예정이니 스마트링크 은하철도에 관심있는 분들은 언제나 문을 두드려 주시면 감사하겠습니다. 그럼 새로운 동료들과 슬슬 날아갈 준비를 하러 이만 :) - 2019. 6. 25 어느 기분좋은 화요일---------------------------------------------------------------------안녕하세요. 스마트링크의 Mike 라고 합니다. 기획과 마케팅을 담당하고있죠. 스마트링크는 작년부터 저희와 함께할 분들을 애타게 찾고 있습니다. 그 사이에 많은 분들을 뵙고 기회를 도모하기도 했습니다. 여러 다양한 경험을 축적하기도 했구요. 이렇게 여러 과정을 거치던 와중에 그동안 아기다리고기다리던, 그리고 열심히 준비했던 성과들이 하나둘 나오기 시작했습니다. 마치 미드에서 시즌이 바뀌는 것처럼 우리에게 근본적인 패러다임의 변화가 있었다랄까요? 이런 변화를 염두하며 지난 채용공고를 봤는데...안되겠어. 다시 써야겠어!그래서 이렇게 시즌2 만을 위한 채용공고를 작성하는 중입니다. 스마트링크의 시즌2는 어떻게 진행되고 그래서 어떤 분들과 함께하고 싶은지 지금부터 이런저런 이야기를 해보도록 하겠습니다.  뭐하는 회사임?스마트링크는 소프트웨어 개발사 입니다. 끝. 참 쉽죠? 그런데 세상은 넓고 소프트웨어 개발사는 넘치고 넘칩니다. 그런데 뭐가 그렇게 다른가? 라고 물으신면! MVP(Minimum Viable Product) 소프트웨어 개발 컨설팅 전문 업체라고 말씀드릴 수 있겠습니다. 이게 뭔말이냐 하면 덩치 큰 SI도 진행하지만 주로 스타트업 또는 초기 사업 아이디어가 빠르게 시장에 진입할 수 있도록 기획, 디자인, 개발, 테스팅, 데브옵스까지 (물론 견적에 따라 달라집니다! 단호! ㅋㅋ) 풀 패키지로 작업하는걸 좋아하는 업체라고 보시면 되겠네요. 그래서 프로젝트 기간이 짧고 굵은게 많죠. 늘어지는 프로젝트 별로 안좋아 합니다. AtoZ로 빠르게, 효율적으로, 효과적으로! 일하는걸 선호하고 실제로 그렇게 일을 진행합니다. 그런데 아마 이런 의문이 드실거에요. 왜 작은일 맡는걸 좋아하지? 사실, 규모가 중요한게 아니라 AtoZ 라는게 중요합니다. (심지어 예산 높은 큰 프로젝트 요청을 까기도 합니다. 꽤 자주;;) 그 이유는? 면접때 질문 주시면 신나게 답해드리도록 하죠 ㅎㅎ 다 이유가 있습니다!  누가 일하고 있는데?AtoZ, 풀패키지로 일하는걸 좋아한다는 대목에서 아시겠지만 있을 사람은 다 있습니다. 기획, 디자인, 개발 인력 모두 있구요. 그래야 일이 되겠죠? 다만 현재 사람수가 많지는 않아요. 소수정예! 하지만 모두 각 분야에서 베테랑들이라 자부합니다. 특히 개발사이니만큼 모든 분야는 개발을 중심으로 돌아가구요, 각 영역을 생판 모르는 분야로 치부하지않고 서로를 끊임없이 알아가고 파악하고 융화되는 방식으로 일합니다. 예를 들면 기획과 개발은 DB구조나 Convention을 공유하고, 디자인은 Front-end 최적화된 디자인과 UI/UX를 뽑아냅니다. 여기서 일일이 언급하기는 뭐하지만 일 잘하는 사람들이 모여있다고 자부하고 있고, 앞으로 동료들도 일 잘하는 사람을 가장 원하고 바라고 있습니다. 일을 잘한다는 기준이 절대적일 수는 없겠지만, 예를 들면 이런거죠. 최대한 정확하고, 낭비나 누수없이, 빠르게 문제를 해결하기 위해 계속 꼼수를 쓰는 사람들! 이랄까요? 세상에 (노는것 포함) 할일이 얼마나 많은데! 극단적 효율을 추구하는 집단이라고 보시면 되겠습니다.  제대로된 꼼수는 사실 탄탄한 정석 바탕에서 나올 수 있다죠.다만 아직 목마릅니다. 일을 더 잘하고 싶어요. 그래서 우리는 시즌1을 보내면서 내부를 다지는 일도 지속적으로 탄탄하게 단내 나도록 해왔습니다. 그리고 슬슬 그 결과들이 눈 앞에 펼쳐지고 있네요. 그래서 결심할 수 있었습니다. 이제 확장의 시기가 왔다! 시즌2로 나아갈 때가 되었다!   시즌2라...시즌1엔 어떻게 했고, 시즌2에서는 어떻게 할건데??시즌1에서 스마트링크 작업방식을 정의내리자면 이렇습니다.천상천하유아독존!!네, 그렇습니다. 각자 부여된 일을 독자적으로 수행해서 최종 결과물을 내는 방식이었죠. 내부적으로 진행하는 일이야 Agile 방법론을 적극 도입한다해도 외부 프로젝트를 진행하는 경우에는 어쩔 수 없는 Waterfall 방식이었습니다. 기획 작업을 마무리하면, 받아서 디자인 작업을 하고, 마지막으로 개발을 완료하는 방식이었죠. 특히 개발은 Ownership을 기반으로한 책임개발제(라 쓰고 독박이라 읽는다)로 운영되고 있었습니다. 이 방식으로 운영했던 이유는 모호한 업무분담과 그로 인한 누수를 최소화하기 위한 방책이었죠. 사공이 많으면 배가 산으로 간다는 속설을 극복할 방법이기도 했구요. 실력있는 개발자를 중심으로 이 방법은 한동안 잘 유지되는듯 했습니다. 그런데 계속 이렇게 운영하다보니 이런 상황이 발생했습니다.될놈될, 안될안 ㅠ 개발 결과물의 빈부격차 ㅠ책임개발제는 결과물이 사람에 의해 결정된다는 의미 입니다. 실무자의 경험이나 실력에 따라 천차만별일 수 밖에 없는거죠. 그러다보니 퀄리티 확보를 위해서는 결국 다시 여러 사람들의 손을 거쳐야하는 이슈들이 종종 발생했습니다. 사실 이는 필연적인 부분일지도 모르겠습니다. Full-Stack 개발을 추구한다해도 결국 저마다 가지고있는 개성과 강점은 다르니까요. 그럼에도 불구하고 지금까지는 딱히 문제 없었습니다. 다만 미래를 염두하면 걱정되는 부분들이 있더군요. 인력이 늘어나고 보다 다양한 사람들이 함께하게된다면 과연 이 시스템이 버틸 수 있을까? 라는 근본적 의문이 드는겁니다. (그래서 이번 채용은 Front-end와 Back-end를 구분해서 진행합니다.) 그리고...Ownership이고 뭐고 다 좋은데 왜 외롭냐...외롭기도 하더군요. 기획, 디자인, 개발 모두가 그랬고 특히 개발자들은 그냥 말 그대로 굉장히 외롭게 되었습니다. 복작이며 한 팀으로 일하는 방식이라기보다는 프리랜서들 조합과 같은 이 상황은 구성원들을 각자 개인의 울타리로 고립시키는 결과로 이어졌습니다. 기획, 디자인, 개발은 각자 나름의 방식으로 일하면 결국 서로 Sync를 맞추기 위한 작업이 추가될 수 밖에 없습니다. 효과적인 분업도 좋지만 결국 우리는 함께 일하는 회사라는 공동체 안에 있습니다. 능률, 효율과 더불어 협업도 굉장히 중요하죠. 적당한 균형점을 찾는게 중요해졌습니다. 앞으로 사공은 엄청 많아질거거든요. 그것도 다양한 특징과 강점을 가진 각양각색의 사공들이 말이죠. 이렇게 사공이 많아져도 배가 산으로 가면 안되죠.  우주로 가는건 괜찮을지도... 사공이 많은 배라면 차라리 이런걸 만들면 어떨까?사공이 많은 멋진 배를 만드는 방법이란 뭘까? 누수 없는 업무처리와 능률을 모두 잡는 방법은 무엇일까? 이런 고민을 하던 와중에 우리에게 필요한건 엔진이란걸 알게 되었습니다. 이 엔진은 이런 조합으로 구성되어야 했습니다.목표한 기능을 정확하고 안정적으로 구현할 수 있는 동력자칫 시야를 좁힐 수 있는 미시적 요소들을 과감하게 skip할 수 있는 돌파력누수없이 매끄럽게 진행되는 안정적 업무 전달계통그리고 이 과정을 우리 모두 함께하고 있다는 응집력 뭔가 뜬구름 잡는 이야기들로 보일지도 모르겠습니다. 하지만 이 조합은 연역적이라기보다는 귀납적입니다. 실제 우리가 고민해온 부분을 해결하고자한 일들의 결과물이 위와 같은 역할을 하고있다는 것이 보다 정확한 표현이겠네요. 그리고 이 엔진은 한 단어로 귀결됩니다.그렇습니다. 컴포넌트.그리고 우리는 Components 를 엔진 삼아 우주전함 대신 은하철도 시스템을 구축했습니다. 이른바 스마트링크 시즌2 은하철도 프로젝트!  은하철도 프로젝트라니... 뭥미?? - 스마트링크 시즌2 은하철도 프로젝트보통 스타트업이 성장하는 모습을 로켓에 비유하기도 합니다. 빠르고 가파르게 수직상승하는 모습을 본딴 것이겠죠. 하지만 우리는 조금 다르게 생각합니다. 한가지 아이템으로 절체절명의 상황을 이겨내고 급성장하는 방법도 좋겠지만 우리는 오히려 안정성과 지속가능성에 더 초점을 맞추고 있습니다. 이를 위해서 스마트링크는 꽤 오랜시간 공들여 Component 구축을 진행했고 그 결실이 드디어 빛을 봤습니다! 장기적으로 효율적이고도 생산적인 구조를 위해 이제까지의 내부 프로세스를 과감하게 변경하고 새롭게 아래와 같은 구조로 진행합니다. 반영구적 Components 엔진을 돌리면서 모두를 리딩하는 곳, 기관실우리의 엔진 Components를 계속 다듬고 발전시킵니다. 내부 프로젝트도 진행하죠.실무자들의 즐거운 놀이터, 1등석이미 잘 구축된 Components로 안락하고 쾌적하고 빠르게 할당된 프로젝트를 진행합니다. 특히 개발자에게는 상용 서비스에서 활용 가능한 React Skill을 마음껏 연마하는 과정이기도 합니다 :)초심자들의 탄탄한 학습의 장, 일반석숙련도와 경험이 적은 초보자들은 체계적인 교육과 안정적인 Components 활용법을 익히고 1등석에 옮겨탈 준비를 합니다.뭔가 괜찮은 열차죠? 은하철도 프로젝트는 크게 이런 구조로 작동하게 됩니다. 이번 채용공고를 통해 모시고자하는 자리는 1등석과 일반석 입니다.베테랑들은 탑승한 동료들을 위해 열심히 기관실을 돌리면서 최대한 안정적이고 쾌적한 작업환경을 위해 움직입니다. 물론 내부적인 방향과 비전을 위한 고민, 세팅도 주도하겠지만 최종적으로는 모든 구성원들과 함께 공유하고 의견을 모아 진행합니다. 기관실과 객석들 역시 유기적이고 탄탄하게 연결돼야 하니까요.가즈아~ 기관실은 구비되어있다!!기관실과 객석이 설국열차처럼 꽉 막혀있지 않습니다. 본인이 원한다면 일정정도 열정과 의지로 기관실에 옮겨탈 수도 있습니다. 이건 순전히 본인의 취향에 달려있다고 생각해요. 세상은 넓고 사람은 다양하고 가치관도 제각각입니다. 그저 선택의 문제일 뿐이죠. 우리는 그저 보다 많은 사람들이 우리의 은하철도에 올라탈 수 있기를 바랄 뿐입니다. 그래서 선택할 수 있는 자리를 마련한 것 뿐이구요. 실무자들이 실무에만 집중할 수 있는 구조는 회사라는 공동체에서 매우 중요하다고 생각합니다. 선택은 여러분의 몫입니다.  1등석과 일반석이라... 좀 더 설명해보지?고민의 공간, 기관실.1등석과 일반석을 설명하자면 먼저 기관실 설명을 하지 않을 수 없습니다. 기관실은 끊임없이 소프트웨어 Core를 생산하는 곳이라고 보시면 되겠습니다. 그 중심은 당연히 Components 겠죠. 세상의 모든 서비스를 커버하겠다는 야심과 함께 사용자에게는 쾌적한 경험을, 개발자들에게는 효율적이고 신속한 개발환경을 선사하는 영역입니다. 그래서 개발언어를 잘 이해하고 보다 핵심적인 영역을 손대고 싶은 사람에게 적합합니다. 실력도 당연히 동반되어야겠지만 이제까지 경험으로 보자면 자기주도적인 취향도 핵심이더군요. 기관실은 이런 사람들이 모여있습니다. 사용자경험 뿐 아니라 내부 개발진들의 의견을 끊임없이 추적하고 해결하는 고민의 공간 입니다.기관실이 잘 할테니까 팔로팔로미~ ㅎㅎ효율의 공간, 1등석위에서 '취향'에 대해 언급했는데요. 1등석은 취향에 따라 자신의 업무방향을 선택할 수 있는 공간 입니다. 잘 짜여진 Components와 Convention에 따라 실제 상용서비스를 만들거나 관리하는 역할을 합니다. 고민의 폭은 줄이고, 실질적인 결과물에 초점을 맞추는 효율의 공간이라고 보시면 되겠어요. 새로운 결과물을 세상에 선보이고, 이들을 잘 작동시키는 사람들이 모여있는 곳입니다. 그러다가 지금 쓰고있는 Components 개선이 좀 더 필요할거 같다 싶으면 자체적으로 해결해도되고 기관실로 넘길 수도 있습니다. 이 부분이 바로 취향의 영역이라고 볼 수 있는데요. 본인의 실력과 더불어 이 취향에 따라서 기관실로 갈지, 1등석에서 작업할지 결정할 수도 있습니다.학습의 공간, 일반석일반석은 다른 말로 초심자의 영역이라고 보시면 되겠습니다. 세상은 급변하고 소프트웨어 변화 역시 엄청나죠. 우리는 끊임없이 학습하고 발전해야만하는 영역에서 일하고 있습니다. 그래서 이 부분을 절대 간과해선 안된다고 생각하고 있어요. 다만 취미 정도의 학습이라면 각자 개인의 소양 정도로 진행하는 것이 적절하겠죠. 일반석은 실제 상용 서비스에 적용 가능한 수준의 학습이 이뤄지는 공간입니다. 그 핵심은 React, Meteor, MongoDB 라고 보시면 되겠구요. 고퀄 서비스들을 실제로 만들어낼 수 있는 핵심 역량을 키울 수 있는 곳입니다. 사람들은 각자 일하는 방법이나 인생설계 방향을 가지고 있습니다. 그리고 여기에 따라 너무 다양한 나름의 스타일을 가지고있죠. 우리는 이 부분을 간과해서는 안된다고 생각해요. 우리가 말하는 취향은 바로 이런 것입니다. 취향에 따라 내가 주도적인지 수동적인지, 스스로 설계하는 스타일인지 주어진 과제를 잘 해결하는 스타일인지 나뉘는게 당연하겠죠. 이 부분은 실력과는 또 다른 축인거 같습니다. 한가지 방식을 강요해봤자 상황이 제대로 돌아갈리는 만무하고 또 그래서도 안됩니다. 일을 잘 하고싶은 스마트링크는 그래서 우리가 운영 가능한 범위 내에서 최대한의 공간과 가능성을 만들고 싶었습니다. 그래서 이런 구조를 생각해낸거구요.좀 더 솔직히 말하자면, 네. 이거 준비하는데 힘들었습니다 ㅠ 그냥 실력있는 사람들이 머리를 맞대고 모이기만 한다면야 이런 고민과 구상이 필요 없을지도 몰라요. 오히려 그게 편하기도 하구요. 척 하면 척~ 착 하면 착~ 아시죠? 그리고 이 은하철도 프로젝트를 채용공고에서 공개하는 것이 과연 좋을까? 라는 고민이 있었던것도 사실입니다. 우리 자뻑모드로로 보자면 중요한 영업비밀일지도 모른다고 생각했거든요. 하지만 채용공고가 다소 길지라도 가능한 범위 내에서는 충분히 미리 공유하는게 좋겠다고 생각했습니다. 사실 이런 생각까지는 쉬운데 실제로 이렇게 구조를 잡는건 생각보다 매우매우 오래걸리고 어렵거든요. 그리고 그 어려운걸 우리는 해냈습니다. Components를 잘 구축해놨다 이겁니다 ㅎㅎㅎ다시 한번 말하자면 스마트링크는 로켓이 아니라 은하철도 입니다!! 날아오른다!!! 이거시 바로 은하철도!!!  알겠고, 그렇다면 구체적인 채용정보를 내놓아라!그래서 누굴 뽑는것인가? 라고 물으신다면 개발자 0명 찾습니다! 0명은 무엇이냐? 좋은 사람이 있으면 있는만큼 욕심을 낼것이다! 이런 욕구와 목마름이 있다는 것이죠! 많이 지원해 주세요! 공통적으로 체크해보실 수 있는 정보를 우선 드릴까요? 현재 사용중인 기술 스택 및 도구공통: Google Drive, Trello, Slack기획: FramerX, Adobe XD디자인: FramerX, Adobe XD 포함 Adobe 모든 제품군, ZeplinFront-end: Semantic UI, React, React NativeBack-end: MeteorTesting: Mocha, JestDevOps: Jenkins, Docker, Phusion Passenger, Nginx, AWSDatabase: MongoDB 근무환경최상의 사무 환경 및 공간 제공 (넓고 쾌적한 책상! 빵빵하고 쾌적한 냉난방시설! 막 엎어져서 작업하는 소파! 등) 식대 지원 (중식/석식) 4대 보험 주5일 근무 Refresh 휴가 출근시간 선택제 (8-5 / 9-6 / 10-7 / 11-8)경조사비 지원 근무지: 서울시 서초구 양재동 4-14 3층워크샵이라 하면 적어도 뷔페와 함께하는 야간 요트 유람 정도는 해줘야하는거 아닙니까? (사실 명목은 지스타…)  알겠고, 개발자 채용요건을 내놓아라! 네, 드...드리겠습니다. 아래를 봐주세요. 참고로 위에서 충분히 설명했듯 우선 1등석과 일반석에 모셔요~ ㅎㅎ Global Spec과 실무경험을 국내에서 탑재할 수 있는 기회를 놓치지 마세요! 이제 개알못 기획자는 아웃! React 코드를 보고 이렇게 반응하는 사람이라면 우리는 이렇게 됩니다 ㅎㅎ기술 스택스마트링크는 2001년 부터 C > C++ > Java > Object Pascal > PHP > JSP > Rails > Python 등의 개발 언어 기반으로 많은 프로젝트를 수행하여 왔습니다. 현재는 Javascript, Nodejs, React, React Native, Meteor, MongoDB의 매력에 흠뻑 빠져 있지만, 프로젝트 진행의 효율을 더(even more productive) 개선할 수 있는 새로운 기술이나 방법론에 대한 목마름으로 언제든 Early Adapter가 될 준비가 되어 있습니다.   모집분야 : 각 영역의 Front-end 혹은 Back-end 개발자를 모십니다.Javascript/Nodejs/Meteor 기반의 웹/모바일 애플리케이션 개발자 React + Meteor + MongoDB 기술 기반의 Web Application 개발 React Native + Meteor + MongoDB 기술 기반의 Mobile Native Application 개발  자격요건 : 개발에 미친 사람!!! 자유로운 소통과 공유의 가치를 잘 이해하고, 자기주도적인 환경에서 최대의 능력을 발휘하며, 긍정에너지 발산이 가능한 분 논리적이고 체계적인 문제해결 능력 및 오픈 마인드 커뮤니케이션 능력 전산 관련학과 학사 이상 또는 동일한 자격 (경력 무관)  우대조건 React, React Native 등의 JavaScript SPA(Single Page Application) 프레임워크 경험 Nodejs + MongoDB 기반 Micro Service Architecture 서비스 개발 경험 영어 커뮤니케이션 능력 (특히, 영문서 이해 능력: 해외 최신 기술을 주로 이용하다보니 한글 자료가 없는 경우가 많습니다.) AWS 등 클라우드 서비스 운영 경험 Git 포트폴리오: 직접 작성한 패키지, 오픈소스 기여 경험Docker 컨테이너 기반 서비스 구축 및 운영 경험 CI 시스템 구축 및 운영 경험 Mocha, Jest 등의 테스팅 프레임워크 또는 TDD(Test Driven Development) 경험  어떻게 지원하면 되는거임? 아래 루트로 지원해주시면 서류검토 후 면접일정을 직접 안내해 드립니다. 이메일과 핸드폰 연락처가 모두 기재되어있으면 참 좋겠죠? 면접이 진행되면 스마트링크에 궁금한 것, 알아보고 싶은 모든 것을 물어보실 수 있습니다! 함께 대화하는 자리라고 생각하시는게 가장 좋을거 같네요. 1. 이메일로 지원하세요! [email protected]해당 정보들도 함께 보내시면 금상첨화!이력서 (희망연봉포함)포트폴리오개발 경력 자료 (github 주소 환영합니다!) 2. 로켓펀치에서도 지원하실 수 있습니다!일반석 채용공고 https://www.rocketpunch.com/jobs/574961등석 채용공고 https://www.rocketpunch.com/jobs/57499 3. 잡코리아도 됩니다!스마트링크 은하철도에 탑승할 개발자 정규직 채용(신입&경력)http://www.jobkorea.co.kr/Recruit/GI_Read/28711079?Oem_Code=C1 4. 사람인도 됩니다!스마트링크 은하철도에 탑승할 개발자 정규직 채용(신입&경력)http://www.saramin.co.kr/zf_user/jobs/relay/view?rec_idx=36338553&view_type=etc   지금 망설이고 있다면???국내에서는 중소기업, 특히 신생기업이나 스타트업에 대한 인식이 그렇게 좋지않죠. 이런 현실적인 부분도 감안해서 저희는 직접적인 코딩테스트나 압박면접 같은건 진행하지 않습니다. 차분하고 진실된 마음의 대화가 가장 중요하다고 생각해요. 본인의 평소 생각을 그저 편안하게 나눈다 생각하고 부담없이 관심만 가지고 다가와주세요 :)이 짤처럼 무서운거 아니에요 ㅋㅋㅋ 편하게 드루와 드루와~지금까지 소개해드린 스마트링크 시즌2, 은하철도 프로젝트 느낌이 어떠신가요? 저희의 설렘과 기대가 잘 전달이 되었을지 모르겠어요. 같은 설렘과 기대가 느껴지신다면 망설이지 마세요! 우리의 은하철도에 탑승할 분들을 그야말로 간절한 마음으로 기다리고 있습니다.  지금 당신은 지원 메일을 보내고있다~!!!
조회수 1021

원하는 대로 뭉치는 GROUP BY

편집자 주전문 용어는 특정의 학술 용어나 기술 용어를 말하는데, 대개 둘 이상의 단어가 결합하여 하나의 의미 단위에 대응하는 말, 곧 합성어의 성격으로 되어 있다. 아래와 같은 전문 용어는 단어별로 띄어 씀을 원칙으로 하나, 편의상 붙여 썼다. 1) 수행 결과 > 수행결과2) 수행 시간 > 수행시간3) 실행 계획 > 실행계획Overview지난 글에서는 ORDER BY를 파헤쳤습니다. 이번에는 ORDER BY만큼이나 자주 쓰이는 GROUP BY를 알아볼 시간인데요. GROUP BY는 컬럼 값을 그룹짓고(중복을 제거하고) 이에 대해 건수나 값의 합을 계산할 때 사용합니다.지난 글 보기: 순서대로 척척, ORDER BY지난 글 보기: 단일 TABLE을 SELECT하자! 1.GROUP BY의 이해GROUP BY의 기본적인 문법은 아래와 같습니다.SELECT     MBR_NM FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 실행계획은 아래와 같습니다. 테이블을 전부 읽어서 temp를 만들고 GROUP BY를 수행하라는 의미죠. GROUP BY가 수행되는 것은 Extra에 Using filesort가 표시된 것으로 유추할 수 있습니다.참고로 Using filesort는 GROUP BY, ORDER BY, DISTINCT 등의 정렬과 관련한 작업을 수행하면 나타납니다. Query를 수행해볼까요?위와 같은 결과가 나왔는데, 수행시간은 3.77초가 걸렸습니다. 이 Query는 MBR_NM의 중복을 제거해서 화면에 표시한 것입니다. 이번에는 아래의 Query를 수행해보겠습니다.SELECT     MBR_NM      ,COUNT(*) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 바뀐 것이 있다면 SELECT 절에 COUNT(*) 가 추가된 것입니다. 실행계획은 다른 점이 없습니다.COUNT(*)는 레코드의 건수를 계산할 때 사용합니다. 위의 계획은 MBR_NM의 값이 같은 건수를 출력하라는 의미입니다. 수행해보겠습니다.수행시간은 3.64초로 비슷하게 나옵니다. 위의 내용을 보면 강나영 1437건, 강다은 1465건, 강도연 1445건 … 인 것을 알 수 있습니다. 만약 테이블의 전체 건수를 알고 싶다면 어떻게 할까요? 아래와 같이 수행해보세요.SELECT     COUNT(*) FROM test.TB_MBR_BAS  ; 수행결과는 다음과 같습니다.2.GROUP BY의 응용(1): 나이 구하기이번에는 나이 컬럼을 추가하고 이름별 나이의 합을 구해보겠습니다. 아래의 명령으로 컬럼을 추가합니다.ALTER TABLE test.TB_MBR_BAS ADD COLUMN AGE TINYINT UNSIGNED DEFAULT 0 COMMENT '나이'; 컬럼이 추가되고, 다음과 같은 구조를 갖출 겁니다.AGE 컬럼에 모두 0이 들어간 것을 알 수 있다.SELECT     * FROM test.TB_MBR_BAS ; 0으로 들어간 값을 1에서 100 사이의 임의 값으로 변경하겠습니다. 만약 내용을 변경한다면 아래 예시와 같이 UPDATE문을 사용하세요. UPDATE test.TB_MBR_BAS SET AGE = TRUNCATE(RAND()*100,0)+1 ; test.TB_MBR_BAS 의 AGE 컬럼 내용을 변경하라는 명령을 하기 위해 RAND() 함수를 쓰고 임의의 값을 발생시겼습니다. UPDATE 및 SELECT를 수행하면 값이 변경된 것을 알 수 있습니다.SELECT     * FROM test.TB_MBR_BAS  ; 변경된 값이번에는 이름이 같은 사람들의 나이 합을 구해볼까요? 합을 구할 때는 SUM 함수를 사용합니다. SELECT     MBR_NM     ,COUNT(*)     ,SUM(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM ; 실행계획은 AGE 컬럼을 추가하기 전과 바뀐 것이 없다는 걸 알 수 있습니다. 실행결과를 보겠습니다.수행시간은 4.3초 걸렸습니다. ‘강나영’이란 이름을 가진 사람의 건수는 1,437건이고, 나이의 합은 74,092인 것을 알 수 있습니다. 합산만 하면 의미가 없으니 평균 나이를 구해보겠습니다. 방법은 SUM / COUNT하는 방법과 AVG 함수를 이용하는 방법 두 가지가 있습니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 실행계획은 이전과 달라진 부분이 없습니다. 수행결과를 보도록 하죠.수행시간은 5.6초 정도 걸렸습니다. 좀 더 빨리 수행하면 좋을 텐데 말이죠. 시간을 단축시키려면 어떻게 해야 할까요?3.GROUP BY의 응용(2): 수행시간 단축하기기본적인 방법은 GROUP BY할 컬럼으로 INDEX를 생성하는 것입니다. MBR_NM으로 INDEX를 생성해보겠습니다.CREATE INDEX IX_MBR_BAS_02 ON test.TB_MBR_BAS (MBR_NM); 생성 후, 이전 Query를 수행합니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 아래의 실행계획이 달라진 것을 알 수 있습니다.실행계획을 보면 전체를 읽어서 처리하는 부분은 사라졌습니다. 대신 IX_MBR_BAS_02 INDEX를 사용하는 것으로 나옵니다. 이미 정렬된 구조를 갖추고 있는 INDEX에서는 GROUP BY 수행 시, 또 정렬하지 않아도 됩니다. 그래서 별도 정렬인 Using filesort가 Extra에 나오지 않은 것이고, GROUP BY에 INDEX를 사용하는 것으로 해석할 수 있습니다. 그렇다면 시간은 얼마나 줄었을까요? 수행해보겠습니다.0.5초 정도 걸렸습니다. 기존 5.6초보다 훨씬 많이 개선된 것을 알 수 있습니다. 시간은 단축되었는데 결과는 같습니다.이번에는 IX_MBR_BAS_02를 기존 MBR_NM에서 MBR_NM, AGE로 생성해 보겠습니다.DROP INDEX IX_MBR_BAS_02 ON test.TB_MBR_BAS; CREATE INDEX IX_MBR_BAS_02 ON test.TB_MBR_BAS (MBR_NM,AGE); INDEX를 생성하고 이전 Query를 수행합니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 달라진 것이 있다면 Extra에 Using index가 표시된 것입니다. 기존에 INDEX가 MBR_NM으로만 구축된 Query는 IX_MBR_BAS_02 INDEX로 GROUP BY하고, TB_MBR_BAS에서 AGE 합을 구한 것입니다. 하지만 INDEX가 MBR_NM, AGE로 구축된 이번 경우는 IX_MBR_BAS_02 INDEX를 이용해 GROUP BY 와 AGE의 합까지 구한 것이죠. 물론 결과는 같았지만, 수행속도는 0.3초로 개선되었습니다.4.GROUP BY의 응용(3): 특정 조건의 결과 출력WHERE마지막으로 성이 김 씨인 경우에만 GROUP BY하여 값을 출력해보겠습니다. 위의 Query에서 WHERE로 조건만 더하면 되는데요.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS WHERE MBR_NM LIKE '김%' GROUP BY     MBR_NM  ; 위의 이미지처럼 WHERE 조건이 들어가면서 type이 index에서 range로 바뀐 것을 알 수 있습니다. 이것을 해석하면 ‘ IX_MBR_BAS_02를 WHERE조건의 범위만큼 처리하라는 것’입니다. 실행결과를 보죠.HAVINGHAVING 절은 GROUP BY로 SUM, COUNT, AVG한 값을 필터 조건으로 걸고 싶을 때 사용합니다. 예시로 위의 Query에서 AVG(AGE) 값이 50보다 작은 것을 출력해보겠습니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS WHERE MBR_NM LIKE '김%' GROUP BY     MBR_NM HAVING AVG(AGE) < 50>결과를 출력하면 아래와 같습니다.AVG(AGE)가 50보다 작은 값들이 출력된 것이 보이는군요.글을 마치며간단한 예제를 소개해드렸지만 큰 규모로 GROUP BY를 하면 재미있는 결과들을 만날 수 있습니다. 예를 들어 대한민국 전체 국민을 대상으로 GROUP BY를 실행하면, 평균 나이가 가장 많은 성 씨를 찾을 수 있습니다. 인구통계학 분석에 적용하면 100년 안에 없어질 성 씨를 알 수도 있고요. 응용할 수 있는 범위가 아주 많겠죠? 이상으로 GROUP BY에 대한 소개를 마칩니다. 글한석종 부장 | R&D 데이터팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발자 #개발팀 #인사이트 #경험공유
조회수 3796

PHP Codeigniter 환경에서 VUE 사용해보기

Overview이번에는 PHP Codeigniter 기반의 서비스에 VUE를 적용시키려고 고민했던 것들을 나누려고 합니다. VUE JS는 가상 DOM을 활용하여 실시간으로 반응 컴포넌트를 제작할 수 있는 프레임워크입니다. 또한, VUE-ROUTER 및 VUEX라는 컴페니언 라이브러리를 통해 url 라우팅 및 전역상태를 관리하기에도 탁월하죠. VUE와 다른 프레임워크와의 비교 부분은 여기를 참고해주세요. 브랜디의 관리자 서비스는 PHP Codeigniter 프레임워크로 제작되었습니다. 하지만 관리자 서비스의 규모가 점점 커지고 기능이 다양해지면서 “자주 사용하는 기능을 묶어 컴포넌트화하자!”라는 숙제가 남아 있었죠. 요즘 잠깐의 여유가 생겨 이때다 싶었습니다. 관리자 서비스에 VUE를 도입하기 위한 시도를 시작했는데요. 얼마 지나지 않아 문제점에 봉착했습니다. 바로 IE9.0…. 개발자의 숙적 IE가 또 한 번 발목을 잡았습니다. 임포트가 되지 않아….VUE를 좀 더 편리하게 사용하려면 JS의 모듈화가 필요했지만, ES2015에서는 import 혹은 require 구문을 지원하지 않아 불편하고, arrow 함수 또한 사용할 수 없습니다. 게다가 VUE의 JAX 탬플릿 구문을 사용할 수도 없었죠!! 뭔가 배보다 배꼽이 더 커질 것 같은 조짐이 보였습니다.결국 Webpack의 도움 없이 VUE를 적용하려던 시도는 여러 가지 난관을 만났고, Codeigniter 프로젝트 내부에서 Webpack을 사용하는 방법을 연구하기 시작했습니다. Webpack은 모듈 번들러입니다. Webpack의 메인 페이지를 방문하면 아래 네 개의 슬로건이 빙글빙글 돕니다.Bundle your scriptsBundle your imagesBundle your stylesBundle your assets아래의 이미지는 Webpack이 무엇을 하는 녀석인지 잘 설명해줍니다.Webpack은 실제로 번들러라고 광고하는것 처럼 Only Webpack 빌드만으로는 소스 파일들을 모아줍니다. 만약 webpack-dev-server로 실행하면 websocket을 통해 소스가 변경됐을 때 실시간으로 화면을 갱신해주는 개발 툴 제공 정도의 역할 밖에 없습니다. (…충분히 훌륭하잖아?)대부분의 기능은 엄청난 확장성을 가진 webpack의 설정으로 모듈로서 작동할 수 있죠. 예를 들면 Babel은 우리의 발목을 잡았던 IE를 위해 ES6로 작성된 js 문법을 IE에서 사용할 수 있는 ES5문법으로 너무나 쉽게 트랜스컴파일할 수 있습니다.하지만… 관리자 서비스는 위에서 언급했듯이 Codeigniter 기반입니다. 따라서 완벽히 VUE와 API서버를 분리하려면 로그인, 메뉴구성, 헤더, 푸터 등 PHP 기반으로 제작된 모든 기능들과 인증 등 기존 방식을 전부 새로 만들어야만 VUE를 온전히 사용할 수 있습니다.문제점들을 모두 해결하고 넘어가기엔 여유가 부족하기 때문에 조금씩 적용하자고 생각했습니다. 덕분에 webpack-dev-server의 실시간 소스 반영 기능을 포기해야만 했죠.(눈물) 우리의 서버는 node기반이 아닌 apache-php 기반이었기 때문입니다.자, 그럼 Codeigniter 프로잭트 하위에 웹팩을 포함시켜 Hello World까지 가는 짧은(?)여정을 시작해봅시다.Hello world로 가는 여정Node, npm 설치맥에서도 유사한 명령어로 제작할 수 있도록 CMD 위주로 진행하겠습니다. 먼저, 여기를 클릭해 Node를 설치합시다. 8.11.3 LTS버전으로 진행했습니다.맥에서는 Homebrew를 통해 간편하게~brew install node 설치 확인npm 잘 설치되었네요.web pack 폴더 생성 및 이동mkdir webpack cd webpack nom init으로 초기화npm init webpack, vue, babel 설치npm install -D webpack webpack-cli webpack-dev-server npm install -D vue-loader vue-template-compiler npm install -D babel-core babel-loader babel-preset-es2015 여기서 VUE는 설치하지 않습니다! 왜냐하면 VUE.js는 로딩만 하면 되고 필요하지 않습니다! (읭?) VUE는 Codeigniter view에서도 사용해야 하기 때문에 해당 view에서 import 해줍니다. 따라서 VUE 컴포넌트가 들어가는 시점에는 이미 전역에 vue.js 가 있습니다. 따라서 굳이 각 모듈마다 VUE를 import 했다가 webpack 설정에서 다시 vue.js를 제외할 필요는 없습니다.VUE와 template 태그를 로딩할 수 있는 로더도 설치하고, 트랜스컴파일을 위한 바벨, IE9를 지원하기 위한 es2015프리셋도 함께 설치합니다.webpack 빌드명령어 package.json의 script부분에 추가"scripts": { "build": "webpack --mode production", "build-dev": "webpack --mode development",   } 이제 VUE를 빌드할 명령어를 작성합니다. 위처럼 두 가지 명령어를 제작해두면, 추후 env를 통해 webpack.config.js를 분기시켜 원하는 환경으로 빌드할 수 있습니다. 또한 production 모드로 빌드할 땐 자동으로 옵티마이저 - uglify 내장 플러그인이 적용되어 익숙한 min.js형태로 빌드되며 development를 빌드할 땐 사람이 알아볼 수 있는 형태로 빌드되고, debugger 코드 또한 살아있습니다.weboack.config.js 작성const { VueLoaderPlugin } = require('vue-loader'); module.exports = {   entry: {     HelloWorld: './src/main.js'   },    module: {     rules: [       {         test: /\.vue$/,         loader: 'vue-loader',       },       {         test: /\.js$/,         loader: 'babel-loader',       }     ]   },    resolve: {     alias: {       'vue$':'vue/dist/vue.esm.js'     }   },    plugins: [     new VueLoaderPlugin()   ]  } webpack.config.js 가 없다면 생성한 후 위와 같이 작성합니다..babelrc 작성{     "presets": ["es2015"] } 테스트용 파일 작성1)main.js 작성import HelloWorld from './HelloWorld.vue' Vue.component('hello-world', HelloWorld); 2)HelloWorld.vue 작성 [removed] export default {   name: 'app',   data: () => {     return {       word1: 'Hello',       word2: 'World'     }   }  } [removed] 테스트 빌드npm run build-dev 빌드를 할 땐 기본적으로 ‘/dist/’ 하위에 소스코드가 떨어집니다. 자, 여기까지 진행하셨다면 폴더 구조는 다음과 같을 것입니다.지금까지 진행한 파일 모습입니다.뷰 컴포넌트가 잘 제작되고 등록되는지 확인하려면 기본 빌드 폴더인 dist 폴더에 Test.html을 작성해 브라우저로 열어봅시다.확인용 html 파일 작성<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>VUE Test</title>     <!-- VUE 플러그인 -->     [removed][removed] </head> <body>                     [removed][removed]     [removed]         new Vue({             el: '#vue'         })     [removed] </body> </html> 잘 나옵니다.정상적으로 VUE가 적용된 것을 확인합니다.코드이그나이터 설치이제 코드이그나이터 프로젝트 내부에서 VUE 컴포넌트를 출력해보기 위해 코드이그나이터 프로젝트를 생성합시다. 먼저 Codeigniter와 XAMPP를 다운로드 받습니다.Codeigniter 받으러 가기XAMPP 받으러 가기프로젝트 폴더 하위에 Codeigniter 프로젝트용 폴더를 생성합니다.mkdir codeigniter-with-vue-webpack cd codeigniter-with-vue-webpack 다운받은 Codeigniter를 해당 폴더에 압축 해제하면 Codeigniter 설치가 끝납니다.XAMPP 설치 및 DocumentRoot 변경XAMPP를 설치하고 DocumentRoot를 테스트 프로젝트 폴더로 설정한 뒤 아파치를 실행합니다.Codeigniter 프로젝트가 생성되었고, 서버 실행이 완료되었습니다. webpack 폴더를 Codeigniter 프로젝트 하위로 이동node-modules는 너무 크기 때문에 기본 파일만 복사하고, npm install로 설치합니다.Codeigniter에서 VUE를 사용하기 위한 webpack dist설정기존의 프로젝트에서 스크립트를 모아두는 폴더 하위로 빌드 결과 파일을 보내기 위하여 webpack 빌드 시 dist 폴더가 아닌 /application/scripts/vue/hello_world 하위로 빌드 결과 파일이 생성되도록 설정합니다.// 기존 module.exports = {   entry: {     HelloWorld: './src/main.js'   },    //... 생략 } // 변경후 module.exports = {   entry: {     '../../application/scripts/vue/hello_world/HelloWorld.js': './src/main.js'   },    //... 생략 } Codeigniter의 load->view 기능을 활용하여 파일 작성1)header.php// application/views/common/header.php <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>VUE Test</title>     <!-- VUE 플러그인 -->     [removed][removed] </head> 2)실제 view// application/views/vue/hello_world/vueTestPage.php <?php $this->load->view( 'common/header' ); ?> <body>                 [removed] [removed]     [removed]         new Vue({             el: '#vue'         })     [removed] </body> <?php $this->load->view( 'common/footer' ); ?> 3)footer.php// application/views/common/footer.php </html> 실제 프로젝트 구성과 유사하게 header, body, footer로 나누어 파일을 작성해봅니다. 실제로는 더 복잡하지만 이 정도만 나누겠습니다.Codeigniter 테스트용 컨트롤러 작성// application/controllers/Vue.php <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');   class Vue extends CI_Controller {      public function index()     {         $this->load->view('vue/vueTestPage');     }  } 정말 심플(?)한 테스트용 파일 작성이 모두 끝났습니다! 이제 잘 작동하는지 확인해볼까요?코드이그나이터에서 helloworld 출력짜잔이번엔 문제의 IE에서 확인해봅시다.IE9.0 환경에서 확인IE에서도 무사히 출력되는군요. 이제 코드이그나이터 환경의 프로젝트에서도 IE까지 지원하며 무사히 VUE를 사용할 수 있게 되었습니다! (시간이 없어서 가상머신에 IE9가 설치된 윈도우7까지 테스트하진 못했습니다!) 모든 작업이 완료한 후, 파일 폴더 구조는 아래와 같습니다.붉은 네모 부분이 실제로 제작하거나 수정한 파일들입니다.Conclusion여기까지가 Codeigniter 프래임워크 환경에서 webpack + vue를 사용하기 위한 웹팩의 설정 과정 및 테스트 결과였습니다. php 서버를 사용해야 하기 때문에 webpack-dev-server의 핫리로드 기능을 사용하지 못하는 건 매우 안타까운 일입니다. 하지만 짧은 시간에 신기술을 도입하면서도 수많은 리스크를 회피할 수 있다는 건 나쁘지 않은 선택이라 생각합니다.위의 웹팩설정을 조금만 활용한다면 다른 프레임워크 프로젝트에서도 무리없이 VUE를 사용할 수 있을 겁니다! 비슷한 고민을 하셨던 개발자님들… 집에 가기 전 말고 오전에 Webpack을 설치해보세요. 안 그러면 저처럼 집에 못갈 수도 있으니까요!참고.gitignore 작성, index.php 제거 등은 내용에 포함하지 않았으며, 아래의 링크로 자세히 알 수 있음.Codeigniter index.php 없애기글강원우 과장 | R&D 개발2팀[email protected]브랜디, 오직 예쁜 옷만 #브랜디 #개발자 #개발팀 #인사이트 #경험공유 #PHP

기업문화 엿볼 때, 더팀스

로그인

/