스토리 홈

인터뷰

피드

뉴스

조회수 1547

개발자 직군 파헤치기 3 | 블록체인 개발자

이번 포스팅은 블록체인 개발자!2017년 대한민국은 가상화폐의 광풍에 휩싸이게 된다. 남녀노소 가릴 것 없이 많은 사람들이 가상화폐에 투자를 했다. 전 세계에 유례가 없을 정도로 국내 가상화폐 투자 열기는 뜨거웠으며 해외의 가상화폐 투자자들은 국내 투자자들의 움직임에 예의주시하면서 투자할 정도였다.이와 동시에 가상화폐의 기술적 원천이 된 블록체인(Block Chain) 기술에 대한 관심도 증가했다. 제2의 인터넷이 될 거라는 찬사를 받으면서 가상화폐의 부상은 뜨거운 관심의 대상이었다. 정부의 가상화폐 규제가 있었지만 시장에서는 블록체인 기술의 잠재적 가능성에 주목을 하면서 이것을 가지고 어떻게 혁신적인 서비스를 제공할지 고심하고 있다. 이에 따라 일반 개발자는 물론이고 기업에서도 블록체인 개발자에 대한 수요와 관심이 늘고 있다.이러한 관심 때문에 개발자를 꿈꾸는 많은 분들이 블록체인 개발자는 무엇을 하고 어떻게 될 수 있는 것인지 궁금해하고 있다. 그래서 이번 포스팅에서는 블록체인 개발자가 되기 위해서는 어떻게 해야 하는지와 더불어, 블록체인 기술에 대한 전망 그리고 블록체인 개발자의 시장 수요에 대한 글을 써 볼 것이다.*이 글은 블록체인 기술에 대한 자세한 설명은 하지 않고 있습니다.*Photo by Andre Francois on Unsplash미래를 여는 신기술, 블록체인의 전망블록체인 기술이 뜨고 있다고 하지만 도대체 어떤 분야에서 적용될 수 있기에 이렇게 많은 관심을 받고 있는 것일까? '딱 이 분야가 유망합니다'라고 말하기가 어려울 정도로 블록체인은 폭넓은 분야에 걸쳐서 파괴적인 혁신성을 가지고 있다. 그중  몇 가지만 추려서 이야기하고자 한다.1. 금융, 은행블록체인의 기술의 특징은 탈 중앙화, 신뢰성, 보안성이다. 전문가들은 기존의 은행들이 하던 업무를 핀테크 기업들이 혁신적인 서비스와 가격으로 대체할 것으로 예상한다. 블록체인 기술이 가지고 있는 신뢰성과 보안성으로 인해 일반 기업들도 거대 은행이 보유하고 있는 보안성을 획득할 수 있는 것이다. 거래 과정에서 제3자를 거치지 않기 때문에 거래의 속도와 효율성 그리고 경제성이 크게 증가한다.핀테크 스타트업뿐만 아니라 거대 금융권의 은행들이나 기존의 대기업들도 블록체인 기술을 이용한 서비스를 발 빠르게 준비하고 있다. 마스터카드는 블록체인 기술을 통해 즉석 지불 시스템을 개발하고 있다. 또한 글로벌 기업 IBM은 서로 다른 국가에 위치한 금융 기관이 블록체인 기술을 이용해서 결제를 처리할 수 있도록 하는 뱅킹 솔루션을 개발했다.현재 이더리움이 선도하는 스마트 계약도 금융권에서 주목하는 분야다. 스마트 계약은 특정 조건이 충족되면 은행과 같은 제3자를 거치지 않고 계약을 이행하게끔 도와준다. 예를 들어, 납품 기업과 발주 기업이 스마트 계약을 맺었다. 납품 기업이 발주 기업의 창고에 물품을 보내고 물품이 도착을 하면(IOT 센서로 감지된다) 납품 기업은 자동으로 결제 대금을 자동으로 받게 된다.2. 물류위에서 블록체인 기술의 특징 중 신뢰성과 보안성을 언급했다. 정보의 신뢰성과 보안성은 물류 시스템에도 파급력을 미칠 것이다. 많은 전문가들이 블록체인으로 인해 물류 시스템에 혁신적인 변화가 가능하다고 말한다. 블록체인 기술이 어떻게 물류 시스템에 적용될 수 있는지 직접 예시로 살펴보자.영국의 소프트웨어 회사 프로비넌스는 블록체인 기술을 이용해서 소매업자와 식당들이 원래 계약했던 대로 재료가 들어오는지 확인할 수 있게 만들었다. 트래킹(tracking) 기술과 결합하여 만든 이 소프트웨어는 재료가 수확되는 과정부터 최종 소비자가 구매하는 단계까지 꼼꼼히 추적하고 관리한다. 공급망의 모든 단계에서 변경 불가능한 데이터가 블록에 추가된다. 이 소프트웨어를 통해 소비자들은 자신이 무엇을 먹는지, 기업이 불법 조업을 통해 재료를 조달한 것이 아닌지, 이 농작물에 대한 적절한 보상이 농부에게 돌아갔는지, 이 식재료가 유기농이 맞는지 명확하게 확인할 수 있다.한편, 중국의 월마트와 IBM이 협력해 중국에서 유통되는 돼지고기의 유통 전 과정을 블록체인 기술을 활용해 추적을 하기도 했다. 월마트는 더 나아가 농산물 공급망의 모든 단계를 추적하기 위한 프로젝트를 IBM과 진행하고 있다. 또한 영국의 신생기업 에버레저는 블록체인 기술을 이용해 다이아몬드와 같은 고부가 가치 상품들의 원산지 추적과 인증을 IBM 블록체인 기술을 활용하고 있다.3. 디지털 콘텐츠블록체인 기술로 디지털 콘텐츠에 대한 지적 재산권 보호를 더 확실하게 할 수 있다. 기존에는 불법적인 경로로 승인되지 않은 디지털 콘텐츠들이 유포가 됐다. 하지만 블록체인 기술로 온라인 콘텐츠에 대한 저작권, 권한, 결제를 관리할 수 있도록 작업할 수 있다. 블록체인 기술을 통해 콘텐츠 원저자의 증명을 더 쉽게 하고 해당 콘텐츠에 누가 접근을 했는지 추적할 수 있다.또한 항상 이슈가 되어 왔던 뮤지션들의 음반 판매 금액에 대해서도 블록체인 기술이 혁신을 가져다줄 것이다. 기존의 중간 단계의 서비스를 없애고 비용을 절감해서 음반 제작자들에게 더 많은 몫이 돌아갈 수 있다. 위에서 언급한 스마트 계약을 통해 라이선스 이슈의 문제들도 해결할 수 있다.블록체인 개발자, 얼마나 핫해?블록체인 기술에 대한 뜨거운 관심에 힘입어 블록체인 개발자에 대한 수요도 크게 증가하고 있다. 아직은 국내에서 가상화폐에 대한 비즈니스가 주를 이루고 있지만 정부의 정책과 시장의 기대와 맞물려 그 수요는 더욱더 커질 예정이다. 여기 블록체인 개발자의 수요에 대한 기사 있다.기사에 따르면 지난 1분기 취업사이트 잡코리아에 블록체인 키워드로 등록된 채용공고는 총 1500여 건이다. 이는 전년 동기 대비 9배 이상 늘어난 수치라고 한다. 또 잡코리아가 분석한 결과 지난해 하반기부터 암호화폐 개발자 수요가 급증했다고 한다. 지난해 1분기와 비교하면 올해 1분기 등록건수는 9배 이상이며 직전 분기와 비교해도 3배에 달한다.다른 아웃소싱 플랫폼 사이트도 비슷하다. 4만 7천 명의 유저를 보유한 위시캣에 따르면 2014년 8월부터 지난달까지 등록된 암호화폐 관련 프로젝트는 108건이다. 그리고 이 중에 절반인 55번이 올해 1분기에 등록이 되었다고 한다. 개발자 커뮤니티 OKKY에 올라온 구인 글에는 월 급여 900만 원을 제시하고 암호화폐 개발하는 개발자를 찾고 있었다. 또 구인 사이트에 올라온 암호화폐 거래소 프로젝트 중 개발비용이 45일 동안 2억 5천만 원에 이른 사례도 있었다.기사에 나온 것처럼 블록체인 개발자의 수요는 암호화폐에 집중되어 있기는 하지만 빠르게 증가하고 있다. 또 많은 기업들이 암호화폐가 아닌 다른 비즈니스의 모델을 찾으면서 블록체인 서비스를 준비하고 있다. 블록체인 개발자는 말 그대로 요즘 가장 핫하다고 할 수 있다.그래서 블록체인 개발자 되기 위해서는?이렇게 핫한 블록체인 개발자가 되기 위해서는 어떤 기술들을 공부해야 할까? 물론 어떤 분야의 개발자가 된다는 것이 특정 기술을 익힌다고 되는 것은 아니다. 웹 개발자가 된다고 해서 자바스크립트와 HTML, CSS를 익힌다고 되는 것이 아닌 것처럼 말이다. 회사마다 진행하는 프로젝트가 있고 그것에 맞춘 기술 스택들을 익혀야 한다. 하지만, 그럼에도 블록체인 개발에 있어서 주류가 되는 기술들은 있다. 이것들을 공부해 가면서 블록체인 개발자를 준비한다면 한층 더 수월해질 것이다.1.솔리디티(Solidity)솔리디티는 블록체인 플랫폼에서 스마트 계약을 만들기 위한 프로그래밍 언어다. 이더리움의 핵심인 스마트 계약을 만들기 위해서는 솔리디티를 배워야 한다. 솔리디티는 EVM(Ethereum Virtual Machine)에서 돌아가도록 설계되었고, 자바스크립트와 비슷한 문법 구조를 갖고 있다. 자바스크립트를 알고 있다면 배우기가 훨씬 수월할 것이다.블록체인은 다양한 분야가 존재하지만 그중 스마트 계약은 가장 대표적인 혁신 기술이다. 그 스마트 계약 기술을 선도하는 이더리움 프로젝트를 다루기 위해서는 솔리디티를 배우는 것이 필수적이다. 블록체인 개발에도 다양한 기술 스택들이 있겠지만 주류 기술을 배운다고 하면 솔리디티를 배워야 한다.솔리디티를 배우기 위해서는 다양한 방법이 있겠지만, 유데미의 강좌를 들으면서 공부하는 것을 추천한다. 저렴한 가격에 퀄리티 높은 강좌를 들을 수 있다. 자세한 사항은 이곳을 참고하면 된다.2.하이퍼레저(Hyperledger)블록체인이 개념이 퍼블릭 네트워크 기반의 시스템이기는 하지만 누구나 데이터를 볼 수 있기 때문에 기밀문서 관리에는 사용되기 힘들다. 특히 금융권이나 기업 문서 같은 경우는 더더욱 그러하다. 그래서 폐쇄적인 프라이빗 네트워크 내에서 블록체인을 활용할 수 있는 기술이 필요하다.하이퍼레저는 이러한 프라이빗 블록체인을 필요로 하는 기업들의 연합체라고 볼 수 있다. 이 기업들은 컨소시엄을 맺고 프라이빗 블록체인을 더 발전시키려고 다양한 분야에서 협업하고 있다. 하이퍼레저 프로젝트는 리눅스 재단에서 주도하며 금융, 은행, 제조, 기술 등 다양한 분야에 관여한다. 그리고 이 프로젝트는 스마트 계약, 분산 합의 네트워크에 목표를 두고 있다.지금까지 에어버스, 엑센츄어, 바이두, IBM, J.P 모건, 히타치, 삼성 SDS 등 다양한 기업이 하이퍼레저에 포함되어 있다. 그만큼 많은 기업들이 하이퍼레저 프로젝트에 관심을 가지고 있다. 하이퍼레저 역시 유데미의 강좌를 통해서 배울 수 있다. 자세한 사항은 이곳을 참고하면 된다.블록체인 개발자의 첫걸음블록체인 개발자가 되기 위해서는 위의 기술 스택뿐만 아니라 기본적으로 백엔드에 대한 지식과 최소한 암호 기법에 대한 기본 지식이 있어야 한다. 또한, 블록체인의 많은 API 및 SDK가 자바스크립트와 nod.js로 이루어져 있다. 무엇부터 시작해야 할지 모르는 분이라면 자바스크립트부터 시작하면서 첫걸음을 떼는 것을 추천한다.블록체인은 IT 기술의 최전선에 있는 기술이다. 그렇기 때문에 산업 동향을 항상 예의주시하면서 빠르게 움직여야 한다. 기업이 원하는 블록체인 기술 스택을 빠르게 습득하고 그에 맞는 실력을 갖추는 것이 중요하다.지금까지 블록체인 개발자에 대해 알아보았다. 많은 내용들을 다루다 보니 각각에 내용들에 깊이 있게 다루지는 못했다. 그래도 이 글을 통해 블록체인 개발자가 되기 위한 가닥은 잡을 수 있었으면 좋겠다.
조회수 592

오픈서베이 이건노 CTO가 ‘공동성장 가능해야 좋은 개발팀’이라 말하는 이유

