스토리 홈

인터뷰

피드

뉴스

조회수 1768

Infrastructure dashboard

와탭랩스는 IT 서비스를 운영하는 개발팀과 운영팀에 도움이 되는 솔루션과 서비스를 만드는 스타트업입니다. IT 서비스를 잘 운영하게 위해서는 Infrastructure의 전반적인 상황을 항시 체크할 수 있어야 하는데요. 이런 기능을 하는 대표적인 화면이 대시보드 입니다. 최근 와탭랩스는 Infrastructure 모니터링 서비스에 대시보드를 넣는 작업을 진행하고 있는데요. 와탭랩스는 대시보드를 통해 Infrastructure를 운영하는 개발팀과 운영팀에 어떻게 도움을 줄 수 있도록 할 것인지 소개하겠습니다. 1. IT 서비스 운영에 사용된 인프라 자산 현황을 알아보자지금 회사에서 사용하는 서버의 대수를 알고 계신가요? 현재 동작하는 서버는 몇대인지 혹시 죽어있는 서버가 있는지 등에 대한 정보는 운영팀에서 항상 체크하는 정보입니다. 하지만 개발팀에서는 잘 모르는 정보이기도 하죠. 이런 기본적인 정보가 대시보드에 나온다면 평소 서비스를 운영하는 감을 잡는데 도움이 됩니다. 이런 정보들은 간략한 수치로도 표현할 수 있는데요. 우리는 아래와 같은 데이터를 수집할 수 있습니다. 서버 기본 정보 (inactive servers / all servers)우리가 사용하는 총 서버의 수자와 비활성화된 서버의 숫자는 우리가 항상 알고 있어야 하는 정보입니다.운영체계별 서버 정보 (Linux / Windows / Unix)운영체계를 섞어 사용하는 경우에는 운영체계에 따라프로젝트가 나눠지기도 합니다. 그렇기 때문에 운영체계별로 서버의 총량과 비활성화된 서버 정보를 알면 도움이 됩니다. 프로세스 수프로젝트의 프로세스 수는 일정한 경우가 많습니다. 전체 프로세스의 숫자가 변경된다면 서비스의 운영 상황에 대해 의문을 가져야 합니다. 이벤트 개수24시간동안 발생한 전체 이벤트의 개수와 아직 해결하지 못한 이벤트의 개수를 보여줍니다. 하루동안 얼마나 많은 이벤트가 발생하는지 그리고 아직 해결하지 못한 이벤트가 있는지 알수 있습니다. 디스크 사용량/전체 용량디스크 사용량은 일반적으로 큰 변화를 가지지 않습니다. 디스크 사용량이 평소와 다르다면 서비스의 장애가 발생했거나 발생할 가능성이 높습니다. 메모리 사용량 / 전체 용량메모리 사용량은 일반적으로 큰 변화를 가지지 않습니다. 메모리 사용량이 평소와 다르다면 서비스의 장애가 발생했거나 발생할 가능성이 높습니다. 수치 데이터의 예 2. 서비스를 구성하는 인프라의 CPU 흐름 전체를 알아보자 CPU 사용량은 변화량이 많은 지표입니다. 변화량을 비교하는 챠트로는 라인 차트가 가장 많이 쓰이지만 라인 차트는 개수가 많아지면 전체 상황이 보이지 않는 문제점을 가지고 있습니다. 또한 실시간으로 추가되거나 삭제되는 인프라가 생기는 클라우드 인프라 상황에서 라인챠트는 표현의 한계를 가지고 있기도 합니다. 이런 문제를 해결하기 위한 방법으로 아래와 같은 온도 차트를 사용할 수 있습니다. 온도 차트는 단위 영역에 밀도에 따라 색상으로 깊이를 표현하는 방식입니다. 최근 많은 양의 데이터를 표현하는 방식으로 많이 사용되고 있습니다. 온도 차트의 예3. 경고가 발생했는지 또는 해결 되었는지 알고 싶다.  CPU 사용량이 설정치 이상으로 높아지거나 디스크 사용량이 높아지거나 프로세스가 사라지는 등 다양한 상황에 대한 이벤트가 발생할 수 있습니다 이런 상황을 쉽게 확인할 수 있다면 서비스 운영 상황에 도움이 됩니다. 이벤트 관리의 예이런 스토리를 기반으로 와탭랩스에서 대시보드를 기획하고 있습니다. 개발자와 디자이너가 함께 토론하고 논의하면서 화면과 스토리를 더 다듬게 되면 첫번째 화면이 나올 예정입니다. 아래는 기획과정에서 나온 화면 리소스 입니다. 아직 기획 단계이기는 하나 첫번째 대시보드가 완성되면 이 페이지가 메인으로 올라갈 예정입니다. 대시보드는 데이타의 종류와 위치등을 수정할 수 있으면 좋지만 우선은 고정형으로 개발하여 제공할 예정입니다. 이번 대시보드는 서비스 첫번째 의미가 강한 메인 화면의 성격에 더 초점을 맞추고 있습니다. 아직 몇몇 논의되는 사항이 많은 화면이지만 빠르게 개발하여 가능한 이른 시일에 소개드리도록 하겠습니다. #와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 1826

소프트웨어 개발자에게 성공이란...

