스토리 홈

인터뷰

피드

뉴스

조회수 1537

개발자의 시간 벌기

Overview지루한 작업은 저와 어울리지 않습니다. 한마디로 귀차니즘이 가득한 개발자입니다. 반복적인 일을 하고 있으면 딴 생각이 많이 떠오릅니다. 특히 개발 과정은 쿼리를 작성하고, 프로그램에 적용하고, 검증하는 일이 자주 발생하는데 필요 이상으로 내 시간을 낭비한다는 생각이 들었습니다. 매번 다시 작업해야 하는 쿼리의 조합을 책상 서랍에 착착! 정리해둔 물건처럼, 코드도 언제든 쓸 수 있게 착착! 준비해두면 시간도 절약되고, 업무도 편리해지지 않을까요. 도대체 최종 결과는....?개발언어를 PHP로 전향하면서 제일 오래 걸리는 부분은 프로그램에서 발생하는 쿼리를 다시 조합하고, 검증하는 작업이었습니다. 프로그램에 사용하는 조건을 체크하고, 대입되는 변수들을 체크하고, 치환할 부분에 넣어주는 작업을 반복해야 하고, 야근하고, 건강 잃고… 쿼리가 정상적으로 조합되지 않으면 어느 부분이 틀렸는지 매번 확인해야 합니다. 이 번거로운 작업을 안드로이드 개발에서 사용하는 logcat 같은 기능으로 만들면 좋을 것 같았습니다. 그래서 PHP용 Log 프로그램을 간단하게 만들기 시작했습니다.Logcat 화면, 한결 보기 편해 보인다. ㅂㄹ개발 컨셉손으로 쓱쓱 그려 보았습니다.PHP 쿼리 요청 코드// sql 디버깅 코드: 쿼리 시작 if (ENVIRONMENT == 'testing') {     if(function_exists('localDebugger')) localDebugger( 'sql_start', "0,".$sql);  } // Run the Query if (FALSE === ($this->result_id = $this->simple_query($sql)))  {     // 소스 생략     if ($this->db_debug)      {              // 소스생략 ...            $this->trans_complete();              // sql 디버깅 코드: 쿼리 에러           if (ENVIRONMENT == 'testing') {               if(function_exists('localDebugger'))  localDebugger( 'sql_error', '0, -- Error  Number: '.$error_no  ."\n--  message: ".$error_msg."\n");           }              // 소스생략 ...      }     return FALSE;  } // 소스 생략 // sql 디버깅 코드: 쿼리 종료 if (ENVIRONMENT == 'testing')  {     if(function_exists('localDebugger')) localDebugger( 'sql_done', ($em + $es) - ($sm + $ss).",");  } PHP 디버그 서버에 요청 코드$callNo = time();           /**           *로컬서버에 디버깅 메세지           * 지정된 서버에 디버깅 메세지 전달           * @access public           * @author BoseungChun           * @param string $message   디버깅할 메세지           */ function localDebugger( $type, $message ) {           global $callNo;           //debugger server           $url = 'http://127.0.0.1:3000';           $ch= curl_init($url);            // 요청 파일 분석           $trace= debug_backtrace();           $fileName= substr( $trace[1]['file'],strrpos($trace[1]['file'], '/') );           $line= $trace[1]['line'];           $fileName2= substr( $trace[2]['file'], strrpos($trace[2]['file'], '/'));           $line2= $trace[2]['line'];             // POST로 로깅 서버에 메세지 전달            curl_setopt($ch, CURLOPT_POST, 1);           curl_setopt($ch, CURLOPT_POSTFIELDS, $callNo.' '.$type.' '.uri_string().' '.$fileName2.':'.$line2."\n".$fileName.':'.$line.' '.$message);           curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);           $response = curl_exec($ch);           curl_close($ch);     } nodejs 일부 코드 // 서버 기동 const http = require('http');   const hostname = '127.0.0.1';  const port = 3000;   const server = http.createServer((req, res) => {       res.statusCode = 200;       res.setHeader('Content-Type', 'text/plain');       var body = '';       req.on('data', function (chunk) {           body += chunk;       }).on('end', function () {           var pos = body.indexOf(' ');           var no = body.substring(0, pos);           body = body.substring(pos+1);           pos = body.indexOf(' ');           var type = body.substring(0, pos);           body = body.substring(pos+1);           pos = body.indexOf(' ');           var uri = body.substring(0, pos);           body = body.substring(pos+1);           pos = body.indexOf(' ');           var file = body.substring(0, pos);           body = body.substring(pos+1);           pos = body.indexOf(',');           addSqlBlock( no, uri, file, body.substring(pos+1), body.substring(0, pos), type );      })      res.end('');  });   server.listen(port, hostname, () => {       console.log('Server running at http://${hostname}:${port}/');   }); // 코드 생략   function addSqlBlock( no, uri, file, sql, ms, type ) {      // UI를 구성해서 코드 블럭를 관리하는 태그에 붙여준다.   } 코드는 위의 코드와 같이 간단한 것들을 사용했습니다. 아래의 이미지는 nodejs를 이용해서 디버깅 메시지를 받을 서버를 만들고, 포트를 열어둔 것입니다. 정리하면 PHP 코드에서 발생하는 쿼리의 최종 내용을 디버깅 서버에 HTTP post 방식으로 전달해주는 구조입니다. 코드는 몇 줄 안 되지만, 꽤나 강력한 도구가 만들어졌습니다."어때요. 참 쉽죠?"짜란~~~ Logger 베타 버전이 도구는 페이지를 요청하는 즉시 쿼리가 잡힙니다. 어떤 페이지 요청에서 어떤 쿼리가 발생하는지 쉽게 분석할 수 있으니 번거롭게 쿼리를 조합하는 과정은 자연스럽게 사라졌습니다.색상으로 쿼리의 속도를 표현했다.이 프로그램의 제작자이지만, 유일한 사용자이기도 합니다. 불편한 게 느껴지면 바로 수정해야 했습니다. 어렸을 때 학습지 좀 풀었던 실력으로 알아서 척척척 스스로 기능을 보강했습니다. 위의 이미지처럼 색상만 추가해도 쉽게 분별할 수 있습니다. 쿼리 실행시간을 추가해 어떤 쿼리가 병목을 잡는지도 빠르게 찾을 수 있습니다.PHP 요청 패스를 넣었더니 개 이득!디버깅에 유용한 정보까지 추가했습니다. 요청된 경로, 쿼리가 실행된 파일의 이름, 라인 위치 모델을 요청한 상위 파일의 이름과 라인 위치를 추가해 트래킹을 보강했습니다. 이쯤 되니 거의 절대반지급입니다. 쿼리 이즈 마이 프레셔스..개발에 필요한 정보들이 노출되니 기쁘지 아니한가!이외에도 현재까지 아래의 기능들을 추가했습니다.쿼리 카피 기능과 신텍스 하이라이트, 쿼리 라인쿼리 에러 메시지 로깅url 요청 단위로 쿼리 묶어주기시간이 지난 쿼리 자동 지우기키워드 검색 기능필요한 걸 직접 만들어 사용하는 것이 귀찮을지도 모릅니다. D.I.Y도 아닌데 말입니다. 하지만 자신의 개발 능력을 활용해 업무 환경을 개선하고, 개선된 만큼의 시간을 다시 투자해 선순환 구조를 만든다면 행복한(?) 개발이 될 거라 생각합니다. (=더 많은 일을 하게 되는 건 안 비밀)오늘은 업무 전, 반복 작업을 개선하면 어떨까요. 참고(사용기술)nwjsPHP (codeigniter)CSS3 + HTML5JQuery글천보성 팀장 | R&D 개발2팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #기업문화 #조직문화 #업무환경 #인사이트 #경험공유
조회수 790