오픈서베이 이건노 CTO(이하 폴)는 훌륭한 개발팀의 첫 단추로 ‘일단 매출이 나는 서비스 만들기’를 꼽는 현실주의 개발자입니다. 돈을 벌어야 생존 가능한 환경이 갖춰지고 이때부터 좋은 팀에 대해 고민을 할 수 있다면서요.  동시에 모두가 즐겁게 일하며 공동성장할 수 있는 팀이라는 이상을 꿈꿉니다. 지속가능한 서비스는 지속가능한 개발팀에서 비롯되는데, 즐겁지 않은 업무 환경에서는 그런 개발팀이 나올 수 없다고 믿기 때문입니다.  이런 현실주의적 몽상가는 주니어로 입사해 개발 조직 리더까지 지낸 이스트소프트에서의 경험으로 오픈서베이 개발팀을 리빌딩합니다. 구성원 모두가 즐겁게 일할 수 있는 환경을 위해 폴은 어떤 고민과 노력을 했을까요?   오픈서베이 이건노(폴) CTO   폴, 안녕하세요!  안녕하세요. 스타트업은 처음이라 직원 간 출퇴근 시간도 다르고 영어 이름으로 불리고 하는 게 익숙하지 않았는데, 17년 4월에 조인해서 벌써 만으로 2년째 다니고 있네요(웃음). 오픈서베이 개발팀을 총괄하고 있는 폴입니다.    현실주의적 몽상가의 오픈서베이 합류 계기가 궁금합니다(웃음).  경영진 미팅이었어요. 저는 주변 후배들이 이직 고민할 때도 그 회사의 경영진을 꼭 보라고 이야기하는 편인데, 제가 오픈서베이에 조인한 결정적인 계기도 하이(황희영 대표)와의 미팅이었어요. 하이를 만나보니 제품에 대한 애정이 정말 크다는 걸 느꼈어요. 대표가 제품에 애정이 많다는 뜻은 정말 하고 싶은 일을 한다는 의미잖아요. 사실 제품에는 관심 없고 주식, 엑싯 이런 거만 고민하는 대표도 있거든요. 그런데 하이처럼 제품에 애정이 정말 많은 대표가 있는 회사라면 저도 정말 믿고 다닐 수 있겠다고 생각했어요.  “대표가 제품에 애정이 많다는 뜻은  정말 하고 싶은 일을 한다는 의미라고 생각해요”   현재 개발팀 구성은 어떻게 되나요?  오픈서베이 개발팀은 현재 프로젝트 매니저 3명, 프론트엔드 개발자 2명, 백엔드 개발자 4명, 그리고 앱 개발자 2명까지 총 11명으로 구성돼 있어요. 최근 회사가 빠르게 성장하면서, 올해는 개발팀도 여러모로 성장하는 한 해가 될 것 같아서 기대됩니다.   팀이 성장하면 어떤 변화가 생기나요? 기업의 규모는 천차만별이지만 업무의 범위는 크게 다르지 않아요. 그러다 보니 인원이 적은 스타트업은 한 명이 얕고 넓게 일하는 구조인데, 회사가 성장하면서 직원이 늘면 각 구성원의 역할을 좀 더 세분화하고 전문화할 수 있게 돼요.  오픈서베이 개발팀도 기존에는 프로젝트 매니저가 기획·QA 등 다양한 역할을 모두 소화했다면 최근에는 좀 더 한 분야에 집중해서 깊게 일하는 식으로 역할의 변화를 주고 있어요. 그래서 서비스 기획자·백엔드 개발자·QA 엔지니어 등 다양한 직군을 채용하고 있고요.   오픈서베이 개발팀의 채용 정보를 알고 싶다면? (링크)   조셉(김경만 오베이 PM) 인터뷰를 보면, 개발팀 세미나 제도를 통해 긍정적인 영향을 많이 받은 것 같아요.  사실 세미나 자체가 주니어 개발자의 발언 기회를 위한 제도예요. 개발자는 스스로 제품이나 기술에 대해 주도적으로 고민할 때 역량이 극대화된다고 생각해요. 그런데 주니어 시절에는 아무래도 고민의 결과를 제품이나 기술에 반영하기 힘들죠. 세미나는 이런 갈증을 느끼는 주니어가 좀 더 의욕적으로 일할 수 있는 창구를 제공하기 위해 도입했어요. 구성원분들 덕에 우리 개발팀에는 잘 적용됐지만, 무작정 도입만 한다고 알아서 잘 작동하진 않는 것 같아요. 세미나가 주니어에게는 동등하게 업무 커뮤니케이션을 할 기회지만, 시니어에게는 사실 귀찮고 번거로운 일이 될 수 있거든요. 해왔던 대로 하는 게 편하다는 생각도 들 수 있고 새로운 기술을 팀에 적용하는 과정에서 드는 리소스도 크고요.    주니어 관점일 때는 생각지도 못했는데 이야기를 들어보니 그렇네요.  사실 저도 마찬가지예요. 저도 CTO이기 전에 개발자니까 주니어 개발자의 신선한 아이디어나 최신 기술을 업무에 적용해보고 싶은 마음도 있어요. 주니어분들의 세미나를 통해 저도 새롭게 배우는 점이 많아요. 그런데 CTO 입장에서는 이를 도입했을 때 우리 제품이나 업무 환경에 어떤 영향이 미칠지를 계산하지 않을 수 없어요. 좋아 보인다고 무작정 도입하면 문제가 터졌을 때 대처할 준비가 안 된 거니까 부담이 너무 크거든요.  그래서 이런 제도는 신중하게 도입하고 모든 구성원이 꾸준히 노력해야 잘 유지되는 것 같아요. 저도 간혹 이런 데서 내적 갈등이 생길 때마다 세미나 제도의 긍정적인 영향을 생각하며 이겨내는 편이에요(웃음). 실제로도 팀 업무 환경 개선이나 기술 수준 향상에 많은 도움이 되고 있고요.   “주니어에게도 고민 내용을 공유할 기회를 주려고 해요. 개발자는 주도적으로 제품을 고민할 때 역량이 극대화되거든요”    ‘코드리뷰’도 비슷한 제도라고 들었어요.  맞아요. 코드리뷰는 제품이나 소프트웨어의 변경사항을 체계적으로 관리하는 형상 관리의 일환이기도 해요. 오픈서베이 개발팀은 각 개발 담당자가 코드를 업데이트하면 슬랙에 자동으로 알림이 와요. 그럼 구성원들은 자유롭게 코드를 열어보고 의견을 내는 거죠. 여기서 담당자가 놓친 오류나 실수를 점검해 주거나, 더 효율적이고 경제적인 코드에 대한 의견을 주고받기도 해요.    그럼 코드리뷰는 보통 어떤 식으로 진행되나요?  마이너한 코드는 비대면 방식으로 온라인에서 수시로 리뷰를 진행하는데, 메이저한 코드 업데이트가 있을 때는 따로 회의를 열어서도 해요. 경우에 따라 방식은 다르지만 적극적으로 진행하려는 편이에요.  코드리뷰 제도를 도입하고 장려하는 이유는 명확해요. 개발자는 여럿이 함께 일할수록 시너지가 난다고 생각하거든요. 개발자 개인의 실력이 아무리 좋아도 본인이 작성한 코드의 오류나 실수를 다 잡아내기는 힘드니까요.  코드리뷰 자체가 구성원들이 의견을 주고받으면서 시스템 전반을 두루 이해하고 배우는 과정이기도 해요. 탄탄한 개발팀은 한명의 개발자가 하나의 시스템을 맡는 게 아니라 여러 구성원이 여러 시스템을 보조하는 구조거든요. 그래야 특정 담당자가 공백일 때 다른 구성원이 대신 문제를 처리해줄 수 있고, 개인의 부담도 줄어드니까요.  개발팀의 조셉과 로빈이 코드리뷰 중인 화면   그러다 자칫 잘못하면 서로의 감정을 상하게 하거나, 주니어를 향한 시니어의 훈육 공간으로 전락할 수도 있을 것 같아요.  그래서 어떤 제도가 좋다고 해도 무턱대고 받아들이면 안 된다는 생각을 해요. 도입에 앞서 서로 인신공격을 하면 안 된다거나 리뷰 내용은 공개된 채널에서만 주고받아야 한다는 등의 세세한 규칙을 정할 필요가 있어요. 코드에 대한 의견이 상대방을 헐뜯으려는 게 아니라 제품 개선과 모두의 성장을 위해서라는 상호 신뢰도 충분히 형성돼 있어야 하고요.    구성원들이 서로 자극을 주거나 보고 배우면서 함께 성장하는 팀을 지향하는군요. 정확히 맞아요. 개발자는 연차나 경력과 무관하게 개인별로 역량의 편차가 좀 있는 편이에요. 하나의 팀에 똑같은 수준의 역량을 갖춘 개발자만 모여 있는 게 오히려 부자연스러울 정도로요. 그래서 서로 다른 역량을 가진 팀원들이 함께 일할 때 시너지가 날 수 있는 방법이 필요해요.  저도 예전에는 이렇게 생각하지 않았어요. 일 잘하는 개발자에게 일을 몰아 주고 그 친구가 일을 다 하게 했죠. 거기에 따라 보상도 많이 주고요. 처음에는 일이 되는 것 처럼 보였는데 그런 식으로 한두 명이 일을 많이 하니까 금방 지치더라고요. 결국 서로 도와 가면서 팀으로 일하는 게 필요하더라고요.   그렇게 생각한 특별한 계기가 있나요? 개발팀장 시절에 새로 합류한 구성원 한명이 기억나네요. 좀 독특했어요. 에러·버그 등 문제가 생기면 원인을 파악하고 해결하는 개발업무를 ‘트러블슛(Trouble Shoot)’이라고 하는데, 그 친구는 다른 구성원이 담당하는 시스템의 트러블슛도 함께 고민하는데 시간을 많이 쓰더라고요.  사실 전 그때까지만 해도 팀원은 자신에게 주어진 일을 잘하면 되고 팀장은 역량에 맞춰 일을 잘 분배해주면 된다고 생각했어요. 그래서 이 친구 모습을 보면서 왜 자기 일은 안 하고 다른 사람 일을 야근까지 하면서 보고 있을까 생각했었죠.  그런데 시간이 지날수록 팀원들의 역량과 그 친구의 역량이 동반 성장하더라고요. 그것도 눈에 바로 보일 정도로 빠르게요. 서로 자극을 주고 함께 고민하면서 결국은 팀 전체가 성장한 거예요. 서로 시너지가 났던 거죠. 그러면서 자연스럽게 성과도 잘 나왔어요.   하지만 의지만으로는 자신의 업무를 넘어서 다른 구성원의 업무를 함께 고민하기는 힘들 것 같아요. 팀에서 함께 일할 수 있는 환경을 잘 만들어 주는 게 중요했던 것 같아요. 이슈 관리, 형상 관리, 버전 관리, 테스트, 릴리즈 등 개발과 운영을 위해서 필요한 기본적인 이해가 서로 있어야 해요. 그리고 개발 업무에만 집중할 수 있게 빌드, 배포와 같은 반복적인 업무의 자동화나 운영 툴 개발과 같은 것도 중요합니다.  그리고 가장 중요한 건 서로에 대한 배려심이라고 생각해요. 이번에 도와주고 다음에 도움을 받고 하는 서로에 대한 배려가 없다면 함께 일하는 문화는 자리 잡을 수 없어요. 일이 나뉘어 있기도 하지만 결국 같은 목적으로 일하고 있는 동료와 팀이라는 것을 알고 서로 배려해 주는 거죠. “좋은 제품은 좋은 개발 환경에서 나온다고 생각해요.  그래서 좋은 환경을 만들어주고 싶어요”   레드(김승엽 개발자) 인터뷰만 봐도, 로빈(권장호 개발자)를 통해 자극을 받아 공동성장하는 모습이 인상적이더라고요. 폴은 이런 레드에게 팀장을 넘어 멘토로서도 다양한 조언을 해주려는 것 같아요. 개발팀 구성원들이 회사 안에서의 성장에 갇히길 바라지 않아요. 좋은 인연으로 만났는데 회사라는 틀 안에서 팀장과 팀원 관계로 한정할 필요는 없다고 생각해요. 틀을 벗어나면 제가 할 수 있는 조언의 범위도 넓어지고 깊이도 훨씬 풍부해지기도 하고요. 인생 관점에서 조언해줄 수 있잖아요. 그럼 반대로 저도 레드를 비롯한 다른 구성원들을 통해 많이 보고 배울 수 있게 돼요.    쉽게 가지기 힘든 생각 같은데, 폴의 주니어 때 팀장님을 통해 배우신 건가요? 아니요. 사실 저는 팀장님과의 기억이 많지 않아요. 주니어로 입사한 지 2년 만에 엉겁결에 팀장이 됐거든요. 처음에는 기존 팀장님이 갑작스럽게 자리를 비우면서 팀장 업무를 임시로 맡았어요. 이때는 인사권 같은 건 전혀 없고 그냥 팀 업무를 할당받아서 각 구성원에게 배분하는 역할만 잠깐 한다고 생각했죠. 그런데 회사에서 “이왕 한 거 너가 계속해라”라며 아예 팀장을 시켜버리더라고요. 그때는 많이 당황했어요. 저도 완전 주니어일 때라 좋은 팀장님 밑에서 이것저것 배우고 싶었거든요. 그런데 이렇게 일찍 팀장이 되면서 이젠 내게 가르쳐줄 사람이 없는 걸까 싶어서 앞이 깜깜했어요 “나도 개발 잘할 수 있는데 왜 매니저 역할을 주는 거지? 내가 개발을 잘 못 한다는 건가?”라는 삐뚤어진 생각도 했고요. 얼마나 막막했으면 구글에 ‘팀장이 하는 일’ 같은 걸 검색한 적도 있어요(웃음).   위기를 어떻게 극복했을지 궁금해요. 그 과정이 지금의 폴 인사 철학에 많은 영향을 줬을 것 같아요.  그래도 어쨌든 팀장 일을 해내야 하니까 시선을 좀 넓혀봤어요. 제게는 이제 직속 팀장은 없지만 저보다 경력 많고 실력 좋은 선배 개발자가 팀원으로 있었고, 다른 팀에 훌륭한 시니어 개발자나 선배 팀장님도 계셨죠. 시선을 넓히니 오히려 제가 보고 배울 사람이 더 많더라고요. 그분들에게 궁금한 걸 적극적으로 묻거나 보고 배우면서 중요한 시기를 잘 보낼 수 있었던 것 같아요.  그때 처음으로 깨달은 게 아닐까 싶어요. 제가 엉겁결에 팀장이 되면서 다른 많은 분들을 보면서 보고 배운 것처럼, 팀원들도 꼭 팀장이 아니더라도 다른 팀원들을 서로 보고 배우면서 긍정적인 자극을 받으며 성장할 수 있다는 걸요. ‘팀장은 팀원에게 가르쳐주는 사람이야’란 생각에 갇혀 있었으면 절대 깨닫지 못했을 것 같아요. 얘기를 해보니 정말로 저 난관을 통해서 지금과 같은 생각을 할 수 있게 된 것 같네요(웃음).  “팀장과 팀원이라는 틀을 벗어나면 훨씬 풍부하게 긍정적인 자극을 주고받을 수 있어요”   폴의 경험과 고민이 결국은 팀 업무 환경이나 문화를 통해 드러나는 것 같네요. 그렇게 봐주시면 정말 고맙죠. 사실 어떻게 하면 더 일하기 좋은 회사와 팀을 만들 수 있을지는 계속 고민되는 부분이에요. 돈 많이 주는 회사가 일하기 좋은 회사라고 간단히 생각해버릴 수도 있는데, 저는 일하기 좋은 회사를 이루는 요건은 좀 더 다양한 것 같거든요. 일단 하는 일이 어떤 가치를 가지고 있고 이것을 쓰는 사람들에게 어떤 가치를 제공해 주는지 알고 있어야 해요. 그래야 내가 하는 일에서 보람을 찾을 수 있으니까요. 물론, 회사에서도 보람을 가질 수 있는 방법을 함께 고민해 줘야겠죠.  보람만으로 회사에 다닐 수 없으니 역세권 사무실, 맛있는 커피, 좋은 경영진, 좋은 팀원 등 중요한 요건들이 엄청 많은데요. 오픈서베이는 서로에게 자극을 주거나 보고 배우며 스스로 성장할 수 있는 좋은 구성원들이 많은 것 같아요. 저도 요즘  구성원들에게 많이 배우고 있습니다.    마지막 질문입니다. 좋은 팀을 위한 폴의 역할은 무엇인가요?  장점을 찾아 주는 게 저의 중요한 일이죠. 잘하는 일을 해야 역량도 극대화되거든요. 장점이 없는 사람은 없다고 생각해요. 장점을 잘 모르는 친구들이 있는데 이런 친구들의 장점을 찾아주고 또 그 장점이 회사에서 잘 발현되도록 도와주는 조력자 역할을 잘 해내는 게 제가 할 일이라고 생각해요.  좋은 장점이 잘 발현되면 개발자는 한 단계 더 성장할 기회가 생겨요. 예를 들어 초기 제품 기능을 빠르게 잘 만드는 게 장점인 친구는 신사업 중심의 일을 할 수 있게 해주면 그 역량이 잘 발현되거든요. 거기서 가치를 인정받고 탄력이 붙으면 지속적으로 좋은 성과를 낼 수 있게 되고요. 이 과정을 저는 “알을 깨고 나온다”라고 표현하는데, 이렇게 알을 깨고 나오면 좀 더 제품이 주는 본질적인 가치를 알게 된다고 생각해요. 개발자로서 일하는 가치와 방법을 알게 되는 거죠. 그런 만큼 오픈서베이의 예비 구성원분들도 좋은 자극을 받으며 성장할 수 있는 계기가 되셨으면 좋겠어요. 회사를 그저 출근해서 일만 해주고 돈을 받아가는 공간이라고 생각하면 회사 다니기가 우울하잖아요. 사람마다 얻어갈 수 있는 건 다 다르겠지만, 긍정적인 영향을 받아 성장하는 계기가 오픈서베이가 될 수 있을 것같아요.    “폴과 함께 즐겁게 일하고 싶으시다면 지금 바로 오픈서베이 입사지원을 해보세요”  
조회수 6473

