스토리 홈

인터뷰

피드

뉴스

조회수 5060

트렐로와 슬랙 함께 쓰기

8퍼센트 컨플루언스에 올렸던 내용을 외부용으로 정리해서 다시 올린다.8퍼센트에서는 슬랙과 트렐로를 함께 사용하고 있다. 슬랙은 이제 쓰지 않는 스타트업을 찾기 힘들 정도로 대중적인 커뮤니케이션 도구가 되었다. 트렐로도 소규모 팀의 프로젝트 관리에 항상 손꼽히는 도구 중 하나이다.슬랙은 좋은 커뮤니케이션 도구지만 프로젝트 관리라는 목적에는 당연하게도 적합하지 않다. 해야 할 일들을 정리해두고, 우선순위를 할당하고 프로젝트의 상황을 시각화 하기에 "대화창"은 부족하다. 그래서 우리는 트렐로를 사용한다. 하지만 도구가 늘어나게 되면 항상 그 도구 사이의 역할 구분과 인터페이스를 고민해야 한다.도구간의 인터페이스는 최대한 간단해야 한다. 슬랙을 통해서 누군가가 프로덕트팀에 일을 요청한다고 해보자. 이 일감은 요청자 혹은 담당자가 프로젝트 관리 도구에 등록해야 한다. (지라의 경우 이슈, 트렐로라면 카드) 그리고 일감을 등록할 때 지난 대화들을 정리해서 기록해 주어야 한다. 노력이 많이 들어가는 일이다. 내가 하고 싶지는 않고 누군가가 해주었으면 하는 바람이 생긴다. 특정일을 위한 노력이 많이 들수록 실제로 그 일이 일어나기는 힘들어진다. 다시 말해 일감을 등록하기 위해 많은 노력이 필요할수록 일감은 관리되지 못한다.회사에서 트렐로를 사용하기로 결정 했을 때에도 간단한 인터페이스를 찾아보았지만 찾지 못했다. 그래서 Slash commands를 사용해서 직접 만들어서 사용했다. 기능은 간단하게/trello add 통계 페이지의 투자 금액을 원단 위가 아닌 백만 원 단위로 보여주고 싶어요.명령을 슬랙에 입력하면 프로덕트팀의 트렐로 보드에 카드를 등록해 주는 것이다. 슬랙을 떠나지 않고 해야 할일을 등록할 수 있는 것만으로 편했다. 하지만 프로덕트팀뿐만 아니라 다른 팀들도 슬랙을 통해 카드를 등록하기를 원했고, 또한 프로덕트팀 내에서도 보다 적절한 보드에 카드를 등록하기를 원했다. 조금은 불편하지만 일단 한쪽에 등록하고 주기적으로 카드를 정리하는 방식으로 사용했다.그러다가 얼마 전 슬랙 App Directory 에서 Trello Integration 을 찾았다. (나는 주기적으로 재미있는 슬랙 앱들을 찾아본다) 예전에 검색했을 때에는 트렐로의 변경사항을 슬랙으로 알려주는 것만 있었던 것 같은데 이 새로운 녀석에는 내가 원하던 기능들이 구현되어 있었다. 예전부터 있었는데 내가 못 찾았었던 건지 (그런 것이라면 억울하다!) 아니면 최근에 새로 생긴 것인지는 모르겠다. 설명을 읽어보면 다음과 같은 기능을 제공한다.슬랙에서 "/trello add" 명령을 통해 보드에 카드를 등록할 수 있다.트렐로 카드와 보드에 참가할 수 있고, 듀데이트 변경, 대화 등록등 여러가지를 할 수 있다.채널에 @trello 를 초대하면 URL을 복붙 했을 때 카드와 보드에 대한 프리뷰를 볼 수 있다.슬랙 팀 멤버를 트렐로 팀과 보드에 원클릭으로 초대할 수 있다.야호! 이거다!당장 사용해보기로 했다. 최초로 "/trello" 명령을 사용하면 슬랙과 트렐로의 계정을 연결하게 된다.계정을 연결한 후 "/trello help" 명령을 입력해 보면 다음과 같은 기능들을 볼 수 있다.항상 시작은 우리의 친구 "help" 다위 명령들이 실제로 어떻게 사용되는지 감을 잡기 위해 가상의 시나리오를 만들어서 하나씩 끼워 맞춰 보자.8퍼센트에서 Open API를 만들기로 결정했다. (개인적으로 내가 하고 싶은 일이다)1. 새로운 프로젝트가 시작된다. 프로젝트 리더는 새롭게 트렐로 보드를 하나 생성한다. 이 보드의 이름을 "오예"라고 하자. ('오'픈 '에'이피아이라서 그렇다) 그리고 적절하게 리스트를 만들어 둔다. 보통 할일, 하고 있는 일, 완료된 일의 구분을 사용한다.2. 이 프로젝트에 대한 내용을 논의할 슬랙 채널도 하나 판다. 이 슬랙 채널을 "#openapi"라고 하자.3. "#openapi"에서 카드를 등록하면 "오예" 보드로 등록되기를 원한다. 그렇다면/trello link 오예를 입력해서 슬랙 채널과 트렐로 보드를 연결한다.4. #openapi"에서 등록된 카드는 "오예" 보드의 "할 일" 리스트로 가기를 원한다. 그렇다면/trello set-list를 입력해서 "할 일" 리스트를 선택해 준다. 여기까지 하면 프로젝트를 시작하기 위한 준비가 완료된다.이제 프로젝트가 시작되었다.5.  사람들이 슬랙 채널에서 할 일에 대한 이야기를 나눈다. "채권 리스트를 API를 통해 제공하면 좋겠다"라는 주제로 이야기가 진행되어 개발하기로 결정했다./trello add 채권 리스트를 API를 통해 제공하기명령을 통해 카드를 등록한다.할일이 등록되었다. 신난다.6. 그리고 언젠가 일을 진행할 때 지금의 대화를 기록해 두는 것이 좋을 것 같으니 "Attatch Conversation"을 눌러 둔다. 카드의 설명에서 지금의 대화로 가는 링크가 저장된다.이 일을 누가 시킨것인지 왜 시킨것인지는 대화를 읽어본다.7. 누가 하는 것이 좋을까? 이야기를 나누다가 역시 만만한 내가 하는 것이 좋겠다고 한다./trello assign @hosung을 통해 담당자를 지정한다.8. 담당자까지 지정했으니 언제까지 이 일을 끝낼 것이지를 정해야 한다./trello set-due next Friday at 5pm으로 다음 금요일 5시까지 한다고 정해 둔다.이런 식으로 일감 등록이 완료된다. 실제 개발을 진행 한다.9. 중간중간 대표님이 업무의 진행 상황이 궁금하실 수 있다. 슬랙 채널에 카드의 내용을 보여주기 위해서는 카드의 URL을 복사한 후/trello https://trello.com/c/w7hrzCUa/1-api명령을 사용한다. 그리고  "어떻게 되어가고 있나요?"라고 물어본다. 물론 좀 더 간단하게/invite @trello를 해서 트렐로 봇을 "#openapi" 채널에 초대해 두면 트렐로 커멘드 없이 "https://trello.com/c/w7hrzCUa/1-api"와 같은 URL을 입력하는 것만으로 카드에 대한 프리뷰를 볼 수 있다.10. "어떻게 되어 가고 있나요?"라는 대표님의 질문에 내가 "문제없이 잘 진행되고 있어요."라고 답하면 대표님은"/trello comment 잘 진행되고 있다고 했음(두고 보겠음)"명령을 사용해 트렐로 카드에 코멘트를 등록해 둘 수도 있다.위 시나리오를 살펴보면 슬랙을 떠나지 않고 트렐로에 카드를 등록하고 필요한 정보를 업데이트했다. 물론 이 일 모두는 트렐로에서 크게 불편하지 않게 할 수 있다. 하지만 대화의 콘텍스트를 잃지 않고 일감 관리를 즉시, 적은 노력을 할 수 있다는 것, 그리고 트렐로에 대한 작업들이 슬랙에서 공유가 된다는 것은 생각보다 큰 장점이다.슬랙에서 논의된 내용을 나중에 정리해서 트렐로 보드에 등록해야지 라고 생각했는가? 이제는 그러지 말자. 일단 Trello Integration을 설치해보자.아마 우리 팀 보다 트렐로와 슬랙을 더 잘 쓰는 팀들이 있을 것이다. 이 글을 읽고 조금이라도 도움이 되신 분들은 우리 팀을 위해 하나의 팁을 남겨주면 좋겠다. 그리고 특히 트렐로 비즈니스를 쓰시는 분들은 슬랙과의 추가 기능들을 더 쓸 수가 있는데 후기를 들려주시면 좋겠다.#8퍼센트 #에잇퍼센트 #스킬스택 #트렐로 #Trello #슬랙 #Slack #협업 #협업툴 #팀워크 #협동 #팀플레이
조회수 3566

Node 서버로 Slack 메신저 자동화하기