[Buzzvil People] Alan Kim, Senior Software Engineer

 Buzzvil People에서는 다양한 배경과 성격 그리고 생각을 지닌 버즈빌리언들을 한 분 한 분 소개하는 시간을 갖습니다. 어떻게 버즈빌에 최고의 동료들이 모여 최고의 팀을 만들어가고 있는 지 궁금하시다면, 색색깔 다양한 버즈빌리언들 한분 한분의 이야기가 궁금하시다면, Buzzvil People을 주목해주세요.1. 간단한 자기 소개 부탁드립니다. 안녕하세요. 김진언입니다. 영어 이름은 Alan Kim 이고, 현재 버즈빌에서 클라이언트 팀의 리더를 맡고 있습니다. 저는 2002년에 병역 특례로 IT업계에서 근무를 시작했고, 첫 직장에서는 연구소 장비들에 들어가는 소프트웨어 개발을 하다가 그 뒤로 모바일 게임 포팅, 게임 서버 개발 등 지금까지 14년 동안 여러 회사에서 여러가지 업무를 해 왔습니다. 소프트웨어를 만드는 능력이 뛰어난 분들은 워낙 많기 때문에  A급 개발자라고 소개할 수는 없겠지만(^^) 컴파일러 관련 시스템 개발이나 게임, 네비게이션 시스템 등 꼭 APP개발에 국한되지 않은 다양한 경험을 해 왔기 때문에 그런 장점을 살릴 수 있는 부분에서는 나름대로 역할을 하고 있다고 생각합니다.  저는 예전부터 개발자로서 여러가지 경험을 하는 것을 중시해 왔는데요. 그러다보니 임베디드 시스템부터 게임, 게임 서버, PC 툴이나 스마트폰 관련 개발까지 다양한 분야의 경험을 쌓아올 수 있었습니다. 그런데 요즘에는 다양한 경험을 하는 것보다 어떤 개발을 하든지 간에 지켜나가야 하는 기준을 세우는 것이 중요하다는 생각을 많이 하고 있습니다. 그러다 보니 코드 자체 보다는 코드를 작성하는 방식에 대한 고민들을 많이 하게 되는 데요. 최근에는 ‘클린 코드’에 대해 많이 관심을 가지고 있습니다. 요즘에는 과거에 비해 Computing resource나 컴파일러 최적화 등이 눈에 띄게 발전해왔습니다. 따라서 무조건 효율좋은 코드를 짜기보다는 조금 효율은 부족하더라도 Readability가 잘 갖추어진 코드를 짜는게 중요하다는 생각을 하게 되었고 클린코드를 위해 고민해야 하는 모듈화 방법이나 디자인 패턴에 대해서 여러가지로 고민 중입니다. 실제로 저희 팀을 운영할때도 굉장히 강조하고 있는 부분이기도 합니다. 개발 이외의 성격적인 부분으로는 평소에 말수가 적어서 종종 과묵한 사람이라 오해받고는 하는데요. 표현력이 서툴러 말수가 적을 뿐, 다른 분들을 싫어하는 게 아니니 오해하지 않으셨으면 좋겠습니다. ^^  2. 어떻게 버즈빌에 오시게 되셨나요? 버즈빌과의 인연을 설명하려면 먼저 Jay와 슬라이드 조이라는 미국 회사를 말씀 드려야 하는데요. Jay는 인포뱅크라는 회사에서 처음 인연이 시작된 동료인데, Jay가 스타트업을 창업한 후 1년쯤 지난 시점에 저에게 연락이 와서, 같이 일해보자는 제안을 했고 그렇게 슬라이드 조이에 조인했습니다.  그 당시에 저는 인프라웨어라는 회사에서 게임 서버를 개발하고 있었는데요. Jay가 권유했던 그 시기가 마침  진행했던 프로젝트가 완료된 시점이었고, 개발자로서 이런 저런 고민을 하던 시기였습니다. 내가 개발하고 싶은 것, 배워보고 싶은 것, 도전해보고 싶은 것과 같은 부분을 현 회사에서 충족할 수 있느냐에 대한 갈등이 심했던 때 였죠. 원래 저는 직장을 선택함에 있어서 제가 정말 하고 싶은 일인지와 리스크가 크더라도 그 결과를 구성원이 함께 공유할 수 있는 구조를 가지고 있는지를 많이 고민했었는데요. 결혼을 하게 되면서 자연스레 조금 더 안정적인 직장을 찾고 싶어서 들어가게 된 곳이 인프라웨어라는 회사였습니다. 하지만 그곳에서 1년간 문제 없이 일하다보니 안정적인 점은 좋았지만 제 의견이 반영되기 힘들다는 점과 개발과정에서 소통이 중시되지 않는다는 점이 저와는 맞지 않는 부분이라고 생각하고 있었습니다. 그렇기 때문에 좋은 타이밍에 연락이 왔다 생각하여 큰 고민 없이 자연스럽게 합류하게 된 것 같습니다. 물론 미래가 불확실 할 수 있는 스타트업으로 가는 것에 대해서 가족들도 염려했지만 당시 슬라이드 조이를 이루고 있던 멤버들이 정말 훌륭하고 의견들도 잘 맞았기 때문에 슬라이드 조이로의 합류를 결정하게 되었던 것 같습니다. 그 후, 여러가지 우여곡절이 있었지만, 슬라이드 조이도 상당한 성장을 이루었고 마침 좋은 기회로 버즈빌과 합병이 되면서 지금은 버즈빌에서 클라이언트 개발팀의 리더로 근무하게 되었습니다. 3. 버즈빌에서 어떤 업무를 담당하고 계신가요? 현재 클라이언트 팀의 리더를 맡고 있지만, 슬라이드조이에서는 백엔드를 전담했었고 버즈빌에서 근무를 시작할 시점에는 광고 서버쪽을 다뤘기 때문에 아직도 약간의 서버쪽 업무를 병행해 가면서 일하고 있습니다. 차츰 앱 서버를 포함한 백엔드쪽 업무를 줄이고, 클라이언트 팀 리더로서의 업무에 주력하기 위해 일부 업무를 서버 팀 개발자에게 옮기고 있습니다. 버즈빌 클라이언트 팀의 업무가 일반적인 클라이언트 개발과 다른 점이 있다면 단순히 하나의 앱을 개발하는 것이 아니라 stable 한 SDK를 개발해야 한다는 점입니다. 여러 버즈스크린 파트너들의 다양한 개발환경에서 동작되어야 하고, 어떤 상황에서든 항상 동작되어야 하기 때문에 시스템 전반에 걸친 깊은 이해가  이 필요한 일입니다. 때문에 단순히 소프트웨어 개발자 보다는 깊이 연구하고 세밀하게 설계하는 능력을 가진 사람이 필요하고 현재 클라이언트 팀의 경우 그런 사람들로 구성이 되어있다고 생각합니다.   클라이언트 팀의 리더가 되면서 아무래도 개발 자체보다는 팀원들이 개발을 잘 할 수 있도록 하는 환경들에대해 더 많은 고민을 하고 관련 업무들을 하고 있습니다. CI(Continuous Integration)나 개발 프로세스 등 흔히 말하는 DevOps에 관련된 일들을 하고 있습니다. 뿐만 아니라 구현 방식에 대한 최종적인 방향을 결정하는 의사결정이나 개발 과제가 내려오는 과정과 개발이 완료된 과제들에 대해 외부의 팀과 커뮤니케이션이 필요한 사항들을 맡아서 관리하고 있습니다. 4. 스타트업에서 혹은 광고업계에서 일하는 느낌이 어떠세요? 스타트업은 한 사람, 한 사람의 목소리가 회사의 성장에 직접적으로 영향을 줄 수 있다는 점이 큰 매력이라고 생각합니다. 저의 경우에는 게임 서버 개발(수천명 규모), 자동차 관련 TF팀(수백명 규모), 스타트업 두 곳, 또 다른 게임회사(60명 규모) 등 많은 케이스의 회사에서 근무를 해 왔기 때문에 큰 차이를 직접적으로 느낄 수 있었는데요. 저에게 스타트업이란 “회사의 성장에 직접적으로 기여할 수 있는 곳” 입니다. 대부분의 회사는 규모가 커짐에 따라 어쩔 수 없이 여러가지 체계가 도입되고, 문화적으로도 경직화 되는것 같아요. 사원 개인이 회사의 의사 결정에 참여 하기는 정말 어렵고, 위로부터 내려온 결정 사항에 자신의 동의 여부와 관계 없이 일이 하는 경우가 대부분입니다. 개인의 개성은 최소화하고 회사라는 체계의 한 부품으로만 움직이게 되고요. 동기부여 없이 그에 따른 무의미한 업무가 반복되면 회사 생활이 정말 재미 없게 되는 거 같습니다. 예를 들어, 특정 Feature를 개발 함에 있어서도 왜 이 Feature에 대한 개발이 필요한지, 어떤 맥락에서 이 Feature의 구현이 중요한지에 대한 커뮤니케이션 없이 그저 과제만 주어지는 경우는 해당 업무에 대한 흥미를 떨어뜨린다고 생각합니다. 하지만 스타트업의 특성상 다른 팀과의 의사소통이 활발하게 진행될 수 있는 환경이다 보니 같은 일을 하더라도 좀 더 큰 맥락에서 파악하고 내가 하는 일에 대한 의미와 기대효과를 고민해보면서 일 할 수 있다는 것이 장점이라는 생각이 드네요. 5. 이것만큼은 버즈빌이 참 좋다! 어떤 게 있으실까요?  아마 많은 분들도 공감하시겠지만, 회사 일이란 게 혼자 하는 게 아니니만큼 같이 일하는 직원이 어떤 사람이냐에 따라서 자신의 업무에도 영향을 받게 되죠. 일에 대한 열정도 없고, 월급 생각하며 대충 일하는 직원과 같이 일하게 되면 다른 팀원들도 영향을 받게 됩니다. 안 좋은 케이스의 일을 몇 번 겪고 나니 일 할 때는 같이 일하는 사람이 어떤 사람인지에 대해 촉각을 많이 세우게 되었죠. 그런데 제가 지금 버즈빌에 근무한 지 1년 반이 넘은 것 같은데, 처음 입사할 때나 지금이나 여전히 느끼는 점은 버즈빌에는 ‘능력자들’이 정말 많다는 점입니다. 보통 회사에서는 10명 중 1명 있을까 말까 할 정도로 특출난 인재들이 한 곳에 모여있다는 그 부분이 정말 인상적이었어요. 스펙도 스펙이지만 보통 사회 초년생이라 일컫는 어린 나이 임에도 일에 대한 진지한 태도와 전문성, 빠른 일 처리 속도 등 대부분의 직원들이 ‘능력자’라 부르기에 손색이 없을 정도입니다. 그런 직원들과 매일 생활하니 저 또한 분발해야겠다는 생각과 함께 많은 의욕을 얻고 있어요.   또한 개발자로서 느끼는 버즈빌은 제가 일했었던 다른 회사들과 극명하게 차이가 있는 곳이라는 생각이 듭니다. 회사가 평등한 문화를 가지고 있다고 PR을 하는 경우가 많은데 버즈빌 만큼 실제로도 수평적인 문화를 가진 회사는 처음입니다. 개발에 관련된 여러가지 의사결정을 함에 있어서도 서로의 의견을 존중하고 워낙 뛰어난 사람들이 많다보니 서로에게 많은 것들을 배울 수 있는게 좋습니다. 저도 팀장이지만 팀원들에게 여러가지를 물어볼 때도 많고 팀원들 통해 새롭게 배우는 것들도 많구요. 이렇게 뛰어난 사람들도 많이 있고 이런 사람들 간에 서로에게 시너지를 줄 수 있는 좋은 문화를 가지고 있다는 점은 분명 다른 회사에서 찾아보기 힘든 장점이라고 생각합니다. 저는 합병을 통해 입사했기 때문에, 버즈빌이라는 회사에 기대를 많이 하고 합류하게 되었는데요. 그 점에 있어서는 200% 이상 충족되었다고 생각합니다. 구성원 한 사람 한 사람을 믿고 자신의 업무에 집중할 수 있다는 것은 저에게 있어 매우 중요한 의미이기 때문에, 현재 회사 생활이 무척 만족스럽네요. 6. 개인적인 목표나 꿈이 있으신가요? 있다면, 버즈빌에서의 경험이 어떻게 도움이 된다고 생각하시나요? 먼 미래에 대한 목표는 ‘돈 걱정 없는 편안한 노후’고요.(^^)  사실 이런 목표를 늘 생각하면서 살고 있진 않습니다. 미래보다는 현재가 중요하고 단기적인 목표에 최선을 다하는 것에 보람을 느끼는 편입니다. 당장 생각나는 목표는…혼자만의 여행일까요? 예전부터 같은 일상에 지치거나 슬럼프가 올때면 한번씩 여행을 가서 충분히 쉬고 생각도 정리하는 시간을 가졌었는데요. 버즈빌에는 다양한 국적의 직원들이 많다보니 그들의 성장환경과 문화 이야기를 들으면 저도 당장 떠나고 싶은 기분이 들 때가 있어요.  가정이 있다보니 혼자 여행을 가는게 쉽지만은 않고 지난 3월에 회사 워크샵으로 발리를 다녀 온 이후로 더욱 눈치가 보이기는 하지만, 몽골에 배낭여행을 가는게 너무 하고 싶네요. 그리고… 생각만 하고 실천을 잘 못하고 있는 부분이 있는데, ‘영어권 나라로의 이민’을 위해 기반을 마련하는 것 입니다. 영어권 나라들의 경우 대부분이 한국에 비해서 삶의 방식이 자유롭고 틀에 박힌 부분이 적다는 생각이 들더라구요. 제가 느끼기엔 아직까지 우리나라가 여유가 없고 바쁜 느낌이 강하게 들어서 좀더 여유로운 환경에서 생활해 보고 싶다는 꿈이 있습니다. 무엇보다 영어가 중요할텐데, 버즈빌에서는 많은 의사 소통을 영어로 하고 있다보니 생각해 보면 엄청 좋은 기회이지만, 아직까지 영어 사용을 적극적으로 하지 않고 있어서 다시 한번 마음을 다 잡고 시작해 봐야겠습니다.