`git push —force` 이야기

안녕하세요. 스타일쉐어 개발팀의 김현준입니다. 훌륭한 엔지니어링 경험을 공유하고 싶어 만든 블로그이지만, 아직까지는 그런 일이 없었던지라, 창피한 장애 경험을 공유하고자 합니다.배경:웹 서비스 디플로이는 프로덕션 웹 서버에서 업스트림 master를 풀 받아 리로드하는 방식으로 진행하고 있습니다.CSS, JS 등의 파일들은 CDN을 위해 매 빌드마다 디플로이 이전에 S3에 업로드합니다. Git 커밋의 SHA1 해시를 키로 사용합니다.장애:어제 새벽 서비스에 긴급한 패치가 있었습니다. 하지만 이 커밋은 8분 후 다시 롤백되는데…오늘 오후 디플로이 이후에 갑자기 웹 사이트의 스타일이 전부 깨져보이기 시작했습니다.심지어 아무리 커밋 로그를 살펴봐도 존재하지도 않는 커밋 해시로 파일을 요청하고 있었습니다.원인:롤백을 git revert 명령으로 하는 대신에, 이전 커밋으로 HEAD를 돌리고 git push --force로 업스트림을 덮어썼습니다.해당 커밋은 이미 디플로이가 되어있었지만, 되돌린 이후에 다시 디플로이를 하지 않았습니다.다음 디플로이할 때 해당 웹 서버 로컬에서 업스트림 master를 풀 받자, (개발자의 로컬이나, GitHub에서 보이는 커밋 트리와 달랐기 때문에) 서로 다른 커밋 해시를 가지게 되었습니다.404교훈:force-push를 (창피한 실수라던지, 지저분한 여러개의 커밋이라던지) 이력을 남기고 싶지 않을 때 사용하는 경우가 있는데요. 이는 위의 사례처럼 해당 커밋을 이미 풀 받은 다른 개발자의 로컬을 꼬이게 하거나, 장애를 유발할 수가 있습니다. 롤백을 하고 싶은 경우엔 revert 명령을, 커밋을 정리하고 싶은 경우엔 각자의 브랜치에서 충분히 rebase를 한 뒤에 올리는 습관을 꼭 가져야겠습니다.#스타일쉐어 #개발 #개발자 #개발팀 #인사이트 #후기 #일지
조회수 8078

Node.js로 Amazon DynamoDB 사용하기