Overview백엔드 업무를 하면 데이터 요청과 CS문의를 자주 받습니다. 날짜만 다를 뿐 같은 유형의 문의가 대부분이죠. 결국 반복적인 업무를 효율적으로 처리할 수 있는 방법을 고민했고, 사내 메신저로 사용하는 Slack의 몇 가지 API를 사용하기로 했습니다.1. 알림봇 만들기비즈니스 로직을 만들다 보면 정해진 시간에 맞춰 작업을 해야 하는 경우가 발생합니다. Slack 메신저에 로그온한 상태에서 스케줄러를 이용해 지정한 시간에 Slack 메세지를 전송해보겠습니다.1)Slack API 유저토큰 받기Slack API에 사용할 해당 계정의 토큰을 받아야 합니다. Slack 가입 절차 및 채널 생성은 생략하겠습니다.https://api.slack.com/custom-integrations/legacy-tokens 접속합니다.Legacy tokens 메뉴에서 아래로 스크롤을 내려 토큰 생성버튼을 누릅니다.계정 패스워드를 입력하여 확인하면 토큰을 생성할 수 있습니다.생성된 토큰을 복사하여 저장합니다.2)Node.js를 이용한 알림봇 구현2-1.Node.js 설치Node.js 다운로드 해당 사이트에서 운영체제 환경에 맞는 파일을 다운받아 설치2-2.프로젝트 생성해당 프로젝트 폴더로 이동 후 명령어 실행$ npm init --yes // package.json 파일 생성2-3.Slack 연동2-3-1. slack-node 모듈 설치$ npm install slack-node --save2-3-2. 유저토큰을 이용하여 해당채널에 메세지 전송const Slack = require('slack-node'); // 슬랙 모듈 사용 apiToken = "발급받은 유저토큰"; const slack = new Slack(apiToken); const send = async(message) => { slack.api('chat.postMessage', { username: 'dev-test', // 슬랙에 표시될 봇이름 text:message, channel:'#general' // 전송될 채널 및 유저 }, function(err, response){ console.log(response); }); } send('메세지 내용'); 지정한 채널에 메시지가 발송됩니다. 하지만 이와 같은 방법은 유저 토큰이 공개 코드에 노출되기 때문에 보안이 취약할 수 있습니다. 유저 토큰이 필요 없어도 해당 채널에 URL을 생성하는 WebHooks API를 이용하여 메시지를 전송해보겠습니다.3) Incoming WebHooks APIWebHooks는 유저 토큰 대신 Webhook URL을 생성해 HTTP 통신으로 Slack 메세지를 전송할 수 있습니다. 다양한 메시지 형식을 지원하고 게시할 사용자 이름 및 아이콘 등을 통합적으로 관리할 수 있는 장점을 가지고 있습니다.3-2. Webhook URL 생성하기Slack 해당채널에서 Add an app 클릭검색필터에 WebHooks 검색Incoming WebHooks 추가채널 선택 후 Incoming WebHooks 생성생성된 Webhook URL 복사하여 저장해당채널에 생성되었는지 확인봇이름 및 아이콘등 기본 설정 변경하여 저장curl 사용 예제$ curl -s -d "payload={'text':'메세지 내용'}" "Webhook URL"Webhook URL 사용 중인 모든 메시지는 통합적으로 기본 설정이 변경된 걸 확인할 수 있습니다.다양한 형식의 메세지를 전송해보겠습니다.const Slack = require('slack-node'); // 슬랙 모듈 사용 const webhookUri = "Webhook URL"; // Webhook URL const slack = new Slack(); slack.setWebhook(webhookUri); const send = async(message) => { slack.webhook({ text:"인터넷 검색 포털 사이트", attachments:[ { fallback:"링크주소: ", pretext:"링크주소: ", color:"#00FFFF", fields:[ { title:"알림", value:"해당링크를 클릭하여 검색해 보세요.", short:false } ] } ] }, function(err, response){ console.log(response); }); } 다양한 형태의 메시지를 전송할 수 있습니다.4) Schedule 연동이제 스케줄러를 이용하여 지정한 시간에 메세지를 전송해보겠습니다.4-1. node-schedule 모듈 설치node-schedule는 Node.js 작업 스케줄러 라이브러리입니다.$ npm install node-schedule --savenode-schedule 코드 작성const schedule = require('node-schedule'); // 스케줄러 모듈 사용 // rule-style 사용 var rule = new schedule.RecurrenceRule(); rule.dayOfWeek = new schedule.Range(3,4); rule.hour = 19; rule.minute = 50; schedule.scheduleJob(rule, function(){ console.log('rule 방식'); }); // cron-style 사용 schedule.scheduleJob('50 19 * * *', function(){ console.log('cron-style 방식'); }); 취향에 맞는 스타일로 사용하면 됩니다.5) 지정 시간에 메세지를 전송하는 알림봇을 작성해보겠습니다.const Slack = require('slack-node'); // 슬랙 모듈 사용 const schedule = require('node-schedule'); // 스케줄러 모듈 사용 const webhookUri = "Webhook URL"; // Webhook URL const slack = new Slack(); slack.setWebhook(webhookUri); const send = async(message) => { slack.webhook({ text:message, attachments:[ { fallback:"구글드라이브: ", pretext:"구글드라이브: ", color:"#00FFFF", fields:[ { title:"[알림]", value:"해당링크로 접속하여 작성해 주세요.", short:false } ] } ] }, function(err, response){ console.log(response); }); } schedule.scheduleJob('5 19 * * *', function(){ send('업무보고 보내셨나요?'); }); 업무보고 시간을 미리 알려주는 알림봇2. 대화봇 만들기업무 문서는 주로 구글 독스와 같은 온라인 문서로 관리하고 있습니다. 하지만 매번 구글 드라이브에서 문서를 찾는 건 정말 귀찮은 일입니다. 번거로운 건 딱 질색입니다. Slack API를 이용해 관련된 키워드를 입력하면 링크 주소를 바로 받을 수 있는 대화봇을 만들어 보겠습니다.1) Slack API Bots 토큰 받기Slack API에 사용될 Bots 토큰을 받아야 합니다.https://{App Name}.slack.com/apps 에 접속합니다.Bots 추가Bots Api 토큰을 복사해 저장합니다.설정한 봇이름으로 Apps 영역에 자동으로 추가됩니다.2) 구글독스 대화봇 코드 작성2-1. botkit 모듈 설치$ npm install botkit --save2-2. 코드 작성const botkit = require('botkit'); // 봇 모듈 사용 const Slack = require('slack-node'); // 슬랙 모듈 사용 const controller = botkit.slackbot({ debug: false, log: true }); const botScope = [ 'direct_message', 'direct_mention', 'mention' ]; controller.hears(['업무보고'], botScope, (bot, message) => { bot.reply(message, '업무보고 링크주소'); }); controller.hears(['가이드', 'guide', '튜토리얼'], botScope, (bot, message) => { bot.reply(message, '가이드 링크주소'); }); controller.hears(['api', '명세서'], botScope, (bot, message) => { bot.reply(message, 'api명세서 링크주소'); }); controller.hears(['일정', '일정관리'], botScope, (bot, message) => { bot.reply(message, '일정관리 링크주소'); }); controller.hears(['비품', '비품정리'], botScope, (bot, message) => { bot.reply(message, '비품관리 링크주소'); }); controller.spawn({ token: '발급받은 봇 토큰' }).startRTM(); 지정한 키워드를 입력하면 해당 링크가 수신 됩니다.3) 데이터문의 대화봇 코드 작성데이터 요청 시 결과 데이터를 보내주는 대화봇을 만들어 보겠습니다. 일단 먼저 데이터문의 전용 Bots을 생성합니다.3-1. Python 연동 요청한 데이터는 Mysql 데이터를 조회해서 전송합니다. 그러면 Mysql 을 연동해야겠죠? Node.js에서도 직접 mysql 연결할 수 있지만, 기존 프로젝트가 Python으로 구현되어 있어 Python을 실행해 필요한 데이터를 추출해보겠습니다.3-2. python-shell 모듈 설치Node.js에서 Python 실행가능하도록 모듈을 설치$ npm install python-shell --save3-3. Mysql Sample Table3-4. 회원테이블에 저장된 가입일시 기준으로 몇일전에 가입한 회원을 추출하여 전송하는 코드 작성해 보겠습니다.const botkit = require('botkit'); // 봇 모듈 사용 const Slack = require('slack-node'); // 슬랙 모듈 사용 const ps = require('python-shell'); // 파이썬 쉘 모듈 사용 // 몇일 전 날짜 구하기 function getDaysAgo(dayNo = 0) { let nowDate = new Date(); let tempDate = nowDate.getTime() - (dayNo * 24 * 60 * 60 * 1000); nowDate.setTime(tempDate); let getYear = nowDate.getFullYear(); let getMonth = nowDate.getMonth() + 1; let getDay = nowDate.getDate(); if (getMonth < 10 xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed> 3-5. Python 코드 작성 # -*- coding: utf-8 -*- import sys import pymysql // mysql 접속 db = pymysql.connect('hostname', user='', passwd='', db='', charset='utf8') cursor_db = db.cursor() exe_query = "SELECT MEMBER_NAME FROM MEMBER_INFO WHERE MEMBER_REGIST_DETE >= '{}' ORDER BY MEMBER_NO ASC ".format(sys.argv[1]) cursor_db.execute(exe_query) all_rows = cursor_db.fetchall() for idx, row in enumerate(all_rows): print(row[0])     지정한 며칠 전에 가입한 회원 이름이 전송됩니다.   로그도 정상적으로 출력됩니다. 3. Node.js 프로세스 관리를 위한 pm2 모듈 설치 Node.js 는 비동기 I/O를 지원하며 단일 스레드로 동작하는 서버입니다. 비동기식 방식이지만 처리하는 Event Loop는 단일 스레드로 이루어져 있어 처리 작업이 오래 걸리면 전체 서버에 영향을 줍니다. 그래서 pm2를 이용해 프로세스별로 상태를 관리해야 합니다. 1) pm2 모듈 설치$ npm install pm2 -g2) 자주사용하는 pm2 명령어 pm2 list -> 실행중인 프로세스 확인pm2 start {node 파일} -> 시작pm2 stop {id or App name} -> 중지pm2 delete {id or App name} -> 삭제pm2 show {id or App name} -> 상세정보pm2 restart {id or App name} -> 재시작pm2 kill -> pm2 종료pm2 logs {id} -> id 앱의 로그 확인 3) pm2 실행화면$ pm2 start bot.js   프로세스별로 앱 이름, 버전, 상태, cpu 및 memory 사용량이 표시됩니다.$ pm2 show 0   해당 프로세스의 상세 정보를 확인할 수 있습니다. Conclusion 지금까지 Node.js 로 유용한 Slack 메신져 API를 알아봤습니다. 반복적인 업무를 하나씩 줄이다 보면 분명 일의 능률을 높아집니다. 하지만 무분별한 자동화는 서버의 부하를 증가시키기 때문에 꼭 필요한지 확인하고 선택하길 바랍니다. 오늘은 여기까지 글곽정섭 과장 | R&D 개발1팀[email protected]브랜디, 오직 예쁜 옷만  
조회수 1223

스위처 고객 문의 담당자의 일기

하루 중 자는 시간 빼고 고객분들과 함께하는데요. 오늘 재밌는 고객 문의가 있어서 이 글을 일기 삼아 하루를 마무리할 거예요.심쿵이 아니라 심쾅..수많은 고객 문의 중 사용조차 못하고 반납해야 하는 경우엔 눈에서 눙물 같은 닭똥이 나와요ㅠㅠ하지만, 일말의 희망을 잡아보고자 스위치 사진을 요청을 해요. (물론, 다음 개선될 제품의 R&D를 위해서 수집하는 목적도 있습니다.)오 이건 가능하지!대화 속 오른쪽 사진은 고객님과 저만의 비밀..(하트)(이때, 설명충이 등장한다.)스위처는 일반적으로 다음과 같은 모양의 스위치에 사용이 가능합니다.버튼 좌우에 밸크로를 붙여 고정을 하는 방식이기 때문이지요.아래 사진과 같이 옆에 장애물이 있으면 밸크로를 붙이지 못해 사용이 어렵습니다.우린 답을 찾을 것이다. 늘 그랬듯이하지만, 밸크로를 떼어서 위로 붙인다면?(그렇게 시간이 흐른 후)공대틱 성공적그리고 계속된 고객분의 인증샤샤샤ㅑㅑㅑ천재이시다. 내가 의미한 바를 100% 이해하셨다.  센스있게, 정면과 측면샷도 보내주셨어요.덕담과 함께 의견도 주셨어요.네! 부착법 얼렁 만들게요!그리고 찾아온 마술 같은 순간너는 장애물이 왼쪽에 있구나?나는 응용의 동물재미있다.두 번째 문의를 주신 분의 경우 밸크로가 떨어져 내일 드리기로 하였어요! 내일부터 잘 쓰실 수 있을 거예요.(그리고 이번엔, 진지충이 등장한다.)벌써 4천 명이 넘는 분들이 스위처 M을 사용해주셨고 많은 의견을 주셨어요. 그동안 주셨던 관심과 사랑 덕분에 항상 어제보다 나아진 모습으로 새로운 고객분들께 인사드리고 있네요. 저희는 살아있는 유기체와 같아서 계속 성장하고 개선되고 있습니다.내년에는 wifi를 위한 허브와 3구 출시를 목표하고 있어요. 그러면 더 많은 의견과 관심이 필요할 것 같네요ㅠㅠ 아무리 작은 의견이라도 귀 기울여 반영하는 자세 잃지 않을 테니 앞으로도 잘 부탁드려요 =)*고객문의 방법은 2가지1. 카카오톡으로 얘기하기 (친구추가하기)2. 네이버 카페에 문의하기 (카페보러가기)#스위처 #Switcher #CS대응 #CS업무 #마케터 #마케팅 #기획 #운영
조회수 714