조회수 2292

개발자에게 필요한 좋은 개발도구들

안녕하세요. 크몽 개발팀 입니다~ 개발자는 무엇인가 개발하기 전에 준비해야될게 있습니다. 바로 개발도구들 과 자신에게 잘 맞는 셋팅이 필요하죠.그래서 이번에 개발환경을 셋팅하면서 알게 된 정보를 공유하기위해 이번 포스트를 작성하게 되었습니다.첫번째 개발도구는 'ampps' 입니다.  ampps는 개발에 있어서 필요한 다양한 개발도구들을 제공해주고 있는데요. 정석대로 하나씩 개발도구들을 설치하게 된다면 많은 시간을 투자해서 설치 및 셋팅을 해야하지만ampps는 한번의 설치만으로 Apache, MySQL, PHP, Python, MongoDB 등등 기본적인 셋팅을 통해 초보개발자이더라도 쉽고 편리하게 사용할 수 있다는점이 가장 큰 장점이라고 생각하고 있습니다.지원되는 운영체제는 Windows, Mac, Linux 모두 지원하기때문에 어느 운영체제는 지원이 안되는 불편함은 없겠네요.사이트 :http://www.ampps.com/ 두번째 개발도구는 'WebStorm' 입니다.  WebStorm은 비쥬얼스튜디오나 이클립스와 같은 통합 개발환경을 제공하고 있습니다.그리고 현재 자바스크립트 프로그래밍에서 절대적인 최고의 에디터로 개발자 사이에서 유명하고 많은 개발자들이 사용하여 개발하고 있습니다. WebStorm의 좋은점은 작성한 코드에서 에러가 있다면 JSHint가 에러부분 밑에 워드프로세서 철자법검사기처럼 빨간 줄로 에러를 표시해 주기때문에 개발자의 실수들을 바로 잡아줄 수 있어서 정말 좋습니다. 그러나 사용자는 30일 평가기간이 끝나면 추가비용을 지불해야 사용할 수 있는데요. 비용을 지불할 만큼 좋은 에디터인점은 변함이 없습니다.  사이트 : https://www.jetbrains.com/webstorm/  앞으로도 공유할 정보들이 생길때마다 크몽팀 블로그에 업데이트 할 예정입니다.포스트 내용에서 찾으시는 정보들을 찾으셨으면 좋겠고 크몽팀 개발자이야기에 많은 관심 부탁드립니다. :)이상 포스트를 마치겠습니다. #크몽 #개발팀 #인턴 #인턴생활 #경험공유
조회수 2475

AWS 서비스를 활용한 Kubernetes 클러스터 구축 - VCNC Engineering Blog