DynamoDB 로컬 설정 (다운로드 버전)실제 DynamoDB 웹 서비스에 액세스하지 않고 로컬에서 애플리케이션 작성 및 테스트를 할 수 있음1. 다운로드 링크에서 DynamoDB 무료 다운로드2. 압축 해제 후 해당 디렉터리에서 아래의 명령어로 실행java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb* Ctrl+C로 중지할 수 있고 중지하기 전까지 수신 요청을 처리함* 기본적으로 8000번 포트를 사용Node.js 용 AWS SDK 설치1. 설치npm install aws-sdk2. 실행// app.jsvar AWS = require("aws-sdk");var s3 = new AWS.S3();// 버킷 이름은 모든 S3 사용자에게 고유한 것이어야 합니다.var myBucket = "dynamodb.sample.wonny";var myKey = "myBucketKey";s3.createBucket({ Bucket: myBucket }, function(err, data) {  if (err) {    console.log(err);  } else {    params = { Bucket: myBucket, Key: myKey, Body: "Hello!" };    s3.putObject(params, function(err, data) {      if (err) {        console.log(err);      } else {        console.log("Successfully uploaded data to myBucket/myKey");      }    });  }});node app.js테이블 생성// CreateTable.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var dynamodb = new AWS.DynamoDB();var params = {  TableName: "Movies",  KeySchema: [    { AttributeName: "year", KeyType: "HASH" }, // Partition key    { AttributeName: "title", KeyType: "RANGE" } // Sort key  ],  AttributeDefinitions: [    { AttributeName: "year", AttributeType: "N" },    { AttributeName: "title", AttributeType: "S" }  ],  // 다운로드 버전인 경우 아래 코드 무시  ProvisionedThroughput: {    ReadCapacityUnits: 10,    WriteCapacityUnits: 10  }};dynamodb.createTable(params, function(err, data) {  if (err) {    console.log(      "Unable to create table. Error JSON: ",      JSON.stringify(err, null, 2)    );  } else {    console.log(      "Created table. Table description JSON: ",      JSON.stringify(data, null, 2)    );  }});node CreateTable.js샘플 데이터 로드1. 이곳에서 샘플 데이터 파일 다운로드데이터 형태는 아래와 같음[    {        "year": 2013,        "title": "Rush",        "info": {            "directors": ["Ron Howard"],            "release_date": "2013-09-02T00:00:00Z",            "rating": 8.3,            "genres": [                "Action",                "Biography",                "Drama",                "Sport"            ],            "image_url": "http://ia.media-imdb.com/images/M/MV5BMTQyMDE0MTY0OV5BMl5BanBnXkFtZTcwMjI2OTI0OQ@@._V1_SX400_.jpg",            "plot": "A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.",            "rank": 2,            "running_time_secs": 7380,            "actors": [                "Daniel Bruhl",                "Chris Hemsworth",                "Olivia Wilde"            ]        }    },    ...]- year 및 title을 Movies 테이블을 위한 기본 키 속성 값으로 사용- info의 나머지 값들은 info라는 단일 속성에 저장- JSON을 DynamoDB 속성에 저장2. 샘플 데이터 Movies 테이블에 로드// LoadData.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();console.log("Importing movies info DynamoDB. Please wait.");var allMovies = JSON.parse(fs.readFileSync("moviedata.json", "utf8"));allMovies.forEach(function(movie) {  var params = {    TableName: "Moves",    Item: {      year: movie.year,      title: movie.title,      info: movie.info    }  };  docClient.put(params, function(err, data) {    if (err) {      console.error(        "Unable to add movie",        movie.title,        ". Error JSON:",        JSON.stringify(err, null, 2)      );    } else {      console.log("PutItem succeeded:", movie.title);    }  });});node LoadData.js테이블에 항목 추가// PutItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";var params = {  TableName: table,  Item: {    year: year,    title: title,    info: {      plot: "Nothing happens at all.",      rating: 0    }  }};console.log("Adding a new item...");docClient.put(params, function(err, data) {  if (err) {    console.error(      "Unable to add item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("Added item:", JSON.stringify(data, null, 2));  }});node PutItem.js- 기본 키가 필요하므로 기본 키 (year, title) 및 info 속성 추가항목 읽기// GetItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";var params = {  TableName: table,  Key: {    year: year,    title: title  }};docClient.get(params, function(err, data) {  if (err) {    console.error(      "Unable to read item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("GetItem succeeded:", JSON.stringify(data, null, 2));  }});node GetItem.js항목 업데이트// UpdateItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";var params = {  TableName: table,  Key: {    year: year,    title: title  },  UpdateExpression: "set info.rating = :r, info.plot=:p, info.actors=:a",  ExpressionAttributeValues: {    ":r": 5.5,    ":p": "Everything happens all at once.",    ":a": ["Larry", "Moe", "Curly"]  },  ReturnValues: "UPDATED_NEW"};console.log("Updating the item...");docClient.update(params, function(err, data) {  if (err) {    console.error(      "Unable to update item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));  }});node UpdateItem.js- 지정된 항목에 대해 수행하고자 하는 모든 업데이트를 설명하기 위해 UpdateExpression을 사용- ReturnValues 파라미터는 DynamoDB에게 업데이트된 속성("UPDATED_NEW")만 반환하도록 지시원자성 카운터 증가시키기update 메서드를 사용하여 다른 쓰기 요청을 방해하지 않으면서 기존 속성의 값을 증가시키거나 감소시킬 수 있음 (모든 쓰기 요청은 수신된 순서대로 적용)실행 시 rating 속성이 1씩 증가하는 프로그램// Increment.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";// Increment an atomic countervar params = {  TableName: table,  Key: {    year: year,    title: title  },  UpdateExpression: "set info.rating = info.rating + :val",  ExpressionAttributeValues: {    ":val": 1  },  ReturnValues: "UPDATED_NEW"};console.log("Updating the item...");docClient.update(params, function(err, data) {  if (err) {    console.error(      "Unable to update item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));  }});node Increment.js항목 업데이트(조건부)UpdateItem을 조건과 함께 사용하는 방법조건이 true로 평가되면 업데이트가 성공하지만 그렇지 않으면 수행되지 않음// ConditionalUpdateItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";// Increment an atomic countervar params = {  TableName: table,  Key: {    year: year,    title: title  },   UpdateExpression: "remove info.actors[0]",  ConditionExpression: "size(info.actors) > :num",  ExpressionAttributeValues: {    ":num": 3  },  ReturnValues: "UPDATED_NEW"};console.log("Attempting a conditional update...");docClient.update(params, function(err, data) {  if (err) {    console.error(      "Unable to update item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));  }});node ConditionalUpdateItem.js다음과 같이 작성하면 아래와 같은 에러 메시지가 표시 됨The conditional request failed"영화에는 3명의 배우가 있는데 배우가 3명보다 많은지를 확인하고 있어 에러가 발생다음과 같이 수정하면 정상적으로 항목이 업데이트 됨ConditionExpression: "size(info.actors) >= :num",항목 삭제// DeleteItem.jsvar AWS = require("aws-sdk");var fs = require("fs");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var table = "Movies";var year = 2017;var title = "The Big Wonny";var params = {  TableName: table,  Key: {    year: year,    title: title  },  ConditionExpression: "info.rating <= :val",  ExpressionAttributeValues: {    ":val": 5.0  }};console.log("Attempting a conditional delete...");docClient.delete(params, function(err, data) {  if (err) {    console.error(      "Unable to update item. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log("DeleteItem succeeded:", JSON.stringify(data, null, 2));  }});node DeleteItem.js다음과 같이 작성하면 아래와 같은 에러 메시지가 표시 됨The conditional request failed특정 영화에 대한 평점이 5보다 크기 때문에 에러가 발생다음과 같이 수정하면 정상적으로 항목이 삭제 됨var params = {  TableName: table,  Key: {    year: year,    title: title  }};데이터 쿼리- 파티션 키 값을 지정해야 하며, 정렬 키는 선택 사항- 1년 동안 개봉한 모든 영화를 찾으려면 year만 지정, title을 입력하면 2014년 개봉된 "A"로 시작하는 영화를 검색하는 것과 같이 정렬 키에 대한 어떤 조건을 바탕으로 일부 영화를 검색할 수도 있음한 해 동안 개봉한 모든 영화// QueryYear.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var params = {  TableName: "Movies",  KeyConditionExpression: "#yr = :yyyy",  ExpressionAttributeNames: {    "#yr": "year"  },  ExpressionAttributeValues: {    ":yyyy": 1985  }};docClient.query(params, function(err, data) {  if (err) {    console.error("Unable to query. Error JSON:", JSON.stringify(err, null, 2));  } else {    console.log("Query succeeded.");    data.Items.forEach(function(item) {      console.log(" -", item.year + ": " + item.title);    });  }});node QueryYear.jsExpressionAttributeNames는 이름을 교체함. 이를 사용하는 이유는 year가 DynamoDB에서 예약어이기 때문. KeyConditionExpression을 포함해 어떤 표현식에서도 사용할 수 없으므로 표현식 속성 이름인 #yr을 사용하여 이를 지칭ExpressionAttributeValues는 값을 교체함. 이를 사용하는 이유는 KeyConditionExpresssion을 포함해 어떤 표현식에서도 리터럴을 사용할 수 없기 때문. 표현식 속성 값인 :yyyy를 사용해 지칭* 위의 프로그램은 기본 키 속성으로 테이블을 쿼리하는 방법. DynamoDB에서 1개 이상의 보조 인덱스를 테이블에 생성하여 그 인덱스로 테이블을 쿼리하는 것과 동일한 방식으로 쿼리 작업 가능. 보조 인덱스는 키가 아닌 속성에 대한 쿼리를 허용하여 애플리케이션에 더 많은 유연성을 부여함한 해 동안 개봉한 모든ㄴ 영화 중에 특정 제목을 지닌 영화year 1992에 개봉한 영화 중에 title이 "A"부터 "L"까지의 알파벳으로 시작하는 영화를 모두 조회합니다.// QueryTitle.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();console.log(  "Querying for movies from 1992 - titles A-L, with genres and lead actor");var params = {  TableName: "Movies",  ProjectionExpression: "#yr, title, info.genres, info.actors[0]",  KeyConditionExpression: "#yr = :yyyy and title between :letter1 and :letter2",  ExpressionAttributeNames: {    "#yr": "year"  },  ExpressionAttributeValues: {    ":yyyy": 1992,    ":letter1": "A",    ":letter2": "L"  }};docClient.query(params, function(err, data) {  if (err) {    console.error("Unable to query. Error JSON:", JSON.stringify(err, null, 2));  } else {    console.log("Query succeeded.");    data.Items.forEach(function(item) {      console.log(        " -",        item.year + ": " + item.title + " ... " + item.info.genres + " ... ",        item.info.actors[0]      );    });  }});node QueryTtiel.js스캔테이블의 모든 항목을 읽고 테이블의 모든 데이터를 반환선택 사항인 filter_expression을 제공할 수 있으며 그 결과 기준이 일치하는 항목만 반환하지만 필터는 테이블 전체를 스캔한 후에만 적용됨// Scan.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var docClient = new AWS.DynamoDB.DocumentClient();var params = {  TableName: "Movies",  ProjectionExpression: "#yr, title, info.rating",  FilterExpression: "#yr between :start_yr and :end_yr",  ExpressionAttributeNames: {    "#yr": "year"  },  ExpressionAttributeValues: {    ":start_yr": 1950,    ":end_yr": 1959  }};console.log("Scanning Movies table.");docClient.scan(params, onScan);function onScan(err, data) {  if (err) {    console.error(      "Unable to scan the table. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    // print all the movies    console.log("Scan succeeded.");    data.Items.forEach(function(movie) {      console.log(        movie.year + ": ",        movie.title,        "- rating:",        movie.info.rating      );    });    // continue scanning if we have more movies, because    // scan can retrieve a maximum of 1MB of data    if (typeof data.LastEvaluatedKey != "undefined") {      console.log("Scanning for more...");      params.ExclusiveStartKey = data.LastEvaluatedKey;      docClient.scan(params, onScan);    }  }}node Scan.jsProjectionExpression은 스캔 결과에서 원하는 속성만 지정FilterExpression은 조건을 만족하는 항목만 반환하도록 조건을 지정. 다른 항목들은 모두 무시됨테이블 삭제// DeleteTable.jsvar AWS = require("aws-sdk");AWS.config.update({  region: "us-west-2",  endpoint: "http://localhost:8000"});var dynamodb = new AWS.DynamoDB();var params = {  TableName: "Movies"};dynamodb.deleteTable(params, function(err, data) {  if (err) {    console.error(      "Unable to delete table. Error JSON:",      JSON.stringify(err, null, 2)    );  } else {    console.log(      "Deleted table. Table description JSON:",      JSON.stringify(data, null, 2)    );  }});node DeleteTable.js#트레바리 #개발자 #안드로이드 #앱개발 #Node.js #백엔드 #인사이트 #경험공유 #데이터베이스 #DB #개발 #AWS #아마존 #NoSQL 
조회수 857

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를 개발 문화로 성공적으로 정착시키는데 가장 중요한 역할을 하는 도구라고 생각한다.
조회수 1837

Circle CI에서 rbenv를 이용해서 Ruby 2.2와 CocoaPods 0.39 버전 사용하기

최근 Circle CI에서 Ruby 버전을 2.3으로, CocoaPods 버전을 1.0으로 업그레이드함에 따라 발생하는 빌드 문제를 rbenv를 이용해서 해결한 경험을 공유합니다. 최종적으로 완성된 Gemfile과 circle.yml 파일은 마지막 섹션에서 확인하실 수 있습니다.1. CocoaPods 1.0지난 2015년 12월에 CocoaPods 1.0.0 베타 버전이 처음 공개되었습니다. CocoaPods이 1.0 버전으로 업그레이드되면서 굉장히 많은 변화가 있었는데요. 가장 큰 변화는 DSL입니다. 추상 타겟Abstract Target과 타겟 상속Target Inheritance이 새롭게 소개되면서, 0.39 버전까지 자주 사용되던 link_with 및 :exclusive => true와 같은 구문이 제거되었습니다.이에 따라 기존에 사용하던 Podfile이 CocoaPods 1.0 버전과는 호환되지 않는 문제가 발생했습니다. 이를 해결하기 위한 가장 좋은 방법은 새로운 DSL을 사용하여 Podfile을 다시 작성하는 것이지만, 꽤 많은 서드파티 라이브러리를 사용하는 StyleShare의 경우 새로운 DSL을 적용하여 빌드하면 각종 문제로 인해 빌드가 정상적으로 이루어지지 않았습니다. 4년동안 유지되고 있는 프로젝트이다보니, 레거시 Objective-C 코드와 라이브러리, 그리고 새로운 Swift 코드와 라이브러리가 혼용되어 사용되는 것도 원인 중 하나일 것입니다.따라서 StyleShare에서는 CocoaPods 0.39 버전을 사용하기로 결정을 했습니다. 하지만 최근 Circle CI에서 CocoaPods 버전을 공식적으로 1.0 버전으로 업그레이드하면서 빌드가 깨지기 시작했습니다. Circle CI 환경에서 CocoaPods 0.39 버전을 사용하려면 어떻게 해야 할까요?▲ ㅠㅠ2. Bundler를 이용해서 Gem 관리하기Bundler는 Ruby로 작성된 라이브러리들의 버전을 관리해주는 강력한 도구입니다. CocoaPods에서 Podfile에 의존성을 기재하듯, Bundler에서는 Gemfile에 의존성을 기재합니다.source 'https://rubygems.org' gem 'cocoapods', '~> 0.39' $ gem install bundler 명령어를 사용하면 Gemfile에 기재된 의존성 라이브러리들을 설치해줍니다. 이렇게 설치된 CocoaPods을 사용할 때에는 $ pod COMMAND 대신 $ bundle exec pod COMMAND 명령어를 사용해야 합니다.$ gem install bundler $ bundle install --path vendor/bundle $ bundle exec pod --version 0.39.0 3. Ruby 2.3과 CocoaPods 0.39Bundler를 사용해서 CocoaPods 0.39 버전을 사용하기만 하면 모든 문제가 해결될 줄 알았습니다. 하지만 더 큰 삽질이 남아있었는데요. 바로 Ruby 2.3 버전이 CocoaPods 0.39 버전과 호환되지 않는 것이었습니다.$ bundle exec pod install Updating local specs repositories Analyzing dependencies 신나게 $ bundle exec pod install 명령어를 실행하니, 의존성을 분석하는 듯 싶다가 갑자기 에러를 주르륵 뱉습니다. 에러 로그의 #### Error 항목을 보면 에러 메시지가 나와있습니다.NoMethodError - undefined method `to_ary’ for #이 에러 메시지로 CocoaPods GitHub 저장소의 이슈를 검색해보면 꽤나 많은 이슈가 올라와 있습니다. 이 이슈들을 보면, 모두 Ruby 버전이 2.3이라는 공통점이 있습니다. Ruby 버전을 2.2로 내렸더니 문제가 해결됐다는 댓글들도 굉장히 많고요. Circle CI의 Ruby 버전을 2.2로 낮추면 문제가 해결될 것 같습니다.Circle CI 문서 내용에 따라 circle.yml에 Ruby 버전을 기재해봅시다.machine: ruby: version: 2.2.5 그러나 Circle CI의 OS X 컨테이너에서는 Ruby 버전 변경을 지원하지 않는다고 합니다.▲ ㅠㅠ (2)4. rbenv를 이용해서 Ruby 2.2 사용하기그러다가 알게된 것이 바로 rbenv입니다. rbenv를 사용하면 여러개의 Ruby 버전을 깔끔하게 관리할 수 있게 됩니다. rbenv는 Homebrew를 사용해서 쉽게 설치할 수 있습니다.$ brew install rbenv rbenv는 ~/.rbenv 디렉토리에 안에 여러 Ruby 버전을 설치하고 관리합니다. rbenv를 설치한 뒤 가장 먼저 할 일은 환경변수 $PATH를 설정해주는 것입니다. $PATH에는 $HOME/.rbenv/shims와 $HOME/.rbenv/bin 경로가 포함되어있어야 합니다.4.1 환경변수 설정하기Circle CI에서는 환경변수를 설정하는 편리한 인터페이스를 제공합니다. 하지만, Circle CI에서 실행되는 각 명령어는 별도의 쉘에서 실행됩니다. 그말인 즉슨, 각 명령어가 실행되기 직전에 새로운 쉘이 실행되고, $PATH 환경변수를 덮어쓰는 .bash_profile이 실행된 후 명령어가 실행된다는 뜻인데요. 이렇게 될 경우 $PATH 환경변수의 가장 우선순위는 항상 /usr/local/bin이 가지게 됩니다. 그리고 같은 이유로 $ export FOO=bar와 같은 명령어도 사용할 수 없게 됩니다.1고민을 하다가 생각해낸 방법은 바로 .bash_profile의 내용을 변경(!)하는 것입니다. 그렇게 되면 우리가 원하는 $PATH를 항상 우선순위로 둘 수 있게 됩니다. 아래와 같이 환경변수를 설정하는 명령어를 .bash_profile의 가장 아랫줄에 삽입하도록 설정했습니다.machine: pre: - echo "export PATH=\$HOME/.rbenv/shims:\$HOME/.rbenv/bin:\$PATH" >> .bash_profile - echo "export RBENV_SHELL=bash" >> .bash_profile 4.2 rbenv에 Ruby 2.2 설치하기그 다음으로 할 일은 원하는 Ruby 2.2 버전을 설치하는 것입니다. $ rbenv install -l을 사용해서 설치 가능한 모든 Ruby 버전을 조회할 수 있고, $ rbenv install 2.2.5 명령어를 사용해서 2.2.5 버전을 설치할 수 있습니다.$ rbenv install -l Available versions: 1.8.5-p113 1.8.5-p114 1.8.5-p115 1.8.5-p231 ... $ rbenv install 2.2.5 이렇게 설치된 버전은 두 가지 방법으로 사용될 수 있습니다. 한 가지 방법은 시스템 전체에서 사용하는 것이고, 다른 한 가지 방법은 프로젝트 단위로 사용하는 방법입니다. 시스템 전체에서 사용하려면 $ rbenv global 2.2.5 명령어를, 프로젝트 단위로 사용하려면 $ rbenv local 2.2.5명령어를 사용합니다.global 명령어를 사용해서 Ruby 버전을 선택하면 ~/.rbenv/version 파일에 선택된 버전이 기록됩니다.$ rbenv global 2.2.5 $ cat ~/.rbenv/version 2.2.5 local 명령어를 사용하면 현재 디렉토리의 .ruby-version 파일에 선택된 버전이 기록됩니다.$ rbenv local 2.2.5 $ cat .ruby-version 2.2.5 local 명령어로 선택된 Ruby 버전은 global 명령어로 선택된 Ruby 버전보다 우선순위가 높습니다. $ rbenv version 명령어를 사용하면 현재 선택된 버전을 확인할 수 있습니다.$ rbenv version 2.2.5 (set by /project/path/.ruby-version) Circle CI에서는 편의를 위해 global 명령어를 사용해서 Ruby 버전을 선택하도록 했습니다.dependencies: pre: - brew update - brew install rbenv - rbenv install 2.2.5 - rbenv global 2.2.5 4.3 Bundler 다시 설치하기rbenv를 사용해서 새로운 Ruby 버전을 설치했기 때문에, Circle CI 시스템에서 제공하는 Gem도 다시 설치해야 합니다. 우리는 Bundler로 Gem 의존성을 관리하기로 했으므로, Bundler만 재설치합니다.$ gem install bundler --no-ri --no-rdoc $ rbenv rehash $ gem install 명령어를 실행한 후에는 $ rbenv rehash 명령어를 실행해서 executable 경로들을 재설정해주어야 합니다.4.4 ~/.rbenv 경로 캐싱하기rbenv를 사용해서 Ruby를 설치하는 과정이 굉장히 오래 걸립니다. 이 경우, Circle CI에서 제공하는 캐싱 기능을 사용해서 이 과정을 한 번만 하고 건너뛸수 있게 됩니다.dependencies: cache_directories: - ~/.rbenv 위와 같이 circle.yml를 설정해주면 컨테이너 실행시 ~/.rbenv 디렉토리가 캐시로부터 설정됩니다. 캐싱된 디렉토리를 사용하는 경우 Ruby 버전이 미리 설치되어있기 때문에 $ rbenv install시에 --skip-existing 옵션을 추가해주어서 캐싱된 버전을 재설치하지 않도록 합니다.5. 마치며최종적으로 완성된 Gemfile과 circle.yml 파일은 다음과 같습니다.Gemfilesource 'https://rubygems.org' gem 'cocoapods', '~> 0.39' circle.ymlmachine: pre: - echo "export PATH=\$HOME/.rbenv/shims:\$HOME/.rbenv/bin:\$PATH" >> .bash_profile - echo "export RBENV_SHELL=bash" >> .bash_profile xcode: version: 7.3 dependencies: cache_directories: - ~/.rbenv pre: - brew update - brew install rbenv - rbenv install 2.2.5 --skip-existing - rbenv global 2.2.5 - gem install bundler --no-ri --no-rdoc - rbenv rehash - bundle install --path vendor/bundle override: - bundle exec pod --version - bundle exec pod install https://circleci.com/docs/environment-variables/#custom ↩#스타일쉐어 #개발 #개발자 #개발팀 #후기 #일지 #인사이트
조회수 6871