회사도 민주적으로 운영될 수 없을까? -에이스프로젝트 운영위원회

탈권위와 소통, 토론을 통해 정책을 펼치고 있는 문재인 대통령이 연일 화제인 요즘.에이스프로젝트에서 2기 째 운영되고 있는 운영위원회를 소개해볼까 합니다.우리는 각자의 의견을 자유롭게 펼칠 수 있는 민주주의 사회에 살고있지만사실 회사에서 진짜 민주주의는 멀게만 느껴질 때가 많습니다.상명하달 문화에 익숙해지길 강요받고때론 부당하고 불합리하다고 느끼는 사규와 제도에 그저 따를 수 밖에 없습니다.왜 그래야 하는지 이유를 물으면나서지 말라는 둥, 조직생활에 맞지 않는다는 둥 핀잔을 듣기 일쑤죠.의견개진이 자유롭지 못한 근무환경은창의적인 사고를 필요로 하는 기업에게도, 주인의식을 갖고 일하고자 하는 구성원들에게도 독이 될 뿐입니다.그래서 에이스프로젝트는 '토론 문화'를 가장 중시해왔습니다.리더들이 토론하는 '리더십 토론', 전직원이 자유롭게 토론하는 캠페인 '로댕 프로젝트', CEO와 함께하는 '타운홀미팅등 다양한 주제로 토론을 진행해 왔습니다.임직원들이 자신의 생각을 이야기할 준비를 마치고2016년 10월부터 '에이스 운영위원회'제도를 도입했습니다.이름도 생소한 운영위원회는말 그대로 회사 운영정책에 대해 논의하는 모임입니다.운영위원은 직원 3명 이상의 추천으로 선발되며 인원수 제한은 없습니다.선출된 운영위원은 자신을 뽑아준 직원들의 의견을 수렴하여 운영회의 시간에 적극 발언합니다.필요하면 직접 발제도 가능합니다.에이스 운영회의는 에이스프로젝트 조직문화 및 운영과 관련된 사안에 대해 논의하고필요에 따라 정책을 결정하기도 합니다.작게는 회식비 지원 체계부터 크게는 역할 중심 문화에 대해서까지논의가 필요하다고 생각되는 모든 주제로 토론합니다.얼마 전 1기 운영위원회가 무사히 6개월의 임기를 마쳤습니다. :)1기 운영위원회를 통해 에이스인 모두가 함께 만든 일들에 대해 공유하고자 합니다.서로의 다른 의견을 토론을 통해 조율하고 합의하는 과정은때론 느리게 느껴질 수 있습니다.그러나 시간이 걸려도 다수의 지지를 얻는 것이 결과적으로 조직에 더 좋은 영향을 끼친다고 믿기 때문에에이스프로젝트는 앞으로도 운영위원회 제도를 적극 활용할 계획입니다.4월부터 2기 운영위원회를 시작했습니다.새롭게 선출된 7명의 운영위원과 에이스인 모두가 더 적극적인 의견으로, 더 좋은 에이스프로젝트를 위해 힘써주세요! :)
조회수 2147

내가 평생 하고싶은 일 찾기.

나는 중학교때 우연히 나간 생물경시대회에서 상을 받게 되었다. 이를 계기로 내가 생물을 좋아하는걸로 믿게 되었고 전공을 선택했다. 하지만 불행하게도 대학교에 와서야 생물을 내가 얼마나 싫어하는지 알게 되었다. 실험실의 퀴퀴한 냄새부터 매번 실험시간에 가운을 가져와야하는것까지 그냥 모든게 싫었다. 억지로 학과 수업을 듣는게 너무 힘들었다. 그래서 앞으로는 내가 하고싶은 것을 하겠다고 마음먹었다. 그리고 그 일을 찾기 위해 노력했다. 골프, 테니스 ,바이크 , 자전거, 사진, 웨이크보드 등등 내가 조금이라도 관심이 가는 분야는 한번씩 건드려 봤다. 그리고 이후 10년동안 깨닫거나 느낀점에 대해서 정리해 보고자 한다.1. 어떤 "A" 분야가 너무 재밌어서 드디어 인생의 진로를 발견했다는 사람들을 종종 마주친다. 나도 진심으로 부럽고 축하해 준다. 그런데 안타깝게도 대부분은 시간이 지날수록 인생을 걸만큼 그 "A" 분야를 좋아하지 않는다는 사실을 깨닫게 되는 것 같다.(친구중 여럿이 사진작가 , 영화 감독에 '잠시' 인생을 걸어본다고 했다.)2. 보통 "A" 분야의 일을 잘해서 좋아하게 된다. 그러다가 본인의 실력이 그닥 별볼일 없다는 사실을 알게되면서부터 그 분야에서 멀어지는 것 같다.(나의 경우 과학분야에 굉장히 소질이 있는줄 알았다. 입학할땐 전액장학금이었지만 3학년때 짤림.)3. 보통 자신만의 진로를 발굴해서 오랫동안 그 분야에 종사했던 사람들은 조금 덜 좋아하더라도 안정적으로 살 수 있는 길을 가라고 한다. 가슴 뛰는 길을 그대로 가라고 말하는 사람들은 보통 아주 크게 성공한 사람들이다.뒤집어 보면 아주 크게 성공하려면 A분야를 찾고 거기에 집중해야 하는것 같다.(내가 제일 존경하는 사람은 한분야만 죽어라 파서 대가로 성공한 사람이다. 그런분들은 눈빛에서 부터 범접할 수 없는 내공이 느껴진다.)4. 대부분의 사람들은 자기가 인생을 걸만한 "A" 분야를 힘들게 찾아서 그 분야에서 죽도록 노력해서 명성이나 실력을 쌓기 보다는 , 그냥 맘에 드는 분야를 정하고 별다른 노력 없이 그 분야에서 성공하기를 바란다.(나의 경우 여행 블로거로 성공하고 싶었다. 걍 사진이 좋았고 여행이 좋았었다.)5. 그냥 맘에 드는 분야중 상위순위를 차지하는게 여행 인거 같다. 여행을 싫어하는 사람은 거의 없다. 하지만 1년이상 치열하게 여행을 위해 여행하는 사람은 별로 없다. 그냥 맘에 드는 일은 "A" 분야가 되기 힘든것 같다.여행은 인생의 appetizer로 남겨두자.(난 아직도 40이 되기전에 유리시아, 북미~남미를 바이크로 횡단을 하고싶다. 왠지 멋지자나?)6. 돈을 많이 버는 경우 일이 힘들어도 그 일을 좋아하는 경우가 많은거 같다. 좋아하기 힘들다면 그일에 대한 사명감이라도 가지게 되는거 같다. 자본주의 사회에서 돈은 진정한 자아실현의 욕구를 마비시킬만큼 강력한거 같다.(수십가지 예를 들수 있지만 분란을 일으킬거 같아서..)7. 돈과 상관없이 정말 자기 일을 좋아하는 사람들을 쉽게 찾을 수 있는 분야가 있다. 바로 강의나 멘토링이다.다른사람을 가르치면서 자신이 성장할 수 있고, 상대방의 성장하는 모습을 볼때의 뿌듯함이 원인인듯.(나도 과외돌이가 성적이 가파르게 오를때 돈과는 상관없는 알수없는 희열을 많이 느꼈다. VC들이 느끼는 희열도 이럴까?)8. 돈이 많으면 무슨 취미든 공부든 재밌게 할 수 있는거 같다.(나는 일단 레이싱용 바이크 , 차를 사서 매주 평일날 트랙을 다니고 스페인어, 중국어를 매일 개인교습받으면서 맛집 블로거가 될테야.)나는 사업하는걸 좋아하고, 바이크타고 여행가는걸 좋아하고, 글쓰는걸 좋아한다. 이것 외에 잘하는게 몇개 있긴하지만 위에 3개 보다 더 즐겁진 않다. 돈이 애초부터 많았다면 참 행복했겠지만 아쉽게도 내가 벌어야 한다.그래서인지 나는 돈을 벌 수 있으면서도 내가 좋아하는 일을 찾고자 애써왔다. 그리고 10년에 걸쳐서 찾은 절충안은 바로 내 비즈니스를 하는것이었다. 물론 힘들다. 그런데 이리 저리 짱구를 굴려봐야 나오는 결론은 항상 같았다.그리고 운이 좋아서 향후에 돈걱정없이 살게 된다면 비즈니스를 하는동안에 쌓은 경험을 통해 나와 비슷한 꿈을 가지고 있는 사람들을 돕고 싶다. 10년동안 빙빙 돌아온것 치곤 참 소박한 인생목표다.#삼분의일 #매트리스 #인사이트 #마인드셋 #경험공유 #조언 #목표 #신념
조회수 1235

바둑 아마 4단, 싱어송라이터…이색 신입사원을 만나다[上]