소프트웨어 개발자들이 생각하는 ‘성공’이라는 단어와 키워드에는 어떤 것들의 의미를 포함하고 있을까? 한편으로는 단편적이고 획일적인 ‘성공’이라는 단어에 너무 많은 개발자들이 매몰되어 있는 것 아닌가 하는 생각을 해본다. 필자 스스로 실무경력 20년을 넘겨서 소프트웨어 개발을 하고 있는 경험을 바탕으로 주변의 성공한 개발자들에 대해서 혼자 생각해 보았다.일반적으로 의미의 ‘성공’이라는 것이 무엇을 의미하는 것인가에 대한 정의는 이번 칼럼의 말미에서 이야기하도록 하자. 정말 많은지 모를 대한민국에서 성공한 개발회사나 개발된 서비스들을 살펴보는 것부터 시작을 하는 것이 정답인지는 필자도 잘 모르겠다. 성공적인 서비스나 소프트웨어, 프로그램은 세상에 선보인다는 것. 그러한 것을 만들어낸 순수한 아이디어나 원천기술로 무장한 기술로 축적되었고, 그 아이디어를  뛰어넘어, 새로운 기술이라고 할 수 있는 것을 보유한 제품이나 상품들이 얼마나 되는지에 대해서부터 냉정하게 필자는 잘 모르겠다라고 먼저 인지하고 넘어가자. 아니, 다시 말하자면, 냉정하게 국내에서 그런 것을 본적이 별로 없는  듯하다.더욱더 삐딱하게 이야기하자면, 국내에서 성공한 개발 서비스들은 대부분 아류작이거나 남의 아이디어를 도용한 제품과 서비스들이 대부분이 아닌가라고 생각한다. 심지어는 특정 솔루션 시장은 오픈소스를 그대로 제품에 반영해 두고서는 자신의 제품인 것처럼 위장하는 사례까지 보이고 있으니, 과연 대한민국 소프트웨어 시장은 과연 얼마나 ‘성공’이라는 키워드를 그대로 사용해도 되는지에 대해서 매우 의문시된다.(물론, 필자의 삐딱한 시선에서만 그렇게 보일지도 모른다.)대한민국의 소프트웨어 시장에서 1위를 지키고 있다고 하는 서비스와 제품들이 되려면 어떻게 해야 하는가?. 삐딱하게 이야기하자면, 오로지, 대한민국에서 성공한 개발회사나 개발자가 되려면, 창의적인 아이디어나, 독특한 아이디어로 무장하는 승부수를 던지기 보다는, 해외의 서비스 중에 알차고, 괜찮은 것들에 대해서 관심을 가지는 것이 중요하다고 생각한다. ( 그래서, 영어공부를 잘해야 하는지도 모르겠다. )필자가, 대기업과 신규사업기획을 할 때에 작업하는 내용을 보고서는 경악을 금치 못했던 경험을 한적이 있다. 정말 상당한 컨설팅 금액( 수십억을 넘긴 비용 )을 지불해서, 대기업이 유명한 컨설팅업체를 통해서 신규사업에 대한 기획과 아이디어에 대한 컨설팅을 받는 것에 전문가의 한 사람의 참여했었다. 그런데, 그 중요한 작업의 모티브는 해외에서 이미 성공적으로 안착한 서비스에 대한 분석과, 한국에서의 서비스 시에 벌어질 일에 대해서 예측을 하는 일을 하고 있었다는 점이다. 새로운 아이디어가 아니라는 점이다.물론, 성공한 서비스를 도입해서, 로컬 화한다는 것 또한 매우 어려운 일이라고 생각하지만, 대부분의 새로운 기획이나 신규 서비스에 대한 작업들의 대부분을 이런 식으로 진행한다는 이야기를 들었을 때에 받은 충격은 정말 놀라운 경험이었다, 물론, 지나고 나서 생각해보니, 그렇게 놀랄만한 경험도 아니었는지 모르겠다. 대부분의 대기업들이 이런 식으로 한다는 이야기를 듣고 더 놀라기는 했지만. 물론, 이렇게 로컬화 한다는 것 자체도 대단한 도전이고 어려운 점이라는 것은 인정한다고 하지만, 이런 로컬화와 아류작에 대해서 비판적인 시야를 가진 필자의 생각은 그렇다.성공한 서비스들은 대부분 아류작들이다?냉정하게 국내에서 성공한 대부분의 서비스들은 아류작들이고, 복제본들이고, 독창적인 아이디어보다는 해외 서비스를 대부분 국내에 안착한 서비스라고 생각한다. 심지어 독창적인 mp3 플레이어마저도, 아이팟의 생태계가 한층 더 발전적인 시장을 창출했으니, 국내에서 만들어진 디지털적인 요소들 중에 독창적인 것이 얼마나 있는가?필자는 생각한다. 예술에 있어서 복제와 창작의 차이는 매우 크다는 것을. 물론, 소프트웨어 개발이 이런 예술에 비견될 정도의 가치를 부여해서 그런 것 만은 아니다. 소프트웨어 개발은 아이디어와 구현하고자 하는 추진력과 열정이 결합되어져서 만들어지는 최고의 가치 구현을 위한 세계이기 때문에 그렇게 생각할 뿐이다.필자가 좋아하는 만화 중에 ‘맛의 달인’이라는 만화에 나온 표현을 그대로 옮기자면 다음과 같은 장면이 나온다. 프랑스의 유명한 요리를 그대로 일본에서 구현하지만, 그 요리에 대한 평가는 ‘프랑스의 요리를 그대로 구현한 요리이다’. ‘매우 아름답지만 최저의 요리’라는 평가를 받는다. 그러한 최저의 요리라는 평가를 받은 이유는 ‘로컬화 한다는 것은 실정에 맞게 고치고, 연구 개발한 맛이라면 완벽하겠지만. 너무도 프랑스 요리와 똑같이 만든 것은 처절한 아류라는 점이다. 지금 먹은 요리에는 프랑스 요리사의 모습이 그대로 남아있다는 점. 원형이 프랑스의 것을 그대로 답습했다는 것.오리지널을 복사했다는 냉정한 평가는 정말 명확하다. 요즘 가장 국내에서 최근에 성공한 서비스를 이야기한다면, 카카오톡과 애니팡을 예로 들 수 있겠다. 다른 사람들은 어떻게 평가할지 모르지만, 정말 대단한 성공을 가진 것은 사실이다. 하지만, 둘 다 원형을 그대로 복사했을 뿐, 새로운 것은 아무것도 없다는 점이다. 아니, 오히려. 기존의 원형을 대한민국의 안 좋은 통신사의 서비스와 결합한 케이스라고 평가를 해야 정확하지 않을까 한다. 원형을 오히려 퇴보시킨 서비스라고 평가하고 싶다.카카오톡은 WatsApp을 그대로 복제했다. 대표적으로 등록되어진 전화번호로 연계하는 원형의 아이디어를 그대로 받아들였다. 하지만, 카카오톡의 새로운 신규 비즈니스 모델인 게임센터는 자체적인 생태계를 만들어서 통제하려 하는 기존의 통신사의 방식과 그다지 차이가 없다고 보인다. 뭐, 돈을 벌어야 하는 기업의 입장을 반대하는 것이 아니다. 단지, 필자의 삐딱한 시선으로는 진보를 위한 선택이 아니라, 퇴보를 위한 선택이었다는 점이 불편할 뿐이다.애니팡도 마찬가지이다. 기존의 게임방식을 그대로 복제했다. 그리고, ‘하트’라는 이름으로 무분별한 ‘스팸’을 활성화해서, 기존 통신사들이 SMS에서 얻어들이는 대량 SMS 발송을 통한 이익을, 그대로 실현한 점이다.물론, 카카오톡이나 애니팡의 ‘이익 실현 구조’는 매우 성공적으로 국내에 론칭한 것은 사실이고, 이러한 구조로 ‘돈’을 벌어야 한다는 점이 매우 안타까울 뿐이다. 개인적으로는 ‘국내’에서는 어느 정도 ‘돈을 버는 성공은’할 수 있지만, 해외에서까지 성공적으로 론칭할 것인지는 조금 의심스럽다. ( 어차피, ‘돈’을 벌면 성공이라는 관점으로는 매우 대성공이다. )넥슨의 카트라이더와 마리오 카드와 같이 일일이 나열하기에는 너무도 많은 사례들이 있어서 굳이 더 나열하지 않겠다.다만. 정말 중요한 것은 복사보다는 진짜가 더 좋다는 점이다. 가령, 오리지널이 존재하는 영역이나 예술과 같은 고부가가치의 영역에서는 ‘화가나 작가가 다른 사람의 작품을 흉내내면  웃음거리밖에 되지 않는다’는 점을 이야기하고 싶다. 필자 개인적으로는 ‘그런 웃음거리를 통한 수익실현’을 그렇게 높게 평가하고 싶지 않기 때문이다.대표적으로 통신사는 ‘스팸’과 ‘보이스 피싱’을 해결하지 못하는가? 에 대해서 필자는 그렇게 생각한다. ‘대량 SMS수입’을 포기하지 못하고, ‘전화번호를 통한 대량 통화의 수익’을 포기하지 못하는 구조적인 문제 때문에 그렇다고 생각한다.과거에 문제가 된 iOS6로 업데이트가 되면서 SKT 아이폰4S에서 발생한 전화번호 호출의 문제, ‘112 신고가 안 되는 아이폰’이라는 기사와 사건에 대한 문제의 근본적인 원인은 SKT가 국제표준 방식을 따르지 않아서 발생한 문제라는 것을 모르는 사람들이 정말 많다. 이 문제를 더 파고들어가면, 부당한 SMS수입을 얻고 있는 국내 통신사들의 부도덕한 점도 드러난다. 2003년 이후 3G 서비스(WCDMA)가 도입되었지만, 문자 메시지 국제표준이 기존의 80 byte에서 140 byte로 늘어났지만, 정작 통신사들은 국제표준규격을 지키지 않으면서 연간 수백억의 이익을 부당하게 얻어냈다. 다만. 아이폰4s 출시 당시 KT는 140바이트를 맞추었지만, SKT는 아직도 80 byte였다는 점을 예로 들고 싶다.국제표준을 따르거나, 해외의 서비스가 ‘돈’이 되는 것에는 빠르지만, ‘돈’이 안 되는 기준에는 미온적이고, 대처가 느린 것에 대해서는 참으로 훌룡(?)한 성공적인 방법이라고 평가를 굳이 필자와 같은 주변 사람이 할 필요가 있을까 한다. 그런 훌륭한 평가는 비싼 컨설팅 비용을 지불한 뛰어난 전문가들이 할 것이기 때문에...내 주변에 성공한 개발자와 성공한 벤처 사업가...성공한 개발자. 고급 승용차를 몰고, 출근하는 개발자의 모습을 본다면, 성공한 개발자의 향기를 느낄 수 있을까? 물론, 일반적으로 그럴 수 있다고 생각한다.자본주의 사회에서 ‘돈’은 그 사람을 평가하는 가장 기본적인 ‘수단’이기 때문이다. 성공하지 못한 필자는 아니지만, 필자 주변에는 고급 승용차인 BMW나 벤츠를 직접 몰고 다니는 성공한 개발자들이 여럿 있다. 그리고, 상당히 많다. 사업을 하는 사람으로부터, 프리랜서인 사람까지 매우 다양하다.분명, 그들은, 자신만의 서비스와 제품을 실현하였고, 시장에서도 안정적인 자신만의 브랜드를 확립하였고, 후배들로 존경을 받고 있으며, 직원들에게 비전과 꿈을 주고 있으며, 새로운 기술과 시장에 대해서 언제나 도전하고 있는 사람들이 있다.그들은 충분히 ‘성공’한 사람들이다.‘복제’와 ‘아류작’이 아니더라도. 독특한 자신들만의 서비스와 제품을 구현하여 성공한 개발자들이 분명 존재한다.그들의 성공요인을 주변의 사람으로서 살펴본다면, 몇 가지의 요인이 있다고 정의할 수 있다. 그것들을 필자의 주관적인 생각으로 정리해보면, 크게 4가지 정도로 정리할 수 있다고 본다.하나. 그들은 뛰어난 개발자는 아니었다.그들은 아주 탁월한 능력을 소유한 개발자들은 아니었다는 점이다. 그리고, 아주 뛰어난 학벌을 가진 개발자들도 아니었다. 개발자 동호회에서 만난 친구도 있고, 직장생활이나 사회생활에서 만난 사람도 있었지만. 그들은 아주 탁월한 재능을 지녔거나, 엄청난 코딩능력, 뛰어난 직관을 지닌 사람만은 아니었다.순수한 개발 능력만 놓고 본다면, 오히려, 뒤처지는 개발자들이었는지도 모른다. 하지만, 뛰어난 개발자들이나 아이디어를 가진 사람들과 친하게 지냈으며, 그들의 도움을 자연스럽게 얻어내는 소통의 달인은 아니었지만, 개발자 커뮤니티에 매우 즐겁게 활동을 하던 사람들이었다.둘. 그들은 우직하지만, 묵묵하게 자신의 상품과 아이디어를 다듬었다.그들은 하나의 아이디어가 실현되는 것을 쉽게 포기하지 않았다. 사업을 하기 전에는 그 아이디어를 실현하기 위해서 애썼고, 속한 회사가 아이디어에 대해서 낮은 평가를 하는 것에 대해서도 크게 실망하지 않았다. 오히려, 반대를 해도 해당 서비스와 제품, 기술에 대한 애정이 정말 높았으며, 그것을 실현하려고 매우 애썼다.처음에는 언제나 소프트웨어는 단순한 것부터 시작한다.그 단순한 것을 꾸준하게 다듬고, 소프트웨어에서 제품으로 다듬어서 시장에서 가치를 인정받을 수 있도록 수년 이상을 투자하고 노력해야만 얻어진다. 그것은 스티브 잡스도 똑같았다. iOS는 하루 이틀 만에 나온 소프트웨어가 아니기 때문이다.심지어, 몇 년 동안 밥을 굶더라도, 자신이 생각하는 가치를 실현하기 위해서 포기하지 않고 도전했던 우직한 도전이 오히려 성공을 만들어 내었다. 분명, 훌륭한 소프트웨어는 뛰어난 기술로 만들어지는 것만은 아니다는 것을 요 근래에서야 필자도 느낀다.필요한 가치가 적정한 가격에 구현되어진 것이 정말 필요하다는 점이다. 뛰어난 기술이 뛰어난 제품을 만드는 것이 아니라, 뛰어난 제품이 뛰어난 기술을 만든다는 것이다. 그것이 사용자들로 하여금, 또 다른 가치를 얻을 수 있는 기능을 제공한다는 것에 대해서 굳이 설명하지 않더라도, 그들은 그 아이디어와 생각을 실현하기 위해서 자신만의 길을 걸었다.정말 우직할 정도로... 필자 주변의 그들은, 몇 년을 일 년에 몇백만 원을 벌더라도, 그 꿈을 포기하지 않았다.셋. 시장과 세상의 시선을 그렇게 두려워하지 않았다. 자신의 ‘가치’와 ‘비전’을 실현했다.자신의 아이디어와 자신의 서비스, 제품을 지키기 위해서 약간의 주변 사람들에게 욕을  얻어먹는 것을  두려워하지 않는다. 필자가 아는 어떤 기업은 시장에서는 냉혈안이라는 말도 듣고, 불법 복제된 제품에 대해서는 가차 없는 소송도 불사하는 어떤 기업을 알고 있다. 하지만, 그 회사와 그 사장에 대해서 필자는 비난하지 않는다. 왜냐하면, 그는 기업 내부의 직원들에게는 절대 급여를 밀리지 않고, 야근을 시키지 않는 최고의 사장이었기 때문이다.시장과 타인에게는 가차 없지만, 자신이 생각한 비전을 실현한 회사를 만들기 위해서 언제나 최선을 다하는 사람이었을 뿐이다. 그리고, 자기 것을 지키기 위해서 애를 썼고, 직원들과의 거리도 언제나 적절하게 유지했다. 냉정하게 기업과 사업이라는 것은 자선사업이 아니라는 것을 잘 알고 있었다. 충분하게 돈을 벌고, 외제 승용차를 사장은 타고 다니지만 ( 외제 승용차를 타는 것도, 대한민국은 간단하다. 법인세를 충분하게 낼 정도로 수익이 생기면, 그 수익으로 차를 리스해서 타면 간단하다는 대한민국의 세법 구조 때문이다. ), 모든 직원들에게 그 이익을 100% 나누어주지는 않는다. 직원은 직원일 뿐이니까.그들은 회사의 재정이 힘들어지면 소속된 직원을 힘들기 전에 내보낼 줄도 알고, 필요하다면... 해고도 그리 어렵지 않게 결정하는 사람도 있다, 영업기밀을  들고나간 직원과 소송도 불사했다. 차라리, 친구와 따로 술을  마실지언정, 직원들과의 ‘관계’는 냉정하고 쿨한 관계를 유지했다. (물론, 그렇지만. 인간관계가 깨어지는 것을 매우 괴로워하는 사람들이다. 다만, 아래 직원들에게 속시원히 이야기를 못할 뿐이다. )넷. 필요한 기술자나 기술은 기필코 얻으려 노력했다.그들은 자신이 부족한 점을 잘 이해하고 있었다. 부족한 것을 오히려, 더 널리, 많이 이야기를 하였다. 그리고, 그것을 커버하기 위해서 매우 많은 노력을 한다. 다 잘하고자 하는 팔방미인이 되는 것이 아니라, 자신이 부족한 점을, 자신이 가장 잘하는 것으로 커버하려 애쓴 것이다. 전문적인 기술을 소유한 사람에게 도움 요청하는 것을 부끄러워하지 않고, 도와준 사람에게 충분한 대우나 접대를 잊지 않았다. 그래서, 그들이 도와달라고 하면, 주변의 전문가들이 아낌없이 그를 도와준다.그 이외에서 그들은 그렇게 ‘성실’하게 일하는 친구들은 아니었다. 실제, 사장이었던 그들이 직원의 입장으로 회사를 다닐 때에는 근태 문제로 지적을 받은 친구들도 꽤 많다는 점이다. 아마도, 사업이나 자신이 좋아하는 일을 하는 것과, 어떤 일이 주어진 상태에서 일을 하는 것은 분명 다른 지도 모르겠다. 직원일 때에 불성실하지만, 자신의 일을 할 때에 성실한 것은 전혀 상관관계가 없어 보인다. 한편으로는 ‘사장’이나 ‘자신의 일’을 하는 사람의 경우에는 특별하게 ‘근무시간’이라는 것 자체는 큰 의미가 없다는 점이 더 정답일 것이다. 하여간, 그들은 성공한 개발자들이고, 성공한 기업인이 되어 있었다. 자신만의 제품이나 서비스를 만들면 자연스럽게 ‘사장’이 되어버리는 것이 소프트웨어 업계의 현실인 듯하다.그렇다면, 대한민국에서 ‘성공’이란 ‘돈’을 의미하는가?강남의 최고급 아파트와 외제 승용차가 성공을 의미할까?자신의 뛰어난 기술력으로 커뮤니티에서 인정받고, 유명해진 명예를 얻는 것이 성공을 의미할까? 다른 사회현상을 생각하면서 다시 한번 비교해보자.요즘 개발자들도 오디션 프로에 영향을 받은 듯하다. 요즘 연예계 지망자들이나 배우나, 가수를 꿈꾸는 친구들이 선배나 멘토들에게 묻는 것이 언제나 똑같다고 한다.그것은 ‘빠르게 성공’하고 ‘빠르게 명예’를 얻는 방법이 무엇이냐 묻는 것이다.어렵고 복잡하고, 길게 걸리는 방법은 무시하고, 오디션 프로에서 1등을 해서, 빠르게 성공하는 방법만을 생각한다고 한다.물론, 그 방법도 있을 것이다.소프트웨어의 세계에도 똑같은 방법이 있다. 대표적인 방법이 유명대학을 가서, S 멤버쉽이 되고, 대기업에 입사해서 경력을 쌓은 다음, 해외의 서비스를 적당하게 분석하다가, 성공적으로 론칭한 서비스를 재빠르게 국내에 도입해서 성공에 이르게 하는 방법이 아마도 가장 빠른 방법일 수 있겠다.물론, 이 방법으로 ‘성공’을 쟁취하려 하는 개발자라고 하더라도. 비난하지 않는다.분명, 그 길은 대다수 ‘성공’이라고 부른다. 하지만, 그 길을 선택하고 집중하는 것 또한 매우 어렵고 힘든 길이다. 선택한다고 얻을 수 있는 길도 아니다.가령, 이 글을 읽는 독자가 학생이라면. 가장 먼저 명문대학을 가는 것부터 시작해야 할 테니, 당장, 이 내용을 덮어버리고, 국영수를 공부하는 것에 몰두해야 하기 때문이다.사실, 가장 넓게 알려진 성공으로 가는 길은 가장 가기 어려운 길인지도 모른다. 경쟁이란 정말 어렵고 힘들 것이라는 것을 잊지 말자.본론으로 다시 돌아와 보자. 개발자로서 '성공'이란 무엇을 의미하는가? 아니, 개발자로서 비전을  갖는다는 것은 무엇을 의미하는가?  원천적으로 개발자의 삶이란 어떻게 살아야 하나요라고 묻는다면,이 문제는 정말 어렵고, 사람마다 다르기 때문에 최선을 다하는 것이 정답이라라는 교과서적인 답변만 늘어놔야 하는지도 모르겠다.이점에 대해서는 이제는 폐간했지만 오랫동안 개발자들의 벗이 되었던 마이크로소프트웨어 잡지에 대해서 원망을  슬쩍해보자.그것은, 나에게 ‘정말 대단히 큰 재미’를 선사했다는 것이 나에게 가장 처음 다가온 충격이었는지도 모른다. 처음에 가진 꿈은 그냥, ‘소프트웨어 개발’을 통해서 삶을 영유할 수 있는 것만으로 나는 행복했다는 점이다. 그래서, 이 소프트웨어의 세계로 진입하게 된 마이크로소프트웨어에 대해서 원망을 해야 하는지도 모르겠다.하지만 필자는 소프트웨어로써 ‘개발자로서 성공’을 하기 위해서, 이 직업과 삶을 선택한 것이 아니라, ‘개발자로 살기 위해서’이 삶을 선택한 것이었다. 나이를 먹고, 무언가를 목표로 살아온 경험을  되돌아본다면, ‘돈’과 ‘명예’를 선택하지 않았을 때에, 오히려, ‘돈’과 ‘명예’를 얻지 않았는가 하다. 오히려, ‘돈’을 선택하던 시기에 ‘돈’을 더 많이 잃어버린 경험도 가지게 되었다.이제는 주변을  되돌아보면, 필자는 꽤 넓은 스펙트럼을 가지게 되었다는 것을 느끼게 된다. 한때는 고인이 되셨지만 대통령이셨던 분부터, 수천억을 소유한 재벌 총수, 의료재단과 대학법인을 소유하신 분, 병원의 원장님들을 비롯한 분들을 비롯하여, 출판계, 영화계, 물론. 다수의 소프트웨어 개발자들까지. 매우 넓은 사람 관계를 만들어본 것 같다.그중에 소프트웨어 개발자들은 참 착하고 바보스러운 사람들이 많은 것 같지만, 한편으로는 너무도 욕심이 많은 사람들이 존재하는 참, 신기한 동네이다.그리고, 여러 계층을 경험해보니. 모든 계층은 똑같이 피라미드 구조를 가지고 있다는 점이다. 대부분 다 똑같았다. 하층의 사람들은 싼 가격에 노동력과 지식을 제공하고, 상위 레벨에서는 적절한 대우 이상과 재미있고 신기한 일들을 많이 한다는 점이다. 이 부분은 어느 계층이나 똑같다.대표적으로 출판일을 경험했을 때에 자신의 이름이 들어간 편집장이 되는 사람과, 그것을 목표로 기획자로 일하는 직원의 급여 수준이나 처우, 대우는 정말 최고급 아키텍트와 SI 개발자를 비교하는 것 이상으로 그 상대 감은 소프트웨어 개발세 상의 것 이상으로 매우 컸다.행복한 개발자라고 한다면, ‘개발이 정말 재미있고’, ‘개발도 잘하고’, ‘소프트웨어 개발 피라미드의 상층부의 일’을 하고 있다는 사람이 있다면. 그 사람은 정말 행복할 것이다. 뭐, 그런 사람은 이 글을 읽고 있지도 않을 것이다.그러나, 개발이 재미있지 않거나, 개발을 뛰어나게 잘하지도 못하고, 소프트웨어 개발 피라미드의 하층부에서 일하고 있다면, 어떻게 생존해야 하는 가에 대해서 정말 심각하게 고민해야 한다.이 글을 읽는 독자가 이제 개발자의 길을 시작한 사람이라면 고민해라, 소프트웨어 개발을 비롯한 모든 전문적인 직업들은 새로운 것을 배우고, 익히고, 소모하면서 계속 변화되는 것을 즐길 줄 알아야 재미있는 직업이다. 그런 것이 아니라면, 정말 힘들고, 피곤하고 어려운 것이 전문직과 같은 직업이다. 만일 그런 것이 힘들다면 다른 일을 알아보는 것이 현명하다.소프트웨어 개발자들과 가장 비슷하게 일하는 웹디자이너들의 푸념이 있다.‘낮은 급여에 야근은 허구한 날, 거기에. 불투명한 미래’에 대한 그들의 이야기를 들으면서, 흔히 소프트웨어 개발자들은 그 질문에 답변한다. ‘너희들은 모니터라도 크지’라고. 대부분의 프로젝트들은 ‘분석’에 의해서 ‘일정’을 만들지 않고, ‘일정’을 통해서, ‘품질’을 선택한다고 봐야 한다.‘정말 하고 싶은 것이 무엇인가?’개발자들에게 물어보면, 대부분 당황하는 경우가 많다. 이것은 개발자이기 때문에 답변을 못하는 것이 아니라, 자신의 비전이나 꿈에 대해서 명쾌하게 정의하지 못하고 있기 때문이다. 주변의 초보 개발자들에게 이야기하고 싶은 점은...가끔은 수필집이나 여행기, 그리고. 다른 사람의 생각과 꿈에 대한 글을 많이 읽어보라고 권하는 것이다. 그러면, 그 비전과 꿈에 대해서 이야기해달라는 사람들이 꽤나 있고는 하다.문제는 그 비전은 누가 정해주는 것이 아니라, 자신이 생각하거나, 자신이 발견하는 것이 옳지 않냐고 다시 이야기를 해준다. 물론, 이렇게 이야기하는 사람도 있다.‘저는 이번 프로젝트에서 인정을 받아서, 다음 프로젝트를 수행할 때에는 팀장이 되고 싶어요!’라고 이야기할 수 있다. 하지만, 이런 ‘단기적인 비전’을 말하는 것은 아니다. 이런 ‘단기적인 비전’만을 따라가다 보면, 냉정하게 수단만 중요시 여기게 되고, 목적 자체를 잃어버린 인생의 방랑자가 될 가능성이 매우 크다.내가 생각하는 ‘성공’이란 과연 무엇인가?또 하나는, 그 ‘성공’의 목표를 너무 작게 가져도 문제이고, 너무 커도 문제라는 점이지만, 그래도, ‘꿈’과 ‘목표’가 있다는 것 자체가 재미있고, 신기하지 아니한가?‘성공은 자신이 정한 것을 이루는 것’을 의미한다고.그럼 ‘꿈’을 어떻게 정의하나요?1. 10년, 20년, 30년 후의 자신의 모습을 상상해보고 정의해봐라.2. 현재 내가 좋아하는 모든 것들을 적어봐라.3. 내가 가장 잘하고 가장 인정받는 것을 적어봐라.보통은 이렇게 끄적거리다 보면, 무언가가 조금은 구체적인 비전이 나올 수도 있지만, 아무렇지도 않은 것이 나올 수 있다. 하지만, 일단, 끄적이기 시작했다면, 다음번에는 좀 더 잘할 수 있다는 것이 중요하다. 가장 중요한 것은 ‘내가 비전에 대해서 생각하기 시작했다’는 점이다. 일단 작심 3일이라도 중요한 결정이다. 그것은, ‘결정’을 하고 ‘결심’을 하기 시작했다는 것이기 때문이다.일단, ‘써야 한다’. ‘생각은 생각일 뿐이다’주변의 개발자들이 가장 잘 못쓰는 말 중의 하나가 ‘머릿속에 다 있다’라는 말이고, ‘글로 쓰기에 너무 어려운 이야기’이다라는 이야기가 가장 잘못된 것이라는 것을 잘 모르는 경우가 많다.‘머릿속에 다 있다’라는 이야기는 한번 생각은 해봤으나, 결론을 내리지 못하였다는 이야기로 들리고, ‘글로 쓰기 어렵다는 이야기’는 그만큼 정리가 안되고, 그 일에 대해서 잘 모른다는 이야기와 똑같다.10년 20년 특정 도메인에서 일한 베테랑이라고 하는 개발자와 일을 할 때에, 자신이 하는 일은 너무도 복잡하여, 설계도나 다이어그램, 순서도, 타이밍 차트 등을 그릴 수 없다는 사람들이 있다.그들과 이야기하고, 그 업무를 다이어그램과 설계도로 만들어 주어도, 그들은 그것 말고, 설명이 안 되는 그 무언가가 있다고 이야기를 한다. 물론, 필자는 그때에 이렇게  이야기해준다.‘만일 그러한 것이 존재한다면. 그것은 당신만이 생각하는 경험이나 당신이 소중하게 생각하는 가치인지 모른다. 하지만, 그것은 어떤 지식이 되기에 매우 부족한 것일 수 있다. 지식은 설명하기 쉽고, 이해하기 쉬운 것이 지식이다. 설명하기 어려운 경험은 정규화되거나 전달되어지기 매우 어렵다’더 쉽게 이야기하면. ‘쉽게 설명하거나 글자로 남기지 못한다면, 당신은 그것에 대해서 잘 알고 있지 못한 것입니다’비전이나 목표 잡기가 너무 어려워요?!그렇다면, 당장 휴일에 컴퓨터를 내버려두고, 아이폰이나 패드와 같은 스마트하다고 우기는 디지털기기를 집안에 던져두고 여행을 떠나는 것이 현명한 방법이겠다. 그리고, 다른 매체를 들여다보고, 개발자 이외의 사람들을 만나서 이야기해보라라고 권유해야 하는 것이 맞을  듯하다.생각 이상으로 소프트웨어 개발자의 세계는 정말 좁다. 그리고, 단편적인 지식들과 단편적인 경험들만이 존재하는 세상인지도 모른다. 그래서, 소프트웨어 개발자들은 ‘관심의 폭을 넓히고,’ ‘자신을 확장’하는 것이 결론적으로는 더 뛰어난 개발자가 된다는 것을 나중에야 깨달을 것이다. 마지막으로 이야기한 한다면, 소프트웨어 개발자에게 ‘성공’이란 일단... 전혀 해보지 않았던 것을 도전해보는 것, 그리고. 삶은 소프트웨어 개발처럼 버전을 나누어서 설명하기 어렵다는 것을 이해하고. 무언가 계속 새로운 것에 도전한다는 것이 진정한 ‘성공’ 아닌가 한다.#와탭랩스 #와탭 #개발자 #개발 #프로그래머 #성공 #성공한개발자
조회수 868