BPM, RPA 그리고 Process Mining(프로세스마이닝)

새로운 IT 기술의 등장과 기업 환경의 변화로 새로운 과학 경영 기법들이 비즈니스 유행어처럼 등장하고 사라지지만 그 가운데서도 변하지 않는 것이 있다면 프로세스 개선과 관련된 대한 끊임없는 노력과 관심일 것입니다.프로세스 마이닝은 이벤트 로그를 기반으로 비즈니스 프로세스를 분석할 수 있는 프로세스 관리 기술입니다. 정보 시스템에서 기록한 이벤트 로그에 포함된 패턴 및 세부 정보를 식별하기 위해 별도의 분석 알고리즘이 이벤트 로그 데이터에 적용됩니다. 프로세스 마이닝은 프로세스의 효율성과 이해를 향상시키는 것을 목표로 하며, “자동화된 비즈니스 프로세스 발견” ABPD (Automated Business Process Discovery)이라는 좀 더 일반화된 명칭으로 불리기도 합니다.이러한 프로세스 마이닝은 어디서 갑자기 나온 개념은 아니고 기존 비즈니스 프로세스 관리 기법에 대한 연구와 데이터 분석 기술이 합쳐져서 나온 산물이기에 “비즈니스 프로세스”와 관련된 기술들을 살펴보고 프로세스 마이닝과의 연관성을 찾아보고자 합니다.BPM (Business Process Management)프로세스 마이닝은 일반적으로 BPM과 데이터 마이닝이 겹치는 중간 영역에 위치합니다.BPM은 비즈니스 프로세스를 발견, 모델링, 분석, 측정, 개선, 최적화 및 자동화하기 위해 다양한 방법을 사용하는 운영 관리 기법을 의미하며, 프로세스를 관리하여 기업 성과를 향상시키는 데 중점을 둡니다. 좁은 의미에서 BPM은 업무 프로세스를 사전에 모델링하고, 설계된 프로세스 대로 업무 결제, 승인, 구매 등의 업무 등이 자동화되어 흘러갈 수 있도록 도와주는 IT 시스템을 지칭하기도 합니다..BPM은 Top-Down 방식으로 프로세스 모델을 그려서, 해당 프로세스 모델 대로 업무를 수행하도록 강제하는 방식이라면 프로세스 마이닝은 이미 수행된 업무로부터 프로세스 모델을 도출하는 Bottom-up 방식을 따릅니다.  하지만 점점 복잡해져 가는 기업 업무 활동을 BPM처럼 중앙 집권적 방식으로 모든 것을 통제하기에는 한계가 있습니다.  BPM의 통제를 벗어난 다양한 여러 시스템을 업무 관점에서 통합적으로 관리하고 모니터링하기 위해서는 개별 시스템은 그대로 두고 이로부터 쏟아져 나오는 로그를 통해 프로세스를 관리하는 분권적 방식이 BPM의 한계를 보완하는 역할을 합니다. RPA (Robot Process Automation)로봇 프로세스 자동화 (RPA)는 소프트웨어 로봇 또는 AI (인공 지능) 작업자의 개념을 기반으로 하는 사무 자동화 기술의 새로운 형태입니다.소프트웨어 '로봇'은 컴퓨터 시스템의 사용자 인터페이스와 상호 작용하는 인간의 행동을 복제하는 소프트웨어 응용 프로그램입니다. 예를 들어, ERP 시스템에 데이터 입력을 실행하거나 실제로 비즈니스 프로세스를 수행하는 것이 소프트웨어 로봇의 일반적인 활동이 될 것입니다. 소프트웨어 로봇은 사람과 동일한 방식으로 사용자 인터페이스(UI)에서 작동합니다. 이것은 기존에 애플리케이션 프로그래밍 인터페이스(API)에 기반한 전통적 형태의 IT 통합과 크게 다릅니다. 즉, 사용자 인터페이스의 데이터 아키텍처 계층을 기반으로 한 기계 간(machine-to-machine) 통신 형태를 취합니다.앞서 언급한 BPM이 프로세스 개선을 위해 프로세스 자체를 재설계하고 변경하려는 방식이라면 RPA는 사람이 하던 현재 방식을 그대로 모방하여 소프트웨어로 대체하여 자동화하는 방식입니다. 이러한 RPA가 업무에 더 많이 적용될 수록 더 많은 시스템 로그가 나올 것이고 이에 대한 성과 분석과 모니터링이 필요해질 것입니다. 프로세스 마이닝은 RPA 도입 전 초기 단계에 전체 프로세스를 분석하여 RPA가 적용될 만한 구간을 식별하여 타당성을 검증하고, RPA 도입 이후의 전후 비교를 통해 지속적으로 업무 효율성을 측정할 수 있는 방법을 제공합니다.앞서 살펴본 것처럼 BPM, RPA, Process Mining 이 세 가지는 서로의 영역을 다투는 것이 아니라 상호 보완적인 존재로 볼 수 있습니다.프로세스 마이닝은 “프로세스”와 관련된 다양한 시스템과 활동들에 대해서 데이터에 근거한 현재 프로세스의 모델링 및 성과 측정 방법을 제공합니다. 이를 통해 과거 혹은 신규 프로세스 혁신 기법들과 맞물려 해당 시스템 및 방법론이 성공적으로 수행될 수 있도록 자동화된 “업무 조언자” 역할을 수행하게 됩니다. [참고 자료]https://en.wikipedia.org/wiki/Business_process_managementhttps://en.wikipedia.org/wiki/Robotic_process_automationhttps://www.minit.io/blog/robotic-process-automation-and-process-mininghttps://medium.com/towards-data-science/unleash-the-value-of-process-mining-4e3b5af4e9d8http://www.cdevworkflow.com/bpm-life-cycle/https://www.uipath.com/blog/the-robotic-process-automation-infographic#퍼즐데이터 #개발팀 #개발자 #개발후기 #인사이트
조회수 2599

WHATAP Python APM 이야기...