봄이다. 비록 미세먼지가 코끝을 괴롭히지만 완연히 따뜻해진 날씨와 남쪽부터 올라오는 개화 소식이 봄이 왔음을 알려준다. 계절의 시작이 봄이라면 회사원의 봄은 신입사원 때 아닐까? 푸릇푸릇한 새싹처럼 새로운 마음가짐도, 일하며 아름다운 꽃을 피우고자 하는 열정도 가득했던 시절. 누구나 한 번쯤은 겪었을 시절. 그래서 준비했다! 이제 입사한 지 반년에서 1년 남짓, 한창 일 배우며 눈망울 초롱초롱한 시기를 겪고 있는 신입 사원들의 이야기를. 첫 번째 편에선 입사 전 각자의 분야에서 열정을 불태워본 경험이 있는 두 사람을 소개한다. “돌 좀 놔드릴까요?” 대답이 떨어지기 무섭게 흑돌과 백돌을 척척 배치하는 손길이 예사롭지 않다. 바둑 문외한의 눈에도 뭔가 규칙이 있는 듯 보였다. 예전 수를 복기하는지 물었더니 그건 아니고 바둑에도 이른바 ‘교과서’가 있단다. 한국기원을 나선 지 10년이 흘렀지만 수없이 놓던 돌의 자리를 몸이 기억하는 모양이다. 열네 살에 아마 4단증까지 따낸 이수림(삼성전자 무선사업부 전략마케팅실)씨다.▲해맑은 미소에 안심해선 안 된다. 자칭 ‘바둑 마니아’ 선배 둘을 다면기(多面棋, 바둑에서 한 사람이 여러 사람을 상대로 동시에 대국하는 일)로 이기는 실력자이니!중학교 진학 대신 한국기원행(行)… 1년 만에 ‘컴백’“아휴, 부끄러워요. 같이 바둑 배운 동기 중엔 프로 선수가 된 언니∙오빠들도 있거든요.” 손사래를 치지만 아마 4단은 “프로 입단도 가능하다”고 평가 받는 실력이다. 그런 그가 바둑 대신 삼성전자를 택했다. 왜?▲어릴 적 수림씨에게 바둑은 재밌는 놀이였다. 위 오른쪽 사진은 그가 일곱 살 때 시(남양주) 바둑대회에서 받은 인증서“프로 입단을 준비할 생각은 없었어요. 어릴 때 바둑이 배우고 싶어 부모님을 졸라 바둑학원에 등록하고 이후 꾸준히 둬오긴 했지만 성격이 워낙 외향적이고 사람 만나는 걸 좋아해 프로 선수가 맞을 것 같진 않았거든요. 바둑은 조용한 스포츠니까요. 그래도 바둑을 좋아하긴 해서 그와 관련된 일을 하고 싶었고 한때 전문 해설가도 꿈꿨죠.” 바둑 방송에 나오는 캐스터나 해설가가 되려면 바둑을 잘 알아야, 아니 일단 잘 둬야 했다. 중학교 진학 대신 한국기원행(行)을 택한 것도 그 때문이었다.“학교 생활을 병행하며 바둑까지 잘 두긴 어렵다고 생각했어요. 그래서 중학교 대신 기원에 다니기로 했죠. (아마 4단) 단증도 그때 땄고요.” 이후 여덟 달 동안 종일 기원에서 바둑만 뒀다. 처음엔 재밌었다. “꿈을 향해 가는 길”이라고 생각해서다. 그런데 문득 주변을 둘러보니 죄다 절박한 맘으로 프로 기사를 향해 달려가는 사람들뿐이었다. “바둑 연구생은 대부분 프로 입단을 꿈꿔요. 근데 사실 그게 정말 어렵거든요. 입단 시험을 거쳐 프로가 되는 사람 자체가 너무 적고 심지어 나이 제한도 있어요. 그런 분들의 꿈과 제 꿈은 차이가 크다고 생각했어요. 그리고 제 성격상 조용히 바둑 두는 건 1년이 한계였던 것 같아요, 헤헤.”교환학생 시절 삼성 로고 보며 해외영업맨 꿈 키워그렇게 다시 학교로 돌아왔고, 또래보다 1년 먼저 고등학교에 입학했다. 하지만 성적은 중학교 교과 과정 3년을 이수한 동급생에 비해 당연히 뒤처졌다. 전교생이 500명인 학교에서 석차가 300등 밖으로 밀려났다. “바둑 세계를 떠나며 ‘내가 정말 바둑 해설가가 될 수 있을까?’란 생각이 들었어요. 어릴 때부터 좋아한 일이었는데 중도에 방향을 틀어버린 것도 맘에 걸렸고요.” 목표가 사라지자 의욕도 붕 떴다. 그러던 중 새로운 기회가 왔다. 미국 국립 교환학생 프로그램에 참여하게 된 것.▲수림씨는 1년간 미국에서 교환학생으로 지내며 잃었던 목표를 다시 찾았다. 위 사진은 당시 친구들과 떠난 여행 도중 호스슈밴드(Horseshoe Band)에서 찍은 것. 아랫줄 오른쪽에서 두 번째가 수림씨다“솔직히 공부가 너무 하기 싫었어요(웃음). 교과 과정을 따라잡기가 너무 힘들었거든요. 그 와중에 교환학생 기회가 와 덜컥 잡았죠. 미국에서 지내며 예전엔 별 생각 없이 지나쳤던 한국 제품이 너무 사랑스럽게 다가왔어요. 한국 글로벌 기업 제품을 보며 ‘우리나라 것’이라고 말할 때의 뿌듯함이란!” 당시 그의 눈에 제일 자주 들어온 게 ‘삼성’이었다. “정말 그땐 삼성 로고만 봐도 뭉클했어요. ‘제품 하나로도 저렇게 우리나라를 해외에 알릴 수 있구나’ 싶더라고요. 하루는 뉴욕을 방문했는데 타임스퀘어 전면에 삼성 광고가 떡하니 박혀 있는 거예요. 순간, 심장이 두근거렸어요. ‘저 회사에서 꼭 일하고 싶다. 한국을 대표하는 글로벌 기업의 일원이 되고야 말겠다!’ 그런 생각을 그때 처음 했던 것 같아요. 교환학생으로 지내는 내내 그 목표를 잊지 않고 있다 귀국했죠.”‘글로벌 기업 입사’란 목표를 세운 수림씨는 무섭게 공부에 집중했다. “고 1 때 성적으론 글로벌 기업에 절대 갈 수 없잖아요(웃음). 정말 그때만큼 열심히 공부한 적이 없었던 것 같아요. 밥 먹는 시간도 아까워 국에 밥 말아 책상으로 가져갔을 정도니까요. 지금 다시 그렇게 하라면 절대 못할 거예요.” 노력은 그를 배신하지 않았다. 300등 언저리였던 성적은 고 2∙3 때 전교 1등으로 뛰어올랐다. 덕분에 원하는 대학에 진학할 수 있었고 해외 영업 전문가를 꿈꾸며 불어불문학을 전공했다. 그리고 거짓말처럼 꿈이 이뤄졌다. 삼성전자의 일원이 된 것이다.“삼성전자 제품은 일상과 가장 밀접하게 관련돼 있잖아요. 스마트폰만 해도 눈뜰 때부터 잠들기 전까지 늘 곁에 두고 쓰니까요. 그래서 길 가다 갤럭시 스마트폰 쓰는 사람들만 봐도 뿌듯해요. 특히 해외 출장 가서 접하면 더 벅차죠. ‘오래 꿈꿔온 일을 진짜 하고 있다’는 생각이 들어서요.” 바둑에 대한 미련은 없을까? 그의 대답은 단호했다. “아쉽진 않아요. 물론 바둑은 지금도 좋아하죠. 그래도 열정으로 치면 바둑에 매진했던 1년보다 글로벌 기업에 들어가기 위해 공부했던 고교 시절이 훨씬 컸습니다.”“바둑으로 익힌 역량, 삼성에서 발휘해보고 싶어요”수림씨는 요즘 마음이 분주하다. “배워야 할 게 많아 바쁘긴 하지만 앞으로의 회사 생활이 너무 기대돼요. 지금은 여기저기서 도움을 받기만 하는데 얼른 업무 역량을 쌓아 선배들을 도울 수 있는 후배가 되고 싶어요.” 그의 ‘바둑 사랑’이 끝난 건 물론 아니다. “이래저래 바둑 덕을 많이 봤어요. 회사 선배들과도 바둑 덕에 빨리 친해질 수 있었죠. 바둑은 주어진 상황에서 상대의 수를 예측한 후 그에 맞춰 최선의 수를 두는 게임이에요. 생각해보면 그런 방식은 어떤 일에나 도움이 돼요. 영업 전략도 경쟁사의 수를 보고 ‘우린 어떤 수를 둬야 최선일까?’ 궁리하는 거잖아요. 바둑을 배우며 익힌 제 역량을 잘 살려 언젠가 삼성전자 해외 영업 전략을 세워보고 싶습니다.” “안녕하세요.” 차분하고 따뜻한 음성에 귀가 번쩍 뜨였다. 김대능(삼성전자 무선사업부 개발실)씨는 그 목소리를 십분 활용, 싱어송라이터로 활동한 이력이 있다. ‘능라이터’란 이름으로 실제 음반도 냈다. 기타 선율과 잘 어우러지는 그의 노래 ‘너가 지나간 나’는 귀에 쏙쏙 박히는 가사가 일품이다. 경험담이냐고 슬쩍 물어봤더니 웃으며 비밀이란다, 알고 들으면 재미없지 않겠냐며.곡의 영감은 여러 곳에서 얻지만 주로 가사부터 쓴 후 그에 맞춰 곡을 붙인다. “제 삶은 한정적일 수밖에 없기 때문에 간접적으로나마 여러 감정을 느껴보려 노력해요. 드라마나 영화, 책을 보다가 와 닿는 글이나 대사를 발견하면 그에 대한 제 생각이나 느낌을 다시 글로 정리해 ‘삼성 노트’ 애플리케이션에 저장해두곤 하죠.”8년간 독학으로 작곡 공부… ‘능라이터’로 음반 발매곡 소재에 꼭 기승전결이 있어야 하는 건 아니다. 최근 발표한 ‘starryNstellar’엔 “별이 빛나는 밤에 보고 싶은 너를 생각해”란 가사가 등장한다. 서양미술사를 공부하다 빈센트 반 고흐의 그림 ‘별이 빛나는 밤’(1889)에서 영감을 얻어 쓴 곡이다. “그림이 마음에 들어 한참을 보다 고흐가 어떤 기분으로 이걸 그렸을지 궁금해졌어요. 당시 즐겨 보던 드라마 ‘도깨비’(tvN) 여주인공 ‘지은탁’ 대사와 그 질문을 연결시켜 노랫말을 썼죠.” 인상파 화가의 그림과 판타지 로맨스 드라마, 전혀 무관해 보이는 둘을 절묘하게 연결시켜 멋진 곡으로 탄생시킨 것이다.▲‘starryNstellar’ 앨범 재킷 사진. 작곡에 영감을 준 고흐 작품 ‘별이 빛나는 밤’을 연상시키는 디자인이 인상적이다▲피아노를 좋아하던 소년은 어느덧 전문 작업실에서 노래를 만들고 부르는 싱어송라이터로 성장했다대능씨는 어릴 때부터 음악에 소질을 보였다. 특히 피아노를 좋아해 남들 앞에서도 곧잘 연주했다. “중학교 진학을 앞두고 예술중학교에 가볼까, 고민한 적도 있어요. 결국 일반 중학교를 거쳐 대학에선 전기전자공학을 전공했지만 음악은 계속하고 싶었죠. 본격적으로 작곡을 해봐야겠다고 결심한 건 스무 살 때부터였을 거예요.”그는 밴드 활동을 한 적도, 음악 동아리에 가입한 적도 없다. 그저 음악이 좋아 8년간 독학으로 공부하고 노래를 만들었다. “그렇게 몇 년 지내다 문득 생각했어요. ‘나도 음반 낼 수 있겠는데?’ 대형 기획사를 거쳐야 음반을 낼 수 있던 시절은 지났으니까요. 사람들에게 제 음악을 들려주고 싶단 생각이 들기도 했고요.” 만들어둔 곡으로 작업을 시작했지만 편곡부터 믹싱까지 다양한 준비가 필요했다. 꼬박 1년간 준비한 끝에 첫 앨범을 품에 안았다. “결과물 자체는 엄청 뿌듯했지만 막상 발매 시점엔 이미 수백 번씩 부르고 들으며 녹음한 곡이라 그런지 별 감흥이 없더라고요. ‘좀 더 잘 부를 수 있었는데’ 싶은 부분이 들리면 후회도 되고.”(웃음)“카페서 내 노래 들리면 뿌듯… 일도 음악만큼 소중”앨범 발매는 그에게 새로운 경험을 안겼다. “강남 쪽에서 친구들과 모임이 있었어요. 어디선가 귀에 익은 멜로디가 흘러나오더라고요. 제 노래였죠. 기분이 정말 좋았어요. 곡 만드는 일은 오래전부터 해와서 그런지 신기하거나 대단하다고 느껴본 적이 별로 없어요. 그런데 앨범을 발표한 후 카페나 가게에서 제 노래가 나오고 회사에 들어온 후엔 주변 분들도 좋아해주시니 괜히 뿌듯하고 그랬어요. 특히 제가 모르는 사람이 제 노래를 듣고 있다고 생각하면 기분이 묘하죠.”▲대능씨는 “음악 작업은 대체로 혼자 조용히 했었는데 회사원이 된 후 무대에 서는 일이 부쩍 잦아졌다”고 말했다. 사진은 삼성전자 신입사원 연수 당시 공연 무대에 올랐던 모습앨범까지 낸 그가 가수의 길을 걷는 대신 삼성전자에 입사한 이유는 뭘까? 대능씨의 답은 의외로 간단했다. “음악을 포기하고 회사를 선택한 게 아니니까요.” 그도 한때는 오디션 프로그램에 도전하거나 기획사를 기웃거렸다. 그러다 문득 생각했다. ‘전공 공부가 적성에 안 맞는 것도 아니고 지금껏 전공과 음악 둘 다 잘해왔잖아. 엔지니어로 일하면서 좋아하는 음악도 병행할 수 있지 않을까?’대능씨가 삼성전자에 입사한 건 지난해. 하지만 1년가량 태스크포스(TF)에서 근무한 탓에 지금 부서에 배치된 건 얼마 되지 않는다. “실무 능력으로만 따지면 말 그대로 ‘신입’이에요. 다행히 선배님들께서 업무를 잘 알려주셔서 적응해가고 있습니다. 뛰어난 실력을 갖춘 엔지니어가 정말 많거든요. 일을 배우는 입장에선 정말 감사한 일이죠. 이렇게 훌륭한 분들이 모인 곳에서 일하고 있단 게 자랑스러워요. 취업을 준비 중인 후배들에게도 ‘꼭 열심히 해서 우리 회사 오라’고 추천 많이 합니다.”“혼자서 차근차근 음반 냈듯 일에서도 답 찾아갈 것”대능씨에 따르면 음악과 일은 다른 듯 닮았다. “제가 작곡을 독학했잖아요. 아무리 악기를 다룰 줄 안다 해도 컴퓨터로 곡 작업을 하는 건 또 전혀 다른 차원이거든요. 기껏 만들어놔도 막상 들어보면 생각한 것과 너무 달라 좌절할 때가 한두 번이 아니었어요. 회사 일도 비슷하다고 생각해요. 모르는 게 많아 막막하죠. 주변에서 많이들 도와주시지만 결국 잘해내려면 저 스스로 어떻게든 부딪쳐봐야 하니까요. 막막함을 이겨내고 음반 내는 데 성공했던 것처럼 일에서도 하나씩 답을 찾아가보려 합니다.”#삼성 #삼성전자 #구성원인터뷰 #기업문화 #사내문화 #조직문화 #신입사원 #임직원 #이색신입사원
조회수 3164