Kubernetes 클러스터를 상용 환경에서 운영하기 위해서는 몇 가지 추가 구성요소를 설치해야 합니다. 예를 들어 Ingress를 만들더라도 실제로 트래픽을 받아줄 Ingress Controller를 설치해두지 않았으면 소용이 없습니다. 그리고 모니터링을 위해 컨테이너의 로그나 CPU/메모리 사용량 등을 수집, 조회할 수 있는 서비스도 필요합니다.다행히 이러한 추가 구성요소 또한 Kubernetes 클러스터 위에서 일반 애플리케이션과 거의 같은 방식으로 작동하므로 설치하는 것이 어렵지는 않습니다. 다만 클러스터를 원하는 대로 구성할 수 있는 만큼 선택의 폭이 넓어서 여러 가지 해법을 놓고 고민하게 될 수 있습니다. 이 글에서는 타다 서비스를 위해 Kubernetes 클러스터를 구성할 때 어떤 선택을 했는지, 특히 AWS 환경에서는 어떤 서비스들을 활용할 수 있는지 공유합니다.서비스를 외부에 노출: NGINX Ingress Controller + NLBIngress Controller 고르기Kubernetes에서 클러스터 내부 서비스를 외부에 HTTP(S)로 노출할 때는 Ingress를 사용할 수 있습니다. TLS 암호화, 로드밸런싱, 호스트명/경로 기반 라우팅 등을 제공해서 상당히 편리한데, Ingress가 실제로 작동하기 위해서는 Ingress Controller가 필요합니다.시중에는 다양한 종류의 Ingress Controller 솔루션이 나와 있습니다. 그중 Kubernetes 프로젝트에서 공식 지원하는 NGINX Ingress Controller와 AWS ALB 로드밸런서를 이용하는 AWS ALB Ingress Controller를 두고 고민을 했습니다.타다에서는 클라이언트(모바일 앱)에 실시간 이벤트를 전달하기 위해 gRPC를 사용하고 있어서 gRPC를 지원하지 않는 ALB는 선택할 수 없었습니다. 그리고 AWS ALB Ingress Controller는 현재 Ingress 하나마다 ALB를 1개 생성하는 구조여서 앞으로 노출할 서비스 수가 늘어난다면 비용 효율이 떨어진다고 판단했습니다. 따라서 NGINX Ingress Controller를 선택하게 되었습니다.NGINX Ingress Controller는 NGINX 웹서버를 기반으로 하므로 gRPC 모듈을 비롯하여 다양한 NGINX 모듈을 통해 굉장히 세세한 부분까지 설정할 수 있습니다. NGINX Ingress Controller는 Ingress나 Ingress가 가리키는 서비스의 엔드포인트에 변화가 생길 때마다 동적으로 NGINX 설정을 업데이트하는 방식으로 동작합니다.NGINX Ingress Controller 로드밸런싱NGINX Ingress Controller를 사용해도 외부에서 오는 트래픽을 적절히 분배해 줄 외부 로드밸런서는 필요합니다. AWS의 로드밸런서는 Classic ELB, ALB, NLB가 있습니다. 앞서 설명했듯이 ALB는 gRPC를 지원하지 않아서 Classic ELB를 TCP 모드로 사용하거나 NLB를 사용해야 합니다. Classic ELB는 동시에 많은 연결을 처리하려면 웜 업이 필요한 단점이 있어 NLB를 사용하기로 하였습니다.최근 NLB가 TLS termination을 지원하기 시작했지만, HTTP/2와 gRPC를 사용하기 위해 필요한 ALPN 정보를 설정할 수 없어서 NGINX 수준에서 TLS 암호화를 처리하고 있습니다. NLB 수준에서 TLS 처리를 하면 무료로 자동 갱신되는 ACM 인증서를 사용할 수 있는 등 여러 가지 이점이 있어서 아쉽습니다.Kubernetes에서 LoadBalancer 타입의 서비스를 생성하면 알아서 AWS 로드밸런서를 만들어줍니다. 하지만 이렇게 해서 NLB를 생성하는 방식은 아직 알파 기능입니다. 따라서 먼저 NodePort 타입의 서비스를 생성하여 모든 노드의 특정 포트에 NGINX를 노출한 다음, 별도로 생성한 NLB에 노드들이 속한 오토스케일링 그룹을 연결해주는 방식으로 직접 설정하게 되었습니다.정리해보면 외부에서 오는 트래픽을 처리할 때는 다음과 같은 과정을 거칩니다.모든 서브도메인(*.tadatada.com)은 NLB를 가리킵니다.NLB의 443 포트로 암호화된 HTTP 또는 gRPC 요청이 들어옵니다. NLB는 적절한 Kubernetes 노드 중 하나의 특정 포트(예: 30000번)로 요청을 전달합니다.Kubernetes 노드에서는 포트 번호를 보고 NGINX 서비스로 향하는 요청임을 알 수 있고 NGINX 컨테이너 중 하나로 요청을 전달합니다.NGINX는 복호화를 한 다음 HTTP Host 헤더를 확인하여 요청을 전달할 Ingress를 알아냅니다. 그리고 해당 Ingress의 엔드포인트 중 하나로 복호화한 요청을 프록시합니다.애플리케이션 컨테이너가 요청을 처리합니다.트래픽 흐름: NLB → NodePort → NGINX Ingress Controller → 내부 서비스Pod에 IAM 역할 부여: kube2iamS3, SQS 등 IAM으로 인증하는 AWS 서비스에 접근하려면 인증 정보가 필요합니다. EC2에서는 액세스 키를 직접 넣는 대신 EC2 인스턴스 프로파일로 인스턴스에 IAM 역할을 부여할 수 있습니다. 하지만 하나의 Kubernetes 노드 (=EC2 인스턴스)에는 여러 Pod이 실행될 수 있기 때문에 Pod마다 다른 IAM 역할을 부여하기를 원한다면 인스턴스 프로파일을 활용할 수 없게 됩니다. (인스턴스 프로파일에는 하나의 IAM 역할만 부여 가능)kube2iam을 사용하면 다음과 같이 Pod 어노테이션으로 IAM 역할을 지정할 수 있습니다.apiVersion: v1 kind: Pod metadata: name: aws-cli labels: name: aws-cli annotations: iam.amazonaws.com/role: role-arn spec: ... 설치나 사용법은 문서를 참고하면 어렵지 않은데, 원리를 간단히 설명해 보겠습니다. EC2 인스턴스 안에서는 특정 IP 주소(169.254.169.254)로 접속하면 EC2 메타데이터 API에 접근할 수 있습니다. AWS SDK는 EC2 메타데이터 API를 통해서 인스턴스 프로파일에 붙은 IAM 역할과 IAM 역할에 해당되는 액세스 키 쌍을 받아오게 됩니다.kube2iam은 모든 노드에 실행되면서 Pod 내부에서 EC2 메타데이터 서버 주소로 나가는 모든 요청을 가로챕니다. 그리고 인스턴스 프로파일 정보와 액세스 키 발급 요청을 kube2iam 서버가 대신 처리합니다. 따라서 Pod 안에서는 인스턴스 프로파일이 부여된 EC2 인스턴스 내부에 있는 것처럼 느껴지게 됩니다.추후 AWS SDK에 EKS 지원이 추가되면 별도로 데몬을 설치하지 않고도 Pod에 IAM 역할을 줄 수 있게 될 것으로 보입니다.로그 수집: fluentd + CloudWatch LogsKubernetes의 컨테이너가 stdout/stderr로 출력하는 로그는 노드에만 쌓이고 컨테이너를 재시작하거나 삭제하면 함께 삭제됩니다. 또한 노드의 디스크가 꽉 차는 것을 방지하기 위해 일정 크기를 넘으면 오래된 로그는 없어집니다. 그러므로 로그가 사라지지 않도록 계속 어딘가에 모아두어야 합니다.AWS에서 활용할 수 있는 로그 저장 서비스에는 CloudWatch Logs가 있습니다. fluentd를 DaemonSet으로 노드마다 하나씩 실행해서 컨테이너 로그를 CloudWatch Logs로 전송할 수 있습니다.CloudWatch Logs에 저장한 로그는 최근 나온 CloudWatch Logs Insights로 검색, 분석할 수 있습니다. 아직 나온 지 얼마 되지 않아서 기능이 많지는 않지만, 간단히 조회하는 용도로는 충분합니다.CloudWatch Logs Insights 사용 예모니터링: PrometheusEC2 인스턴스 하나에 서비스 하나를 띄워서 사용할 때는 CloudWatch로 CPU 사용률 등의 지표를 측정할 수 있었습니다. 하지만 Kubernetes를 사용하면 여러 서비스가 하나의 인스턴스에서 동시에 실행될 것이므로 인스턴스 수준의 지표는 무의미합니다. 특히 최소 실행 단위인 컨테이너 수준의 CPU 사용률 같은 값을 측정해야 하는데, CloudWatch를 사용하기에는 과금 체계가 적합하지 않습니다.기본 제공되는 5분 간격의 EC2 지표는 무료지만 CloudWatch에 커스텀 지표를 올리게 되면 지표 당 비용을 지불해야 합니다. 이 때 '지표'는 지표 이름 + 고유한 차원(dimension)의 조합입니다. 예를 들어 CPUUtilization이라는 이름의 지표가 PodName=server-aaaaaaaa과 PodName=server-bbbbbbbb라는 다른 차원으로 올라온다면 각각을 다른 지표로 취급합니다. 따라서 지표 수가 너무 많아지지 않게 조정해야 하는데 그러면 상세하게 모니터링하기가 어렵습니다.비용 문제도 있고, Kubernetes의 여러 가지 정보를 CloudWatch로 내보내는 기존 도구가 없었기 때문에 다른 방법을 찾아보게 되었습니다. 그래서 Kubernetes 모니터링을 위해 많이 사용하는 Prometheus를 선택했습니다. Prometheus를 온전히 사용하기 위해서는 다양한 컴포넌트들이 필요한데, Prometheus Operator Helm 차트를 사용하면 비교적 쉽게 구축할 수 있습니다.Prometheus는 Kubernetes 클러스터 모니터링 외에 애플리케이션 모니터링에도 사용할 수 있습니다. 타다의 애플리케이션들은 Spring Boot로 작성되어 있는데 Spring Boot Actuator와 Micrometer의 Prometheus 지원을 사용해서 애플리케이션 수준의 지표도 Prometheus로 모니터링하고 있습니다. 특히 Prometheus Operator를 사용하면 모니터링 대상을 추가할 때 Prometheus 설정 파일을 수정하지 않아도 Kubernetes에 ServiceMonitor 리소스를 등록하기만 하면 되어서 편리합니다.Prometheus로 수집된 지표는 Grafana 대시보드로 시각화하고, 정해진 조건에서 Alertmanager를 통해 PagerDuty와 Slack에 알림을 보냅니다.Grafana 대시보드의 모습자동 처리량 확장: Cluster AutoscalerKubernetes에서 자동 처리량 확장은 크게 두 종류로 나눌 수 있습니다. 먼저 Horizontal Pod Autoscaler로 CPU, 메모리 사용량에 따라 Pod의 수를 자동으로 조정할 수 있습니다. HPA가 실제로 동작하기 위해서는 오토스케일링을 위한 지표를 제공하는 Metrics Server를 설치해야 합니다. 그런데 부하가 증가해서 HPA가 Pod 수를 늘리려고 할 때 워커 노드에 여유가 충분하지 않으면 새로운 Pod을 실행할 수 없어서 소용이 없습니다. 이 때 워커 노드의 수를 자동으로 조정해주는 것이 Cluster Autoscaler입니다. Cluster Autoscaler는 노드 수를 증가시키기만 하는 것이 아니라 여유가 생겼을 때 노드 수를 자동으로 줄여서 불필요한 비용이 발생하지 않도록 해줍니다.AWS 환경에서 Cluster Autoscaler는 EC2 API를 통해 EC2 오토스케일링 그룹의 Desired Capacity 값을 필요한 노드 수로 조정하는 방식으로 작동합니다. 따라서 Cluster Autoscaler에는 EC2 API를 호출할 수 있는 IAM 권한을 주어야 합니다. 이를 위해 위에서 소개한 kube2iam을 사용할 수 있습니다. 그리고 Cluster Autoscaler가 오토스케일링 그룹을 자동으로 발견할 수 있도록 미리 정해진 태그를 붙여야 합니다.한 가지 주의할 점은 노드의 오토스케일링 그룹이 여러 가용 영역(AZ)에 걸쳐있으면 안 된다는 것입니다. 오토스케일링 그룹이 여러 AZ에 속한 경우 AZ 간 인스턴스 수의 균형을 맞추려고 하는데 이 과정에서 인스턴스가 예기치 않게 종료될 수 있습니다. 이 때 해당 노드에 실행되어 있던 Pod이 안전하게 종료되지 않을 수 있기 때문에 AZ마다 오토스케일링 그룹을 따로 만들고 AZ 간 균형은 Cluster Autoscaler가 맞추도록 설정해야 합니다.도움이 되는 링크들위에서 소개한 컴포넌트들은 다음과 같은 Helm 차트를 통해 설치해서 사용하고 있습니다.stable/nginx-ingressstable/kube2iamincubator/fluentd-cloudwatchstable/prometheus-operatorstable/metrics-serverstable/cluster-autoscalerEKS Workshop: AWS 환경에서 Kubernetes 운영할 때 참고할 만한 정보가 많이 있습니다.Kubernetes Slack 채널: #eks 채널에는 AWS 직원들도 접속해 있어서 높은 확률로 답변을 받을 수 있습니다.
조회수 1248

스푼 라디오 오디오 랩 팀의 Jason을 만나보세요!