백엔드 서비스로 Python을 사용한다면 만나게될 상황을보다 쉽게 해결하기 위한 와탭의 Python APM, 개발하게 된 이유입니다.파이썬은 배우기 쉽고, 어디서나 실행되는 언어라고 이야기되며, 인기도 높습니다. 생각보다 많은 곳에서 배울 수 있으며, 혼자 배우기도 좋습니다. 그런데, 이 규모가 확대되어서 스타트업의 경우에 Python을 사용하여 백엔드 서비스를 개발하는 경우를 찾는 것이 어렵지 않습니다. 또는, 수학적인 알고리즘이거나 ML(머신러닝)과 같은 영역이거나 블록체인등에서 Python을 사용하여 API geteway나 broker를 사용하는 경우에 한정한 상황을 고려하고 있습니다.Python으로 백엔드 서비스를 만들 때에는 성능과 설계 부분에 대해서 많은 걱정을 하게 됩니다. 이런 상황을 만나게되는 개발자는 여러가지 문제를 만나게 됩니다. 그 문제에 와탭은 집중합니다.!와탭은 백엔드 서비스를 Python으로 개발시에 만나게 되는 상황을 가장 최우선으로 생각하게 되었습니다.Python으로 '설계', '개발'되고 '테스트'된 후에 '배포'되는 상황에서 서비스의 불완전함과 속도상의 문제, 리소스의 불협화음등을 '유지보수'하는 단계를 '성능 튜닝'이라고 정의하고, 이를 고려한 상황을 보다 단순화하는 것이라고 생각하게 되었습니다. 이를 어떻게 처리하느냐가 와탭 Python의 핵심 가치라고 생각하였습니다.----- 이 부분은 Python korea 페이스북에서 '배권한'님이 지적하신 내용을 기반으로 일부 첨언되었습니다.----- python native 개발자들에게는 불필요한 설명에 해당됩니다.파이썬은 분명, 읽기 쉽고 사용하기 쉬운 것은 장점이며, 라즈베리파이 위에서 동작되는 기민함은 정말 매력적입니다. <- 원래 문장.(* 현재에는 jvm도 동작합니다. 하지만, 작고 기민하게 다양한 IoT 디바이스에서 폭넓게 활용되는 것은 파이썬의 장점은 분명하지 않나 합니다. 이 부분에 대한 지적이 있어서 첨언합니다. )내부 구성상 비동기식으로 쓰레딩이 아니라, 단일 이벤트 루프를 사용하는 비동기식 작성은 매우 효과적입니다. <- 원래 문장.(* 이 부분도 asyncio나 gevent등에 대한 이야기이고, CPython의 언어 구현상 GIL때문에 쓰레드가 비효율적이라는 이야기를 거론하고 싶었으나, 일반적으로 파이썬에 대한 언어를 사용할때에 대부분 사용하는 이유가 단일 이벤트 루프기반의 비동기식 작성이 매우 일반적으로 사용되기 때문에, 이렇게 서술되었습니다. 하지만, 이런 설명은 백엔드로 Python을 사용하는 경우에 대부분의 프레임웍들에서 처리되고 있기 때문에 서술이 불분명하다는 지적이 있었습니다. 당연, 백엔드 서비스를 개발할때에 사용되는 wsgi interface등에 맞추어서 서술되는 경우에는 이런 설명이 무의미합니다.다만, 이렇게 서술한 이유는 Java를 기반으로 APM이 개발되어졌기 때문에 이 부분에 대한 서술이나 설명이 필요하다고 생각한 저의 과도한 설명이 되겠습니다.이 부분은 Python Native개발자들에게는 불필요한 설명이 되겠습니다. 하지만, 백엔드 서비스를 개발하면서 만나게될 환경에서는 이 부분에 대한 이해가 어느정도 필요하다고 생각되어 서술된 내용이라고 생각해주시면 감사하겠습니다. )----------------------------------------------------------------------------------------------------------------------이 방식은 복잡한 자원 경쟁이나 교착상태를 발생하지 않게 되며, 기본 코딩과 유지보수를 정말 수월하게 만들어 줍니다. 그만큼 일관성이 높은 수학 알고리즘을 구현하는데 매우 적합합니다. 하지만, 냉정하게, 비즈니스 로직이나 분기가 많은 업무 로직에 적합한 언어는 아닙니다.하지만, 수학적 알고리즘 기반의 주요 모듈 위에 데이터베이스가 일부 필요하고, 웹서비스의 형태로 가동되는 구조라면 파이썬은 매우 훌륭한 선택이 되고 있으며, 생각보다 많이 사용됩니다.그런 이유 중의 하나는 파이썬의 멀티패러다임 구성과 같은 구성에서는 자바에서처럼 굳이 프린트를 위해서 객체지향 클래스를 만들 필요 없이 간단한 함수형 스타일도 가능하게 구성이 됩니다. ( 자바 8에서는 이런 함수 기능도 추가되었습니다. )단순한 구조와 방식 때문에 파이썬 개발은 요즘처럼 ML이나 AI 등의 기술적 요소들이 많이 사용되는 환경에서는 매우 효과적입니다. 백엔드 파이썬 개발이 많이 보이게 되는 이유이기도 하죠.또한, 파이썬 개발의 단점이라고 지적되던 문제들도 현재에는 실행 속도 문제는 사실상 큰 문제가 되지 않는 상황입니다. 일례로, 파이파이(PyPY)로 실행된 파이썬 코드는 웬만한 수준의 C 코드보다 빠르게 동작합니다.굳이 더 지적하자면, 모바일 컴퓨팅과 브라우저에 따른 웹 애플리케이션 클라이언트는 굳이 파이썬으로 작성할 필요성을 느끼지 못한다고 이야기하는 정도입니다.하지만, 이런 파이썬 개발에 가장 큰 문제가 있습니다.테스팅 없이는 동작하기 어렵고,실제 동작 환경에서만 등장하는 오류의 발생파이썬의 특성상 동적 입력 형태에 따르는 더 많은 테스팅을 필요로 하고 있으며, 실제 실행시간에만 나타나는 오류를 찾는 것이 가장 큰 문제가 있습니다. 이 부분은 수많은 파이썬 개발자들을 괴롭히고 있습니다.( 단편적으로 파이썬 개발환경이 매우 고도화되어있지 않으며, 파이썬으로 백엔드 서비스를 만들 것이라고 예측하지 못한 점도 있을 것입니다. 앞으로 파이썬 개발이 더 고도화 되기를 기원합니다. )이 가장 큰 문제를 잡기 위해서와탭은 집중하였습니다.파이썬 백엔드 개발 시의 문제 해결!물론, Python도 디버깅에 대한 지원 유틸리티가 존재합니다.pdb라는 파이썬 디버깅 모듈을 통해서 Step over/Step into, 중단점(breakpoint) 설정, 콜 스택 검사, 소스 리스팅, 변수 치환 등을 할 수 있습니다.‘Phthon -m pdb 파이썬 파일. py’의 형태로 디버그 동작 화면에서 세부적인 동작을 트레이스 해보는 방식을 사용하거나, pdb모듈을 import 한 후에 pdb.set_trace()를 중단하고 싶은 부분에 넣어서 사용하는 방식도 사용됩니다. 또한, 디버그 세션을 사용하는 방식이며, PDB를 사용하여 디버깅하는 방식들도 흔하게 사용됩니다.PyCharm, PTVS, Spyder 등의 IDE를 사용해서 디버깅을 하는 방법은 전통적인 개발환경과 동일하게 사용할 수 있습니다.하지만, 이 방식들은 백엔드 서비스에는 맞지 않게 되며 개발자들은 백엔드 서비스 동작시에 디버그 추적을 위한 로그를 거는 방식을 흔하게 사용하게 됩니다. ( 너무도 전통적인 방식이죠. )정말 백엔드로 파이썬을 사용하고 있다면, 오류 추적이나 동작 메커니즘을 추적한다는 것은 매우 귀찮고 번거로운 작업이 됩니다.만들어지는 파이썬의 모든 파일에 해당 로그를 넣었다가 빼었다가, 배포의 오류를 만나는 상황까지 매우 번거로운 작업들이 끊임없이 반복되게 됩니다. 이런 상황들을 추적하기 위한 APM의 추적 기능들을 찾게 됩니다.또한, Python의 특징상 수학 알고리즘으로 구성된 API 중개인의 형태를 취할 경우에 DB에 대한 접근을 위한 ORM에서의 추적과 외부 웹 호출들이 뒤섞이게 되면서 오류 추적은 매우 짜증스러운 단계로 진화되게 됩니다.Python으로 백엔드 개발을 하게 되면만나게 되는 매우 짜증스러운 상황이죠.그래서, 와탭의 Python APM은 이 문제에 집중하기 위해서 와탭 고유의 문제 해결 방식을 그대로  아키텍처로 적용하여서 개발시에 편하고 빠르게 성능을 추적할 수 있도록 제작되었습니다. Python 백엔드 개발을 위한 최선의 방향을 제시합니다.Python개발자는 와탭의 APM을 설치하면 매우 손쉽게 웹 트랜잭션의 단계, 에러 추적, 클래스 추적, DB의 형태 및 Slow Query추적, 외부 호출 메커니즘의 구성 등을 설치 이후부터 빠르게 추적할 수 있으며, 개발자의 실수이거나 다른 외부 호출의 문제, DB와의 관계 등을 빠르게 잡아낼 수 있습니다.에러를 추적하기 위한 로그를 동작한다던지, 실환경시에 배포를 다시 한다던가 하는 귀찮은 작업을 모두 제거하는 것뿐만 아니라, 매우 통계적으로 의미 있는 와탭의 트랜잭션 추적 메커니즘을 사용할 수 있게 됩니다.파이썬을 기반으로 백엔드를 구성하는 곳이라면,와탭 APM은 매우 의미 있는 결과를 도출할 수 있습니다.와탭 Python의 세부적인 기능을 조금 더 상세하게 설명드리겠습니다.가장 먼저, 실시간 트랜잭션 모니터링!5초 주기로 트랜잭션을 수집하는 와탭의 방식은 서버의 부하를 최소화하면서 가장 의미 있는 데이터들을 수집하고 데이터 기반으로 오류와 트랜잭션을 빠르게 추적할 수 있게 합니다.파이썬 개발 시의 동작성을 체크하기 위한 와탭만의 고유의 진행 중인 트랜잭션 실시간 모니터링 기능인 아크 이퀄라이져와 동작된 웹 트랜잭션의 종료시간을 기준으로 시각화하여 동작된 트랜잭션의 상황을 한눈에 파악할 수 있습니다.와탭 Python APM위의 그림을 보면, Active Transaction으로 불리는 원형( 아크 이퀄라이져라 함 )으로 실제 동작중인 트랜잭션의 개수와 동작속도 등을 체크할 수 있으며, Hitmap을 통해서 종료된 트랜잭션의 속도를 시각화하여 볼 수 있습니다. 이 두 개의 시각화 만으로도 느린 트랜잭션을 추적 관리할 수 있습니다.Python 트랜잭션 추적 및 분석개발자는 단지 APM을 동작시켰을 뿐이지만, postgreSQL 데이터베이스에 연결하고 SQL문장을 주고받는 부분들을 하나의 시각화된 관점으로 나열해서 확인할 수 있습니다.각각의 동작 시간을 추적하는 것은 물론이고, 이 내용은 ORM으로 매핑된 상태에서도 SQL의 동작 순서대로 시각화되기 때문에 순서가 꼬이거나 문제가 발생되는 부분들을 손쉽게 찾아볼 수 있게 합니다.이외에도 와탭 APM( Java, Node, PHP 등의 모든 APM)에 기본적으로 제공되는 트랜잭션 추적 모듈 이외에도 사용자가 원하는 모듈 추적에 대한 기능들을 플러그인 형태로 정의할 수 있습니다. 더 복잡한 추적을 위해서 와탭의 고유기능을 추가적을 확대 사용이 가능합니다.WHATAP_HOME 의 plugin.json파일에 적절한 내용을 수정하여 특정 모듈의 데이터를 추적할 수 있습니다. 특정 모듈의 데이터를 추적하거나, 사용자 별로 원하는 모듈을 추적할 수 있습니다.*사용 안내:•[module_name]: 추적하고자 하는 대상의 모듈 명. import 하는 모듈 명 이기도 하다.•[class_name]: 추적하고자 하는 대상의 클래스 명. 없다면 ‘’(empty string)으로 사용한다.•[def_name]: 추적하고자 하는 대상이다.•args_indexes: 추적하고자 하는 대상의 아규먼트 인덱스. 여러 개일 경우 , 로 구분한다.•kwargs: 추적하고자 하는 대상의 키워드 명. 여러 개일 경우 , 로 구분한다.Plugin 기능 사용위의 예제에서는 Plugin과 SQL update문장의 순차적인 실행,세부 Plugin 설정에서 사용자의 모듈명, 추적 클래스 명, 추적대상과 아규먼트 인덱스, 키워드 등을 추적할 수 있습니다.*사용 예:plugin.json{"[module_name]": {      "class_name": "[class_name]",      "def_name": "[def_name]",      "args_indexes": ", ",      "kwargs": ", "},"httplib2": {      "class_name": "Http",      "def_name": "request",      "args_indexes": "1",      "kwargs": "method"},"faker.providers.address": {      "class_name": "Provider",      "def_name": "street_address",      "args_indexes": "",      "kwargs": ""}}두 번째, 데이터베이스를 매핑한 ORM과 SQL의 순서와 속도, Slow Query!매우 당연하게 파이썬을 기반으로 백엔드 개발을 할 경우에 데이터베이스를 사용하게 되며, 이에 대한 Slow Query와 관련된 추적하는 것이 개발자에게 필요하게 됩니다. 향후, RDS기반을 사용하게 되면 Query추적은 대부분의 데이터베이스 처리에 기본이 될 것입니다.현재 지원되고 있는 mysql / postgresql에 대하여 SQL Query, Fetch Count, SQL Query수행 시간을 수집합니다.Python개발 시에 RDBMS(관계형 데이터베이스 관리 시스템)를 선택하면 거의 항상 ORM(객체 관계 매핑) 라이브러리를 함께 사용하게 됩니다.특히, 파이썬에서는 이런 ORM라이브러리가 다양하고 사용하기 쉽기 때문에, 매우 흔하게 사용하고 있습니다.ORM의 장점으로는 쿼리를 생성하거나 추상화하는 대신, 데이터 베이스 시스템에 대한 접근을 쉽게 할 수 있는 장점이 있습니다. 다만, 이러한 장점 때문에 실제 만들어진 쿼리가 어떠하고 쿼리 수행 시간이 얼마나 걸리는지에 대해서는 추적이 어렵다는 점이 있습니다.이처럼, 파이썬의 특징상 ORM(객체 관계 매핑) 라이브러리를 사용할 경우에 추상화된 쿼리가 어떻게 동작하고, 실제 어떤 상황으로 발생 및 동작되는지를 한눈에 파악할 수 있게 합니다.ORM으로 매핑된 SQL의 순차적인 동작 상태 파악그리고, 세 번째. 외부 호출 추적파이썬 백엔드 개발 시에 사용되는 외부 호출(request/httplib2)등의 외부 호출과 관련된 호출 정보 및 수행 시간 등을 수집합니다.외부 호출을 사용하는 경우에는 각각의 호출에 대한 지연시간에 대해서 세밀하게 추적해야 하므로, 이와 관련된 에러와 지연시간 등을 추적하는 것은 매우 중요한 개발 시의 관점입니다.Python 외부 호출 추적마지막 중요 관점 네 번째는, 튜닝을 위한 다양한 프로파일 데이터의 제공을 이야기할 수 있습니다.와탭의 파이썬 에이전트는 위에서 나열되는 성능 저하를 위한 요소들의 전체적인 관점에서 수집하고 그 데이터들을 시각화할 수 있습니다.데이터베이스를 효율적으로 사용하고 있는지, 사용하는 ORM툴과 매핑과의 관계, 쿼리와 쿼리의 수행 시간과 상태에 대한 추적, 외부 호출시간과 각각의 지연되는 외부 호출과의 관계와 순서 등이 전체적으로 백엔드로 개발되는 Python의 성능 튜닝에 영향을 주게 되는 것이죠.그 이외에도 전체적으로 백엔드 서비스의 TPS, 응답 시간, 서비스 리소스 사용량과 어떤 에러가 발생되고 있는지를 알 수 있습니다.서비스 사용자가 사용하는 상세한 정보들을 프로파 일릉 함으로써 이들의 연관관계를 한분에 파악하게 해줍니다. 와탭에서 관리되는 프로파일 정보는 - 트랜잭션, SQL Query, 외부 HTTP호출, Error, User Agent, Client IP 등의 상관관계들입니다.그리고, 덤으로... Python이 설치 운영되는 전체적인 패키지의 버전을 한눈에 파악할 수 있는 것은 너무도 당연한 기능입니다.설치된 Python 패키지 확인그리고, 와탭의 DNA를 그대로 이어받은 APM이기 때문에, 기본적인 APM의 기능들을 대부분 담고 있습니다. 처음 와탭 APM을 접하시는 분들을 위해서 간단하게 설명드리면 다음과 같습니다.CUBE 메뉴는 시간을 기점으로 와탭 Python APM이 설치된 이후부터 현재까지의 모든 상황들을 추적 관찰할 수 있습니다. 주말에 오류 간 난 상황이라던지, 특정 오류의 발생 시점을 알고 있는 경우에 빠르게 해당 문제가 발생한 위치나 SQL 등을 추적할 수 있습니다.상세한 일간, 주간, 월간 리포트나 MAU 등을 추적할 수 있는 리포트 기능들은 와탭만이 가지고 있는 장점에 해당됩니다.Python으로 백엔드 웹서비스를 개발하고 계시다면, WHATAP Python APM은 개발과 운용을 매우 풍요롭고 빠르게 해줍니다.파이썬 백엔드 서비스 개발자라면 와탭 APM!
조회수 1280