eventlet을 활용한 비동기 I/O 프로그래밍

안녕하세요. 스포카 크리에이터팀 문성원입니다. 현대적인 프로그래밍 환경에서 네트워크는 더는 특정 직군의 개발자만 접하는 분야가 아닙니다. 그런 만큼 대량의 요청을 네트워크를 통해 송수신하는 프로그램이 생각보다 성능이 나오지 않는 경우를 경험하신 분들도 많으실 겁니다. 물론 스포카 개발팀도 예외는 아니었습니다. 그래서 오늘은 저희의 이러한 경험과 그 해결책-eventlet을 통한 비동기 I/O(Asynchronous I/O)-에 대해 소개합니다.Why우선 스포카 개발팀에서 겪었던 문제부터 시작하죠. 얼마 전 페이스북(facebook)의 FQL(Facebook Query Language)를 통해 정보를 수집해서 이를 활용하는 기능을 작성해야 했습니다. 기존의 함수들은 필요할 때마다 FQL을 요청하는 방식이었고 당연히 이건 너무 느렸죠. 그래서 생각한 것이 “하루의 일정 시간마다 대량의 FQL 요청을 보내서 필요한 정보를 미리 갱신시켜놓자.”였습니다. 여기까진 좋았죠. 이때 제가 작성한 코드의 얼개를 살펴보면 대강 이렇습니다.# 페이스북 계정들을 가져와서 반복하면서for account in FacebookAccount.query:    account.update() #FQL을 보내자.view rawgistfile1.py hosted with ❤ by GitHub그런데 문제가 있었습니다. 기존의 FQL을 보내는 FacebookAccount.update()는 FQL요청이 완료될때까지 멈추고 기다립니다. 대부분의 FQL요청이 2, 3초 정도 걸린다고 했을 때 이러한 지연은 매우 치명적입니다. 대안이 필요했고 자연스레 떠오른 것이 서두에 소개한 비동기 I/O(Asynchronous I/O)였습니다.Asynchronous과거 일부 고급 서버 개발자만 알고 있는(혹은 알아야 하는) 기술로 치부되던 ‘비동기(Asynchronous)’란 개념은 2000년대 들어 등장한 Ajax(Asynchronous JavaScript and XML)의 성공 이후 많은 개발자에게 강한 인상을 줬습니다. 사용자는 HTTP 요청이 끝날 때까지 멈추어 있는 하얀 화면으로부터 해방되었고, 다양하고 많은 요청과 응답들이 자연스럽게 서버로 흘러들어 가서 나왔습니다. 개발자들의 이러한 경험과 통찰은 이후 node.js와 같은 플랫폼의 등장에도 많은 영향을 끼쳤습니다.다시 문제로 돌아가죠. 그렇다면 이러한 비동기에 관한 개념은 위의 상황을 어떻게 해결할 수 있을까요? 문제의 원인부터 다시 살펴봅시다. 2, 3초 정도씩 걸리는 FQL 요청이 문제일까요? 물론 요청이 매우 빨리 처리된다면 별도의 처리 없이도 저 코드는 문제없이 동작합니다. 하지만 현실적으로 이런 I/O의 속도를 빠르게 하는데에는 물리적으로 한계가 있습니다. 오히려 여기에서 주목해야 할 점은 ‘2, 3초’ 보다 ‘기다린다’라는 점입니다. FacebookAccount.update() 같은 경우, I/O가 처리되는 동안 CPU는 하던 일을 멈추고 문자 그대로 기다리게 됩니다. 만약 CPU가 멈추지 않고 다른 요청을 보낸다면 어떨까요? 이렇게 말이죠.비동기만으로는 부족하다?이러한 아이디어는 그동안 많은 개발자가 대량의 I/O를 다루는 올바른 방식으로 여겨왔습니다. 하지만 보통 이러한 비동기 I/O를 통한 구현은 동기식 I/O와는 좀 다른 형태를 띠게 됩니다. 이렇게 말이죠.# http://docs.python.org/library/asyncore.html#asyncore-example-basic-http-clientimport asyncore, socketclass HTTPClient(asyncore.dispatcher):    def __init__(self, host, path):        asyncore.dispatcher.__init__(self)        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)        self.connect( (host, 80) )        self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path    def handle_connect(self):        pass    def handle_close(self):        self.close()    def handle_read(self):        print self.recv(8192)    def writable(self):        return (len(self.buffer) > 0)    def handle_write(self):        sent = self.send(self.buffer)        self.buffer = self.buffer[sent:]client = HTTPClient('www.python.org', '/')asyncore.loop()view rawgistfile1.py hosted with ❤ by GitHub불행하게도, 이 경우 기존에 사용하던 urllib2대신 HTTP 요청을 처리하는 핸들러를 이처럼 재작성 해야합니다. 거기에 FacebookAccount.update()의 호출 방식마저 바뀔 수 있죠. 더군다나 콜백(Callback) 투성이의 코드는 유지보수가 쉬어 보이지도 않습니다. 여러모로 손이 많이 가는 상황이죠.결국, 기존 코드를 최대한 수정하지 않으면서도, 어느 정도 성능은 보장되는 그런 해결책이 필요했습니다. 그런 해결책이 있을까요? 다행히도 그렇습니다.What저희가 해결책으로 택한 eventlet은 Python(정확히는 CPython)에서 코루틴(Coroutine)을 지원하기 위해 만들어진 greenlet을 이용해 작성된 네트워크 관련 라이브러리입니다. 생소한 용어가 갑자기 튀어나와서 놀라셨을지도 모르니 우선 eventlet에 대해 설명하기 전에 앞에 나온 용어들을 찬찬히 한번 살펴보죠.코루틴과 greenlet먼저 코루틴(Coroutine)부터 살펴보죠. 전산학도라면 누구나 그 이름을 한번은 들어봤을 도널드 카누쓰(Donald Knuth)는 자신의 저서 The Art of Computer Programming에서 코루틴을 다음과 같이 설명합니다.Subroutines are special cases of more general program components, called “coroutines.” In contrast to the unsymmetric relationship between a main routine and a subroutine, there is complete symmetry between coroutines, which call on each other.코루틴은 우리가 잘 알고 있는 서브루틴(Subroutine)과 달리 진입점(Entry Point)이 여러 개일 수 있습니다. 쉽게 이야기하면 실행을 멈췄다가(Suspend) 재개(Resume)할 수 있다는 점인데요. 이 특성을 살리면 우리가 익히 아는 스레드(Thread)처럼 쓸 수 있게 됩니다. 다만 스레드와 달리 코루틴은 비선점적(Non-Preemptive)이기때문에 코드의 흐름을 전적으로 사용자가 제어할 수 있습니다.하지만 불행히도 모든 언어에서 이런 코루틴이 지원되진 않습니다. greenlet은 이런 코루틴을 CPython에서 지원하기 위해 작성된 라이브러리입니다.eventlet코루틴을 통해 스레드를 대체할 수 있다는 점에 주목한 사람들은 greenlet을 통해 유용한 네트워크 라이브러리를 만들어냈습니다. eventlet도 그 중 하나죠. 잠시 eventlet의 소갯글을 봅시다.Eventlet is a concurrent networking library for Python that allows you to change how you run your code, not how you write it.위에서 볼 수 있듯이 eventlet은 사용성에 중점을 두었습니다. 기존의 블로킹 I/O 스타일의 프로그래밍에 익숙한 개발자들도 쉽게 비동기 I/O의 장점을 얻을 수 있게끔 하는 게 목적이죠.특히 저희가 주목한 점은 eventlet의 멍키패치 기능입니다. 멍키패치는 본래 동적 언어에서 런타임에 코드를 고쳐서 별도의 파일 변경 없이 본래 소스의 기능을 변경하는 것을 말합니다. eventlet은 eventlet.monkey_patch 메서드를 통해 표준 라이브러리의 I/O 라이브러리를 논블러킹으로 동작하게끔 변경해서 코루틴에 적합하게 만듭니다.How앞서 소개한 eventlet.monkey_patch를 이용하면 실제로 고칠 부분은 정말로 적어집니다. 다음 코드가 eventlet을 이용해 변경한 전부입니다.import eventleteventlet.monkey_patch() #표준 라이브러리를 변환# 여러가지 import를 하고...pool = eventlet.GreenPool()# 페이스북 계정들을 가져와서 반복하면서for account in FacebookAccount.query:    # 코루틴들에게 떠넘기자.    pool.spawn_n(FacebookAccount.update, account)        pool.waitall()view rawgistfile1.py hosted with ❤ by GitHub정말 적죠? 조금만 구체적으로 살펴보죠. 우선 eventlet.monkey_patch는 socket이나 select등의 Python 표준 라이브러리를 eventlet.green 패키지안에 정의된 코루틴 친화적인 모듈들로 바꿔치기 합니다.# from eventlet/pathcer.pydef monkey_patch(**on):    """Globally patches certain system modules to be greenthread-friendly.    The keyword arguments afford some control over which modules are patched.    If no keyword arguments are supplied, all possible modules are patched.    If keywords are set to True, only the specified modules are patched.  E.g.,    ``monkey_patch(socket=True, select=True)`` patches only the select and     socket modules.  Most arguments patch the single module of the same name     (os, time, select).  The exceptions are socket, which also patches the ssl     module if present; and thread, which patches thread, threading, and Queue.    It's safe to call monkey_patch multiple times.    """        accepted_args = set(('os', 'select', 'socket',                          'thread', 'time', 'psycopg', 'MySQLdb'))    default_on = on.pop("all",None)    for k in on.iterkeys():        if k not in accepted_args:            raise TypeError("monkey_patch() got an unexpected "\                                "keyword argument %r" % k)    if default_on is None:        default_on = not (True in on.values())    for modname in accepted_args:        if modname == 'MySQLdb':            # MySQLdb is only on when explicitly patched for the moment            on.setdefault(modname, False)        on.setdefault(modname, default_on)            modules_to_patch = []    patched_thread = False    if on['os'] and not already_patched.get('os'):        modules_to_patch += _green_os_modules()        already_patched['os'] = True    if on['select'] and not already_patched.get('select'):        modules_to_patch += _green_select_modules()        already_patched['select'] = True    if on['socket'] and not already_patched.get('socket'):        modules_to_patch += _green_socket_modules()        already_patched['socket'] = True    if on['thread'] and not already_patched.get('thread'):        patched_thread = True        modules_to_patch += _green_thread_modules()        already_patched['thread'] = True    if on['time'] and not already_patched.get('time'):        modules_to_patch += _green_time_modules()        already_patched['time'] = True    if on.get('MySQLdb') and not already_patched.get('MySQLdb'):        modules_to_patch += _green_MySQLdb()        already_patched['MySQLdb'] = True    if on['psycopg'] and not already_patched.get('psycopg'):        try:            from eventlet.support import psycopg2_patcher            psycopg2_patcher.make_psycopg_green()            already_patched['psycopg'] = True        except ImportError:            # note that if we get an importerror from trying to            # monkeypatch psycopg, we will continually retry it            # whenever monkey_patch is called; this should not be a            # performance problem but it allows is_monkey_patched to            # tell us whether or not we succeeded            pass    imp.acquire_lock()    try:        for name, mod in modules_to_patch:            orig_mod = sys.modules.get(name)            if orig_mod is None:                orig_mod = __import__(name)            for attr_name in mod.__patched__:                patched_attr = getattr(mod, attr_name, None)                if patched_attr is not None:                    setattr(orig_mod, attr_name, patched_attr)        # hacks ahead; this is necessary to prevent a KeyError on program exit        if patched_thread:            _patch_main_thread(sys.modules['threading'])    finally:        imp.release_lock()view rawgistfile1.py hosted with ❤ by GitHub이렇게 바꿔치기된 eventlet.green안의 모듈들은 I/O에 의해 블럭되는 경우 다른 코루틴에 제어권을 넘기는 식으로 지연을 방지합니다.다른 대안들사실 이러한 목적으로 사용되는 라이브러리는 eventlet만 있는 것은 아닙니다. gevent는 eventlet에서 영향을 받았지만, libevent를 기반으로 하여 더욱 나은 성능과 성숙한 인터페이스를 갖추고 있습니다. 저희처럼 libevent의 설치에 제한이 있는 환경이 아니라면 이쪽을 살펴보셔도 좋습니다.만약 이벤트 주도적 프로그래밍(Event-Driven Programming)에 흥미가 있으신 분은 Twisted역시 좋은 대안이 될 수 있습니다.#스포카 #개발 #개발자 #인사이트 #꿀팁
조회수 756