인상이 좋은 비결은.. 원래 이렇게 생겼어요 (찡긋)오디오 랩 팀의 막내, 알고 보니 세상 모든 매력을 덕지덕지 붙이고 다니는 Jason을 인터뷰해보았습니다.근데 대체 왜 이렇게 인상이 좋은 거예요? 출처: 알파카 월드 - 제이슨 닮은꼴"그냥 정말 원래 이렇게 생겼어요 하하. 웃는 상이예요. 사실 어릴 땐 눈이 좀 더 찢어지고(?) 올라가 있어서 좋은 인상이 아니었는데, 좋은 인상으로 변하더라고요..(나이 탓인가..) 웃는 게 습관이 되어버렸어요"인싸도 아싸도 아닌 '그럴싸'"인싸요? 아니에요 인싸. 그냥 저는 좀 알고 보면 반전도 많고 '모순덩어리' 일뿐이에요. 그래서 저를 표현하는 한 마디도 저는 '모순덩어리'라고 할래요. 예를 들면, 저는 해병대 출신인데 수영을 못하고요. 이성적인 것 같은데 또 되게 감성적이에요. 발라드를 되게 좋아하는데 제 노래방 18번은 '거꾸로 강을 거슬러 오르는 저 힘찬 연어들처럼'이에요. 사색하는 거 좋아하는데 또 가만히 있는 건 싫어요. 시간 아깝더라고요. (빵긋) 사내 제이슨 feat. 카이와 헤이든 듣고 싶은 당신의 스푼 라이프오디오 랩팀은 어떤 부서인가요?"오디오 랩팀은 스푼 라디오에서 오디오 방송 통신 기술을 연구하고 개발하는 부서입니다. 저희의 궁극적 목표는 세계 최고 오디오 기술 플랫폼이 되는 것이에요. 그리고 오디오 랩에서 제가 하고 있는 업무는 안드로이드 OS 클라이언트에 오디오 기술 개발하는 업무를 맡고 있어요. 오디오 랩팀에 막내이긴 한데.. 재간둥이 역할은 제가 맡고 있지 않아요 하하.. 저희 팀의 재간둥이 역할은 Ben님께서 하고 계십니다"스푼에 입사하기까지"제 입으로 말해도 되나요? 저는 수학을 좋아하진 않았는데, 잘했어요. 국어랑 사회 같은 문과계열 과목을 싫어했는데 이공계 쪽이 저와 적성에 맞더라고요. 수학 1등급 나왔는데 메가스터디 박 XX 선생님께 이 자리를 빌려 감사드립니다. 인강이 저를 만들어주셨어요.저의 원래 장래희망은 항공기 정비사였어요. 언제부터 비행기를 좋아했는지 모르겠지만 초등학교 때부터였던 것 같아요. 고3 때 진로를 정해야 하는데 항공정비과와 전자공학과와 고민을 했었어요. 그러다가 결국엔 전자 공학과 에 진학하게 되었고 자연스럽게 꿈 하고 멀어지게 되더라고요. 사실 항공 소프트웨어 쪽으로 일을 하게 될 줄 알았는데 다른 쪽으로 방향이 틀어지다 보니 어느덧 30대가 되어 있었어요. 사실 처음에 저는 스타트업에서 일하게 될 줄 몰랐어요. 이직을 준비하던 차에 제가 직접 스푼 라디오를 사용해보고, 기사도 읽게 되었고 Neil(대표)의 세바시 강연을 보고 이곳에서 일하고 싶다! 비전이 있다!라고 생각해서 오게 되었어요"내가 함께 일하고 싶은 사람서글서글한 사람을 좋아해요. 제가 그렇게 잘 못하는 편이라서요. 낯을 좀 많이 가리는데 저와는 다른 성향인 사람이라면 시너지 효과가 날 것 같아요파일럿 제이슨알고 싶은 Jason의 이야기해병대 출신부터 비행기 조종사까지"제가 안 그래 보이지만.. 사실 해병대 출신이에요. 해병대 왜 갔냐고 물어보신다면, 멋있어 보여서 가게 되었어요. 그게 전부예요. 복식 호흡하는 게 멋있어 보이더라고요. 원래 하고 싶은걸 다 하면서 살자라는 위주인지라, 꼭 무엇이든 하고 말거든요. 원래 꿈이 비행기 조종사였는데 꿈을 못 이루었으니 취미로도 해보자!라는 생각이 들어서 시작하게 되었어요. 한국에서도 할 수 있는데 제약이 너무 많아서 회사를 그만두고 미국에 갔어요. 여태 모아둔 돈 다 쓰고 왔어요. 4개월 정도 미국에서 하루 10시간씩 비행을 했었는데, 정말 행복했어요. 고등학교 때는 사실 실용음악도 준비했었어요. 아카펠라 중창단에 속해있었는데 2학년이 되고 이걸 진로로 결정하기엔 아니라고 판단이 들어서 그만두긴 했지만요. 그래서 대학교에 들어가고 밴드부에 들어가서 보컬을 맡았었어요. 저 점심시간에 혼자 코노가요. 같이 가기엔 부끄러워서.. 혼자 갑니다"유노윤호의 열정, 최강창민의 쿨함"제가 원래 자소서에 경청을 잘하는 사람이라고 적었는데 사실 가끔 듣는 것도 귀찮아요 하하.. 그리고 본인 이야기하는 것도 민폐라고 생각해서 잘하지 않는데 인터뷰하다 보니 엄청 많이 하게 되었네요. 근데 또 제가 남한테 지는 거 안 좋아해서 벤이랑 운동 누가 더 많이 하나 내기해서 요즘 매일 아침 출근 전에 수영 배우고 있고 화, 목은 영어학원을 다니면서 자기 계발을 하고 있어요. 목표가 없으면 안 되는 것 같아서 늘 목표를 일부러 세워요. 그래서 예전엔 사진도 배우러 다녔어요. 아 참! 수영을 배우다 보니 요즘 새로운 목표는 '라이프 가드'를 하고 싶어 졌어요. 이렇게 하고 싶은걸 하면서 열정적이게 살게 된 계기는 아마 아버지의 영향이 큰 것 같아요. 아버지가 매일 이렇게 말씀해주셨거든요"꿈을 꾸고 살아라, 돈은 따라온다! 반려견 '나무'의 아빠 Jason"저희 집 강아지 이름이 '나무'인데요. 식목일이 생일이라서 나무라고 지었어요. (나무 이야기할 때 눈빛이 초롱초롱해지면서 나무의 사진 보여주시던 제이슨) 나무는 귀엽고요. 비가 오나 눈이 오나 항상 저를 반겨줘요. 그래서 고마운 친구예요. 회사랑 집이 거리가 좀 멀어서 자취를 할까 생각했는데, 그러면 강아지가 혼자 집에 있어야 하니 안쓰러워서 하고 싶지 않았어요. 제가 없더라도 다른 가족들이 나무를 보살펴 줄 수 있어서 다행이라고 생각해요.팀원들이 Jason을 한마디로 표현한다면?Ian: JSON - "가볍고 빠르고 효과적이어서"*JSON [JavaScript Object Notation] :경량의 DATA교환 형식Ben: 알파카계의 알파치노 - "알파카처럼 온순한 외모의 소유자이지만 속엔 야망과 강한 카리스마를 가진 남자라서"
조회수 841

웹기반 컨텐츠 저작 도구 셀프(XELF) v1.0 GS인증 획득

웹기반 컨텐츠 저작 도구 셀프(XELF) v1.0 (Web-based Contents Authoring Tool XELF v1.0)이 한국정보통신기술협회(TTA) 소프트웨어 시험인증연구소로부터 GS인증 1등급을 획득하였습니다.  셀프(XELF)는 별도의 프로그램 설치 없이도 접속만으로 웹브라우저 상에서 다양한 용도의 콘텐츠를 저작할 수 있는 디자인 플랫폼입니다. 디자인 전문가가 아니어도 누구나 손쉽게 프리젠테이션, 웹브로셔, 유저 인터페이스, 문서 등 비즈니스 및 교육환경에 필요한 다양한 콘텐츠를 디자인할 수 있습니다. 또, 이렇게 제작된 콘텐츠는 클릭만으로 SNS에 공유하거나 이메일로 전달하는 등 간편하게 활용할 수 있는 장점을 가지고 있습니다.   GS인증은 엄격한 시험을 통해 품질이 우수한 소프트웨어를 인증해주는 국가공인 소프트웨어 품질인증제도로 공공기관에서 우선 구매 대상으로 지정되기도 합니다. ISO 국제표준을 기준으로 SW의 기능성, 신뢰성, 효율성, 사용성, 유지보수성, 이식성, 성능 등을 평가하고 검증을 거쳐 부여되었습니다. ㈜그로비스인포텍은 이번 GS인증을 계기로 디자인 플랫폼으로서의 기술성과에 자신감을 가지고 향후 계획된 베타서비스 준비에 최선을 다하고 있습니다. 더 나은 사용성과 기술적 안정성을 목표로 다양한 환경에 적용하고 테스트를 진행하고 있습니다. 곧이어 더 향상된 성능과 기능으로 찾아뵙길 기대하겠습니다. 감사합니다.
조회수 3078

챗봇과 인공지능 머신러닝 ㅡ Part 1/2

스타워즈를 보신 분이라면 거기에 나오는 난쟁이 로봇 R2D2와 키다리 로봇 C3P0를 아실 것이다. 친근한 R2D2는 전자음을 조정해 인간과 대화를 하며 주로 말 잘하고 박식한 로봇인 C3P0가 통역을 해준다.이런 충실하면서 똑똑한 친구들이 옆에서 항상 나를 도와준다면 어떨까? 정말 좋을 것이다. 만약 매일 보는 스마트폰 안에서도 나의 질문에 답해주는 이런 고마운 친구들이 있다면 얼마나 좋을까? 이런 저런 생각을 하다보면 우리는 대화형 로봇의 필요성을 느낀다.챗봇(Chatbot)이란?챗봇의 정의는 “대화형 인터페이스 상에서 규칙 또는 지능으로 유저와 소통하는 서비스”이다. 이 말을 하나하나 풀어보자.먼저, 대화형 인터페이스란 뭐지? 어렵다. 쉽게 설명해 보자. 인터페이스는 사람과 컴퓨터를 연결하는 장치라고 한다. 역시 어렵다. 아! 그냥 스마트폰 앱으로 보면 된다. 그럼 소통한다는 말은 대화한다는 것이므로 스마트폰 앱에서 일방향이 아닌 양방향이 가능하다는 얘기다. 어! 이상하다. 양방향이라면 나의 말에 응대하는 로봇은 뭐로 움직이는 거지? 궁금하다. 누가 일정한 규칙으로 만들어 논건지 아니면 우리처럼 지능이 있는 건지. 지능이 있다면 그런 지능은 뭐지? 점차 우리는 자연스럽게 인공지능에 다가간다.인공지능(Artificial Intelligence)이라는 용어는 1956년 미국 다트머스의 한 학회에서 존 매카시가 처음 사용했다고 한다. 원래 인공지능은 소프트웨어인 정신을 말하고 로봇은 하드웨어인 육체를 말하는 것이지만 정신없이 육체가 존재할 수 없는 것처럼 로봇을 얘기하면 당연히 인공지능은 따라간다.학자들은 인공지능을 강(强)인공지능과 약(弱)인공지능으로 구분한다. 간단히 얘기하면 강인공지능이란 자의식이 있는 인간에 가까운 지능이고 약인공지능은 자의식이 없다. 자아가 없으며, 명령받은 일만을 수행한다. IBM의 왓슨(Watson), 작년에 인공지능의 붐을 가져온 구글의 알파고(Alpha-GO) 등은 모두 약인공지능이다. 이런 인공지능을 구현하는 기술은 무엇인가? 바로 기계한테 학습을 시키는 머신러닝(Machine Learning)이다.1959년 아서 사무엘은 머신러닝을 "기계가 일일이 코드로 명시하지 않은 동작을 데이터로 부터 학습하여 실행할 수 있도록 하는 알고리즘을 개발하는 연구 분야"라고 정의했다. 여기서 학습이란, 입력 값을 받아 결과 값을 내는 모델을 만드는 표현과 표현을 통해 주어진 업무가 얼마나 잘 수행됐는지 알아보는 평가, 그리고 평가에서 설정한 기준을 찾는 최적화로 구성된 일련의 과정을 말한다. 중요한건 우리가 시키지 않은 일도 학습에 의해 자율적으로 처리한다는 것이다. 정말 신기하지 않은가?이제 챗봇이 뭔지 감이 잡힌다. 스마트폰 앱상에 존재하는 로봇인데, 물론 육체는 화면의 아이콘으로 밖엔 안보이지만 인공지능을 가지고 머신러닝에 의해 동작을 하면서 우리와 대화를 하는 그분. 그렇다면 이제 남은 건 이분의 지능이 어느 정도인지 또 얼마나 일을 잘하는 지로 판가름 난다.우리는 평생 공부를 한다. 이제는 학교를 졸업하고 나서도 항상 배워야 한다. 학습이 없다면 지능도 없다. 학습은 일일이 지도받는 지도학습과 알아서 공부하는 자율학습이 있다. 알아서 공부하려면 먼저 머리에 지식이 많아야 한다. 역시 기계도 사람과 비슷하게 배운다.  다음시간엔 챗봇에게 학습을 시켜 지능을 가지게 하는 방법에 대해 알아본다.> Part 2에서 계속
조회수 3029