웹 서비스 개발자가 APM을 사용해야 하는 이유

백엔드 서비스를 만들고 운영하는 개발자라면, 지금 바로 APM 서비스를 사용해 보세요. 와탭의 APM은 국내 수많은 Enterprise 기업에서 자사의 서비스를 분석하기 위해 사용되고 있으며 많은 효과를 보고 있습니다. 북미에서는 이미 수많은 스타트업이 DevOps의 기본 도구로 APM을 선택하고 있습니다. APM은 원래 대규모 서비스를 운영하는 분들이 전문적으로 사용하고 있었지만 최근 트렌드는 운영자에서 개발자로 이동하고 있는 서비스 이기도 합니다. 특히 와탭의 APM은 개발자 분들을 위한 스택 분석 기능이 있습니다. 개발자라면 와탭 APM 서비스가 제공하는 아래의 3가지 스택 분석 기능을 꼭 사용해 보세요. 유니크 스택탑 스택액티브 스택많은 개발자들이 자신이 만든 서비스가 어떻게 동작하는지 또는 웹 서비스에 어떤 영향을 주고 있는지 알지 못합니다. 하지만 와탭 애플리케이션 성능 모니터링(APM) 서비스를 사용하면 메소드가 애플리케이션에서 어떻게 사용되는지 얼마나 사용되는지 알수 있습니다. 와탭은 다른 APM 서비스와 다르게 10초에 한번씩 활동중인 트랜잭션을 검사하여 트랜잭션에 콜스택정보를 저장하고 있습니다. 그리고 이렇게 저장된 스택정보를 가지고 3가지 형태로 가공하여 보여주는데, 이 것이 유니크 스택 / 탑 스택 / 액티브 스택입니다. 먼저 유니크 스택은 가장 많이 사용된 스택 정보를 보여주는 방식입니다. 트랜잭션에서 실행되고 있는 메소드가 A 이고 이를 호출한 메소드가 모두 일치하는 스택을 유니크 스택이라고 합니다.1. A() ← C()2. A() ← C()3. B() ← D()4. B() ← E()5. B() ← F()위와 같은 경유 유니크 스택은 아래와 같이 통계를 내어 보여 줍니다. 40% A()    A()    C()20% B()    B()    D()20% B()    B()    E()20% B()    B()    F()이렇게 콜스택 정보 전체를 기준으로 분석을 하는 경우에는 성능에 영향을 주는 기능 단위의 분석이 가능합니다. 하지만 성능에 영향을 많이 주는 메소드를 알고 싶을 때가 있습니다. 이런 경우에 사용하는 것이 탑 스택 분석입니다. 아까와 같은 상황을 예를 들겠습니다.1. A() ← C()2. A() ← C()3. B() ← D()4. B() ← E()5. B() ← F()이런 상황에서 탑 스택 분석은 아래와 같이 가장 많이 사용되느 메소드를 알려줍니다. 60% B()    33% D()    33% E()    33% F()40% A()    100% C()유니크 스택에서는 A() ← C() 가 가장 많이 사용된 스택이라는 것을 알려주지만 탑 스택에서는 B() 메소드가 가장 많이 사용된 메소드라는 것을 알려줍니다. 이 두가지 내용을 통해 가장 많이 사용되는 메소드의 집합가 가장 많이 호출되는 메소드를 알아 낼 수 있습니다. 만일 서비스를 메소드 단위에서 개선하고 싶다면 이 정보를 기반으로 개선 작업을 진행하면 많은 도움을 받을 수 있습니다. 위에 화면에서 메소드를 선택하면 메소드를 호출한 스택들의 정보를 확인 할 수 있습니다. 마지막으로 액티브 스택입니다. 액티브 스택은 WAS 서버와 URL 그리고 발생 시간을 기준으로 저장된 콜스택의 정보를 보여줍니다. 서비스 성능이 떨어진 시간대의 콜스택 정보를 확인 함으로써 메소드 구간에서의 튜닝 정보를 제공합니다. 액티브 스택은 핵심 기능이 하나더 있습니다. 바로 서비스가 동작하는 스탭정보에 통합됨으로써 문제를 바로 확인할 수 있는 기능입니다. 와탭의 APM에서만 분석가능한 기능이며 특허로 등록되어 있습니다. 액티브 스택은 통계 관점이 아니라 실행 관점에서 문제를 바라보고 있습니다. 우리가 만든 웹 어플리케이션을 고객에 입장에서 보면 아래와 같이 동작합니다. 고객 → 웹 서비스 요청 → 서버 접속 → 서비스 접속 → 애플리케이션1 → 메소드 1 → DB 1접근 → Query 1 → Query 2 → 메소드 2 → 파일 접근 → 메소드 3 → 결과 취합 → WAS 통과 → 웹 서비스 결과 반환 일반적으로 애플리케이션 모니터링은 이런 상항을 아래와 같이 보여줍니다. 서비스 접속 → Query 1 → Query 2 → 파일 접근 → 트랜잭션 종료와탭의 애플리케이션 모니터링은 수집된 콜 스택 정보를 기반으로 아래와 같이 보여줍니다.  서비스 접속 → Query 1 → 메소드 2 → Query 2 → 파일 접근 →메소드 3 → 트랜잭션 종료위에 상황은 트랜잭션에서 메소드 2와 메소드 3이 수집된 경우에 트랜잭션의 스탭의 실행시간에 맞쳐서 정보를 재구성하는 것을 보여주고 있습니다. 이렇게 확인하게 된다면 메소드에서 발생하는 성능 문제를 확인 할 수 있습니다. APM 서비스는 와탭 / 뉴렐렉 / 데이터 독과 같은 서비스들을 통해서 2주에서 한달간 언제든 무료로 사용가능합니다. 다만 메소드에 대한 분석 기능은 와탭의 APM에서만 제공하는 기능들이 많습니다. 개발자라면 한번쯤 와탭의 APM 서비스를 통해 자신이 만들고 운영하고 있는 서비스에서 가장 많이 사용되는 메소드가 무엇인지 확인 해 보시기 바랍니다. Tip!! APM은 개발시에 사용하는 디버깅 도구라기 보다는 막대한 량의 트랜잭션이 발생하는 운영과정에서 사용되는 도구입니다. 트랜잭션 자체가 적다면 원하는 데이타가 안 나올 수 도 있습니다. 와탭으로 모니터링 하기 - 목차 바로가기#와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지 #서비스소개
조회수 13140

슬랙봇, 어디까지 만들어봤니?