[어반테이스트] 새우는 어디에... 애슐리w를 다녀오다!

어반베이스 입사 '3'주차에,어반동료 '3'명이서 함께하는어반 테이스트 '3'기!제목 : 새우는 어디에....(테이스트 3기는 셀카가 메인)입사한지 얼마되지 않아 얼떨결에 어반테이스트 3기 리더가 되고서는.....처음으로 딱! 떠올랐던 미슐랭에 선정된 음식점을 가보즈아! 했으나.... 역삼역 인근에서 미슐랭에 선정된 음식점을 찾기가 힘들었습니다. (우리가 잘 못찾은건가.....=o=;;)그렇게 고민 중에마침, 회사가 있는 건물 '아주빌딩' 옆건물 GS타워 지하에 위치한 '애슐리w '에서 새우 축제가 한창이라는 정보를 얻어 듣고서는,새우+@ 라도 양껏 먹어보자는 심산으로 더이상 고민없이 바로 애슐리로 gogo!(절대 가까워서 간게 아님, 진짜 그런게 아님) 역삼역 7번출구로 나오자마자 보이는 건물인 아주빌딩을 지나 바로 옆에 있는 건물이 바로 GS타워! 밥 먹으로 가는 순간만큼 행복한 순간이 또 없어요...><(세상 순수한 미소를 가진 어반의 꽃미모 담당 정준&용필)가는 길목에서 혜인님의 발길을 멈출 수 밖에 없게 한... 포스터......행보가냐..? (전라도 사투리 버전)그렇게 도착한 애슐리 입구 앞 전경입니다! "하악하악, 그래, 새우라도 마음껏 먹어보자"우리를 이곳으로 이끌게 했던... 이 포스터,이때까지만 해도 저희는 새우를 배터지게 먹을 수 있겠다는 행복한 기대를 하고 있었더랬죠..저희는 자리를 안내받자마자 부푼 마음을 가득안고 샐러드바가 있는 곳으로 향했습니다!  사실... 음식이 더 가득 채워졌을때 찍으려고 했는데, 너무 많은 사람들이 이용중이였기 때문에 사진을 찍기에는 어려웠어요 흑 열심히 접시에 담아 보았습니다ㅋㅋㅋ 근데 위의 포스터에서 기대하게 만들었던 만큼의 다이나믹한 새우는 찾아보기가 힘들었어요ㅠㅠ심지어 혜인님은 새우 한마리도 드시지 못하셨다는 후문이...... 왠지 저녁 스페셜 메뉴가 아니었나 싶습니다.. 샐러드바로는 도저히 만족할 수가 없어서 메인메뉴를 시켜보기로 합니다.(어반 테이스트 고마워요 ♡)사실, 보통 뷔폐에 가면 단품 메인메뉴를 주문하지 않는 경우도 많기때문에 애슐리에서의 메인메뉴 주문은 처음인 것 같아요! 양고기&전복 스테이크, 뉴욕 스톤 스테이크, 메인메뉴를 주문하면 메뉴 1개당 음료 2개씩 제공해주는 세트 행사중!완성된 요리가 아닌 뜨겁게 달군 돌판위에 셀프로 익혀먹게끔 나왔습니당!양고기는 고기 특유의 냄새가 조금 났지만, 같이나온 소스에 찍어 먹으면 그런대로 먹을만 했으나스테이크는 정말 너무 질겨서 얼마 안되는 양을 남겼어요........ㄸㄹㄹ 1인당 3,000원을 내면 무제한으로 이용이 가능한 와인도 있었으나, 우리는 오후 근무가 남아있기에 아쉽게도 패스.... 용필님이 이번 애슐리에서의 식사 중 가장 맛있었다는 오른쪽의 무알콜 와인홍차 ㅋㅋ (웃어야 하나 울어야 하나.....) 열심히 먹고 귀요미 인증샷 ㅋㅋ (안본눈 삽니다...)그렇게 애슐리에서의 식사를 마무리하고 GFC에 위치한 홍차전문점으로 향합니다."클로리스 티 앤 커피" 요기 분위기도 맛도 정말 좋아요!홍차를 마시며제가 다니는 보드게임 동호회 이야기, 용필님의 클라이밍 취미생활 이야기, 혜인님의 다이어트 이야기 등등동료들과 처음으로 서로에 대해 알수 있었던 대화의 시간을 이어갔어요~~~그리고 빠질 수 없는 셀카타임ㅋㅋㅋ 이야기 보따리를 풀다보니 어느새 2시간이라는 시간이 훌쩍 지나 있었습니다ㅠㅠ2시간이라는 시간이 넉넉할거라 생각했는데,일단 선택했던 음식점이 뷔폐였기 때문에 계속 왔다갔다 움직이느라 예상시간을 많이 소비했고,팀원들과 충분한 대화를 즐기기엔 너무 아쉬운 시간이었어요ㅠㅠ다음에 기회가 또 주어진면 퇴근 후에 여유롭게 다녀와야 겠습니다!! 이렇게 점점 어반 테이스트 노하우가 쌓여지겠죠?(그렇다면 와인도!! 캬!!!)출처: https://blog.naver.com/urbanbaseinc 
조회수 1159

아띠 #19. 자칭타칭 아띠 비주얼, 마린!