우아한 설계의 첫걸음, ES7의 decorator

하루가 멀다 하고 신기술이 쏟아지는 요즘 자바스크립트 또한 계속해서 새로운 모습으로 바뀌고 있습니다. ECMAScript 2015(이하 ES6)에 새롭게 등장한 Arrow function, Class, Generator 등이 그중 하나라 할 수 있습니다. 오늘은 ECMAScript 2016(이하 ES7)에서 새롭게 제안된 Decorator에 대해 알아보려 합니다.Decorator란?ES7 스펙 명세(링크)에는 Decorator를 아래와 같이 설명하고 있습니다.선언된 클래스와 그 프로퍼티들을 디자인 시간에 변경할 수 있는 편리한 문법위 문장만 봐서는 도대체 Decorator가 어떤 역할을 하는지 감이 오지 않습니다. 백문이 불여일견이라고 예제를 통해 Decorator를 어떻게 활용할 수 있는지 알아보겠습니다. 아래 코드는 Decorator를 이용해 설계한 클래스 코드의 일부입니다.@withSuperEngine class Car {     ...   @readOnly  manufacturer = 'ZOYI'   ... } 클래스와 클래스의 프로퍼티가 어떤 성질을 가지고 있는지 한눈에 보이시나요? Car는 슈퍼 엔진을 가지고 있고 manufacturer는 변경할 수 없는 값이라는 것을 소설을 읽는 것처럼 쉽게 이해할 수 있습니다. 이처럼 Decorator를 이용하면 코드를 우아하게 작성할 수 있습니다. 그렇다면 어떻게 Decorator를 정의하고 사용할 수 있을까요?Decorator는 최종적으로 채택된 스펙이 아니기 때문에 babel과 함께 사용해야 합니다. babel 설정은 링크에서 확인할 수 있습니다.Decorator의 선언 및 사용방법Decorator는 사실 함수입니다. 함수를 선언한 뒤 ‘@’ 키워드를 이용해 선언된 함수를 Decorator로 사용할 수 있습니다. @withSuperEngine, @readonly, @say.hello, @hello(...) 등이 사용 가능한 Decorator의 호출 형태입니다. Decorator는 클래스를 꾸밀지, 클래스의 프로퍼티를 꾸밀지에 따라 선언하는 방법이 달라집니다.클래스 프로퍼티의 Decorator먼저 클래스 프로퍼티의 Decorator를 정의하고 사용하는 방법에 대해 알아보겠습니다. 이 경우에는 프로퍼티의 descriptor를 인자로 받아 새로운 descriptor를 반환하는 형태를 가집니다. (descriptor에서 설정할 수 있는 여러 값은 링크를 확인해주세요.)그럼 이제 readonly 역할을 하는 Decorator를 작성하고 테스트를 해 보도록 하겠습니다.function readonly(target, property, descriptor) {     descriptor.writable = false   return descriptor } class Car {     @readonly   manufacturer = 'ZOYI' } const myCar = new Car()   myCar.manufacturer = ‘JOY’ // 새로운 값을 할당하려고 한다면 에러가 납니다. 또 다른 예제로 클래스의 프로퍼티를 열거할 때 열거 대상에서 제외하는 Decorator를 작성해 보겠습니다.function nonenumerable(target, property, descriptor) {     descriptor.enumerable = false   return descriptor } class Car {     @nonenumerable  acceleration = 10 manufacturer = 'ZOYI' } const myCar = new Car()   for (let key in myCar) {     console.log(key)  // manufacturer 만 출력이 된다. acceleration는 열거 대상에서 제외된다. } 단 몇 줄만으로 우리는 클래스의 프로퍼티를 읽기 전용으로 만든다던지 열거 대상에서 제외했습니다. 참 편리하지 않나요? Decorator의 활용은 여기서 끝나지 않습니다. 메모이제이션을 하는 메서드를 만들수 있고 클래스에 자동으로 바인드된 메서드로 만들 수도 있습니다.Decorator는 제안된 지 얼마 안 됐지만 많은 사람들이 활발히 연구 중입니다. github에는 지금도 계속해서 Decorator에 관련된 라이브러리들이 올라오고 있습니다. 그중 core-decorators.js는 미리 정의된 유용한 Decorator 패키지를 제공합니다.클래스의 Decorator클래스의 Decorator는 타겟 클래스의 생성자를 인자로 받습니다. 사용자는 인자로 받은 생성자를 입맛에 맞게 바꾼 뒤 반환을 해 주면 됩니다.function setAnimalSound(sound) {     return (target) => {     target.prototype.sound = sound     return target   } } @setAnimalSound('oink') class Pig {     say() {     return this.sound   } } @setAnimalSound('quack') class Duck {     say() {     return this.sound   } } const pig = new Pig()   console.log(pig.say()) // ‘oink’ 출력 const duck = new Duck()   console.log(duck.say()) // ‘quack’ 출력 위 코드처럼 오리나 돼지의 울음소리를 클래스 내부에서 정의하지 않고 클래스 Decorator를 사용해서 정의할 수 있습니다.(사실 이런 코드는 설계 관점에서 봤을 때 바람직하지 않지만 Decorator를 사용할 수 있는 여러 방법 중에 하나라고 봐주시면 감사하겠습니다.)클래스 Decorator는 클래스의 생성자를 바꾸는 것에 국한되지 않고 완전히 다른 클래스의 생성자로 바꿔치기도 할 수 있습니다. 아래 코드는 그 예제를 보여줍니다.function withBus(target) {     return class Bus {     say() {       return 'I am bus'     }   } } @withBus class Car {     say() {     return 'I am car'   } } const car = new Car()   console.log(car.say()) // ‘I am bus’ 출력 이런 구현 방식은 특정 상황에서 클래스 자체를 하이재킹 함으로써 전통적인 분기문 예외 처리가 아닌 보편적인 프로그래밍을 할 수 있게 도와줍니다.클래스 Decorator는 Cross-Cutting-Concern(전체 설계에서 빈번하게 나오는 관심사를 쉽게 모듈화 시키지 못하는 상황)이나 React에서 컴포넌트 하이재킹을 쉽게 해결해줄 수 있는 방법을 제공합니다. 이런 상황을 어떻게 효율적으로 처리하는지에 대해서는 Decorator를 소개하는 글의 취지에 맞지 않아 다음에 연재할 글에서 다룰 예정입니다.마무리이상으로 ES7에 새롭게 제안된 클래스 및 클래스 프로퍼티에 사용할 수 있는 Decorator에 대해서 알아봤습니다. Decorator는 Java, Python과 같은 언어에서 이미 존재하는 문법이기 때문에 이런 설계가 기존에 없던 새로운 방법은 아닙니다. 하지만 오랫동안 ES5에 머물던 자바스크립트가 ES6, ES7 그리고 최근에는 ES8까지 빠르게 변하고 있는 스펙 속에 다른 언어의 장점을 품는 것은 그 자체로 상당히 도전적인 변화라 생각합니다. Decorator 문법은 클래스와 그 파라미터를 꾸밀 수 있는 것에 멈추지 않고 함수의 파라미터에도 꾸밀 수 있게 드래프트 버전이 나온 상태입니다. 자바스크립트에서 Decorator를 이용한 우아한 설계가 어디까지 발전할 수 있는지, 그리고 향후 자바스크립트의 행보가 기대됩니다.#조이코퍼레이션 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 1869