스포카에서 다년간 일하면서 나에게는 몇 가지 별명이 생겼다. 그 중 하나는 봇맘(Bot mom)이다. 다른 스타트업에서처럼 으레 스포카에서도 주어지는 일만 하는게 아니라 작고 큰 문제를 스스로 발견하고 고민할 기회가 왕왕 생긴다. 나 또한 그런 기회가 있었고 그러던 중 (귀차니즘을 극복하기 위해라고 쓰고) 일을 더 효율적으로 하기 위해(라고 읽는다) 봇(Bot)에 재미를 느끼게 되었다. 그리고 하나 둘 봇으로 문제를 해결하게 되었고 어느새 사람들이 그 별명을 붙여주었다.봇(Bot)2014년 즈음부터 스포카는 슬랙(Slack)을 사내 메신저로 사용하기 시작했다. 슬랙 도입 초창기에는 기본적인 업무 커뮤니케이션과 아틀라시안 제품군(JIRA, Confluence 등), Github 등 사내 업무 툴의 슬랙 라우팅 기능으로만 슬랙을 사용하였다. 하지만 기본 기능 만으로는 실제 업무 환경에서 불편한 부분들이 더러 있어 슬랙봇 기능을 점차 활발히 사용하게 되었다. 팀마다 사용빈도는 다르지만 현재 많은 직원이 슬랙봇을 활용하고 있는데 지속적으로 업무 환경을 개선하는데 봇 기능이 상당한 기여를 하고 있다.인터넷 상에서 자동화된 작업(스크립트)를 실행하는 응용 소프트웨어봇(Bot)은 위와 같이 설명되고 있다. 예를 들어, 슬랙에서 사용자가 설정한 단어가 입력되거나 시간대가 되었을 때, 설정했던 이미지나 텍스트가 자동으로 나오는 기능이라고 생각하면 된다.슬랙에서 기본적으로 제공하는 슬랙 봇과 Reminder 기능만 잘 활용해도 누구나 업무환경 개선을 시도해볼 수 있다. 개인적으로 스포카의 봇 활용(hacking)1은 어떠한 다른 팀과 비교해도 뒤지지 않는다 생각한다. 실제 업무에 적용한 사례를 보면 봇이 무엇인지, 무엇을 할 수 있는지 아는데 도움이 될 것이다. 큰 도움이 되고 있었던 사례를 모아 소개하겠다.2Case1. 자연스럽게 직원들에게 세뇌시키기상황 및 의도서비스 내 용어가 팀별로 다르게 쓰이거나 여러가지로 불리고 있는 것들이 있었다. 혹은 서비스가 런칭/업데이트되면서 개편된 제품/기능이름들이 있었다. 이는 아는 사람끼리는 문제가 없지만 신규입사자나 아직 전달이 덜된 타팀과 소통할 때에는 오해가 생길 수 있었다. 이런 상황에서 UXD팀에서는 추가적으로 새로운 이름을 알리고 즉각 교정 효과를 볼 수도 있는 효율적인 방법을 고안하고자 했다.1-1. 도도 매틱이 도도 메시지로 서비스명이 변경되었음을 알리는 봇이다1-2. 개편된 제품/기능이름을 알릴 때 쓰였던 슬랙봇들. 시간이 지나면서 제 임무를 다하고 사라졌다.효과잘못된 단어를 사용할 때마다 봇이 알려주니 즉각 교정 효과가 나타났다. 사람마다 교육되는 기간을 달랐지만 점차 잘못된 단어를 사용하는 사람들이 사라졌고, 몇 개월 후에는 옛날의 잘못된 단어가 무엇인지 까먹은 사람도 있었다. 그리고 시간이 지나고 제 목표를 달성한 슬랙봇들을 삭제하기까지 이르렀다.Case2. 개발자님 도와주세요ㅠㅠ상황 및 의도디자이너가 코드를 다루다가 가끔 알 수 없는 함정에 빠질 때가 있다. 서버가 왜인지 켜지지 않는다거나 원인을 명확히 알 수 없는 에러가 뜬다거나 하는 경우다. 그런 때면 개발자에게 도움을 요청하는데, 개발자의 입장에서는 진행하고 있던 업무를 잠시 중단하고 해결할 수 있는 커맨드를 알려주거나 알아보는데 시간이 걸릴 수 있다. 이럴 때 봇이 취해야하는 커맨드를 알려준다.봇으로 개발자가 도와줘야 하는 단계가 하나 줄었다!효과개발자가 도움요청 메시지를 보기 전, 디자이너가 먼저 바로 응급처치를 해볼 수 있어 덜 답답했고 개발자도 하나의 예상원인을 제거할 수 있어 빠르게 상황을 파악할 수 있었다.Case3. 항상 똑같은 질문과 답변은 그만!상황 및 의도기억력의 한계와 투명한 업무 진행상황 공유를 위해 이슈 기록 등 문서 작성에 기를 가하는 문화가 있다보니 사내위키문서가 자연스레 방대해졌다. 찾고자 하는 문서가 어딨는지 못 찾아 메일함과 위키사이트를 헤매고 못 찾으면 항상 팀원들에게 물어보게 되어 괜히 미안한 상황이 있었다. 그냥 누군가 물어볼 때 딱!하고 찾아주었으면 했다.다른 경우로는, 매번 특정 팀에게 물어보는 것이 있다. 사이트 내 친절히 설명을 작성하고 공지해도 정보 접근이 귀찮거나 어려운 곳에 있으면 바로 담당자에게 물어서 바로 올바른 답변을 얻고자 하게 된다. 이런 경우, 같은 질문을 하는 사람은 수십 명인데 답변하는 사람은 한 두명여서 답변하는 담당자는 피로해질 수 있다.3-1. 우리팀 주간미팅 회의록이 어딨더라...?3-2. 디자인팀에게 요청할 때 뭘 알려드려야 하지?3-3. 이 지역 담당자가 누구더라?효과원하는 문서의 바로가기 링크를 바로 얻거나 정보를 얻을 수 있어 위키 메뉴를 헤매지 않고 시간을 절약할 수 있었다. 반복적으로 물어보게 되는 사항을 물어보고 싶을 때 불편한 마음을 전혀 가지지 않아도 되었다.Case4. 이번엔 누구에게 의견을 물어볼까?상황 및 의도현재 스포카 Visual design팀(이하 VD팀)은 5명이며 디자인이라면 모두 관심을 가지고 의견을 주는데 주저함이 없다. 어떤 이슈를 진행할 때 중간 점검의 느낌으로 가볍게 1~2명에게 리뷰를 받고 싶을 때가 있다. 항상 같은 사람에게만 리뷰를 부탁하는건 아닌지, 다양한 의견을 받아보고는 싶은데 누구에게 돌리는게 좋을까, 리뷰어 선정에 고민을 하게 될 때가 있다. 혹은 이슈진행자가 정해지지 않았을 때 마음의 짐을 덜고 책임자를 정하는 잔인한 방법이 되기도 한다.(ㅋㅋ) 5명인데 1명 혹은 2명을 고르고 싶으므로 or/and를 병기하여 모든 경우의 수를 정리하여 봇을 만들었다.VD리뷰랜덤효과누구에게 리뷰를 맡길지 고민하는 시간이 줄었다. 타팀에서도 VD팀 누군가에게 리뷰를 부탁하고 싶을 때 활용되기도 한다. 하지만 휴가 중이라던지 가끔 리뷰를 볼 수 없는 사람이 계속 무작위로 나올 때가 있어 두세번 봇을 불러야 하는 일이 있다.Case5. 다나와 대화형 봇 (심화)앞서 소개한 유형들이 너무 단순하다고 느껴진다면 키워드 봇을 연속적으로 활용해보는 방법도 있다. 채팅형 봇을 만든 듯한 착각을 느끼게 할 수 있다.사이즈 다나와 (혹자는 이 사례를 보고 슬랙해킹의 정점을 달려가는 것 아니냐 감탄하였다.)Case6. 잊는 법이 없는 나만의 비서!봇이 일상화되니 왠만한 정기적인 업무일정은 무조건 봇으로 만드는게 습관이 되었다. 예전에는 다른 봇제작 서비스를 통해 만들던 기능이었는데, 슬랙에 리마인드(Remind) 기능이 업데이트 되면서 더 편해졌다. 리마인드 기능 설명은 이쪽을 참고 바란다.6-1. 스프린트 시작 알림 봇6-2. 데일리미팅 알림 봇6-3. 주말의 시작을 알리는 봇6-4. 파트타이머 급여 처리를 잊지 않도록 도와주는 비서봇Case7. 슬랙 API를 활용한 데이터드리븐 봇 (고급)상황 및 의도지금까지 소개한 것들은 회사 내부에서 업무를 진행할 때 도움을 받거나 내부 커뮤니케이션을 위한 것들이었다. 이번에 소개할 것은 회사 서비스와 관련된 개발자 친화적인 방법이다. 서비스 내 DB와 슬랙에서 제공하는 API를 접목하여 별도의 트래킹(tracking)툴 없이 실제 사용자의 행동 중 주요하게 알아야 하는 것을 슬랙봇으로 만든 것들이다.7-1. 부정적립으로 의심되는 이벤트를 알려주는 봇7-2. 매장 잔여코인 알림과 코인결제완료를 알려주는 봇효과별도의 트래킹툴이나 웹사이트에 접속할 필요 없이 실시간 데이터를 파악할 수 있었다. 또한 서비스에 주요한 영향을 끼치는 사용자의 실제 행동을 팀원들과 함께 빠르게 공유할 수 있었다.봇을 만들 수 있는 다른 방법슬랙의 리마인드 기능을 쓰지 않더라도 봇을 부릴(?) 수 있는 방법이 있다. 슬랙봇은 슬랙을 사용해야하고 관리자 권한이 있어야 설정 가능하다. 그러므로 개인적으로 쓴다면 아래 2가지 서비스들을 추천한다. 조합할 수 있는 서비스가 다양하니 자동화할 수 있는 아이디어가 있다면 시너지가 엄청날 것이다. 업무 뿐만 아니라 일상생활에도 활용할 수 있다.Zapier글쓴이가 슬랙에 리마인드 기능이 없을 때 애용하던 서비스이다. 무료 플랜으로 사용하면 설정할 수 있는 봇 개수와 작동하는 횟수가 제한적이지만 소소하게 가끔 필요한 것을 쓰기에는 괜찮다. 업데이트가 계속 되고 있으니 시도해보시라.IFTTTIf this, then that. 컨셉별 봇 레시피가 잘 정리되어 있어 바로 일상생활에 적용해볼 아이디어를 제공한다. 슬랙 외에도 다양한 앱과 연동하여 사용할 수 있는 장점이 있다.슬랙봇과 스포칸업무에 유용한 봇을 위주로 소개했으나 스포카의 슬랙봇은 업무의 즐거움을 향상시키는 스포칸의 드립 아카이브 역할을 하기도 한다. 업무에 활용하는 것만큼 다양한 방식으로 소구되고 있는데, 드립의 특성상 시간이 지나면 그 재미가 무뎌지는 것들이 있어 굳이 소개하지는 않겠다. 또한, 그외 개발자분께서 직접 창의적인 봇용 앱을 만든 사례도 여러 개 있었는데 나중에 기회가 되어 소개를 해볼 수 있으면 좋겠다.계속 슬랙이 업데이트되면서 나 외에도 비IT직군도 슬랙봇을 잘 활용해나가고 있고, 다른 팀원들도 번뜩이는 위트를 겸하며 슬랙봇을 활용하고 계시다. 여러가지로 활용되고 있는 슬랙봇은 하나의 값진 유산이라고 생각되기까지 한다. 간단한 기능임에도 더 집중해야 할 곳에 집중할 수 있도록 도와주기도 하고, 동료 간의 유대감을 깊게 만들기도 하기 때문이다. 스포카 외에 슬랙을 사용하는 다른 회사/팀들도 각자 사용하고 계시는 툴을 재밌고 유용한 방식으로 활용하며 팀 커뮤니케이션에 보탬이 되었으면 좋겠다.시스템 혹은 프로그램의 문제를 고치기 위한 행위 ↩이 포스팅의 예시 중에는 1~2년 전 스포카의 슬랙에서 활발히 쓰였다가 현재는 잘 사용되지 않는 경우도 있다. ↩#스포카 #개발 #개발자 #사내문화 #조직문화 #인사이트 #꿀팁
조회수 1177

EOS Token 생성과 발행, 전송

이번시간에는 배포한 Contract를 통해 Token 발행과 전송을 해보겠습니다. 이를 위한 준비는 아래 2미디엄 글을 참조해주세요EOS Smart Contract 를 위한 준비EOS Smart Contract 배포먼저 저번 시간에 배포한 token 발행 abi 를 확인해 보겠습니다.$ cleos get abi hexlanthenryget abiabi를 확인하다보면 actions 라는 항목에 총 3개의 action이 있음을 확인할 수 있습니다. 이 3개의 name이 실행할 수 있는 action입니다. token발행은 create action을 통해 진행할 수 있습니다.Token 생성$ cleos push action hexlanthenry create '["hexlanthenry", "10000000000.0000 HEX"]' -p hexlanthenrycreate action 실행 결과create action 을 통해 ‘HEX’ 토큰을 100억개 생성했습니다. create 라는 action의 인자는 account_name(hexlanthenry), maximum_supply(10000000000.0000 HEX) 입니다. 즉 첫번째 인자는 토큰의 발행자를 나타내며, 두번째 인자는 토큰의 최대 수량을 나타냅니다.이 인자가 어떻게 들어가는지는 abi 의 struct 를 확인하면 알 수 있습니다.abi의 create structparameter 1 : account_name type— issuerparameter 2 : asset type — maximum_supply+ 저번 강의에서 공지한데로 다음 포스팅에서는 abi가 무엇을 뜻하는지, 이를 통해 어떻게 action을 실행할 수 있는지 알아보도록 하겠습니다.Token 발행생성과 발행 이 2개의 개념이 헷갈릴 수 있습니다. create action을 통한 생성은 최대 발행량을 결정 하는 것이며, issue action 은 토큰을 유통 시키는 것입니다.create : token 생성과 동시에 최대 발행량 결정issue : token 의 유통따라서 issue action을 통해 이전에 생성한 HEX token을 발행해보겠습니다.$ cleos push action hexlanthenry issue '["hexlanthenry", "10000.0000 HEX", "initial issue"]' -p hexlanthenryissue contract 실행 결과issue action 역시 data로 어떤 인자가 들어가는지는 abi를 통해 확인 가능합니다.abi의 issue structparameter 1 : account_name type — toparameter 2 : asset type — quantityparameter 3 : string type — memomemo 는 transfer 가 어떤 목적인지에 대해 설명해주는 인자 입니다. 생략해도 되는 값으로, 원하시면 parameter 개수를 유지하는 선에서 empty string을 넣으시면 됩니다. memo를 어떻게 쓰면 유용한지에 대해서도 다른 포스팅에 담도록 하겠습니다.issue가 잘 실행 되었는지 확인해 보겠습니다.$ cleos get currency balance hexlanthenry hexlanthenry저는 issue 를 4번 수행한 후 balance 를 체크 했기 때문에 총 40000개의 HEX token이 존재하는 것을 확인 할 수 있습니다.hexlanthenry 의 HEX token개수예외사항1create 하지 않은 token을 issue 할 경우해당 symbol 이 존재하지 않음예외사항2생성한 token 수보다 많은 양을 issue 할 경우maximum supply를 초과함Token transfer마지막으로 token을 다른 계정에 전송 해보도록 하겠습니다. 다른계정에 token을 보내야 하기 때문에 계정을 생성하거나 존재하고 있는 계정을 사용하시면 됩니다.아래 명령으로 hexlanthenry 계정이 babylion1234 계정으로 10000개의 HEX 토큰을 보냅니다.$ cleos push action hexlanthenry transfer '["hexlanthenry", "babylion1234", "10000.0000 HEX", "first"]' -p hexlanthenrytransfer 실행결과transfer 시 들어가는 data에 대해서도 abi를 확인해보겠습니다. 다른 action보다 많은 인자를 필요로 합니다. [“hexlanthenry”, “babylion1234”, “10000.0000 HEX”, “first”]abi의 transfer structparameter 1 : account_name type — fromparameter 2 : account_name type — toparameter 3 : asset type — quantityparameter 4 : string type — memo실제로 babylion1234 계정을 확인해 보면, 방금 배포한 HEX token을 보유하고있는 것을 확인할 수 있습니다.babylion1234의 HEX 보유이번 포스팅에서는 token을 생성과 발행 그리고 전송을 다뤄봤습니다. EOS는 Ethereum 과 달리 토큰 발행을 매우 쉽게 진행할 수 있습니다. 이 두 dapp의 차이에 대해서도 포스팅을 하고 싶으나 우선 다음 포스팅에서는 contract 개발의 기초를 다루도록 하겠습니다.감사합니다.#헥슬란트 #HEXLANT #블록체인 #개발자 #개발팀 #기술기업 #기술중심

기업문화 엿볼 때, 더팀스

로그인

/