Story #19. 자칭타칭 아띠의 비주얼 담당하고 있는라이더 '마린'을 소개합니다 :)자기소개 부탁해전 마린이에요. 아띠의 비주얼을 담당하고 있죠!!(하하) 어떻게 아띠를 처음 들어오게 됐어?처음에 김난도 선생님의 <내 일>이라는 책을 보고 관심이 생겨서 인터넷에서 아띠를 찾아봤어. 아띠 블로그도 보고 페이스북 좋아요도 누르면서 찾아보는데, 신입 라이더 모집기간이 이미 끝났더라고. 그래서 엄청 아쉬워했었어!(웃음)  그때 내가 군인이어서 당장 어떻게 할 방법은 없어서 그냥 평상 생활을 하는데, 내가 어느새 맨날 아띠 이야기만 하고, 아띠만 찾아보고, 아띠에 대해서 애들한테 계속 설명을 하고 있더라고. 그래서 비록 내가 지금 군인이어서 함께 할 수는 없지만, 이런 마음을 IJ한테 전달하고 싶었어. 그래서 IJ의 용기에 대해서 존경심을 표하고, 나도 기회가 되면 하고 싶다는 내용으로 편지를 썼지. 한 달 동안 답장이 안오더라고!(웃음) IJ가 처음에 답장 안 하려고 했었는데, 권이 답장하라고 해서 한 달 만에 답장을 받았어. '편지 잘 받았고 전역하면 그때 보고, 건강하게 전역하라'고. 그리고 4월에 전역한다고 하니까 구글 지원서 주소를 보내줘서 작성하고, 합격 통지를 말년 휴가 때 받았어. 엄청 기뻤지. 그래서 나는 전역한다는 기쁨보다 아띠에서 일할 수 있다는 기쁨이 더 컸어. 그래서 전역하고 바로 서울로 올라 와서 첫 날 케빈이랑 면접 보고 찜질방에서 저녁 12시에 합격했다고 문자받고 너무 좋았지. 그러면서 점점 아띠에 미쳐갔지.(웃음) 어떤 점이 그렇게 좋았어?음, 좋아진 이유에 대해서는 생각해보지 않았는데 그냥 정말 자연스럽게 좋아하게 된 것 같아. 자연의 흐름이었어.(웃음) 내가 아띠인력거라는 게 있다는 소식을 접한 이후에는 이걸 무시할 수가 없었어. 무조건 하고 싶었어. 그냥 내 속에서 그렇게 시킨 것 같아. 이성적으로 생각하고 판단했던 일이 아니고, 가슴이 시키는 일이었어. 진짜 그랬어! 그때 IJ한테 편지 쓸 때가, 새벽에 잠을 자다가 인력거 타는 꿈을 꿔서 일어나서 편지를 쓴 거야!(웃음) 그 새벽에 일어나서 렌턴 키고, '지금 아띠 때문에 잠을 잘 수가 없다, 인력거가 머리에서 떠나질 않는다'고 그렇게 편지를 썼어.  그리고 내가 처음 들어갔을 때가 영상을 많이 찍는 시즌이어서 비디오도 많이 찍고 열심히 일을 할 수 있었지. 타이밍이 좋았어. 인력거를 타면 제일 좋은 점은?크게 보면 이 세상이고, 좁게 보면 북촌인 이 곳에서 지나가는 사람들이랑 이야기를 나눌 이유가 없잖아. 그런데 내가 인력거를 탔다는 이유만으로, 그 사람들이랑 이야기를 나누고 함께 인력거를 타고서 나중에 내릴 때는 서로 친구가 되는 게 너무 재미있어! 그리고 나중에는 영어 투어의 맛을 알았지. 한국에 처음 온 외국인들이 느끼는 설레는 감정도 느껴지고, 그 사람들한테 내가 도움을 줄 수 있다는 게 기분 좋더라고.  처음 들어왔을 때는 어땠어?사실 처음에 많이 놀랐어. 제일 처음엔 케빈의 압박 면접에 놀랐어. 면접 볼 때 다른 사람이랑 같이 봤는데, 왜 아띠를 하려고 하나라는 질문에 나는 '23년 살아오면서 처음으로 하고 싶은 일이다. 내가 이렇게 하고 싶으니 좀 뽑아달라'고 말했었거든. 그런데 옆이 있는 친구는 그냥 단순히 돈을 벌려는 개념으로 왔던 거야. 그래서 그 친구는 케빈한테 많이 깨졌었지. 그때 조금 충격을 받았어. 다른 한 번은 생각보다 소통이 잘 안됐다는 느낌을 받았던 적이 있어. 그때 내가 함께 하면서 아띠에 도움을 주고 싶었고, 안 좋은 점들은 고쳐나가고 싶다고 느꼈어. 그래서 주 5회로 고정하고 시작하게 됐지. 그래도 아띠만큼 좋은 사내 문화를 가지고 있는 곳은 없다고 생각해. 우리만의 규칙들이 있잖아. 그런 것들은 정말 좋고, 잘 가꿔나갈 필요성이 있는 것 같아. 그리고 아띠에는 경쟁이 없잖아. 어느 회사에 경쟁이 없겠어? 그런데 아띠는 누구 하나가 내가 매출을 적게 벌어왔다고 뭐라고 하는 사람도 없고, 남이 나보다 매출을 많이 벌어왔다고 해서 스스로가 못났다라고 생각할 필요도 전혀 없다고 생각해. 다른 라이더들도 그냥 쟤가 운이 좋았구나 라고 생각하고 넘기니까 그런 경쟁이 없는 문화가 좋은 것 같아. 제일 힘들었을 때는?정신적으로 가장 힘들었을 때는 이번에 추억 때 집에 내려가서 친척들이 모였을 때였어. 학교 잘 다니고 있냐는 질문에 휴학하고 아띠인력거 하고 있다고 대답하니까 다들 그냥 고개만 끄덕이는 분위기였어. 아무도 나를 이해해주지 않는 분위기였지.(웃음) 그때 정말 부모님한테 가장 미안하면서 힘들었어. 아띠 나오는 뉴스 보여드리니까 아버지가 그제서야 허락해주시고 응원해주셨었지만, 속으로는 많이 걱정하셨을 거야.  그리고 내가 추석 때 아띠에 예약이 너무 많아서 가족들이랑 끝까지 못 어울리고 일찍 올라왔거든. 아띠는 남들 쉴 때 일하는 서비스업이니까, 남들 쉴 때 못 쉬는 게 좀 힘들더라. 특히 추석 때 다른 가족들은 다같이 다니는 데, 우리 가족들은 부산에 다 있고 나는 부산에서 서울로 혼자 올라와서 있으니까 제일 힘들었지.  육체적으로 가장 힘들었을 때는 무릎이 안 좋을 때인데, 정말 좋은 손님을 태웠을 때는 내가 무릎이 아픈지도, 땀이 나는지도 몰라. 라이딩을 마치고 들어오면 그때 알지. 그런데 조금 무례한 손님을 만나거나 내가 하는 이야기에 관심도 없고 왜 인력거를 타는지 모르겠는 느낌을 주는 손님을 만나면 체력적으로 정말 힘들어. 인력거가 앞으로 안 나가는 기분이야. 시간도 안가고. 그런데 좋은 손님들 만나면 1시간, 2시간 정말 금방 가. 어떤 손님이 제일 기억에 남아?어떤 노부부가 있었어. 할아버지께서 오랜 투병생활을 하셨는데, 병원에서 큰 희망이 없으니 할아버지한테 무리하게 치료는 그만하고 집에서 잘 쉬시다가 편히 보내드리자는 결정이 아띠를 타러 오기 하루 전에 났었대. 할아버지는 말씀도 잘 못하시고 거동도 힘드신데, 따님들이 인력거 예약해서 타신 거야. 1시간 동안 투어를 하고나서 할머니는 반응을 보여주셨었는데 할아버지는 말씀도 없으시고 표정 변화도 없으셔서 '재미없으셨나'생각했었거든. 그런데 인력거 투어가 끝나고 할아버지를 내려드리는데, 내 손을 딱 잡으시면서 딸들이 가자고 하시는데 안 가시는 거야. 그러면서 할머니 가방을 손으로 툭툭 치면서 나한테 용돈을 주라고 그러시는 거야. 이미 투어 비용은 지불하셨었는데도 계속 내 손을 안 놓으시면서 안 가시더라고. 그래서 결국 감사하게도 용돈을 조금 받았었어. 그리고 한 일주일 뒤에 그 따님한테서 문자가 왔었어. 할아버지가 편안하게 돌아가셨다고. 그때 나 정말 울었어.  할아버지께서는 오랜 투병생활에 지치셨는데 마지막으로 세상 구경을 나랑 함께 하신 거야. 그때 느낀 게, 우리가 인력거 타면서 정말 많은 손님들을 만나는 만큼 대부분 같은 투어루트를 돌면서 조금 지칠 때가 있어. 그런데 손님에게는 일생에 한번 뿐일 수도 있는 인력거를 타는 기회이고, 누구에게는 생에 마지막으로 세상을 구경하는 기회이고, 어떤 어린 아이에게는 처음 북촌을 구경하는 기회인 거잖아. 그래서 '그런 한 순간, 한 순간을 그 사람한테 정말 헛되이 돌려주면 안되겠구나'라는 그런 생각이 들더라고. 그때 그 할아버지를 통해서 그리고 할아버지께서 너무 좋아하셨고 만족하셨고 고맙다고 하는 문자를 받으면서 많은 생각이 들었어. 정말 잊혀지지 않을 손님이야.  그래서 나는 아띠를 버릴 수가 없어!(웃음) 난 지금 내가 아띠에 많이 스며들었다고 생각해. 내 욕심인데, 내가 없으니까 아띠가 안 굴러갔으면 좋겠어! 내가 없는 아띠를 생각하기도 싫어.(웃음) 아띠가 즐거운 순간에 내가 항상 있었으면 좋겠어.  마지막으로 하고 싶은 말사실 지금 아일랜드로 6개월간 가는 건데 겁이 안나. 왜냐면 내가 지금 아띠를 6개월 했는데 6개월 전에 처음 서울 올라왔을 때 나한테 아무것도 없었어. 그런데 지금은 이렇게 같이 밥을 먹고, 같이 무언가를 하자고 얘기 해주고 이제 잠시 떠난다고 하니까 같이 이런 슬픔을 공유해주는 좋은 가족들이 생긴거야. 딱 6개월이었어.그래서 나는 아일랜드에 가서도 똑같을 거라고 생각해. 어딘가에 던져졌을 때도 버틸 수 있는 힘이 생긴 것 같아. 아무튼 지금 이렇게 처음부터 끝까지 함께 해주는게 아띠인 것처럼, 아띠는 나에게 너무 너무 소중해. 나 스스로도 자아가 성립되는 기간이었어. 나중에 되돌아보면 이렇게 즐겁게 많은 사람들을 만나고, 많은 에너지를 얻을 수 있었던 순간을 꼽으면 지금 요 근래 6개월일 거라고 생각해. 많이 생각날 꺼야, 아띠!자석에 이끌리는 것처럼, 상사병에 걸린 것처럼,아띠를 알게 된 순간부터 인력거와 사랑에 빠진 마린의 러브스토리였습니다!마린이 아띠를 많이 생각하듯, 아띠도 우리 간판 라이더 마린이 많이 생각나네요~ :)아일랜드에서도 마린답게 몸도 마음도 씩씩하게 잘 지내리라 믿습니다.건강히 돌아와 아띠와 다시 즐겁게 라이딩하길 바래봅니다!#아띠라이더스클럽 #팀원소개 #팀원인터뷰 #팀원자랑 #기업문화 #조직문화 #사내문화
조회수 328

컴공생의 AI 스쿨 필기 노트 ⑤ 베이즈 결정이론