[Tech Blog] Keep Principles in Mind

원칙(Principle)은 중요합니다. “난 원칙대로 살지 않겠어!” 라고 외치고 싶더라도, 원칙이 있고 원칙을 충분히 이해하고 있지 않다면 그저 사춘기 소년/소녀의 이유 없는 반항 정도로 밖에 들리지 않을테니까요. 사실 대부분의 이런 경우 원칙 보다는 “규칙(Rule)대로 살지 않겠다”에 가깝지만, 여기에서는 그냥 넘어가도록 하죠. 소프트웨어 개발에도 다양한 원칙들이 존재합니다. 학부 수업에서 잠깐 들었거나 이런 저런 글들을 읽다가 접해 봤을 이런 원칙들은 실제 서비스를 만들면서 바쁘게 기능을 추가하고 버그를 수정 하느라 어느새 기억 속에서 잊혀지곤 하죠. 정신없이 기능을 구현하다가 문득 코드를 돌아봤을 때 ‘이게 왜 여기에 있지’ 라는 의문이 든다면 한 번쯤 원칙을 되새겨 보라는 신호가 아닐까요? 이 글에서는 Clean Architecture 와 Clean Code 등의 저자로 유명한 Uncle Bob(Robert C. Martin)이 얘기하는 S.O.L.I.D Principles 에 대해 얘기해 보려고 합니다. SOLID 원칙은 밥 아저씨가 2000년도 자신의 논문 Design Principle and Design Patterns 에서 OOD(Object-Oriented Design)를 위해서 제안한 5가지 원칙의 앞 글자만 떼서 붙여졌습니다. Object-Oriented Design 을 대상으로 제안된 원칙이지만 Agile 개발 등의 개발 방법론 핵심 철학에도 적용될 수 있는 개념들 입니다. S.O.L.I.D Principles Single Responsibility Principle Class 는 오직 한 가지의 책임이 주어져야 하고, 오직 한 가지 이유에서만 변경되어야 합니다. 보고서를 편집하고 출력하는 모듈에 대해서 생각해 볼까요. 해당 모듈은 두 가지의 이유로 변경될 가능성이 있습니다. 보고서의 내용이 바뀌었을 때도 변경되어야 하고, 보고서의 형식이 바뀌었을 때도 변경되어야 합니다. 편집 과정 때문에 모듈을 변경하다 보면 해당 변경 사항이 출력 부분에도 영향을 미칠 가능성이 상당히 높습니다. 이 경우 내용을 편집하는 모듈(i.e 내용을 담당하는 모듈)과 출력하는 모듈(i.e 형식을 담당하는 모듈) 두 가지로 나뉘어야 합니다. “할 수 있다고 해서 해야 한다는 뜻은 아닙니다.” Open / Closed Principle Class, Module, Function 등의 소프트웨어 구성 요소는 확장(extension)에 대해 열려 있어야 하며, 변경(modification)에 대해 닫혀 있어야 합니다. 어떤 모듈이 Data Structure 에 필드를 추가하거나 함수를 추가하는 등 확장이 가능하다면 그 모듈은 확장에 대해 열려 있다고 표현합니다. 반면에 어떤 모듈이 수정 없이 다른 모듈에 의해 사용될 수 있다면 그 모듈은 닫혀 있다고 표현합니다.  public class CreditCard {     private int cardType;       public int getCardType() { return cardType; }       public void setCardType(int cardType) { this.cardType = cardType; }          public double getDiscount(double monthlyCost){          if (cardType == 1) {              return monthlyCost * 0.02;          } else {              return monthlyCost * 0.01;          }     } }  위 CreditCard class 에 새로운 카드 타입을 추가하려고 하면 getDiscount 함수를 변경할 수 밖에 없습니다. 이 경우 Open/Closed Principle 을 위반된다고 볼 수 있습니다. “코트를 입기 위해서 개복 수술을 할 필요는 없으니까요.” Liskov Substitution Principle 프로그램 상의 Object 들은 프로그램의 정확성을 해치지 않으면서 하위 타입의 Instance 로 변경 가능해야 합니다. 하위 타입 함수 인자의 반공변성(Contravariance), 하위 타입 함수 반환 타입의 공변성(Covariance), 상위 타입의 예외를 상속하지 않는 추가적인 예외 발생 금지 등의 요구 사항이 있습니다. OOP 에서 상속 개념을 배울 때 이해를 돕기 위해 주어진 몇 가지 예시들이 있었을텐데, 우습게도 우리가 생각하기에 타당한 상속에 관한 예시들 중 의외로 원칙을 위배하는 경우가 많습니다. Liskov Substitution Principle 을 위반하는 대표적인 예시는 정사각형과 직사각형입니다. 정사각형은 직사각형의 일종이니 Square가 Rectangle을 상속받는 것이 충분이 타당한 것으로 보입니다. 정말 그럴까요? Rectangle 의 넓이를 구하는 함수의 테스트를 구성해 봅시다.  Rectangle rect = new Rectangle(); rect.setWidth(10); rect.setHeight(20); assertEquals(200, rect.getArea());  여기에 new Rectangle() 대신에 new Square()가 rect 에 할당되면 어떻게 될까요? 넓이는 400 을 반환하기 때문에 테스트는 실패하겠죠. 정사각형이 직사각형을 상속 받으면 Liskov Subsitution Principle 을 위반한다고 볼 수 있습니다. 상속은 문제를 해결하는데 있어서 상당히 유혹적인 방법입니다. 하지만 상당히 많은 경우에 상속을 오용할 가능성이 높습니다. “오리처럼 생기고 오리처럼 꽥꽥 거리더라도, 배터리가 필요하다면 오리가 아닙니다.” Interface Segregation Principle 많은 것을 아우르고 일반적으로 사용 가능한 하나의 interface 보다 특정 클라이언트를 위한 여러 개의 interface 가 낫습니다. Xerox는 Stapling(프린터기가!?), Fax 등의 다양한 기능이 포함된 신규 프린터 소프트웨어를 개발 도중, 더이상 개발이 불가능할 정도로 프로그램이 번잡 해졌다는 것을 인정하고 밥 아저씨에게 도움을 요청합니다. 문제는 Job Class 하나가 모든 기능을 다 구현하고 있다는데 있었습니다. 이 비대한 Class 는 Client 입장에서 사용되지도 않을 모든 함수를 알 수 있게 구성 되어 있었죠. 이 문제에 대해 밥 아저씨는 Interface Segregation Principle 을 적용하여 각 Client 입장에서 사용해야 하는 함수 만을 가지고 있는 각 interface 들을 따로 만들었습니다. 그리고는 다음에 나올 Principle 인 Dependency Inversion Principle 을 통해서 해당 기능을 구현하게 함으로써 문제를 해결했습니다. Dependency Inversion Principle “추상화에 의존해야지, 구체화에 의존하면 안됩니다.” 상위 계층의 모듈은 하위 계층의 구현이 아니라 추상화에 의존해야 합니다. 상위 계층이 하위 계층의 구현에 의존하던 전통적인 의존 관계를 역전 시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있습니다. 예를 들어 Dependency Injection 은 이 원칙을 따르는 방법 중 하나 입니다. Conclusion 세상에 나쁜 프로그램은 있습니다. 당장 눈에 보이는 기능이 똑같다고 같은 프로그램인 것은 아닙니다. 생각보다 많은 코드들이 ‘그 곳에 넣을 수 있기 때문에’, ‘그 곳에 넣어도 돌아가기 때문에’ 깊은 고민 없이 그 곳에 정착합니다. 당장 좀 더 빠르게 기능을 추가해서 주변 사람들의 박수를 받을 수도 있습니다. 허나 이것들이 쌓이면 더이상 손댈 수 없는 코드가 되고, 문제를 느끼고는 Refactoring을 하자고 다짐하고, 모두 엎은 다음 또 다시 같은 코드를 만들게 되겠죠. 쉬운 코드가 가장 만들기 어려운 코드이고, 그런 좋은 코드는 좋은 원칙으로 부터 나옵니다. 변화에 적응할 수 있는 프로그램, 의도가 쉽게 읽히는 프로그램, 문제 발생 가능성이 적은 프로그램, 쉽게 확장할 수 있는 프로그램 등 좋은 프로그램을 만드는 것은 우리가 실제로 목표하는 것을 달성하기 위해서 정말 중요합니다. 이는 그저 경험이나, Tweak 만으로 이루어지지 않습니다. 다양한 신규 기술들과 Framework 들을 두루 섭렵하면서 활동 반경을 넓히고 경험을 쌓았다면, 가끔은 잠시 서서 원칙에 대해 되돌아 보는 것은 어떨까요?   *버즈빌에서 활기찬 개발자를 채용 중입니다. (전문연구요원 포함)작가소개 Whale, Chief Architect “Keep calm and dream on.”
조회수 1865

파이썬의 개발 “환경”(env) 도구들