파이썬의 개발 “환경”(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월에 한 번 써보았으나, 아직은 실무에서 쓰기에는 이르다는 결론을 내렸습니다. 이에 관한 그때의 제 감상은 별도의 글로 다루었습니다. ↩#스포카 #파이썬 #개발팀 #개발자 #인사이트 #후기 #일지
조회수 1637

비트윈 PC 버전 개발기

지난 10월 20일, 비트윈 PC 버전의 오픈 베타 테스트를 시작했습니다. PC 버전 덕분에 컴퓨터 앞에서 일과 시간을 보내는 직장인들도 편리하게 비트윈으로 연인과 대화할 수 있게 되었습니다. 이 글에서는 PC 버전에 어떤 기술이 사용되었는지 소개하고 약 4개월의 개발 기간 동안 겪은 시행착오를 공유합니다. 비트윈 PC 버전 스크린샷개발 플랫폼 선택¶PC 버전 개발을 본격적으로 시작하기 전에 어떤 개발 플랫폼을 선택할 것인지 많은 고민을 했습니다. MFC나 WinForms 같은 네이티브 플랫폼, Qt 등의 크로스 플랫폼 라이브러리, 그리고 웹 기반 앱 등의 여러 후보를 가지고 토론을 거쳐 웹 앱으로 개발하기로 했습니다.웹 기반으로 개발하게 된 가장 큰 이유는 생산성입니다. PC 버전 팀이 웹 기술에는 이미 익숙하지만 다른 플랫폼은 경험이 많지 않았습니다. 또한, 비교적 자유롭게 UI를 구성할 수 있으며 기존의 각종 개발 도구를 이용하면 빠른 이터레이션이 가능할 것으로 예상했습니다.단, 사용자가 기존에 설치한 웹 브라우저를 통해 접속하는 방식이 아니라 브라우저 엔진을 내장한 실행 파일을 배포하는 방식을 택하기로 했습니다. 여러 브라우저 환경에 대응하지 않아도 되고, 브라우저에서 지원하지 않는 일부 시스템 기능을 직접 확장해서 사용할 수 있기 때문입니다.서버 아키텍처의 변화¶비트윈 서버의 서비스 로직은 Thrift 서비스로 구현되어 있습니다. 그리고 Alfred라는 자체 개발 라이브러리를 사용하여 Thrift 서비스를 Netty 기반의 서버로 구동합니다.기존의 비트윈 모바일 클라이언트는 채팅 서버와 Thrift의 바이너리 프로토콜로 통신하고 있습니다.1 그러나 웹 플랫폼에서는 서버와 지속적으로 양방향 연결을 유지하려면 WebSocket 프로토콜을 사용해야 하므로 Alfred에 WebSocket 프로토콜 지원을 추가하였습니다. 애플리케이션이 아닌 라이브러리 수준의 변화였기 때문에 기존 서비스 코드에 영향을 거의 주지 않고 새로운 프로토콜을 지원할 수 있었습니다.Alfred에 웹소켓 지원을 추가하였습니다.비트윈 PC 버전 셸¶비트윈 PC 버전은 크게 HTML과 자바스크립트로 작성된 웹 앱 부분과 웹 앱을 브라우저 엔진으로 구동해주고 플랫폼 API를 제공하는 셸 (Shell) 부분으로 구성되어 있습니다.비트윈 PC 버전 구조PC 버전 셸은 Chromium Embedded Framework (CEF)를 사용합니다. 이름에서도 알 수 있듯이 Chromium 브라우저 엔진을 애플리케이션에 내장하기 쉽도록 감싸놓은 라이브러리입니다. CEF는 Evernote나 Steam 등 웹 브라우저를 내장한 애플리케이션에서 널리 사용되고 있어 선택하게 되었습니다.2자바스크립트에서 셸이 제공하는 플랫폼 API를 호출할 때는 CEF의 Message Router를 사용하였습니다. Chromium은 멀티 프로세스 구조로 이루어져 있어, 렌더 프로세스에서 작동하는 자바스크립트 코드가 브라우저 프로세스에서 작동하는 C++ 코드를 호출하고 결과를 돌려받기 위해서는 별도의 처리가 필요합니다. Message Router는 이 두 프로세스 사이의 비동기 통신을 지원합니다. 이를 통해 창 투명도 조절이나 트레이 알림 표시 등 원래는 웹 플랫폼에서 지원하지 않는 기능을 확장하여 지원할 수 있었습니다.CEF에서는 Chrome 개발자 도구를 사용할 수 있어 디버깅이 용이했고, 디자이너 옆에서 바로바로 좌표나 색상 등을 바꿔볼 수 있어 협업에도 도움이 되었습니다.그러나 PC 버전을 개발하면서 가장 많은 시행착오를 겪은 부분이 CEF를 다루는 것이었습니다.문서화가 잘 되어있지 않습니다. 그래서 실제 작동 방식을 확인하기 위해 직접 소스 코드를 읽어야 하는 경우가 많았습니다일반적인 웹 브라우저에서는 잘 작동하는 API를 CEF가 자원하지 않거나 버그가 있어 다른 방식으로 구현해야 할 때가 있습니다.CEF에 노출된 API에만 접근할 수 있어 Chromium에서 제공하는 플랫폼 추상화 레이어를 활용할 수 없었습니다.비트윈 PC 버전 웹 앱¶비트윈 PC 버전의 주요 애플리케이션 코드는 HTML과 자바스크립트로 작성되어 있습니다. 자바스크립트로 큰 규모의 애플리케이션을 작성할 때 발생하는 여러 가지 어려움을 피하고자 React 라이브러리 및 최신 자바스크립트 기술을 적극적으로 활용하였습니다.React¶React는 Facebook에서 개발한 오픈 소스 자바스크립트 UI 라이브러리입니다. 일반적인 웹사이트보다는 비교적 복잡한 인터페이스를 구현해야 했기 때문에 jQuery처럼 간단한 라이브러리로는 부족할 것으로 생각하여 비트윈 PC 버전은 처음부터 React를 사용하였습니다.전통적인 개발 방식에서는 UI를 변경해야 할 때 기존에 렌더링 된 DOM 요소에 명령을 내립니다. 예를 들어 어떤 항목을 삭제하려면 그 요소를 찾아서 삭제 명령을 내리게 됩니다. React를 사용할 때는 이와 달리 해당 요소가 사라진 DOM 트리 전체를 다시 생성하면 React가 이전 트리와 새 트리를 비교하여 바뀐 부분만 반영해줍니다. 전체를 다시 렌더링하기 때문에 기존에 DOM 트리가 어떤 상태였는지 신경 쓰지 않고도 원하는 상태로 쉽게 변경할 수 있어 UI 코드의 복잡도를 줄일 수 있습니다.또한, React의 컴포넌트 시스템은 독립적인 UI 요소들을 서로 영향을 주지 않고 조합할 수 있도록 해주어, 한가지 컴포넌트를 수정했을 때 의도하지 않은 다른 컴포넌트와 간섭하는 문제가 적게 발생합니다. 비트윈 PC 버전에는 약 40가지의 React 컴포넌트가 쓰이고 있습니다.자바스크립트 모듈 시스템¶모든 코드를 한 파일에 넣으면 코드를 관리하기가 힘들어집니다. 따라서 서로 관련 있는 코드끼리 모듈로 나누어야 하는데, 자바스크립트에는 모듈 시스템이 기본적으로는 제공되지 않습니다. 비트윈 PC 버전에서는 CommonJS 표준을 따라서 모듈을 나누고, 이를 웹 브라우저가 해석할 수 있는 형태로 합쳐주는 Webpack 빌드 툴을 사용했습니다.Webpack은 자바스크립트뿐만 아니라 CSS나 이미지, JSON 파일 등도 모듈로 취급할 수 있고, 플러그인으로 지원하는 모듈 종류를 추가할 수 있습니다. 비트윈 PC 버전을 빌드할 때 실제로 사용하는 플러그인은 다음과 같은 것들이 있습니다.jsx-loader: React에서 사용하는 JSX 코드를 자바스크립트로 변환합니다. 또한, 미래의 자바스크립트 문법을 현재 브라우저에서 지원하는 형태로 변환합니다.less-loader: LESS 파일을 CSS 파일로 변환합니다.css-loader: CSS에서 참조하는 외부 리소스를 인식하여 의존성을 파악해줍니다.url-loader: 파일 크기가 일정 이하인 리소스를 Base64 인코딩으로 내장해줍니다.ECMAScript 6¶ECMAScript 6는 차기 자바스크립트 표준입니다. 현재 자바스크립트의 불편한 점을 많이 해소하기 때문에 장점이 많이 있습니다. 일부 기능은 이미 브라우저에 구현되어 있지만, 아직 지원되지 않는 기능도 있어서 jstransform을 통해 ECMAScript 5 코드로 변환하여 사용하였습니다.화살표 함수: 익명 함수를 (a, b) => a + b와 같은 문법으로 훨씬 간단하게 선언할 수 있습니다. 또한, this 변수의 스코프를 현재 코드 상의 위치에 따라 결정해줍니다.클래스: 다른 언어와 유사한 클래스 문법을 제공합니다. 상속이나 접근 제한도 가능합니다.해체(destructuring) 대입: 객체의 필드를 바로 같은 이름의 변수에 대입할 수 있습니다. 예를 들어, var {a, b} = {a: 1, b: 2}; 같은 코드를 작성할 수 있습니다.기타 사용된 패키지¶RSVP.js: Promise/A+ 구현을 제공하는 라이브러리로, Promise 패턴을 사용하여 비동기 로직을 알아보기 쉬운 형태로 작성했습니다.FormatJS: 다국어, 국제화 지원을 위한 라이브러리입니다. UI 메시지 번역이나 날짜, 시간 등의 포매팅에 사용했습니다.정리¶비트윈 PC 버전은 개발 비용을 줄이기 위해 웹 플랫폼 기반의 네이티브 애플리케이션으로 개발되었습니다.비트윈 서버에서 사용하는 Alfred 라이브러리에 WebSocket 프로토콜 지원을 추가하였습니다.Chromium Embedded Framework를 브라우저 엔진으로 사용하여 웹 앱을 구동하고 웹 플랫폼에서 제공하지 않는 기능을 확장하여 사용했습니다.자바스크립트 코드의 복잡도를 줄이기 위해 React, CommonJS, ECMAScript 6 등의 기술을 활용하였습니다.VCNC Engineering Blog, 비트윈 시스템 아키텍처, 2013년 4월↩Wikipedia, Chromium Embedded Framework - Applications using CEF↩저희는 언제나 타다 및 비트윈 서비스를 함께 만들며 기술적인 문제를 함께 풀어나갈 능력있는 개발자를 모시고 있습니다. 언제든 부담없이 [email protected]로 이메일을 주시기 바랍니다!
조회수 920

Culturalization of Video Game Soundtracks: An Interview with Pierre Langer, Managing Director & Founder of Dynamedion

 Game culturalization, the process of cultural adaption, is the key to successfully launching video games in foreign markets. The main aspects are to make content suitable, understandable, and meaningful for the gamers of the targeted markets. To achieve these objectives, it is necessary to look into the five central pillars of culturalization: history, religion, ethnic and cultural tensions, geopolitical situations, and in-game elements.One in-game element that must be considered is music. To learn more, we interviewed the video game music expert and composer Pierre Langer, founder and managing director of Dynamedion based in Mainz, Germany. Pierre will tell us more about his internationally renowned company, the video game music business, and the culturalization process of video game soundtracks.  Pierre Langer  Dear Pierre, please let us know more about you and your company and the key services that you provide.  Pierre Langer: Dynamedion was founded by Tilman Sillescu and me in early 2000. We started with work-for-hire audio in the German games industry doing music composition, sound design and later also interactive audio integration and Live Orchestra production. We were the first to produce with live orchestra for a German game, and we eventually rolled this out as a service for other composers and game developers all over the world.Today we are one of the biggest game audio studios in the world with nearly 50 people doing music composition, music licensing, sound design, source sound recordings, audio integration, audio software development, live orchestra and live choir recording, and orchestration and arrangement for all sorts of media. We are still very much focused on video games, having worked on more than 1,800 games, but we also do a lot of movie trailers, TV series, and films.In 2009 we started a sub company of Dynamedion called BOOM library, which produces original sound effects collections as products that can be licensed by audio professionals throughout the world. BOOM Library is today recognized as one of the most popular and high-quality sound effects libraries in the world. Apart from that we also run two side labels with royalty-free stock music in a unique adaptive format (SmartSound) and a new product line of virtual software instruments (SONUSCORE). Our latest addition to our services is that we have become well known for high end vehicle recordings (cars, airplanes, helicopters, bikes, tanks, etc.) – that is a lot of fun, but also a huge challenge to source all sorts of rare or weird or super expensive vehicles.So, in short: we are specialists for everything that has to do with music & sound for games – everything except voice overs, and our music or sound effects or live productions have been used and heard in nearly every large game worldwide. As an example, we recently have been involved in these titles: Assassin’s Creed Series, Elder Scrolls Online, Monster Hunter Online, Battlefield V, League of Legends, Destiny 1 & 2, Lineage II, Horizon Zero Dawn, Fortnite, Mortal Kombat Series, World of Tanks, Hitman Series, Total War Series.Currently we are working on five super large unannounced titles, all international.  What part of the world do your requests mainly come from?  Pierre Langer: It is very international, really. Up until 2009 we had a very strong (overly strong I would say) position in Germany, working on nearly every German game title, quite some in France and some occasional overseas projects. Meanwhile this has completely changed: we are doing a good amount of German titles, but the major part comes from the US, UK, Scandinavia, Japan, Korea and China – China being one of the most important markets now.  Have you experienced a shift or a change over the years in game creation from Western countries to an international mix?  Pierre Langer: Absolutely! It seems that the five big “individual” markets (North America, Europe, China, Japan / Korea) are getting closer to each other. Even very self-sustaining markets, like the Japanese market, are opening up for more international projects coming in, but they are also looking into getting their own games distributed internationally, and of course into becoming as successful as possible worldwide. And then there is a huge amount of projects coming from all the emerging markets, so it seems that there is really no end to a lot of new great games. The biggest challenge with a new game certainly is to make yourself “heard” or do something special that your competition does not do, in order to stand out in a new market.  Orchestral Session - Dynamedion  What is culturalization in terms of video game soundtracks and sound effect production?  Pierre Langer: It is actually a very straightforward thing and kind of a no-brainer, since audio is a rather inexpensive asset for a game, while it has a huge emotional and atmospheric impact. Culturalization of a game means that you adapt the game to the specific requests of a new market. Western world audiences are used to different things than Chinese players, for example. So, if a Chinese game developer wants to push a game into the Western market, the game should be “westernized” so to say. This certainly already happens with gameplay mechanics and with graphics and – of course – with the localization. But simply changing the texts and voice over from Chinese to English doesn’t adapt a Chinese game to an EU or US audience. The look and feel of a game need to change as well, and this is where music and sound “culturalization” comes in: adapting the music and sounds (and the way of implementation and audio functionality in the game) to the specific audience that is being targeted. This does of course work in all directions – Japan to China, China to Europe, Europe to Korea, etc.  Can you give us some examples of audio culturalization in specific markets? (E.g. MENA, South America, China/Asia)  Pierre Langer: Let me go back a few years, to our very first larger game title we did music and sound culturalization for. It was “Runes of Magic” by Runewaker Entertainment, a developer based in Taiwan. The game was not extremely successful in Taiwan and Mainland China, but a German publisher by the time (Frogster) saw some great potential in that game. So, they licensed the title and got the rights to publish it in Europe and the US. In some respects, the game was a mess for a Western audience, partly due to the music and the sound + the implementation of all audio. The marketing people at Frogster understood this very quickly and started working on all these issues. The music and sound side was done in a matter of a few weeks: they asked us to replace the soundtrack by using music we had in our back catalogue (music for games that we had written, that either failed, or that had been unsuccessful – which we kept the rights to) and write a few new themes that would work as the iconic main themes of the game, so that the audience has something new and recognizable. We did that, with a full focus on writing and licensing music that would be ideal for the target audience. Then we did a similar thing with the sound effects: we simply threw out all the stuff that was in there and replaced it with sounds that where produced to fit a Western audience. To give you a very quick example: Asian players are used to high frequency sounds, very aggressive, very loud, the whole sound atmosphere being very crowded. European and US players are used to low frequency sounds – sub-bass, deep impacts, rumbling and more focused sound design (you hear one thing prominently, and everything else gets balanced down to make space for the one important sound going on). This is a very clear and super important difference – and it is also easy to fix with some new content and some new mixing.  What are typical issues that occur in sound culturalization?  Pierre Langer: Typical issues are that there needs to be some trust from the developer to the sound team. In most cases, the developer asks for culturalization from their home market to a foreign market. So, a US developer asking us to adapt the sound to fit a Chinese audience better needs to trust us that we know what we are doing, since the US developer doesn’t know themselves (otherwise they wouldn’t need us). Then there is always a big challenge with the correct audio integration. The most important bit is certainly to replace music and sound effects, to get a fitting new set of assets for the target market. However, even the best assets do not help if they are poorly integrated. Simply swapping them is not enough if the way they are being played back is not fitting. This then needs some more time and attention and focus, since we need to work with the developer directly to e.g. add some audio functionality, balance mix and master the audio, or introduce an interactive music system. It can be a very elaborate thing, but you can achieve a lot of additional quality with the most basic strategies that only cost a lower 5 digit budget.  Dear Pierre, thank you for your time and effort in providing us such enlightening insights into your work!About Pierre:Pierre was born near Frankfurt / Germany. After years of playing in bands as a guitar player in his teens, he decided to take his studies in classical music at the Johannes Gutenberg University in Mainz..A few months before his final exams he met Tilman Sillescu in early 2000, Dynamedion was founded a few weeks later. In the first years of Dynamedion Pierre worked on basically every single bit of the job you can do as an audio person in the games business: music composition, sound design, audio integration, audio management, design of audio tool chains, recording, mixing, mastering, project management, etc.As the thing grew and all the other guys joined in, Pierre focused more and more on the business side of things, leaving the creative work to the really focused experts.Nowadays Pierre enjoys keeping in touch with all the different clients of Dynamedion, thinking up new product lines and business ideas to further expand the reach and prominence of Dynamedion and all related sub-labels such as BOOM Library, Sonic Liberty, Sonuscore... and more to come.The Interview was conducted by Moritz Demmig. 
조회수 991

HyperCut으로 인물사진 필터를 만들었습니다

얼마전 하이퍼커넥트의 아이디어 제안 채널에서 나온 이야기입니다.mel 은 사업그룹의 터키지역 담당 팀에 있는 친구인데, 꾸준히 좋은 제안과 아이디어를 주는 훌륭한 동료입니다. 이번에는 최근 여러 스마트폰이나 사진 앱들에서 나타나기 시작한 인물사진 모드 를 아자르에서도 지원하는게 좋겠다는 제안이었습니다.스마트폰이 자체 기능으로 인물사진 필터를 제공하는 경우는 보통 듀얼 카메라를 사용해 인물 외의 배경을 흐릿하게 만들어 심도를 표현합니다. 하지만 모두가 듀얼 카메라를 탑재한 스마트폰을 쓰는 것은 아니기 때문에, 이런 인물사진 모드를 소프트웨어적으로 구현하는 앱들도 존재합니다. mel 이 보여준 링크의 인스타그램도 그렇게 구현했네요.인물사진 모드를 소프트웨어적으로 구현하려면, 영상에서 얼굴을 포함한 사람을 배경으로부터 정확히 분리해 내는 기술이 필요합니다. 그리고 사진을 찍을 때에 실시간으로 프리뷰를 보아야 할테니까 이것을 실시간으로 처리할 수 있을 정도의 성능도 필요하구요.하이퍼커넥트에서는 머신러닝, 특히 영상과 이미지를 다루는 분야에 대해 지속적으로 투자와 연구를 해 왔습니다. 영상에서 인물을 분리해내는 문제는 크게 Image Segmentation 의 범주에 속합니다. 좀 더 직접적으로 Portrait segmentation 이라고 부를 수도 있습니다. 이를 잘 하기 위해서 하이퍼커넥트에서는 자체적인 학습 데이터를 만드는 것부터 시작하여 기술 개발을 지속적으로 추진해 왔고, 그 결과 Machine Learning 팀에서 이미 실시간으로 얼굴과 배경을 분리해내는 - HyperCut - 이라는 기술을 확보한 상태입니다. 아직 실제 서비스에 탑재되진 않았지만 이미 하이퍼커넥트의 주요 서비스인 아자르의 개발 버전에서는 HyperCut을 응용한 여러가지 이펙트를 사용할 수가 있습니다. 그리고, 그 중에 인물사진 모드 필터도 이미 있습니다.mel 의 제안이 있던 날 오후 아이디어 제안 채널에 이런 답이 달렸습니다.모델이 되어 주신 분은 하이퍼커넥트의 CTO 인 ken 이네요. 아자르 개발 버전에서 HyperCut 을 응용한 인물사진모드 필터를 사용하고 찍은 사진입니다. 아자르의 저장하기 기능을 사용했더니 UI 없이 오른쪽 아래에 아자르 로고만 남게 되었네요. 아직 실서비스에는 포함되지 않았지만, 최적화와 튜닝 과정을 거쳐 조만간 많은 사용자들이 HyperCut 을 사용한 이펙트를 쓸 수 있게 될 예정입니다.#하이퍼커넥트 #개발 #개발자 #아이디어 #아이디에이션 #구체화 #협업 #팀워크 #팀플레이

기업문화 엿볼 때, 더팀스

로그인

/