이번 5회차 수업에서는 베이즈 결정이론(Bayes Decision Theory)과 가우시안 혼합모형(Gaussian Mixture model)에 대해 배웠어요.1980년대 이후 세계 금융시장에서 위험관리를 계량화한 것은 확률이론, 그중에서도 ‘베이즈 정리’가 있었기에 가능했어요. 이전의 경험과 현재의 증거를 토대로 사건의 확률을 추론하는 알고리즘 덕분에 온갖 파생상품이 탄생했어요. 그런데 베이즈 정리는 오랫동안 금기시됐는데요. 주관적인 믿음을 측정하기 때문에 합리적이지 않다는 이유에서였다고 해요. 하지만 베이즈 정리의 활용도는 갈수록 커지고 있어요. 암호 해독부터 전쟁 중 의사결정, 실종된 사람이나 선박의 위치 추정, 암 발병률 예측, 스팸메일 걸러내기 등 무한대에 가깝다고 해요. 이번  필기노트에서는 베이즈 결정이론에 대해 알아볼게요.Bayes Decision Theory베이즈 결정이론은 패턴 인식을 위한 통계적 접근 방법이에요. 베이즈가 제시한 통계적 방법을 통해 의사 결정을 하는 방법이죠. 전통적 통계 방식은 통계적 추리를 할 때 표집으로 얻은 정보만 사용해요. 베이지안 확률이 전통적 통계 방식과 다른 점은 학습자가 기존에 가지고 있는 사전 정보를 활용한다는 것인데요. 불확실한 상황에서 통계적으로 얻은 정보를 가지고 의사 결정을 해야 하는 경제학, 경영학 등 여러 분야에서 많이 사용되고 있어요.베이즈 결정이론에 사용되는 베이즈 정리(Bayes rule)에 대해 간단한 예시를 들어볼게요.우리가 은행 지점장이라고 가정해봐요. 고객에게 돈을 빌려줄 수는 있지만 아무에게나 막 빌려줄 수는 없겠죠?그래서 은행 고객을 high-risk, 즉 돈을 빌려줘도 안 갚을 확률이 높은 고객과 low-risk, 즉 돈을 빌려주면 갚을 확률이 높은 고객으로 나눌 거예요.그런데 은행 고객이 돈을 갚을지 안 갚을지를 판단하는 기준이 있어야겠죠? 그래서 고객의 연봉(yearly income)과 현재 은행 계좌 보유금액(savings)을 가지고 판단할 거예요. 이렇듯 변수가 두 개만 있을 때 우리는 이항분포를 사용해서 의사를 결정해요. 위에서는 두 가지 고객이 존재하므로 이항분포를 사용해서 고객에게 돈을 빌려줄지 여부를 결정하죠. 결정을 내릴 때는 확률이 큰 쪽을 선택할 거예요. 확률이 큰 쪽을 선택하는 것은 이성적인 판단이기 때문이에요. 그래서 고객 x가 high risk일 확률(P(C=1|x)이 x가 low-risk일 확률(P(C=0|x)보다 크다면 1이라는 결정을 내리고, 작다면 0이라는 결정을 내려요.하지만 우리가 내리는 결정에도 error(=risk)가 존재하겠죠?확률의 합은 항상 1이고 결정은 항상 P(C=1|x)나 P(C=0|x) 중 확률이 큰 쪽이기 때문에 1에서 그 확률을 빼면 그 결정의 error가 돼요. 베이즈 결정이론은 이처럼 분류하고자 하는 물체들에 대해서 사전 정보가 주어지는 경우에 사용이 될 수 있는 이론이에요.Bayes’ rule베이즈 결정이론에는 베이즈 정리(Bayes’ rule)가 사용되는데요. 자세히 살펴볼게요.- P(C) : prior probability(선행 확률, 특정 사건이 일어날 것에 대한 추가 정보를 획득하지 못한 확률)로 여기서는 x가 어떤 값을 가지든 C가 1일 확률을 말해요.- p(x|C) : likelihood(우도, C가 주어졌을 때 조건부 확률) C가 주어졌을 때 x를 가지고 있을  확률을 말해요. 따라서 x값에 따라 확률이 달라져요. 예를 들어 p(x|C = 1) 은 C가 1인 즉 high risk인 고객이 x를 가지고 있을 확률을 나타내요.- p(x) : evidence(증거)는 C와 상관없이  x가 나타날 확률이에요.- p(C|x) : posterior probability(사후 확률)로 우리는 사후 확률을 기반으로 아래와 같이 decision을 내려요.위의 예시처럼 두 가지 고객만 있는 상황(이항분포)이 아니라 K명의 고객이 있는 경우(다항분포)는 어떻게 계산할까요? 이 경우에도 베이즈 정리가 적용되는데 식이 조금 달라져요.p(x) 구하는 식만 달라지고 나머지는 위에서 봤던 예시와 같아요. 그리고 이항분포의 error는 1에서 둘 중에 큰 확률을 뺐듯이 다항분포의 error도 아래와 같이 구해요.Loss and Risk위의 이항분포에서는 고객에게 돈을 빌려줌으로써 돈을 못 받는 손실(Loss)이 존재하고 돈을 못 받을 것 같은 고객에게 빌려주지 않음으로써 생기는 손실이 존재해요. 이 중 어떤 것이 더 손실이 적을지 생각해봐야겠죠?의사 결정을 하는 행동(action)을 αi라고 했을 때 αi에 대한 손실을 λik라고 정의할게요.위의 식은 예상되는 손실값이에요. 이 손실값은 실제로는 k인 상황이지만 행동 αi를 취해서 생기는 손실이에요.손실을 줄여야 하기 때문에 가장 작은 손실이 생기는 행동을 취해야 해요. 따라서 위의 식을 보면 argmin함수를 이용해서 k개의 행동 중 가장 작은 손실을 취해요.Reject 의사 결정이 어려운 경우에는 의사 결정을 피하는 것이 더 적절한 경우도 있어요. 이때는 어떠한 행동도 하지 않는 행동 αK+1을 추가해요.action αK+1을 추가하면 αK+1에 따른 손실 λik 또한 하나가 더 늘어요.위의 수식은 reject 행동을 포함했을 때 결정을 내리는 식인데 간단하게 참고하시면 될 것 같아요.이번에는 베이즈 결정이론에 대해 자세하게 다뤘는데요. 이번 수업은 교수님께서 많은 것을 가르쳐주셔서 저 같은 초보자가 듣기에 조금 힘든 점이 있었어요. 벌써 8주차 이론수업의 절반 이상이 지났는데요. 5주 동안 배운 많은 이론들을 코드로 능숙하게 표현하는 데에는 많은 노력이 필요하겠지만, 이만큼 왔다는 것만으로도 뿌듯한 기분이 들어요. 8주차부터 시작하게 될 팀 프로젝트에서 실력 발휘를 하기 위해서 더 열심히 수업에 임해야겠어요!* 이 글은 AI스쿨 - 인공지능 R&D 실무자 양성과정 5주차 수업에 대하여 수강생 최유진님이 작성하신 수업 후기입니다.
조회수 22569

Next.js 튜토리얼 9편: 배포하기

* 이 글은 Next.js의 공식 튜토리얼을 번역한 글입니다.** 오역 및 오탈자가 있을 수 있습니다. 발견하시면 제보해주세요!목차1편: 시작하기 2편: 페이지 이동 3편: 공유 컴포넌트4편: 동적 페이지5편: 라우트 마스킹6편: 서버 사이드7편: 데이터 가져오기8편: 컴포넌트 스타일링9편: 배포하기 - 현재 글개요아래와 같은 궁금증이 생긴 적이 있나요?어떻게 내가 만든 Next.js 애플리케이션을 배포할 수 있나요?아직 배포에 대해 이야기하지 않았지만 배포하는 것은 꽤 간단하고 직관적입니다.Node.js를 동작할 수 있는 곳이라면 어디든 Next.js 애플리케이션을 배포할 수 있습니다. 매우 간단한 ▲ZEIT now로 배포하는 데에도 불구하고 어떤 잠금 장치도 없습니다.설치이번 장에서는 간단한 Next.js 애플리케이션이 필요합니다. 다음의 샘플 애플리케이션을 다운받아주세요:아래의 명령어로 실행시킬 수 있습니다:이제 http://localhost:3000로 이동하여 애플리케이션에 접근할 수 있습니다.Build와 Start처음으로 프로덕션에 우리의 Next.js 애플리케이션을 빌드해야 합니다. 빌드는 최적화된 프로덕션의 코드 세트를 생산합니다.이를 위해 간단히 다음의 npm 스크립트를 추가하세요:그런 다음 하나의 포트에서 Next.js를 시작해야 합니다. 사이드 렌더링을 수행하고 페이지를 제공합니다. (위의 명령으로 빌드됩니다)이를 위해 다음의 npm 스크립트를 추가하세요:이러면 3000 포트에서 우리의 애플리케이션이 시작됩니다.이제 프로덕션에서 애플리케이션을 동작시키 위해 다음의 명령어를 실행할 수 있습니다:두 개의 인스턴스 실행하기애플리케이션의 인스턴스 두 개를 실행시켜 봅시다. 대부분 앱을 수평으로 확장하기 위해 이 작업을 수행합니다. 처음으로 start npm 스크립트를 다음과 같이 변경해봅시다:만약 Winodws라면 next start -p %PORT%로 스크립트를 변경해야 합니다.이제 애플리케이션을 처음으로 빌드해봅시다.npm run build그러면 터미널에서 다음의 명령어로 실행시켜 봅시다:PORT=8000 npm startPORT=9000 npm startWinodws에서는 다른 명령어를 실행시켜야 합니다. 하나의 옵션은 애플리케이션에 cross-env npm 모듈을 설치하는 것입니다.그런 다음 커맨드 라인에서 cross-env PORT=9000 npm start를 동작시켜 주세요.두 개의 포트 모두에서 애플리케이션에 접근할 수 있나요?- 네. http://localhost:8000와 http://localhost:9000 둘 다 접근할 수 있습니다.- http://localhost:8000에서만 접근 가능합니다.- http://localhost:9000에서만 접근 가능합니다.- 둘 다 접근할 수 없습니다.한 번의 빌드로 많은 인스턴스 실행시키기보다시피 애플리케이션을 한 번 빌드해야 합니다. 그런 다음 원하는만큼의 많은 포트들을 시작할 수 있습니다.▲ZEIT now에 배포하기Next.js 애플리케이션을 빌드하고 시작하는 방법을 배웠습니다. npm 스크립트를 사용하여 모든 것을 수행했습니다. 그래서 원하는 배포 서비스를 사용해서 동작하도록 애플리케이션을 설정할 수 있습니다.하지만 ▲ZEIT now를 사용하면 딱 한 번의 과정만 수행하면 됩니다.다음과 같은 npm 스크립트만 추가해주세요:그런 다음 now를 설치해주세요. 설치 후 다음 명령어를 적용해주세요:now기본적으로 애플리케이션의 루트 디렉터리 안에서 "now" 명령어를 실행합니다.여기에서 애플리케이션을 시작하는 포트로 8000 포트를 지정했지만 ZEIT now에 배포할 때 변경하지 않았습니다.그러면 ZEIT now에 배포할 때 애플리케이션에 접근할 수 있는 포트는 어떤 것일까요?- 8000- 443 (혹은 언급되는 포트가 없음)- URL에 언급한 모든 포트- 에러를 표시한다. "443 포트에서만 시작할 수 있습니다"ZEIT는 항상 443 포트를 사용합니다실제로 8000 포트에서 애플리케이션을 시작해도 now에 배포될 때는 443 포트를 사용해서 접근할 수 있습니다. ("https" 웹사이트의 기본 포트)이것은 ▲ZEIT now의 특징입니다. 원하는 포트에서 애플리케이션을 시작해야 합니다. ▲ZEIT now는 항상 443 포트로 매핑합니다.로컬에서 애플리케이션 빌드하기▲ZEIT now는 npm build 스크립트를 발견하고 빌드 인프라 내부에 빌드합니다.하지만 모든 호스팅 제공자가 이와 같은 것을 가지고 있지는 않습니다.이 경우 로컬에서 다음의 명령어를 사용해서 빌드할 수 있습니다:npm run build그런 다음 .next 디렉터리를 사용하여 애플리케이션을 배포하세요.커스텀 서버를 사용하여 애플리케이션 배포하기우리가 막 배포한 애플리케이션은 커스텀 서버 코드를 사용하지 않았습니다. 하지만 만약 사용한 경우에는 어떻게 배포할 수 있을까요?다음의 브랜치로 체크아웃하세요:커스텀 서버를 사용하여 애플리케이션을 실행하기 위해 애플리케이션에 Express를 추가해주세요:npm install --save express애플리케이션 빌드하기이를 위해 next build를 사용하여 애플리케이션을 배포할 수 있습니다. 다음의 npm 스크립트를 추가해주세요:애플리케이션 시작하기프로덕션 애플리케이션임을 알리기 위해 커스텀 서버 코드를 생성해야 합니다.이를 위해 server.js로부터 이 코드를 살펴봅시다.이 부분을 살펴봅시다:그러면 프로덕션으로 이와 같이 애플리케이션을 시작할 수 있습니다.그래서 "npm start" 스크립트는 다음처럼 변경됩니다:마무리Next.js 애플리케이션을 배포하는 것에 대해 거의 다 배웠습니다.문서에서 Next.js 배포하기에 대해 더 배울 수 있습니다.배포에 대한 질문이 있다면 자유롭게 Slack에서 물어보거나 issue를 제출하세요.#트레바리 #개발자 #안드로이드 #앱개발 #Next.js #백엔드 #인사이트 #경험공유

기업문화 엿볼 때, 더팀스

로그인

/