안녕하세요. 스포카 프로그래머 홍민희입니다.파이썬 패키징 생태계에서 개발 환경을 구성하기 위해 널리 쓰이는 virtualenv나 pyvenv, virtualenvwrapper 같은 각종 도구가 왜 필요한지 (또는 자신에게는 큰 도움이 안 되는지) 알려면 그 이전의 파이썬 라이브러리 배포 방식에 대한 이해가 많은 도움이 됩니다. 여기서는 필요한 몇 가지 역사적 사실과 파이썬 패키징 개념 중 현재의 생태계 이해에 필요한 것들을 위주로 정리하고, 최종적으로 각자의 필요에 따라 어떤 도구를 활용하면 될지 지침을 제안합니다.sys.path패키징이고 뭐고 아무것도 없던 90년대 말에는 라이브러리 소스 코드 파일들을 타르볼(tarball)로 압축해서 배포했습니다. 쓰는 사람은 그걸 자신의 애플리케이션 소스 트리 안에 풀어서 사용했습니다.파이썬에는 지금도 sys.path라는 인터프리터 전역적인 상태가 존재합니다. PATH 환경 변수가 실행 바이너리를 찾을 디렉터리 경로들의 목록인 것과 비슷하게, sys.path도 import foo를 하면 foo.py (또는 foo/__init__.py) 파일을 찾을 디렉터리 경로들의 목록을 담습니다. 그리고 기본 동작으로 그 목록의 맨 처음에는 현재 디렉터리(./)가 들어갑니다. 따라서 라이브러리 타르볼을 애플리케이션 소스 트리에 풀어두면 import해서 쓸 수 있습니다.하지만 자신이 작성한 애플리케이션 코드와 남이 작성한 라이브러리 코드를 같은 소스 트리에서 관리하는 것은 여러모로 불편합니다. 따라서 라이브러리는 애플리케이션 소스 트리와는 별도의 디렉터리(예: ../libs/)에 풀어서 관리하고, 애플리케이션 소스 코드 맨 위에 아래와 같이 써두는 패턴이 많았습니다.import sys sys.path.append('../libs') 또는 sys.path를 소스 코드를 건드리지 않고 조작하기 위해 PYTHONPATH 환경 변수를 활용하는 경우가 많았습니다.세기말, 파이썬 1.5를 쓰던 때의 이야기입니다.site-packages새 천 년이 밝았고 파이썬 2.0이 나왔습니다. 표준적인 라이브러리 배포 방식 및 설치 방식이 제안되었고, 표준 라이브러리에 distutils도 들어왔습니다. (지금도 setuptools는 distutils에 의존하고, pip는 setuptools에 의존합니다.) 제안된 방식은 이랬습니다.애플리케이션 코드가 아닌 라이브러리 소스 코드는 모두 /usr/local/lib/pythonX.Y/site-packages/ 디렉터리 안에 둡니다. X.Y는 파이썬 인터프리터 버전이고, 경로는 인터프리터를 빌드할 때 (./configure) 정합니다. 데비안 계열은 site-packages 대신 dist-packages라는 이름으로 바꿔서 빌드하는 등, 파이썬 인터프리터의 설치 방식에 따라 달라집니다. 어떻게 정하든 이를 site-packages 디렉터리라고 부릅니다. 파이썬 인터프리터를 빌드할 때 경로가 결정되므로, 파이썬 인터프리터 별로 각자의 site-packages 디렉터리를 갖게 됩니다. (한 시스템에서 여러 파이썬 버전을 설치했을 때 pip 역시 pip2.7, pip3.6 등과 같이 버전 별로 명령어가 생기는 것도 같은 이유입니다.)기본적으로 sys.path 목록에는 맨 앞에 현재 위치(./), 뒤쪽에는 site-packages 경로가 들어있습니다. import를 하면 현재 위치에서 찾고, 없으면 site-packages를 찾아본다는 뜻입니다.표준 라이브러리의 distutils.core.setup() 함수는 라이브러리 파일들을 시스템의 site-packages 디렉터리에 복사해주는 함수입니다. 라이브러리 타르볼 파일 맨 바깥에는 이 함수를 이용해 라이브러리를 시스템 site-packages에 설치해주는 스크립트를 setup.py라는 파일명으로 포함하는 관례가 있었습니다. pip 같은 게 없던 때에는 라이브러리 타르볼을 받아서 푼 다음 python setup.py install 명령을 실행하는 것이 일반적인 라이브러리 설치법이었습니다. 지금도 pip는 *.whl 파일이 아닌 *.tar.gz/*.zip 파일인 패키지를 설치할 때 내부적으로 python setup.py install 스크립트를 실행합니다.참고로 이때 정립된 파이썬 패키징 표준은 리눅스에서 쓰이는 dpkg나 RPM 같은 일반적인 패키징 방식을 의식하며 만들어졌습니다.1 당시는 도커는 커녕 가상화 자체가 보편적이지 않던 때로, 한 시스템에 여러 애플리케이션을 함께 설치해서 쓰는 멀티테넌시 환경이 일반적이었기 때문입니다.workingenv파이썬으로 작성한 애플리케이션 여럿이 한 시스템에 설치되면 공통으로 의존하는 라이브러리의 버전을 결정하는 게 문제가 됩니다. A 애플리케이션은 foo >= 1.0.0, < 2>에 의존하고 B 애플리케이션은 foo >= 1.5.0에 의존하면 시스템에 설치할 수 있는 foo의 버전은 >= 1.5.0, < 2>으로 한정됩니다. 만약 C 애플리케이션을 설치하려는데 foo > 2.0.0에 의존한다면, A나 C 중 하나는 포기해야 합니다.시스템에 파이썬 애플리케이션을 단 하나만 설치한다 해도, 설치하는데 시스템 관리자 권한이 필요하다는 것도 문제였습니다. 일반적으로 site-packages 디렉터리는 시스템 관리자만 수정할 수 있고 나머지는 읽기만 가능한 /usr 아래 어딘가로 정해졌기 때문입니다. 이를 우회하려고 사용자가 시스템에 설치된 파이썬 인터프리터를 쓰지 않고 직접 파이썬 인터프리터를 빌드해서 사용하는 편법도 쓰였습니다.이런 문제를 해결하기 위해, 애플리케이션·프로젝트마다 별도의 site-packages 디렉터리를 두는 방식이 제안됐습니다. 나중에 virtualenv을 만들게 되는 이안 비킹이 그 전신인 workingenv를 만들어 이 아이디어를 실현했습니다. 현재의 virtualenv 사용 방식은 workingenv에서 만들어진 것입니다.애플리케이션마다 별도의 “환경”(env)을 만듭니다.애플리케이션을 실행하기 전에 우선 그 “환경”을 “활성화”(. bin/activate 또는 Scripts\activate.bat)합니다.workingenv가 만들어주는 활성화 스크립트는 PATH와 PYTHONPATH 환경 변수를 재정의하여 시스템에 설치된 파이썬 인터프리터의 실행 바이너리 디렉터리 및 site-packages 디렉터리를 가리키는 대신, “환경” 내의 bin/ 및 site-packages 디렉터리를 바라보도록 해줍니다. 이안 비킹은 이렇게 분리된 실행 파일들(bin/)과 site-packages 등을 묶어서 “환경”이라고 명명했는데, workingenv 이후로 파이썬 패키징 및 배포 분야에서 이 용어가 정착됩니다.최근에 만들어진 신생 언어의 패키지 관리자는 대부분 파이썬과 달리 애플리케이션·프로젝트마다 별도의 환경을 두고 설치되는 경우가 많습니다. 예를 들어 npm은 -g 옵션을 일부러 켜지 않는 한 현재 디렉터리를 기준으로 ./node_modules 디렉터리에 라이브러리를 설치하게 되어 있고, 별도의 “활성화” 없이도 노드 인터프리터가 해당 경로에서 라이브러리를 찾습니다. 하지만 파이썬의 패키징 표준은 앞서 언급한 것처럼 멀티테넌시 환경이 일반적이었던 시대에 만들어졌고, 또 많은 라이브러리가 실행 파일도 함께 제공하기 때문에2 PYTHONPATH 뿐만 아니라 PATH 환경 변수도 재정의해야 해서 activate 과정이 필요합니다.workingenv는 파이썬 웹 프로그래머 사이에서 빠르게 퍼지기 시작했습니다. 웹 애플리케이션은 정통적인 CLI 및 GUI 애플리케이션과 달리 FHS 표준 같은 것에 크게 구애될 필요가 없었고, 웹 애플리케이션의 배포도 점차 가상화 기술을 통해 완전히 격리된 시스템에 설치되는 식으로 보안 문제에서 많이 자유로워졌기 때문입니다.무엇보다 workingenv는 프로그래머가 여러 프로젝트를 동시에 작업하는 경우 골치 아팠던 라이브러리 버전 충돌 문제를 우회했기 때문에, 배포 도구보다는 개발 도구로 정착되는 면이 컸습니다.virtualenv이안 비킹은 PYTHONPATH를 조작하여 별도의 site-packages 공간을 두는 workingenv의 방식이 복잡하게 패키징된 기존 라이브러리 및 프로젝트에서 호환되지 않는 문제로 골머리를 썩이다, 아예 PYTHONPATH를 이용하지 않는 방식으로 새 도구를 만듭니다.새로운 방식은 아예 파이썬 인터프리터 실행 바이너리를 복사한 뒤, sys.path 기본값에 박힌 시스템 site-packages 경로를 환경 내 site-packages 경로로 바꿔버리는 것이었습니다. 이러한 동작 원리의 차이는 이용자 입장에서 크게 중요한 것은 아닙니다.하여튼 이안 비킹은 virtualenv라는 이름으로 새 도구를 만들었고, workingenv를 빠르게 대체했습니다.virtualenvwrapper앞서 언급한 것처럼, workingenv와 그 후계자인 virtualenv는 저자의 의도와 무관하게 애플리케이션 배포보다는 개발 용도로 더 널리 쓰입니다. 파이썬 프로그래머가 새로운 프로젝트를 시작할 때는 항상 “환경”도 생성합니다. 또 개발을 시작할 때마다 “활성화” 과정도 거칩니다. 너무나 반복적이기 때문에 당연히 이를 자동화하는 도구도 만들어졌습니다. virtualenvwrapper는 바로 그런 목적으로 만들어진 bash/zsh/fish 스크립트 모음입니다.여러 단축 명령을 제공하지만, 핵심 기능은 다음의 두 가지입니다.A라는 프로젝트 작업을 시작할 때마다 cd ~/projects/a; . .venv/bin/activate라고 쳐줘야 했던 것을 workon a 명령으로 줄여줍니다.프로젝트 디렉터리마다 .venv/ 또는 .env/ 등의 이름으로 환경 디렉터리를 생성해두고 버전 관리 시스템에서는 제외되도록 .gitignore 목록에 해당 디렉터리를 넣었어야 했습니다. 예를 들어 ~/projects/a/.venv/, ~/projects/b/.venv/ 같은 식이었습니다.virtualenvwrapper를 쓰면 환경 디렉터리들을 일정한 위치로 모아줍니다. 위치는 기본값이 없으며 virtualenvwrapper 설치할 때 WORKON_HOME 환경 변수를 통해 입맛대로 정할 수 있습니다. 예를 들어 WORKON_HOME을 ~/.virtualenvs/ 디렉터리로 정했다면, 프로젝트별 환경은 ~/.virtualenvs/a/, ~/.virtualenvs/b/ 같은 식으로 저장됩니다.pyvenv파이썬 3.3부터는 virtualenv가 아예 파이썬에 내장됐습니다. 환경을 만드는 명령어는 virtualenv가 아닌 pyvenv로 좀 다르지만, 그 이후의 과정은 같습니다. 파이썬 3만 사용한다면 이제 virtualenv를 따로 설치할 필요가 없어진 것입니다.참고로 아래에서 설명할 pyenv와는 다른 도구입니다. 철자의 “v”에 주의해주세요.pyenv애플리케이션을 개발할 때는 하나의 파이썬 버전을 정하면 되지만, 라이브러리는 여러 파이썬 버전과 호환되어야 합니다. 그러다 보니 라이브러리 개발자는 여러 버전의 파이썬을 시스템에 동시에 설치할 필요가 있습니다. 데드스네이크스 PPA나 데드스네이크스 홈브루 탭 같은 것을 이용해서 설치할 수도 있지만, 보통은 pyenv를 많이 씁니다.pyenv는 동시에 여러 버전의 파이썬을 시스템에 설치해주며, 이렇게 설치된 파이썬은 시스템의 패키지 시스템(데비안·우분투의 APT나 맥OS의 홈브루 등)을 통해 설치되는 것이 아니라, pyenv가 다운로드와 빌드 및 설치를 직접 하여 별도로 관리합니다. 설치된 파이썬들은 PEP 394에 따라 일정한 형식으로 이름지어진 명령어(예: python2.7, python3.6)로 실행할 수 있게 됩니다.또한, 여러 파이썬 버전 중에 하나의 시스템 기본 파이썬 버전도 선택 가능하며, 특정 프로젝트 디렉터리 안에서만 기본 파이썬의 버전이 달라지게 할 수도 있습니다.pyenv-virtualenvpyenv가 여러 파이썬 버전을 동시에 설치해주기는 하지만, 그렇다고 자동으로 site-packages가 프로젝트마다 격리되는 것은 아닙니다. 예를 들어 pyenv로 파이썬 3.6을 설치한 뒤, 파이썬 3.6으로 두 프로젝트를 한 시스템에서 개발할 경우 두 프로젝트는 시스템 site-packages를 함께 쓰게 됩니다.따라서 pyenv를 쓰더라도 virtualenv는 따로 써야 하는데, 따로 사용할 수도 있지만 pyenv-virtualenv를 쓰면 pyenv virtualenv 명령으로 프로젝트에 쓸 파이썬 버전 지정과 가상 환경 생성을 한 번에 할 수 있게 됩니다.비슷하게 pyenv와 virtualenvwrapper를 통합해주는 pyenv-virtualenvwrapper 같은 도구도 있습니다.마치며여러 파이썬 개발 환경 관리 도구를 소개했지만, 여기 있는 모든 도구를 꼭 써야 하는 것도 아니고, 가장 최근에 나온 도구로 하루빨리 갈아타야 하는 것도 아닙니다. 글을 쓴 저 자신도 pyenv 같은 도구가 나온 지 몇 년이나 지났고 주변에서 쓰는 사람이 많음에도 쓰지 않고 있습니다. virtualenvwrapper를 대체하는 Pipenv 같은 실험적인 방식3도 생겨나고 있지만, 어느 쪽이든 동시에 여러 파이썬 프로젝트를 작업하는 사람이 아니라면 굳이 쓸 필요가 없는 도구입니다. 각자의 용도에 따라 필요한 수준의 도구를 이용하면 됩니다. 2017년 10월 현재, 아래의 지침으로 정리할 수 있겠습니다.파이썬 프로그래머가 아니지만, 파이썬 애플리케이션을 설치해서 이용합니다.시스템에서 제공하는 패키지 관리자(APT나 홈브루 등)를 통해 애플리케이션을 설치하세요.파이썬 프로그래머가 아니지만, 파이썬 애플리케이션을 유난히 많이 이용합니다.pipsi를 이용해 파이썬 애플리케이션을 설치하는 것을 권합니다.파이썬 프로그래머이고, 하나의 애플리케이션을 개발합니다.파이썬 3.3 이상을 이용할 경우 pyvenv로 개발 환경을 만들어서 개발하세요. 그 이전의 파이썬 버전을 이용할 경우 virtualenv를 활용하세요.파이썬 프로그래머이고, 여러 애플리케이션을 개발합니다.virtualenvwrapper를 활용하세요.파이썬 프로그래머이고, 여러 애플리케이션을 다양한 파이썬 버전으로 개발합니다.pyenv-virtualenvwrapper를 활용하세요.파이썬 프로그래머이고, 라이브러리를 개발합니다.pyenv와 tox를 활용하세요.파이썬으로 만든 애플리케이션을 distutils를 통해 패키징한 뒤, RPM 기반의 리눅스 배포본 용으로 python setup.py bdist_rpm 명령을 통해 *.rpm 파일을 제공하기도 했습니다. 이를 통해 애플리케이션을 설치할 경우, 각 파일들은 리눅스 FHS 표준과 해당 시스템 설정에 따라 흩어지게 됩니다. ↩예를 들어 파이썬에서 가장 많이 쓰이는 국제화 라이브러리인 바벨은 pybabel 명령어를, 구문 강조 라이브러리인 파이그먼츠는 pygmentize 명령어를, 장고는 django-admin 명령어를 제공합니다. ↩저는 2017년 4월에 한 번 써보았으나, 아직은 실무에서 쓰기에는 이르다는 결론을 내렸습니다. 이에 관한 그때의 제 감상은 별도의 글로 다루었습니다. ↩#스포카 #파이썬 #개발팀 #개발자 #인사이트 #후기 #일지
조회수 2598

코드 커버리지 80% 넘긴 썰

첫번재 코드를 짜기까지2015년 1월이었던 것으로 기억해. 당시 전 회사에서 테스트를 정착시키기 위해서 노력을 하고 있었는데, 사실 잘 되지 않았어. 그래서 혼자 ‘Testing Goat’를 따르며 공부를 하고 있었어. 그때 8퍼센트 이효진 대표와 연락이 닿았고, 초기 개발을 좀 도와 달라는 요청을 받았어. 옳다구나! 실전에 적용해 볼 수 있겠다 생각이 들어서 도와주기로 했지이것이 8퍼센트의 첫번째 commit간단한 기능을 가지고 있어서, TDD를 하면서 unit test와 functional test를 붙여서 전달해줬지. 책에 있는 내용을 열심히 활용해서 코드를 짜긴 했지만, 테스트 코드와 함께 결과물을 전달해서 스스로 뿌듯해했어. 물론 그때까지만 해도 내가 8퍼센트 들어갈 거라고는 생각도 하지 못했지. (사람의 인생이란 참)2015년 PyCon에서 발표테스트 없이 코드를 짜다가, 테스트와 함께 개발을 하다 보니 이게 너무 좋은 거야. 그래서 발표를 해야겠다는 생각을 했어. 그래서 아래 꼭지들을 내용으로 발표를 했어. ㅇ 테스트가 왜 필요할까요? 어떤 테스트가 필요할까요?ㅇ 좋은 테스트란 무엇인가요?ㅇ unittest 소개 및 활용ㅇ 테스트 관련 툴 소개ㅇ 내가 하고 있는 테스팅 과정 소개발표를 준비하면서 팀 단위에서 이런 것들을 제대로 한번 해보면 좋겠다는 생각을 했어. 내가 돌아왔다2015년 11월에 8퍼센트에 CTO로 조인을 하게 되었어. 처음으로 CTO로 일을 하게 된 것이었으니까, 이런저런 꿈에 부풀었지. 그중 하나가 ‘테스팅을 제대로 한번 해보자’라는 생각이었어. 코드를 살펴보니까 뭔가 내가 처음에 작성해서 넘긴 후에도 테스트 코드가 추가된 흔적은 있는데 제대로 동작하고 있는 것 같진 않더라고. 일단 기존에 있던 테스트들을 정리했어. 동작해야 하는 것 들을 정리하고, 필요 없는 것들을 지웠지. 그리고는 git push hook 에 테스팅을 추가했어. unittest가 돌지 않으면 push를 하지 못하도록 해버렸어.당시에는 bitbucket을 쓰고 있기도 했고 특별히 CI툴을 붙이지 않은 상태였어서,  기록이 남아 있지 않더라. 하지만 당시의 코드 커버리지가 한 20% 정도였을 것 같아. 그 뒤로 PR을 통해 코드 리뷰를 할 때에는 테스트가 짜여 있지 않은 경우에는 관련된 테스트를 추가해 달라고 요청을 했어. 하지만 구성원들이 테스트를 편하게 짜게 될 때까지는 꽤 시간이 걸렸어. 특히 unittest.mock, freezegun , fixture 등을 사용해서 테스트 상황을 잘 구성하는 것에 익숙해지는 것에 시간이 걸렸던 것 같아. Travis 의 도입 2016년 1월에 github으로 갈아타면서 travis를 도입했어. 기존에는 push을 할 때마다 전체 테스트를 돌리도록 했었는데, 테스트의 양이 늘어나면서 push의 시간이 오래 걸리는 문제가 있었어. 그래서 travis에서 테스트를 돌리도록 했어. 이제는 테스트가 안 돌아도 push 까지는 할 수 있는데 PR merge는 할 수 없는 상태가 된 거지. 그 이후에는 flake8을 돌려서 스타일 체크를 시작했어. 그래 생각난다. 개발팀에서 하루 날 잡아서 PEP8에 맞춰서 코드들을 수정했어. 그렇게 한 이후에도 수정할 것들이 많이 남아 있어서 모듈 단위로 수정을 하면서 해당 모듈을 추가로 검사할 수 있도록 travis와 commit hook에 추가해 나갔어. 결국 다 정리되긴 하더라. 그리고는 주요 브랜치에 대한 빌드를 깨뜨린 사람이 음료수를 쏘는 규칙을 만들었어. (주요 브랜치가 깨진다는 것은 로컬 환경과 travis 모두에서 테스트를 생략했다는 이야기거든)지금은 github flow  라서 develop branch 는 없어FactoryBoy의 사용테스트가 점점 늘어나서 한 1500개 정도가 되었어. 점점 모델도 많아지게 되면서 fixture로 테스트 데이터를 관리하는데 한계가 왔어. 예를 들면 신용평가를 한번 하면 데이터가 200여개가 쌓이는데, 신용평가 모델에 대한 테스트를 하려면 그것들을 다 fixture로 만들어야 했어. 그래서 개발팀의 한 분(누군지 기억은 안나는데 고마워요)이 FactoryBoy를 추천해 주셨고, 쓰기로 했지. 지금까지 만들어졌던 fixture 들을 모두 factory 기반으로 옮기는 것도 간단하지는 않았어. 하지만 새롭게 만드는 것부터 적용하고 과거 테스트들을 고칠 때마다 조금씩 조금씩 수정을 했더니, 다 고쳐지긴 하더라고. 그 이후로는 새롭게 모델을 만들 때에는 항상 관련된 TestFactory를 함께 만들어 주게 되었어.테스트 커버리지 측정도구 도입이걸 처음에 왜 붙였는지는 잘 모르겠어. 사실 그전까지는 테스트 커버리지를 재미로 측정해 본 적은 있었지만 꾸준히 측정을 해야겠다는 생각을 해보진 못했었거든. 그런데 이 수치가 측정이 되기 시작되면서부터는 많은 것들이 바뀌었어. 처음 측정 했을 때가 63.59%바뀐 게 무엇이냐고 하면, PR에서 '공식적인 잔소리'가 가능해졌어. 이게 테스트를 작성하다 보면 자괴감이 들 때가 있거든. 내가 봤을 때 너무나 자명한 것에 대한 테스트를 작성할 때야. 그런데 이 테스트라는 것이 지금의 내 기준으로 보면 안 되고, 다른 누군가 그리고 혹은 미래의 나를 기준으로 바라봐야 하거든. 그래서 자괴감을 느낄 시간에 그냥 짜야해. 근데 우리가 사람인지라 가끔 나태해 지거든. 나태해 지면...뭐. 나라고 예외는 없지UI 테스트에 대한 좌절처음에 테스트를 시작했을 때에는 selenium을 이용해서 UI에 대한 functional test가 있었어. 그리고 꽤 오랫동안 유지가 되었었지. 그 이후에는 멀티플랫폼에 대한 테스트를 하기 위해서 sauce labs를 통해서 firefox, IE, mobile browser 에 대한 테스트도 자동으로 진행했었어. 그런데 이 테스트는 한번 동작시키는데 시간이 너무 오래 걸리다 보니 로컬 환경에서 테스트가 쉽지 않더라. 그래서 CI환경에서만 테스트를 돌리게 했어. 그랬더니 수정하고 다시 CI에서의 테스트를 위해 push 해야 하고 또 기다리게 되더라고. 이런 어려움 때문에 중단했다, 재개했다, 중단했다, 재개했다를 몇 번 반복한 이후에 지금은 작성하고 있지 않아. 우리 팀의 프런트엔드를 이전 작업이 어느정도 되고 나면, UI 테스트를 꼭 다시 시도해 볼 생각이야.80%의 공약70%가 넘고 나니까 전체 테스트 커버리지를 올리는 것이 쉽지 않았어. 그래서 개발팀에 공약을 하나 걸었지.그날이 금방 올것 같지는 않았어그랬더니 사람들이 코드를 지우기 시작하더라고... 물론 사용되지 않는 코드를 말이야. 그리고 아예 브랜치 이름을 "80percent"라고 만들더니 예전에 테스트 코드를 작성하지 않던 시절의 코드까지 테스트를 붙이기 시작했어. 보이니? 그래프 마지막, 사람들의 욕망이?사실 80%가 특별한 의미가 있는 숫자는 아니야. 그냥 100줄의 코드에서 80줄의 코드가 테스트가 되고 있다는 것이지. 그래도 우리가 2년 동안 테스트를 중요하게 생각하고, 열심히 노력해 온 결과라고 생각하면 좀 뿌듯해. 달성흠. 나는 약속을 중요하게 생각하는 사람이야. 그리고 우리 팀원들은 나보다 더 약속을 중요하게 생각한다는 것을 알게 되었어.  아. 그리고 위 사진에 디자이너 두 분이 있어. 디자이너 분들도 commit 한 코드가 있으니 점심을 먹을 자격이 충분하지. 암암. 그렇지.이렇게 해서 80%를 달성하기까지의 과정을 적어 봤어. 짧은 글에 적혔지만 사실 2년의 시간이 걸렸고 아마 팀원들의 몇천 시간이 들어간 일일 거야. 모두들 고마워~끝!사람들을 낚아 보기 위해서 글 제목을 "~썰"로 지었다가, 평소에 잘 쓰지 않는 스타일의 쓰기 글이 되어 버렸다. 글의 남은 부분에서는 80%를 달성하고 나니 어떤 점이 좋은지 앞으로는 어떤 부분을 잘 하고 싶은지를 추가로 적어 보겠다.테스트를 작성하니까 무엇이 좋은가?테스트를 작성하게 되면 코드리뷰가 더 쉬워진다. 코드를 읽다가 잘 이해가 되지 않으면 테스트 코드를 살펴본다. 작성된 코드는 어떻게 사용되는가? 작성된 코드는 어떤 기능인가? 작성된 코드에서 주의해야 하는 점은 무엇인가? 를 효과적으로 알 수 있다.코드 수정에 자신감이 생긴다. 내가 오래전에 짠 코드, 다른 팀원들이 짠 코드는 수정하기가 무섭다. 특히 우리 회사와 같이 대부분의 코드 수정이 실제 돈의 흐름에 영향을 주는 경우는 더욱 무섭다. 하지만 테스트가 있으면 자신감이 생긴다. (그렇다고 안 무서운 것은 아니다.) 특히 시스템이 복잡해질수록 정적 분석 혹은 QA로 특정 코드에 대한 수정의 영향을 파악하기가 어렵다. 자동화된 테스트 외의 답은 없다고 생각한다. 11월에는 작성한 코드 보다 삭제한 코드가 더 많다. 이렇게 리팩토링이 가능하다.이제 수정하지 못하는 코드는 오래된 코드, 작성자가 퇴사한 코드가 아니라 테스트가 없는 코드가 되었다.테스트가 정착되기까지 키가 된 것은 무엇이었나?자동화를 통한 강제였다고 생각한다. 첫 번째 시점은 git hook을 사용한 시점이었다. commit을 할 때 flake8 체크를 하고 push를 할 때 테스트를 돌려주었다. 사람들은 스타일을 맞추지 않으면 commit을 할 수 없게 되었고, 기존의 테스트를 깨뜨리게 되면 코드를 push 할 수 없게 되었다. 두 번째 시점은 CI툴의 도입이었다. 내가 작성한 코드는 테스트를 통과했지만 maste에 있는 코드와 merge가 된 것을 기준으로 테스팅을 할 수 있게 되었다. 세 번째 시점은 테스트 커버리지 측정이었다. 신규로 작성되는 코드들이 우리가 원하는 수준의 테스트 커버리지를 만족시키는지 확인할 수 있었다. 자동화되지 않은 상태에서 매번 개발자에게 "테스트가 깨졌어요", "테스트를 추가해 주세요.", "여기는 코딩 스타일이 맞지 않아요."라고 말하는 것은 피곤한 일이기도 하고, 장기적으로 보면 동작하지 않는다. 자동화 외의 방법은 없고, 이 자동화된 방법은 새롭게 입사한 사람들이 테스팅에 손쉽게 적응하도록 한다. 앞으로의 테스팅에 대해사실 커버리지가 테스팅의 전부는 아니다. 커버리지만 올리는 의미 없는 테스트도 작성할 수 있다. 하지만 기본적으로는 python이 런타임 시에 다양한 에러를 발생시키기 때문에 어느 정도 이상의 커버리지 테스트는 필수라고 생각한다. 앞으로 주요한 모듈에서는 커버리지를 90% 이상을 맞추고 나머지 영역에 대해서는 80% 이상을 유지할 생각이다. 그리고 테스트의 질은 코드 리뷰로 해결해야 하겠다. 지금 unittest 가 약 3500개 정도 작성되어 있는 상태이다. 이 테스트를 동작시키는데 로컬에서는 약 3분 정도 CI환경에서는 10분 정도가 걸린다. 이 테스트를 기다리는 시간 동안 생산적인 일을 크게 하지 못하는 경향이 있어서 이 시간을 줄이기 위한 노력을 해야 한다. 마지막으로는 프런트엔드에 대한 테스트를 추가해야겠다. 글을 마치며이 글은 나의 눈에서 바라본 것을 기준으로 적었기에 내가 다 한 것처럼 느껴진다. 하지만 전혀 그렇지 않다. 이 모든 작업은 나 혼자 한 것이 아니라 우리 팀이 한 것이다. 더 나은 개발을 목표로 함께 달리고 있는 팀원분들께 감사를 전한다. #8퍼센트 #에잇퍼센트 #개발 #개발팀 #삽질 #팀워크 #팀플레이 #성장 #성과
조회수 1169

AndroidAnnotations 과 테스트

이 포스팅은 총 4부로 이어지며 현재는 4부입니다.1부 : Android, MVC, MVVM, MVP2부 : Android 와 Annotation3부 : AndroidAnnotations 과 MVC4부 : AndroidAnnotations 과 테스트앞선 3개의 포스팅을 통해 AndroidAnnotations 과 MVC 가 view 에 관여하는 동작들이 모두 View 로 분리된 것을 확인할 수 있습니다.이러한 구조덕분에 Model 에 대한 테스트와 View 에 대한 테스트가 명확히 구분지어지게 되었습니다.Test 코드를 작성함에 있어서 View 에 대한 테스트가 다소 어려움이 있다는 것을 감안한다면 Model 에 대한 테스트만 집중할 수 있는 구조가 테스트에 대한 접근을 더욱 쉽게 해줍니다.다음은 앞선 포스팅에서 정의된 코드 중에서 Model 에 대한 테스트입니다.※ 테스트코드는 Robolectric 을 이용하여 작성하도록 하겠습니다.Model Test@RunWith(RobolectricGradleTestRunner.class) public class MainModelTest { private MainModel mainModel; @Setup public void init() { mainModel = new MainModel(Robolectric.application); } @Test public void testGetReleaseState() { // given String version = "3.19" // not yet released // when boolean isReleased = mainModel.getReleaseState(version); // then assertThat(isReleased, is(equalTo(false)); // given version = "3.18" // released // when isReleased = mainModel.getReleaseState(version); // then assertThat(isReleased, is(equalTo(true)); } }위와 같이 Model 만 별도로 테스트가 용이해졌습니다.Presenter TestPresenter 에 대한 테스트는 Model 에 대한 테스트와 다릅니다.Activity 에 커플링이 높기 때문에 해당 Activity 를 직접 바인딩해야 합니다.@RunWith(RobolectricGradleTestRunner.class) public class MainViewTest { private MainActivity mainActivity; private MainView MainView; @Setup public void init() { mainActivity = Robolectric.buildActivity(MainActivity.class).create().start().resume().get(); MainView = mainActivity.mainView; } @Test public void testGetVersionText() { // given String version = "3.19" // when MainView.versionEditText.setText(version); // then assertThat(MainView.getVersionText(), is(equalTo(version)); } }Jandi Team은 View 를 테스트하기 위해서 Presenter 와 Activity 의 패키지 Level 을 같은 Level 로 유지하고 있습니다.AndroidAnnotations 에서 DI 를 설정하기 위해서는 해당 변수나 메소드는 최소 Package Scope 로 정의해야하기에 위와 같은 형태의 Field 접근을 볼 수 있습니다.정리AndroidAnnotations 를 활용한 MVC 패턴의 전환의 또다른 이점은 이와 같이 테스트를 명확히 분리할 수 있다는 장점을 주었습니다. 물론 이 방법은 MVVM, MVP 로 구현하였을때보다 나은 형태라 할 수는 없으나 View 에 대한 테스트가 좀 더 용이해진 것이라 생각합니다.※ Activity 는 왜 테스트하지 않나요?MVP 패턴에서 Activity는 Controller 의 모습을 지니고 있습니다. 이는 Unit Test 가 아닌 Behavior 테스트에 가까운 모습이며 다른 방식으로의 테스트코드 구현이 필요하다고 생각합니다.#토스랩 #잔디 #JANDI #개발 #개발자 #개발팀 #기술스택 #일지 #후기 #꿀팁 #인사이트
조회수 1646

iOS Graphic Interface 살펴보기 (1/2)

1.intro: 애정하는 iOS, 애증의 Xcode프론트엔드 개발자가 가장 기쁠 땐 언제일까요? 여러 가지가 있죠. 직접 만든 스무스한 애니메이션을 볼 때, 고생해서 작업한 하드코어 고난도 레이아웃이 잘 작동할 때, 작업한 화면을 사람들이 ‘예쁘다ʼ고 말해줄 때 등등. 그러므로 iOS는 모든 프론트엔드 개발자가 동경하는 OS라고 말할 수 있습니다. 대부분의 굵직한 Transition들을 알아서 Animate해주고, 프레임레이트가 복잡한 레이아웃 효과도 부드럽게 표현해주기 때문에 ‘예쁘다ʼ, ‘쾌적하다ʼ는 말이 절로 나오는 OS이기 때문이죠. 물론 그만큼 손도 많이 갑니다. 사실 iOS는 신기한 점이 많습니다. Xcode를 사용하다 보면 Interface Builder에서 ctrl+드래그를 사용하여 Code로 Reference를 가져오는 방법부터 String값으로 찾아가는 Xib/StoryBoard 파일까지.. 다른 플랫폼 및 IDE에서는 겪어보지 못한 새로운 경험들을 만나죠. 덕분에 다년차 개발자의 멘탈도 Xcode-iOS를 만나면 탈탈 털립니다. 시간이 지나면 이 독특하고도 불편한 Xcode를 사랑하고, 저주하는 상황까지 생깁니다.그래서 오늘은 많은 iOS 루키들이 겁내고 괴로워하는 iOS의 Graphic Interface를 살펴보고자 합니다. 맨땅에 헤딩할 때 헬멧이라도 쓰고 있으면 그나마 덜 아프니까요.2.Point, PixelAndroid에서는 다양한 기종의 스크린을 지원하기 위해 자체적으로 dp라는 수치 개념을 만들어 사용합니다. 파편화된 디바이스들을 모두 지원하는 레이아웃을 구성하려고 고안한 효율적인 방법이죠. iOS에도 이와 같은 개념이 있습니다. 바로 포인트(Point)인데요. Xcode의 ImageAsset 파일을 열면 이런 것을 찾을 수 있습니다. 1X, 2X, 3X바로 이 화면에서 볼 수 있는 1x,2x,3x라는 문구가 포인트 개념을 설명하고 있습니다. 포인트는 디바이스의 물리적 픽셀을 2배, 3배로 압축해 사용하는 iOS 만의 독특한 단위입니다. 이 개념이 처음 쓰인 건 iPhone 4, 즉 레티나 디스플레이가 등장하면서부터 인데요, 기존의 iPhone 3Gs와 물리적 화면 크기는 동일한데, 4배의 픽셀 수를 가지는 레티나 디스플레이에 기존의 앱들을 그대로 보여주자니 픽셀 단위로 정의된 기존의 모든 이미지/레이아웃이 절반 크기로 줄어드는 문제가 발생했습니다. 따라서 별도의 작업 없이 디스플레이하기 위한 방법으로 고안된 게 바로 포인트입니다.포인트는 픽셀을 2배, 3배로 압축해 1포인트라는 단위로 규정하고, 그 단위를 Nib(Xib) 에디터 및 개발 과정에서 사용합니다. 앞으로 여러분이 iOS 개발을 하면서 접할 기본 단위는 바로 포인트가 될 겁니다. 2X 혹은 3X는 단어는 픽셀을 2배, 3배로 압축했다는 의미입니다. 개발자의 편의를 위해서 만들어진 개념이 오히려 개발자에게 혼동을 주는 아이러니한 상황이 펼쳐졌습니다. 사실 이 픽셀-포인트의 개념이 처음 등장했을 때는 꽤 편리했을 겁입니다. 당시만 해도 iPhone4와 iPhone3Gs의 해상도를 구분하지 않고 작업할 수 있는 획기적인 방법이었으니까요. 하지만 지금은 iPhone5, iPhone7 Plus, iPhone X 등 다양한 장비들이 등장했습니다. 그래서 iOS 개발자는 포인트를 단지, 픽셀의 또 다른 이름처럼 느낄 뿐입니다. 애플도 자신들이 이렇게 다양한 해상도의 iPhone을 출시하게 될 줄은 몰랐을 겁니다.애플의 해상도 춘추전국시대 / 출처: paintcodeapp3.Storyboard, Nib (Xib)iOS UI 디자인의 꽃이 무엇인지 묻는다면 그것은 단연 Storyboard와 Xib일 것입니다. Storyboard는 기획자들이 사용하는 그것과 유사한 개념입니다. 하나의 큰 틀에 화면 단위로 여러 장의 기획안을 놓고, 그것들의 시퀀스를 한 눈에 알아볼 수 있도록 하는 보드입니다.Storyboard는 Segue와 같은 시퀀스 설정을 직접 할 수 있고, 연결된 하나의 Flow를 시각적으로 펼치기 좋습니다. 프로토타이핑을 위한 적절한 툴인 셈이죠.UIStoryboard 예시 - 브랜디 iOS의 Main StoryboardNib(혹은 Xib, 이하 Xib로 지칭)는 조각조각 단위의 화면이나 재활용을 많이 하는 CollectionViewCell 등의 화면 작업에 적합합니다. 이 점이 Storyboard와는 다르죠. (CollectionViewCell에 대한 자세한 포스팅은 여기를 클릭하세요.)물론 Storyboard에서 할 수 있는 작업은 대부분 Xib로도 가능하지만, 각각의 용도를 다르게 해서 사용하는 경우가 많습니다. 예를 들어, 브랜디 iOS 프로젝트는 Storyboard에선 큰 틀의 화면을 다루고, Xib에서는 CollectionView Cell과 ReusableView, Custom Component등을 다루고 있습니다. UICollectionViewCell.xibStoryboard와 Xib로 인터페이스 작업을 할 때는 파일의 컨텐츠가 너무 비대해지지 않도록 조심해야 합니다. Storyboard가 비대해지면 많은 작업자가 동시에 파일을 수정할 수도 있는데, VCS를 사용하면서 Storyboard나 Xib 파일의 충돌이 발생하면 병합하는 과정이 매우 고통스럽습니다. 그러므로 Storyboard는 서로 충돌하지 않도록 더 큰 그림을 그리고, 해당 Storyboard를 Senior 개발자가 관리할 수 있도록 안전장치를 두도록 합시다. 야 이거 소스 건드린 사람 나와 Storyboard와 Xib는 기본적으로 XML 기반의 파일입니다. 혹시라도 충돌이 발생하면 UI로 확인이 불가능하기 때문에, Xcode에서 해당 Storyboard, Xib 파일을 우클릭한 후 Open As > Source Code 메뉴를 클릭하면 XML 형식으로 브라우징할 수 있습니다. 해당 충돌 부분을 찾아가서 수정하고 다시 확인하면 UI로 볼 수 있습니다.소스코드로 스토리보드 보기4.From Storyboard, to CodeStoryboard와 Xib에서 구현한 컴포넌트들을 ViewController의 SourceCode에서 다룰 일이 분명 생길 겁니다(언제나 그렇죠). 그럴 땐 Outlet이라는 개념을 이용해서 Storyboard 와 SourceCode를 연결하는데요.네, 코드가 아닙니다. 포토샵하는 기분으로 ctrl + 마우스 좌클릭 드래그를 해주시면 됩니 다. 이 기능은 다른 IDE에서 보기 힘든 건데요. 나름 쓸만합니다. 익숙해지면 여러 가지 컴포넌트, 유닛들을 Outlet으로 처리할 수 있습니다. 코딩을 자유롭게 할 수도 있고요. 예를 들어, LayoutConstraint를 Outlet으로 처리하면 해당 Constraint를 코드 시퀀스에 따라 자유자재로 변경할 수 있게 되는 것처럼 말이죠.물론 이보다 선행되어야 할 작업은 Storyboard에서 해당 ViewController가 연결될 ViewController를 지정하고, 해당 ViewController의 파일을 미리 만들어야 합니다.5.Extraction of ViewControllerStoryboard에서 ViewController A를 연결했는데, ViewController B 에서 ChildViewController로 ViewController A 를 사용하고 싶다면 어떻게 할 수 있을까요? (간장공장공장장) 당연한 이야기지만 코드를 통해 구현 가능합니다. 필요한 것은 Storyboard 파일명과, Storyboard에서 미리 지정한 ViewController A 의 Identifier, 두 가지입니다. Storybo/rd에서 ViewController A를 연결했는데, ViewController B 에서 ChildViewController로 ViewController A 를 사용하고 싶다면 어떻게 할 수 있을까요? 당연한 이야기지만 코드를 통해 구현 가능합니다. 필요한 것은 Storybo/rd 파일의 이름과, Storybo/rd에서 미리 지정한 ViewController A 의 Identifier, 두 가지입니다. instantiateViewController From Storyboard/**  현재 화면에 디스플레이중인 UIWindow 객체로부터 UITabBarController를 반환받는 메  소드  - parameter window: UIWindow  - returns: UITabBarController */ fileprivate func tabBarControllerFromStoryboard() -> BRTabBarController {  let storyBoard = UIStoryboard(name: "mainStoryboard", bundle: nil let viewController = storyBoard.instantiateViewController(withIdentifier: "mainTabBarController") return viewController as! BRTabBarController  // 잘못된 viewController를 추출한 경우 nil exception } 비슷한 방법으로 Xib에 작성된 View도 추출할 수 있습니다. Xib파일 하나에 여러 View가 정의되어 있다면, 각각의 View를 필요에 따라서 사용할 수도 있습니다.Extraction From Xiblet nib = UINib(nibName: NSStringFromClass(BRDropdownSelector.self) let components = nib.components(separatedBy: ".").last!, bundle: nil) let view = components.instantiate(withOwner: nil, options: nil).last as! BRDropdownSelector  // 잘못된 view를 추출한 경우 nil exception 6.LayoutConstraints For Flexible UI더 유연한 레이아웃 동작을 원한다면, Static하게 선언된 수치보다는 LayoutConstraint로 제한적 범위 안에서 유동적으로 동작할 수 있도록 View를 주물러 주는 게 좋습니다. 예를 들어, 어떤 두 컴포넌트 사이의 최대 너비를 100으로 지정하되, 컨텐츠 사이즈에 따라 더 작아질 수도 있도록 하려면, LayoutConstraints의 Less than or Equal기능을 사용하는 것처럼 말이죠.Less than or equalLess than or Equal뿐만 아니라 Greater than or Equal도 존재합니다. 상황에 맞게 사용하는 지혜가 필요하죠. LayoutConstraint에는 Multiplier라는 개념도 있습니다. 만약 컴포넌트 A 절반 너비의 컴포넌트 B를 작성하고 싶다면, 그리고 이 조건이 화면 크기와 관계없이 동일하게 적용되기를 원한다면, 컴포넌트 B의 너비를 컴포넌트 A와 동일하게 Constraint로 지정하고, Multiplier를 0.5로 지정하면 됩니다. Multiplier는 단어 그대로 ‘배수ʼ라는 의미입니다.이처럼 화면 해상도에 구애받지 않는 유연한 UI를 작성하고 싶다면 LayoutConstraint 의 사용은 필수입니다. 브랜디 iOS 앱이 다양한 해상도의 iOS 디바이스에서 동일한 비율 로 출력되는 것도 이러한 LayoutConstraint를 사용했기 때문이죠.7.View를 핸들링할 그곳앞서 정리한 방식들을 사용해서 Storyboard, Xib 파일을 훌륭하게 작성했다면, 이제는 ViewController의 소스코드로 돌아올 차례입니다. View Size를 이벤트에 따라 변경하거나, 숨겼던 View를 보여주는 등의 작업들을 할 차례입니다.Storyboard나 Xib에서 작업한 View를 코드 상에서 다룰 일은 많습니다. 99.78% 이상 ViewController에서 View를 다루어야만 하죠. 무조건입니다.viewDidLoad() 에서 View는 대부분의 초기화 작업을 합니다. 그것은 소스코드를 다루는 개발자에게도 마찬가지죠. Storyboard에서 연결한 Outlet들도 이 Function에서부터 nil값이 아니게 됩니다. 따라서 뷰에 필요한 초기화 작업 (Button의 Title 지정, ImageView의 이미지 지정 등) 을 viewDidLoad()에서 모두 하면 됩니다. viewDidLoad()는 그 이름처럼 ViewController가 생성되었을 때 단 한 번 호출됩니다. 다시 거치지 않는 코드이기 때문에 ViewController에서 사용할 변수들을 초기화하는 등의 작업도 이 자리에서 할 수 있습니다. viewDidLoadoverride func viewDidLoad() {      super.viewDidLoad()     /* do 초기화 in 여기 */ } 다만 여기서 아무리 해도 안 되는 작업이 있습니다. View 사이즈를 해상도에 맞게 변경하는 작업 같은 것 말이죠. LayoutConstraint를 통해 지정된 사이즈를 가져올 때, 화면을 꽉 채우도록 Constraint를 지정해도 로그를 찍으면 엉뚱하게 더 적은 값 이나 큰 값이 나올 수도 있습니다. 이런 경우에는 아무리 viewDidLoad()에서 열심히 Constraint의 값을 가져와도 결과가 똑같을 겁니다.개미지옥override func viewDidLoad() {      super.viewDidLoad()     // 백년동안 코딩해도 화면 해상도가 다르게 나와요 } viewWillAppear() 에서는 viewDidLoad()에서 작동하지 않던(?) 코드를 적용할 수 있는 자리입니다. Constraint들로 지정된 사이즈들은 viewWillAppear()에서부터 각 디바이스의 해상도에 맞게 적용됩니다. 여기서부터는 화면 크기에 맞춘 SubView들의 사이징이나 Constarint들로부터 추출한 값이 의미가 있습니다.viewWillAppearoverride func viewWillAppear() {     super.viewWillAppear()     // 이제 아마 화면이 나올 차례인가봐요 } viewDidAppear()는 출력된 화면에 실행할 코드를 작성하는 자리입니다. 화면이 등장한 이후 보여줄 팝업창이나, 튜토리얼을 출력하는 건 여기서 해야 합니다. viewWillAppear()는 예상되는 출력 화면에서 호출되기 때문에, 실제로는 화면이 없는 상황에서도 호출될 수 있습니다. 만약 해당 viewController의 출력이 확실히 완료된 후 에 실행되어야 하는 이벤트라면, 이 Function에서 코드를 작성해야 합니다. viewDidAppearoverride func viewDidAppear() {     super.viewDidAppear()     // 화면 출력이 끝났답니다. 마음껏 코딩하세요! } 네, 지금까지 루키들을 위한 GUI 만들기의 기본 과정은 다 알려드렸습니다. 많은 개념과 기능, 방법론이 존재하지만 일단 이 정도면 알아도 첫 번째 iOS 앱 UI를 만들 준비는 어느 정도 마친 겁니다. 그럼 마지막으로 UI를 구성하면서 유용하게 사용할 수 있는 팁을 알려드리겠습니다. 8.Little Tricks1) Clip it, or not Clip it.ImageView를 다루다 보면 자주 발생합니다. 지정된 ImageView의 사이즈보다 이미지가 크면 이미지가 ImageView의 영역을 빠져나가버리는 건데요. 이것은 Label이나 View에서도 동일합니다. 작성한 컨텐츠가 부모 View보다 큰 경우 부모 View의 프레임을 벗어납니다. 이런 경우, 재부팅하세요. clipsToBounds 값을 true로 지정해주면.. view.clipsToBounds = true 매-직! 이 작업은 코드뿐만 아니라 Storyboard상에서도 가능합니다. Xib에서도 동일합니다. Storyboard에서 클리핑2)Circular View요즘 많이 사용하는 동그라미 모양 프로필 이미지 때문에 고생하는 고심하는 개발자들이 많을 겁니다. iOS에서는 이 작업을 view의 Layer를 편집하는 방식으로 아주 간단하게 처리할 수 있습니다.self.layer.cornerRadius = self.frame.size/2.0 self.layer.masksToBounds = true self.clipsToBounds = true 위의 코드를 사용하면 아래와 같은 이미지를 출력할 수 있습니다.둥글게 클립핑된 최신 트렌드의 ImageView를 간단하게 출력했습니다. 물론 위에서 언급한 clipsToBounds 값을 true로 지정해주는 것도 잊지 마시고요. 이 코드를 응용하면 모서리가 둥근 직사각형 뷰도 만들 수 있습니다. 원하는 곡률을 적용할 수 있죠. view의 Layer를 다루는 방법을 공부한다면 다양한 상황에서 유용하게 사용할 수 있을 겁니다.3)NSAtrributedString 클라이언트가 다양한 형태의 Font, Color의 텍스트를 한 문장에 넣어달라고 한다면 어떻게 작업해야 할까요? 스타일마다 Label 묶음을 만들어서 각각의 단어를 지정해주는 방법이 있습니다. 하지만 텍스트 또는 문장 구성이나 스타일이 서로 다른 묶음으로 변경된다면 어떨까요? 또 다시 새로운 기준으로 Label 묶음을 만들어야 할까요? 이럴 때 사용하기 좋은 녀석이 바로 NSAttributedString입니다. 볼드체, 보통체가 혼합된 텍스트에 색상이 다른 텍스트가 혼재되어 있는 Attributed String이렇게 다양한 형태의 텍스트를 한 문장에 담을 수 있고, 변경되는 내용이 있더라도 코드로 간단하게 수정하면 됩니다. 브랜디 앱에서도 NSAttrributedString을 많이 사용하고 있습니다. 브랜디 iOS 앱의 간지나는 UI 속 요소요소를 차지하고 있는 중요한 녀석이죠. 4)Debug Wirelessly 각종 케이블이 난잡하게 널부러진 책상을 보면 한숨이 나옵니까? 걱정하지 마세요. 이제 하나는 줄일 수 있을 겁니다. Xcode로도 무선 디버깅을 할 수 있기 때문이죠. 먼저 디바이스를 맥에 연결하고, Xcode가 활성화된 상태에서 Window > Devices And Simulators 항목을 클릭합니다. Devices and Simulators그런 다음 출력된 화면에서 원하는 디바이스를 선택하고 Connect via Network를 체크 합니다. (디바이스에 암호가 설정되어 있어야 합니다.) 지구본 모양이 디바이스 오른쪽에 있다면 무선 디버깅이 가능한 상태입니다. 무선디버깅체크9.Outro: 긴 글을 마무리하며아장아장 걸음마 시절이던 첫 개발 프로젝트 작업이 생각납니다. 클라이언트는 끝도 없이 요구를 하는데 구현하는 방법을 몰라 막막했던 적이 많았습니다. 여러 실수를 겪고 나서야 많은 것을 알게 되었죠. 그때를 생각하면 이제 막 iOS 개발을 시작하는 분들께 하나라도 더 도와주고 싶답니다. 지금 막 iOS 개발자가 되었나요? 그렇다면 이 포스팅은 분명 당신의 검색 한 번, 실수 한 번을 줄여줄 수 있을 겁니다.글이정환 과장 | R&D 개발1팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발자 #개발팀 #인사이트 #경험공유 #iOS
조회수 1272

AWS Lambda + API Gateway로 API 만들어보자

Overview좋은 아침입니다. 오늘은 AWS Lambda와 API Gateway 이용하여 API를 만들어보겠습니다. 서버 구축부터 해야 하지만 이번 글에서 서버는 따로 필요 없습니다. 당황하셨나요? 괜찮습니다. 이 글을 보면 곧 이해가 될 겁니다. 우선 Lambda와 API Gateway부터 알아봅시다. Lambda는 서버를 프로비저닝하거나 관리하지 않고도 코드를 실행할 수 있게 해주는 컴퓨팅 서비스입니다. 브랜디 랩스에는 이미 이것을 활용한 예제가 많은데요. 아마 아래의 포스팅들을 보시면 도움이 될 겁니다.SQS + Lambda: 이상근 팀장님CodeStar + Lambda + SAM으로 테스트 환경 구축하기: 천보성 팀장님API 호출부터 결과 확인까지API Gateway는 규모에 상관없이 API 생성, 유지 관리, 모니터링과 보호를 할 수 있게 해주는 서비스입니다. 이 글에서는 API를 호출해 결과를 확인하는 걸 목표로 진행하겠습니다.최종 API 호출 URL* GET /v1/reviews/{review-no}/comments* POST /v1/reviews/{review-no}/comments AWS(Amazon Web Service) 가입 절차는 생략하겠습니다. 1.AWS 로그인 후 API Gateway 시작!AWS에서도 설명되어 있듯이 API gateway엔 이와 같은 장점이 있습니다.1. API 개발 간소화: 새로운 버전을 신속하게 반복하고, 테스트하고, 출시할 수 있습니다.2. 규모에 따른 성능: 백엔드 시스템에 대한 트래픽 관리하여 유동적으로 API 호출하여 성능을 높이는데 도움이 됩니다.3. SDK 생성: 사용자 지정 SDK를 만들어 애플리케이션에서 신속하게 API를 테스트하고 배포할 수 있습니다. 2.API 생성새 API로 엔드 포인트 유형을 지역으로 선택하여 생성하세요. 엔드 포인트 유형1. 지역 : 현재 리전에 배포2. 최적화된 에지 : CloudFront 네트워크에 배포3. 프라이빗 : VPC에서만 엑세스 가능3.최종 호출 url로 순차적으로 리소스 생성리소스 이름과 리소스 경로를 입력하고 리소스를 생성합니다.리소스는 호출할 수 있는 특정 URL입니다. 생성된 리소스로 /reviews 주소가 만들어졌습니다.다음은 /reviews 주소 뒤에 {review-no}를 생성합니다. 리소스 경로에 {} 가 포함되어 있으면 경로 파라미터를 나타냅니다.마지막 리소스를 생성하게 되면 위의 이미지와 같이 /reviews/{review-no}/comments 리소스가 생성되었습니다. 이제 메서드에 연결할 Lambda 함수를 먼저 생성하겠습니다.4.Lambda 함수 생성GET, POST 메서드에 연결할 각각의 Lambda 함수를 생성합니다.‘Hello from Lambda’ 문자열로 리턴되는 Lambda 함수가 생성되었습니다. 생성된 Lambda 함수를 API Gateway 메서드에 연결해보겠습니다.5.메서드 생성GET, POST 메서드를 생성합니다.메서드의 의미* POST : 새로 생성(Create)* GET : 조회(Read)* PUT : 수정(Update)* DELETE : 삭제(delete)* PATCH : 일부만 수정(Update) 새 메서드의 통합 유형을 Lambda 함수로 선택하고 기존에 생성한 함수명으로 입력한 다음 저장을 누릅니다.메서드 실행 화면입니다. 해당 메서드에 통합 요청할 Lambda 함수가 연결됩니다. 연결된 Lambda 함수를 눌러보겠습니다.왼쪽 목록 트리거 추가하는 부분에 API Gateway가 연결되었습니다. 그럼 이제 정상적으로 호출되는지 테스트해보겠습니다.테스트를 클릭하면 오른쪽에 요청에 대한 결과가 나옵니다. 조금 전에 연결했던 Lambda 함수에 ‘Hello from Lambda’ 값으로 출력됩니다. 이제 리소스로 추가한 경로 파라미터를 매핑하여 출력해보겠습니다.메서드 요청에서는 사용자에게 노출되는 API를 정의할 수 있습니다. 리소스로 경로 파라미터를 추가하게 되면 메서드 요청 -> 경로 요청 부분에 자동으로 추가되어 있습니다.통합 요청에서는 백엔드와의 통신 방식을 지정할 수 있습니다. 메서드 요청에서 보낸 URL 경로 부분을 매핑시켜야 합니다. 명명 규칙은 아래와 같습니다. method.request.{"path" | "querystring" | "header"}.{param_name}매핑 템플릿을 추가하여 수신된 요청을 변환하여 통합 백엔드로 보내야 합니다. 정의된 템플릿이 없기 때문에 매핑 템플릿을 추가한 후 메서드 요청 패스스루로 지정합니다. 그러면 클라이언트가 제공한 요청이 변환없이 통합 백엔드로 전달됩니다.클라이언트가 요청한 경로 파라미터 출력하도록 Lambda 함수를 수정합니다.이제 다시 테스트를 해보겠습니다. 경로에 값을 요청하여 응답 본문에 출력되는 걸 확인할 수 있습니다.6.API 배포스테이지 정보를 입력하고 배포를 클릭합니다.스테이지 상세 정보에 API 호출 주소가 생성됩니다. Postman으로 생성된 API주소를 입력하여 정상적으로 return 값을 확인합니다.Conclusion정말 긴 과정이었습니다. 지금까지 API Gateway를 이용하여 API 생성부터 배포까지 알아봤습니다. API Gateway를 사용하면 서버 없이 높은 확장성을 가진 백엔드 애플리케이션을 구축하고 운영할 수 있게 될 겁니다. 백엔드에 관심이 있는 개발자에게 이 글이 도움이 되길 바랍니다.글곽정섭 과장 | R&D 개발1팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발자 #개발팀 #인사이트 #경험공유
조회수 6315

[SQL 데이터분석] 증감율 구하는 간단한 방법

sql에서는 = 등호가 비교연산자로 사용됩니다.대신 := 이렇게 콜론(:)과 등호(=)를 같이 쓰면 대입연산자로 쓸 수 있어요.select @prev := users.id // @prev 라는 임시변수에 users.id 값을 넣어라. from users가입일자로 사용자수를 구해보면, 아래처럼 가입일로 group_by 를 해서 구하죠.select date(created_at) as '가입일' , count(1) as '가입자수' from users group by 1 order by 1 desc;// 가입일 | 가입자수 // --------------------------- // 2017-08-02 100 // 2017-08-01 50그럼 전일 대비 증감율을 구하려면 어떻게 할까요?select date(created_at) as '가입일' , @prev as '전일 가입자수' , (count(1) - @prev) / @prev as '증감율' , @prev := count(1) as '가입자수' from users group by 1 order by 1 desc;// 가입일 | 전일 가입자수 | 증감율 | 가입자수 // -------------------------------------------------------- // 2017-08-02 50 1.0 100 // 2017-08-01 50 0 50증감율을 계산하는 count(1) / @prev까지는 @prev 에 전일 가입자수가 저장되어 있구요.@prev := count(1) 에서 당일 가입자수로 할당이 됩니다.저는 := 이 연산자를 알기 전엔 self-join 형태로 증감율을 구했는데데이터를 가오는 속도는 := 이 연산자가 훨씬 빠른것 같습니다.다음엔 self-join 으로 증감율을 구하는 법도 한 번 올려볼께요.#티엘엑스 #TLX #개발 #개발팀 #개발자 #꿀팁 #인사이트 #조언
조회수 1087

잔디 iOS 개발자 Chris, 그가 처음으로 공개한 '잔디 1호 사원' 스토리

편집자 주: 잔디와 함께 하고 있는 멤버는 총 50여 명. 국적, 학력, 경험이 모두 다른 이들이 어떤 스토리를 갖고 잔디에 합류했는지, 무슨 일을 하고 있는지 궁금해하는 분들이 많습니다. 잔디 블로그에서는 이 궁금증을 해결해 드리고자 ‘맛있는 인터뷰’를 통해 ‘잔디’ 멤버들의 이야기를 다루고 있습니다.◇ 우리가 앉아 있는 이 공간이 어떤 곳인지 소개해 달라Chris: 설마 했다. 내가 맛있는 인터뷰 대상자가 될지는.. 머리가 멍해 고통받던 중 당신이 추천한 그릴 타이로 오늘 장소를 선정했다. 이름만 들었을 땐 ‘거기 뭥미?’ 이랬는데, 와보니 알겠다. 예전에 와 본 적이 있다.◇ 자기소개 좀 해달라C: 반갑다. 잔디에서 iOS 개발 파트를 담당하고 있는 1호 사원 Chris라고 한다. 아주 오랜 기간 동안 원래 이름인 ‘봉규’라고 불렸다가 얼마 전 회사 내 호칭에 변화가 생겼다. 아직 Chris로 불리는 게 어색하다.◇ 어떤 일을 하며 월급을 받고 있는지?C: 앞서 소개했듯 난 iOS 개발자다. 이 글을 읽는 독자분들 중 아이폰으로 ‘잔디’를 사용 중이라면, 필시 내가 개발한 잔디를 이용하고 있는 거다. 마음이 조금 아프지만 기획에 대한 관심으로 지난 겨울 잠시 PM 팀으로 외도했었다. 하지만 결국 내 마음의 고향, iOS 개발로 돌아왔다.◇ PM팀으로 외도를 했던 이유가 궁금하다C: 기획이라는 업무에 관심이 많았다. 개발을 하다 보니 자연스레 기획에도 관심을 갖게 되었다. 한 번쯤 해보고 싶었던 일이었기 때문에 롤이 주어졌을 때 정말 재미있게 일했다.하지만 PM 일을 직접 해보니 마냥 재미있기만 하지는 않더라. 비즈니스는 물론이고 개발자와 디자이너의 의견을 수렴해 조율까지 해야 하는데 모두의 의견을 100% 반영할 수 없으니 여간 괴로운 일이 아니더라. 기획자의 길이 쉽지 않다는 것을 깨닫게 되었다.그리고 PM의 업무라는 게 쉽게 눈에 띄지 않는 일이다. 제품이 아무리 잘 나와도 기획자에게 ‘기획 참 잘나왔어요’ 라고 말하는 경우를 많이 접하진 않았을 거다. 여러분 주위에 기획자를 만나게 되면 ‘고생이 많으십니다’라고 응원 한마디 해줬으면 좋겠다.◇ iOS 개발자로 컴백한 이유는 무엇인가? 향간의 소문엔 코딩이 그리워 개발자로 돌아갔는 소문이 있다C: 회사 측에서 기획보다는 iOS 개발을 다시 맡아주면 좋겠다는 이야기를 들었다. 사실 별다른 고민 없이 제안을 받아들였다. 아무래도 초기부터 개발한 자식 같은 iOS가 늘 머리 한 구석에 있었다. 물론, 잔디를 사랑하는 마음도 크게 한 몫 했다. 결코 어필하고 싶어 이런 멘트를 남기는 게 아니다.◇ 보여주기 멘트인 것 같지만 감동 받았다. 그렇다면 Chris에게 잔디 iOS란 무엇인지 조금 더 말해달라C: 나의 분신이다.  iOS는 곧 Chris다. 아무것도 없는 백지상태에서 지금에 이르기까지 수많은 과정이 있었고, 그 과정의 중심엔 언제나 내가 있었다. iOS는 분신이라는 단어 외엔 표현할 방법이 없다. 오바가 아니라 사무실 어딘가에서 누군가 ‘iOS’ 라고 속삭이면 몸이 반응한다. iOS에 대한 이야기는 곧 나에 대한 이야기와 마찬가지이니까.내가 곧 잔디 iOS이자, 잔디 iOS가 곧 나이다.그만큼 애착을 갖고 개발 업무에 임하고 있다.◇ 멘트가 찰지다. 듣기론 PM 팀의 데니스와 특별한 인연이 있다고 하는데?C: 동아리 이야기를 하는 것 같다. 사회에 나오기 전 연합 동아리 활동을 한 적이 있는데, 데니스가 그 동아리 후배다. 기수 차이가 많이 나 직접적으로 알던 사이는 아니었다. 내가 동아리에 잔디 채용 공고를 공유해 데니스가 합류하게 되었다. 특별한 인연이라면 특별하다고 볼 수 있다.◇ 어떤 동아리인지 궁금하다SOPT라는 연합 동아리로 선배들이 후배들에게 개발/디자인 등에 대해 강의하는  동아리다. 당시 나는 학년 차가 조금 되어 수업을 듣기보단 가르치는 역할을 맡았어야 했는데, 매주 시간을 내어 수업을 준비할 자신이 없어 디자인 수업을 들었다.◇ 잔디 1호 사원은 역시 남다른 것 같다. 디자인 수업은 어땠는지?C: 그 수업을 통해 내가 디자인에 소질이 없다는 사실을 깨닫게 되었다. 그림을 그리면 늘 내가 생각한 것과는 다른 결과물이 나오더라.◇ 그런데 정말 잔디 1호 사원인가?C: 말 그대로 1호 사원이다. 회사가 법인으로 등록하기 이전부터 함께 했다. 얼마 전 잔디 2주년 파티가 있었다. 나는 입사한 지 2년이 넘었다. 격세지감을 느낀다. 처음 잔디에 들어왔을 때, 나를 제외한 모든 사람이 C-Level이었다. 그리고 나서 개발자, 디자이너가 순차적으로 들어왔던 걸로 기억한다.◇ 법인 설립도 전에 잔디를 어떻게 알고 지원했나?C: 제대를 3개월 앞둔 군인 시절, 아이폰 개발자를 찾는 연락을 받았다. 그렇지 않아도 제대하고 바로 개발 경험을 쌓을 수 있었으면 좋겠다고 생각했다. 솔직히 말하면 그 당시엔 잔디가 어떤 회사인지 탐색이나 해보자는 생각에 멤버들을 만났다.◇ 그럼 사람들을 만나고 입사를 결심한 건가?C: 당시에는 아무것도 없었다. 잔디라고 말은 해도 유형적인 형태의 무언가가 존재하지 않았다. 멋진 사람들과 함께하며 일을 배울 수 있을 것 같다는 생각에 합류했다.◇ 마음가짐이 남다를 것 같다C: 내 스스로 창립 멤버라 생각하고 있다. 어찌 되었든 잔디가 지금의 모습을 갖추기 전부터 함께 해서인지 애착이 남다르다. 첫 직장이라는 사실도 한 몫하고 있고.◇ 그때로 다시 돌아가면 똑같은 결정을 할 것인가?C: 물론이다. 솔직히 좋은 결정이었다고 생각한다. 잔디가 이렇게 잘 성장하고 있고, 지금은 누구보다도 잔디의 성공을 확신한다.◇ 마지막 질문이다. 여름 휴가 계획은?C: 스타트업인이 휴가라니? 하하. 농담이다. 아쉽지만 아직 여름 휴가 계획이 없다. 생기면 알려주겠다.◇ 맛있는 인터뷰의 공식 마무리! 다음 인터뷰이에게 묻고 싶은 질문이 있다면?C: 꼭 물어봐 주셨으면 한다. “잔디에서 이루고 싶은 꿈이 있다면?”을 물어봐 달라.#토스랩 #잔디 #JANDI #iOS #개발자 #모바일개발자 #앱개발자 #팀원소개 #팀원인터뷰 #팀원자랑 #기업문화 #조직문화 #사내문화
조회수 935

DevOps 문화 안에서의 APM의 역할 [2] (DevOps+JENNIFER)

전편에서는 개발 프로세스 내에서 모니터링 단계의 문제점과 이를 해결하기 위한 방법으로 APM의 역할이 DevOps 진영에서는 매우 중요한 이슈가 되고 있다고 정리했었다. 또한 모니터링 프로세스의 세부 단계와 모니터링 기준 값 설정에 대한 내용을 다뤘는데, 이를 기반으로 제니퍼를 활용하여 모니터링하는 방법에 대해 알아보려고 한다.장애 발견 및 알림제니퍼에서 이벤트 발생 조건은 컴파일 에러나 응답 시간 초과, OOM과 같은 애플리케이션 에러 유형이나 액티브서비스 개수, 응답 시간, CPU 사용률, 힙 메모리 사용률 등 서비스나 시스템의 상태 값으로 설정될 수 있다. 그리고 이벤트 설정시 외부연동 활성화 기능을 사용할 수 있으며, SMTP(Simple Mail Transfer Protocol) 모듈을 기본으로 제공한다. 또한 고객이 직접 이벤트 모듈을 구현할 수 있도록 인터페이스와 유틸리티를 제공한다. 참고로 제니퍼를 사용하는 고객사 중에서 자체적으로 구축한 관제 시스템에 제니퍼 이벤트를 연동하여, 별도의 WAS 경고 시스템을 만든 사례도 있다.   서비스 부하량 제어 (운영)제니퍼는 PLC(Peak Load Control)라는 서비스 부하량을 제어할 수 있는 기능을 제공한다. 트랜잭션 유입 차단의 기준이 되는 최소/최대 액티브서비스 개수를 설정하고, 해당 임계치 값 초과시 사용자에게 가이드해줄 수 있는 메시지나  리다이렉트 페이지를 설정할 수 있다.   만약에 대상 애플리케이션(서버 또는 WAS)이 처리 중인 액티브서비스 개수가 설정한 임계치 값을 초과하면 들어오는 사용자 요청은 거절되며 액티브서비스 이퀄라이저 차트의 요청 효과가 반사되고, 색상 또한 붉은색 계통으로 변하게 된다.사용자의 요청(Request)이 거절되면 PLC 관리 화면에서 설정한 메시지가 보이거나 아래와 같은 화면으로 리다이렉트 되며, 모니터링 대상 애플리케이션의 액티브서비스가 임계치보다 낮아지면 원래의 화면으로 돌아올 수 있다.  장애 원인 분석 (개발)개별 트랜잭션에 대한 프로파일 데이터를 분석하기 위해서는 대상이 되는 패키지나 클래스를 알아야 하는데, 적용 범위에 따라 프로파일 데이터 크기가 매우 커질 수 있으므로 실제로 운영되는 서비스에는 큰 부담이 될 수 있다. 하지만 제니퍼의 자동 프로파일링과 스택트레이스 기능은 설정한 응답시간을 초과한 트랜잭션에만 적용되기 때문에 실제 운영 단계에서 사용하기에 적합하다. 프로파일이란 트랜잭션의 시작점이 되는 메소드의 호출 구조를 상세하게 분석하는 기능을 말하며, 스택트레이스는 앞에서 설정한 기준 값을 초과하는 순간에 호출된 메소드 구조에 대한 로그를 남기는 것을 말한다. 만약에 설정한 응답시간을 초과하여 의심이 될만한 트랜잭션을 분포도 차트에서 찾았다면, 트랜잭션 분석 화면을 통해 문제 시점의 스택트레이스 정보를 참고하거나 응답이 지연되는 프로파일 데이터를 구간 별로 검색하여 콜-트리를 통해 문제가 되는 메소드 위치를 정확히 알아낼 수 있다.소스코드가 배포되었다면 트랜잭션 분포도 차트에서 배포 시점에 세로 축이 하나 그려진다. 해당 축을 선택하면 새로 추가되거나 수정된 리소스 목록을 조회할 수 있으며, 리소스의 배포 전/후의 내용을 분석하는 코드리뷰 기능은 개발 환경에서 반영된 소스코드를 분석해야하는 번거로움을 덜어준다.배포 이후에 액티브서비스가 빠르게 처리되지 못하고, 트랜잭션 분포도 차트가 기존의 패턴과 다르게 형성이 된다면 새로 반영된 소스코드에 문제가 있을 가능성이 매우 높다.결론인류 사회에서 자신이 속해 있는 환경과 전혀 다른 이질적인 문화나 새로운 생활 양식을 접할 때 받는 충격과 공포를 문화 충격(Culture Shock)라고 하는데, 이는 IT 분야에서도 크게 다르지 않다. 사실 DevOps는 몇년 전부터 계속 주목받고 있으며, 많은 소프트웨어 개발 조직에서 시도하고 있는 개발 방법론이다. 하지만 새로운 문화에 대한 거부감으로 인해 제대로 적용되지 못하고 있는 것이 현실이다.DevOps가 추구하는 가치인 존중과 신뢰를 바탕으로 개발과 운영의 원활한 의사소통과 협업 관계 형성은 말처럼 쉽지 않다. 어떻게 보면 이상적일 수 밖에 없는 추상적인 개념이지만 본문에서 다뤘듯이 APM을 상호 간의 의사소통 도구로써 잘 활용한다면 이상이 아닌 보다 현실에 가까워질 수 있다고 필자는 확신한다. APM은 소프트웨어 제품과 서비스를 빠른 시간에 개발 및 배포하는 것을 목표로 하는 DevOps를 개발 문화로 성공적으로 정착시키는데 가장 중요한 역할을 하는 도구라고 생각한다.
조회수 1407

잉여와 SW 개발의 관계...

IoT의 관점과 함께 최근에 주목을 받는 시계열 DB들이 있다. OpenTSDB나 인플럭스 DB, Graphite와 같은 것들이다. 신기한 것은 최신의 기술이나 플랫폼이라고 불리는 것들은 국내에서는 거의 등장하지 않는다. 대부분 미국이나 유럽, 이제는 중국이나 러시아에서 등장한다. 물론, 일본에서는 새로운 언어도 많이 등장했다.집안의 전기 사용량을 측적하건, 공기 측정이 되었건 1초에 한번 측정하는 센서에서 만들어지는 데이터를 자세하게 분석하려면 이 데이터를 수집하고 모아야 한다. 그리고, 최소 연단 위 정도는 모아서 무언가를 분석하거나 추이를 살펴보아야 할 것이다.더군다나, 센서가 하나가 아니라 여러 개 라면 모여지는 데이터의 량은 상당할 것이다. 기존의 RDB에 축적하는 것은 이런 경우에 좀 맞지 않는다. 데이터가 계속 용량을 늘려나가는 구조이기 때문에 NoSQL형태의 데이터 스토어를 생각하게 된다. 코치이건 하둡이건 몽고이건 여러 가지가 생각난다. 실시간으로 추적 분석하려면 Apache Storm이나 spark도 생각날 것이다.일단, 센서가 시간의 추이에 따라서 데이터를 모으는 형태에 적합한 시계열 DB에 적합한 방법들에 대해서 나름 적합한 형태로 개발되는 구조를 가진 DB들을 어렵지 않게 찾아볼 수 있다. 이 글 가장 앞에 언급한 것들이다.관련 자료를 찾아보고 싶으면, OpenTSDB는 http://opentsdb.net , InfluxDB는 https://influxdb.com을 찾아보라. 나름 매력적으로 시계열 형태의 데이터를 모으기 좋은 구조로 디자인되는 설루션을 만날 수 있다.오늘 글에서 언급하고 싶은 것은... 이러한 특정 요점에 맞는 설루션들이 왜? 국내에서는 나타나지 않는가에 대해서 끄적거려 보고 싶어서이다. 과연, 이러한 태도와 행동, 행위가 특정 개발자의 탁월함 때문일까? 아니면, 국내에 있는 개발자들이 게으르고, 자신의 이익만을 위해서 일하는 것 때문일까?삐딱한 아키텍트는 그 부분을 이렇게 해석한다.하나. 잉여가 없는 부가가치가 적은 일을 매번 수행하는 국내의 경영자들의 문제.둘. 반복적인 작업이나 자신의 일의 미래에 대해서 큰 관심 없는 개발자의 자세셋. SI형태로만 진행되는 국내 프로젝트이기 때문에 만들어진 플랫폼이나 유틸리티 성의 서비스를 외부에 오픈하지 못하는 경우가 빈번함.이 3가지의 가장 큰 이유 때문에 국내에서는 특정 용도나 특정 의미의 환경에 잘 어울리는 설루션들이 오픈소스로 발전되고, 더 넓게 쓰이는 플랫폼까지 진화하지 못한다고 생각한다. 하나씩 나름대로 이유를 이야기해보자.하나. 잉여가 없는 부가가치가 적은 일을 매번 수행하는 국내의 경영자들의 문제일단, 부가가치가 높은 소프트웨어나 서비스를 개발한다면, 적절하게 배분되어진 팀과 일정, 부가가치가 높기 때문에 피드백을 통해서 품질을 높이기 위한 시도들이 반복되어진다. 하지만, 대부분 1회성으로 끝나거나, 단기적인 일거리를 해결하기 위해서 소프트웨어를 개발하는 경우가 대부분이기 때문에 사소한 잉여도 발생하기 어렵다.고품질을 지향하는 소프트웨어 개발을 추구한다면 매우 당연하게 잉여시간과 잉여 일정, 잉여인력이 투입되는 것이 정상이다. 매우 당연하게 소프트웨어 개발자들은 게으르기 때문에 반복적인 일을 싫어하고, 게으르기 때문에 소프트웨어의 품질을 높이기 위해서 공을 들인다.이런 게으른 소프트웨어 개발자들이 품질 높이기를 포기하는 이유는 간단하다. 그 소프트웨어가 재사용될 가능성이 거의 존재하지 않고, 또다시 요구사항에 따라서 난도질을 해야 하는 경우에 품질 높이기를 시도하지 않는다.결론적으로 소프트웨어 개발자들이 고품질을 만들지 않는 이유는 처음부터 비즈니스 기획과 부가가치에 대한 이윤과 투입되는 비용에 대해서 잘못된 비즈니스 모델을 만든 기획자나 경영자가 그 책임을 져야 한다. 물론, 그런 환경을 주었더라도 잘못된 개발자를 뽑은 '인력관리'의 미스에 대해서도 그 역시... 경영자가 책임져야 한다.대부분 고품질의 소프트웨어가 나타나지 않거나, 잉여가 만들어지지 않는 이유는 경영자가 미 숫하고, 비즈니스 모델을 잘못 디자인해서 그러하다.둘. 반복적인 작업이나 자신의 일의 미래에 대해서 큰 관심 없는 개발자의 자세하지만, 경영자의 잘못과 거의 비슷한 수준의 개발자의 관심 없는 자세인 경우가 문제가 되는 경우도 많다. 잉여가 주어졌음에도 빈둥거리거나, 자신만의 놀이를 위해서 그 시간과 비용을 투자하는 경우도 간혹 있다. 하지만, 필자가 만나본 대부분의 개발자들은 그런 자세가 된 소프트웨어 개발자의 행태 또한 그 소프트웨어 개발자가 걸어온 그 전회사의 경영자의 문제라고 지적하고 싶다.반복적인 일을 줄이고, 미래의 코드에 대해서 신경 쓰는 자세는 소프트웨어 개발자가 기본적으로 갖추어야 하는 자세임에도 불구하고, 이러한 자세를 파괴하는 형태의 업무 구조와 생각 자체를 파괴하는 형태로 일을 구성하는 경영진과 같이 일한 개발자들은 슬프게도 잉여를 빈둥거리게 하는데 익숙하게 된다.필자가 개발자 구인 시에 가장 주목하고, 관심을 가지면서 걸러야 하는 개발자는 그러한 회사를 거쳐왔거나 그러한 프로젝트에 매몰되었던 사람들은 피하는 것이다. 한번, 그런 자세가 파괴된 개발자는 다시 자세를 정상으로 복구하는데 엄청난 리소스와 시간이 투입된다.냉정한 사람들이라면 이러한 사람들을 '동료'로 받아들이는 것을 싫어할 것이다.셋. SI형태로만 진행되는 국내 프로젝트이기 때문에 만들어진 플랫폼이나 유틸리티 성의 서비스를 외부에 오픈하지 못하는 경우가 빈번함.슬프지만, 3번째의 경우가 사실은 한국에서는 50% 이상 의미 있는 형태로 개발되었음에도 불구하고, 사장되거나 외부에 노출될 수 없는 형태가 되는 경우를 빈번하게 경험했다. 필자 역시, WebService개발 초기에 3 Tier개발에 어려움을 겪는 개발자들을 위해서 SQL 문장을 그대로 WebService에서 CRUD형태로 전송하고 데이터셋과 DB커서를 2 Tier의 형태로 손쉽게 개발할 수 있는 플랫폼과 컴포넌트를 개발했지만, 이 역시, SI에 종속된 결과물이 되면서 외부에 오픈할 수 없는 경우가 되는 것을 빈번하게 경험했다.슬프지만... 이 3가지의 큰 이유 이외에도 '잉여'가 없는 개발 일정이나 개발자에게 여유가 없어지면서, 정말 더럽게 재미없는 소프트웨어 개발이 반복되는 경우를 많이 보았다. 하지만, 필자의 경험은 그럼에도 불구하고 개발을 총괄하고 있다면, 자신의 팀에 있는 개발자에게 약간의 잉여와 고품질을 위한 리소스에 대한 배려를 취하면서 동료직원이 오픈소스를 창출하거나 외부에 오픈할 수 있는 정도의 다듬는 여유를 만들어 줄 수 있다고 생각한다.가장 훌륭한 CTO나 개발 총괄의 역할은 그 시간을 정말 즐겁다고 생각하는 동료 개발자에게 약간의 잉여와 여유를 허가하는 것이며, 그 잉여가 결론적으로 자신이 속한 개발 조직의 효율이 향상되고, 개발 문화가 부드러워지는 아주 의미 있는 개발 조직으로 완성되어가는 첫 번째 단추라는 것을 알기를 바란다.현재 훌륭한 개발 조직일수록, 카페와 같은 공간만을 만드는 것만으로 끝나는 것이 아니라, 개발 공정이나 개발 프로세스 상에 리뷰와 의미 있는 문서화 작업, 피드백과 리팩터링과 같은 시간을 배분하는 이유도 그 때문이라는 것을 잊지 않기를 바란다.훌륭한 하드웨어 적인 공간 위에 재미를 추구하고 의미를 추구하는 잉여가 존재하는 개발 공정을 탑재한 개발 조직이야말로 성공할 수 있는 전제조건을 하나 더 갖춘 곳이라는 것을...

기업문화 엿볼 때, 더팀스

로그인

/