스토리 홈

인터뷰

피드

뉴스

조회수 2847

Eclipse 디버거 사용법

꽤 많은 분들이 디버거의 존재 자체를 모르고 있거나 혹은 디버거가 있다는 사실은 알아도 그 효용성에 의문을 제기하곤 합니다. 왜냐하면, 우리에겐 Log 클래스나 혹은 printf같은 훌륭한(?) 디버깅 도구가 있다고 생각하기 때문이죠. 물론 이렇게 필요한 변수를 찍어보면서 어떤 곳에서 버그가 있는지를 알아보는 일이 잘못된 일은 아닙니다만 복잡한 여러 상황이 맞물려 재현되는 버그는 이러한 고전적인(?) 방법을 써서 알아보기가 매우 어렵습니다.원인을 정확히 그리고 빨리 파악하려면 디버거의 사용법을 숙지하고 사용하는 것이 가장 좋습니다. 대부분의 개발 환경에서 디버거를 제공하는데 다행히 이클립스에서도 쓸만한 디버거를 내장하고 있습니다.오늘 포스팅에서는 이클립스 디버거 사용법에 대해 다루어 볼까 합니다.이클립스 디버거 뷰이클립스는 디버거 뷰를 제공하여 디버거를 사용할 수 있도록 합니다. 디버거 뷰는 어디에서 확인할 수 있을까요? 바로 우측 상단에 Debug 뷰에 들어가면 그곳에서 확인할 수 있습니다.디버깅의 시작그렇다면 어떻게 디버깅을 활성화한 상태로 프로그램을 실행할 수 있을까요? 상단 메뉴의 Run에서 프로그램을 실행할 때 Debug를 이용하여 프로그램을 실행하면 디버거가 작동하게 됩니다.브레이크 포인트 설정과 뷰보통 디버깅을 할 때 가장 먼저 하는 일이 브레이크 포인트를 잡는 일입니다. 브레이크 포인트를 에러가 일어나는 라인이나 혹은 의심이 가는 변수를 추적할 수 있는 라인쯤에 잡아놓고 프로그램을 디버깅하면 해당 라인을 실행할 때 디버거가 작동하게 되고 그곳에서 프로그램을 라인 별로 진행해가며 관찰을 진행할 수 있게 됩니다.브레이크 포인트 설정은 매우 간단합니다. 편집기 왼쪽에 파란 부분(마커 바)을 더블 클릭하게 되면 파란 원이 생기는데 이 원이 브레이크 포인트입니다. 혹은 오른 클릭하여 Toggle break point를 누르면 됩니다. 설정 후 다시 더블 클릭하게 되면 브레이크 포인트가 사라지게 됩니다.또한, 디버그의 브레이크 포인트 뷰에서 지금까지 걸어놓은 모든 브레이크 포인트들의 위치를 확인할 수 있고 활성화/비활성화, 삭제도 할 수 있습니다. 여러 브레이크 포인트가 걸려있을 때에는 이 탭에서 확인하고 관리하는 것이 더 편합니다.또한, 디버깅을 진행하고 있는 도중에도 다른 의심이 가는 라인에 브레이크 포인트를 걸 수 있습니다.스텝 단위 진행지정한 브레이크 포인트에 다다르면 동시에 디버거가 작동하게 되고 그 라인부터 스텝 단위의 진행을 할 수 있게 됩니다.이제 이 뷰의 버튼들을 이용하여 현재 상황을 진행하거나 되돌릴 수 있습니다. 자주 사용하는 버튼의 사용법을 알아보면Resume : 다음 브레이크 포인트를 만날때까지 진행합니다.Suspend : 현재 작동하고 있는 쓰레드를 멈춥니다.Terminate : 프로그램을 종료합니다.Step Into : 메서드가 존재할 경우 그 안으로 들어가 메서드 진행 상황을 볼 수 있도록 합니다.Step Over : 다음 라인으로 이동합니다. 메서드가 있어도 그냥 무시하고 다음 라인으로 이동합니다.Step Return : 현 메서드에서 바로 리턴합니다.Drop to Frame : 메서드를 처음부터 다시 실행합니다.등이 있습니다.실제로 디버깅 화면에서 버튼들을 눌러보면 쉽게 그 쓰임새를 아실 수 있습니다.변수의 상태 확인을 쉽게 해주는 변수 뷰디버깅을 진행하는 도중 변수의 값이나 객체의 상태를 알고 싶은 상황이 생기게 됩니다. 현재 의심이 가는 변수 이외에도 이 변수에 영향을 끼칠 다른 변수들이나 객체들의 상황을 실시간으로 검사할 필요가 있을 때 변수 뷰를 이용하면 도움을 얻을 수 있습니다.이곳에서 변수나 객체의 상태를 확인하고 변수의 상황에 대해서 저장할 수 있습니다. 변수나 객체의 상황을 모두 저장해서 클립보드에 붙이고 싶은 일이 생기면 해당 변수를 오른클릭 후 Copy Variables를 선택합니다.편집 창으로 돌아가 변수에서 Command + shift + i를 누르게 되면(혹은 오른 클릭 후 Inspect를 선택) Inspector 창이 뜨게 됩니다. 이 창에서 다시 한번 Command + shift + i를 누르면 해당 변수를 Expression 뷰로 보내게 되고 이곳에서 지속해서 변수의 상태를 관찰할 수 있게 됩니다.Expression 뷰 이용Expression 뷰에서는 변수 이름을 입력하거나 수행해보고 싶은 명령어를 직접 입력하여 그 결과 값을 관찰할 수 있습니다. 결과 값을 관찰할 뿐만 아니라 Expression에 써놓은 변수들은 명시적으로 지우지 않는 이상 계속해서 관찰을 수행하기 때문에 변해가는 상황을 지속해서 관찰할 일이 있는 변수나 명령문을 등록해놓기에 좋습니다.Display 뷰 이용디스플레이 뷰에서는 현 문맥에서 사용할 수 있는 명령어를 실행하거나 변수의 값을 조작하는 일을 수행하기에 적합한 환경을 제공합니다. Expression에서도 비슷한 기능을 제공하지만, 디스플레이 뷰를 이용하는 것이 더 편합니다. 메모장과 같이 쉽게 쓰고 지울 수 있기 때문입니다.또한, 원본 코드의 수정 없이 편하게 현재의 맥락을 변화시킬 수 있는 것이 가장 큰 장점이라고 볼 수 있습니다.필요한 명령어들을 적어놓은 후 실행하고 싶은 부분만 드래그하여 수행하거나 혹은 값을 리턴받을 수 있습니다. 지금은 boolean변수 하나의 값을 바꿔보기도 하고 조건 값에 따라 무언가를 리턴 받도록도 해놓은 상황을 스크린 샷으로 담아보았습니다.값을 반환받고 싶을 때는 두 번째 버튼을, 단순히 실행만 할 때에는 세 번째 버튼을 누르면 됩니다.두 번째 버튼을 눌러 값을 반환받는 상황입니다.단순히 실행만 하려면 세 번째 버튼을 누릅니다.브레이크 포인트에 조건 걸기브레이크 포인트에 조건을 거는 것이 굉장히 유용할 때가 있습니다. 특히 반복문안에 들어가 있는 코드들을 디버깅할 때 유용하지요. 반복문의 경우 모든 상황을 검사한다기보다는 특정 조건에서 값이 어떻게 들어가는지를 분석하는 경우가 더 많은데 이러한 상황을 검사하기 위해서 브레이크 포인트에 조건을 걸어야 합니다.브레이크 포인트를 거는 과정까지는 똑같습니다. 브레이크 포인트를 건 후 그 포인트에서 오른 클릭을 하면 Breakpoint properties 옵션이 있는 것을 확인할 수 있습니다. 이 옵션에서 조건문을 설정하여 디버거의 활성화 조건을 설정할 수 있습니다.먼저 Conditional을 활성화하여 어떤 조건에서 디버깅 화면으로 전환할지를 쓰면 되는데 이 창에 조건식을 쓰면 됩니다.또 hit count를 이용하여 조건을 걸 수도 있습니다. hit count에 값을 적용하면 해당 라인에 브레이크 포인트가 hit count만큼 잡힌 이후 디버깅 화면으로 전환하게 됩니다. hit count옵션은 반복문에서 한 100번쯤 이후에 디버깅을 시작하고 싶거나 하는 일이 생길 때 유용하게 쓸 수 있습니다.#스포카 #개발 #개발자 #꿀팁 #조언 #인사이트 #디버거 #디버깅 #디버그 #Eclipse
조회수 3543

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]브랜디, 오직 예쁜 옷만  
조회수 1599

개발자 커리어 전환기1| 하드웨어 개발자, 소프트웨어 개발자가 되기로 마음먹다.

개발자는 도대체 어떻게 되는 거고 누가 되는 거야?코드스테이츠가 가장 많이 받아온 질문 중 하나입니다. 그래서 준비한 특급 연재! 개발자 커리어 전환기! 매주 Immersive를 수강하고 있는 수강생 한 분과 인터뷰해서 어떻게 개발을 시작하게 되었는지, 또 현재 무엇을 배우고 있는지에 대한 인터뷰를 포스팅하려고 합니다.아무것도 모르는 비전공자 출신 분들이(물론 전공자 분도 계십니다!) 개발자가 되어가는 과정을 생생하게 보실 수 있습니다. 그럼, 첫 번째 포스팅의 주인공 이야기를 시작하겠습니다.코드스테이츠 코딩 부트 캠프, Immersive 6기 과정이 시작되었습니다. 지난 5기 데모데이를 들뜬 마음으로 지켜보던 Pre-course 수강생들이 어느덧 새로운 Immersive 과정의 주인공이 되었는데요.오늘은 하드웨어 개발자 출신으로서 커리어 전환을 위해 코드스테이츠를 찾아온 6기의 전한길님을 만나봤습니다. Q) 한길님 반갑습니다. Precourse 수료를 축하드리며 간단한 자기소개 부탁드려요.- 안녕하세요! 전한길입니다.Q) 정말 간단하네요! 보통은 인터뷰어를 위해 좀 더 길게 합니다만...- 아... 전 대학에서 전자공학을 전공했고요. 어쩌다 보니 전자회로 설계일을 하게 되었어요. 원래는 소프트웨어 쪽에 관심이 있었는데 하드웨어 쪽으로 일을 했습니다. 사실, 당시에는 집 가까운 회사를 찾다보니..(웃음) 어쨌든! 커리어 전환을 위해 코드스테이츠에 오게 되었습니다.Q) 원래 이쪽에 관심이 있으셔서 소프트웨어 엔지니어로 커리어 전환을 하시는 건가요?- 자신만의 기술을 가질 수 있다는 점이 좋아서 소프트웨어 엔지니어를 하기로 결심했어요. 저는 회사생활을 6년 동안 했는데요. 하루하루 똑같은 업무와 일상이 지루하더라구요. 직급이 올라간다고 해서 더 나아질 거 같지도 않았고...사실 깊이 생각하는 성격이 아니에요. 무작정 회사를 나와서 고민했죠. 그러다가 "나만의 기술을 가질 수 있는 매력적인 직업을 갖자"는 저만의 원칙을 고수한 끝에 소프트웨어 엔지니어가 되기로 결심했어요.Q) 그러면 특별히 코드스테이츠를 선택하신 이유가 무엇인가요?- 처음에는 국비지원과정도 알아봤어요. 국비지원과정에서 공부를 할까 하다가 우연히 친구 소개로 코드스테이츠를 알게 되었죠.'자기 주도적 학습'이라는 단어에 끌렸어요. 전 코딩이 언어랑 비슷하다고 생각하거든요. 문법을 잘 안다고 영어를 잘하는 건 아니잖아요. 아는 것도 중요하지만 습관이 중요하다고 생각해요. 지름길을 가면서 스스로 코딩을 많이 해볼 수 있을 거 같아서 코드스테이츠를 선택하게 되었죠.코딩은, 아는 것도 중요하지만 습관이 중요하다고 생각해요Q) 이건 개인적으로 매우(?) 긴장되는 질문인데, 실제로 Pre-course는 어땠나요?- 코드스테이츠 학습 방식 자체가 강의식이 아니다 보니 생각한 대로 '자기 주도적 학습 위주'고, 특히 실제로 코딩을 많이 해봐서 좋았어요.그리고 위에서 얘기한 것처럼 저는 지름길이 필요했는데요. 방향을 잘 잡아주셔서 좋았어요. 단계별로 공부할 수 있는 내용이 잘 정리되어있더라구요. 시간을 효율적으로 쓸 수 있었습니다.Q) 담당자로서 매우 뿌듯한 답변이네요. :) 특히 어떤 프로젝트가 가장 기억에 남나요?- *twittler 를 만들었을 때가 가장 기뻤어요. 뭐라고 말로 표현하기는 어려운 감정인데, 실제로 눈에 보이는 걸 만들었을 때 성취감이 크더라구요. 그 성취감이 동기부여가 되어서 더 열심히 했던 거 같습니다.*twittler: 코드스테이츠 Pre-course과정에서 수행하는 프로젝트로, 트위터의 일부 기능을 구현한 프로그램한길님이 구현한 twittlerQ) 이제 막 Immersive 과정이 시작되었는데요. 과정에서는 어떤 걸 기대하나요?- 코드스테이츠의 체계적인 커리큘럼과... 웹 개발자로 취업하는 거??Q) 교과서 같은 답변이네요.^^ 3개월 뒤면 웹 개발자가 되어있을 거라고 믿습니다. 그렇다면 어떤 개발자가 되고 싶나요?- 기술을 잘 아는 개발자가 되고 싶어요. 개인적으로 호기심이 많아요. 블록체인부터 빅데이터까지.. 새로운 기술과 관련된 단어들을 들으면 호기심이 생기죠. 이렇게 호기심이 생겼을 때 그 기술에 대해 이해하고 실제로 기술을 잘 구현하는 개발자가 되고 싶어요. 소위 말하는 백엔드 쪽에 더 관심이 있는 거 같아요. 앞으로도 이 방향으로 나아가고 싶구요.음.. 그리고 하나만 덧붙이면, 제 생활도 잘 지킬 수 있는 개발자가 되고 싶어요. 일도 일이지만.!Q) 마지막으로 코드스테이츠를 다른 사람에게 추천한다면?소프트웨어 엔지니어가 되고 싶으신 분들에게 꼭 추천하고 싶어요. 독학을 해도 좋은 점이 있겠지만.. 체계적인 커리큘럼을 따라가면서 방향성 있는 공부를 하면 효율적일 거 같아요. 시간을 아낄 수 있죠. 커리어 전환을 고민하시는 분들에게도 적합하구요.그리고 무엇보다 같은 길을 가는 사람들과 커뮤니티를 형성하고 함께 공부할 수 있다는 점이 코드스테이츠의 가장 큰 장점이라고 생각합니다.
조회수 1084

EOS Proxy Voting이란?

우선 EOS BP 투료를 한 번쯤 해보신 분들은 매번 새롭게 등장하는 BP 후보들은 넘쳐나고 그들의 이름과 공약을 확인하는 것이 귀찮다고 느끼셨을 수 있습니다.또한 어렵게 공약을 확인하고 정말 이 팀이 EOS를 위해 무엇을 할 수 있는지 다른 팀들과 어떤점이 다른지 꼼꼼하게 비교하여 선거한 여러분의 소중한 투표권 파워는 시간이 지날수록 가치가 줄어들게 됩니다.그렇다면 나 대신에 꾸준히 선거를 대신해줄 사람이 있다면 얼마나 좋을까요?사실 이런 문제에 대해 EOS도 알고 있었으며, 어떤 해결 방법이 있을지 생각해왔습니다.그래서 바로 만들어진 것이 EOS Proxy Voting입니다.Proxy란 ‘대리인’이란 의미를 갖고 있습니다.따라서 EOS Proxy Voting은 EOS BP 대리 투표 시스템을 뜻합니다.이 대리인 투표권을 신청하게 되면 여러분은 더 이상 투표에 대해 고민하실 필요가 없게 되는 거예요!이제 이 Proxy 시스템을 어떻게 이용하는지 방법을 소개하고자 합니다.1. 어떻게 Cleos를 통해 다른 사람에게 나의 투표 권한을 넘길 수 있나요?나의 투표 권한을 Cleos를 통해 다른 사람에게 넘기기 위해선 다음과 같은 명령어를 입력해야합니다.간단하지요? 이 명령어는 eosaccount12가 자신의 투표 권한을 proxyvoter34에게 넘기겠다는 의미를 갖고 있습니다.2. 어떻게 툴킷을 통해 다른 사람에게 나의 권한을 넘길 수 있는 건가요?대표적으로 https://eostoolkit.io/vote/setproxy에서 Proxy를 설정하는 방법을 안내해드릴게요! (참고로 https://www.myeoskit.com/#/tools/proxy/https://eosvoter.eosphere.io 에서도 가능합니다. )나의 proxy를 툴킷을 통해 다른 사람에게 넘기기 위해선 먼저 Scatter 구글 확장 프로그램을 설치해야 합니다.Scatter 설치 후 EOS 계정 및 접속 정보를 Scatter에 등록하셔야 합니다. (Scatter에 정보를 등록하는 방법은 곧 업데이트 하도록 하겠습니다.)그렇다면 등록을 다 하셨을 테니 다음으로 넘어가겠습니다.우선 EOStoolkit에 접속하셔서 스캐터 계정으로 로그인하셔야 합니다.로그인 하셨다면 이제 왼쪽 카테고리에서 [Manage Voting] 항목을 보실 수 있을거에요![Manage Voting]를 클릭하시면 Voting에 관한 여러 항목이 촤르르 나오게 되는데 그 중에 [Set Proxy]를 눌러주세요!자 그럼 아래 화면에 나온 대로 그대로 따라하신 후 저장만 해주시면 됩니다.드디어 투표 권한을 지정 Proxy에게 넘기게 되었습니다.3. 어떻게 내가 설정한 Proxy를 해제할 수 있나요?Proxy 지정을 하고 며칠동안 투표에 신경을 쓰지 않았다가 오랜만에 들어간 투표 사이트에서 내가 지정한 대리인이 행사하는 나의 투표권이 마음에 들지 않을 땐 어떻게 해야할까요?해제를 해야겠지요!그렇다면 지금 내가 지정한 Proxy가 마음에 안들어서 해제하고 싶을 때는 어떻게 할지도 알아보겠습니다.Proxy 설정을 했다면, 저 네모박스에 체크되어 있을겁니다. 그 체크를 해지 하면 간단하게 내가 설정한 Proxy를 해제하게 되는 것입니다.아주 간단하네요.그럼 이제 다음은 내가 직접 Proxy가 되기 위해선 어떻게 할 수 있을지 알아보겠습니다.그 방법도 마찬가지로 Cleos 또는 Toolkit 과 Scatter를 통해 할 수 있습니다.4. Cleos를 통해서 내가 직접 Proxy가 될 수 있는 방법은 어떤게 있나요?내가 직접 Cleos를 통해 Proxy가 되기 위해선 다음과 같은 명령어를 입력해야합니다.이 명령어는 proxyvoter34는 Proxy로 지정되었는 의미를 갖고 있습니다.5. 어떻게 툴킷을 통해 내가 직접 Proxy가 될 수 있는 건가요?우선 툴킷을 통해 Proxy로 등록하기 위해선 가장 먼저https://eostoolkit.io/vote/setproxy 에 나의 Scatter 계정으로 로그인해야 합니다.(참고로 https://www.myeoskit.com/#/tools/proxy/https://eosvoter.eosphere.io 에서도 가능합니다. )로그인 하셨다면 왼쪽 카테고리에서 [Manage Voting]을 찾아주세요!찾으셨다면 해당 항목의 아래 항목에서 [Create Proxy] 를 클릭해주세요. 그럼다음과 같은 화면이 나오게 됩니다.아래 나와있는 설명 그대로 적어주시고 저장해주시면 됩니다. 다 완료하셨으면 드디어 Proxy가 되셨어요!6. 더이상 Proxy로 활동하고 싶지 않으면 어떻게 해야 하나요?더 이상 Proxy로서 활동을 하고 싶지 않다면 마찬가지로 [Manage Voting]를 통해 Proxy 철회를 할 수 있습니다.[Manage Voting]를 클릭 후 아래 항목에서 [Resign Proxy]을 누르시면 됩니다. 첫 번째 Resign 버튼은 Proxy 등록을 해지하는 것이고 두 번째 Unregister 버튼은 등록한 정보를 삭제하는 버튼입니다.각각의 버튼을 눌러 그대로 진행하시면 Proxy 철회가 완료될 거예요!자 여기까지 이제 EOS Proxy Voting을 하기 위해Proxy 설정하는 방법을 알아보았습니다. 어렵게 보이지만 Scatter 연동만 하면 Proxy를 설정하거나 내가 직접 Proxy가 되는 것은 어렵지 않습니다!아 참고로, 현재 등록된 모든 Proxy 리스트를 Aloha EOS Proxy Research Portal에서 확인할 수 있습니다.또한 해당 사이트에서 Proxy들이 자신들이 Proxy로 활동하면서 어떻게 투표를 행사할 것인지에 대한 공약도 자세히 나와있으니 한 번쯤 들어가서 보시면 Proxy를지정하는 데에 있어서도, 내가 직접 Proxy가 됨에 있어서도 도움이 될 거예요!#헥슬란트 #HEXLANT #블록체인 #개발자 #개발팀 #기술기업 #기술중심
조회수 864

[Tech Blog] How we pipe data

버즈빌에서는 미국과 일본을 비롯한 전 세계 30개국에서 1,700만 이상의 유저의 행동에 대한 데이터를 수집하고 있습니다. 이 데이터에는 유저들이 잠금화면에서 어떤 Action을 수행하는지부터 잠금화면에 어떤 광고가 노출되고 유저들이 어떤 광고를 클릭 하는 지 등의 정보들이 포함되는데요. 이러한 데이터는 여러 종류의 다른 소스로부터 오고 각기 다른 종류의 DB (MySQL, DynamoDB, Redis, S3 등등) 에 저장됩니다. 하지만 데이터를 분석하고 활용하기 위해서는 이렇게 흩어져서 저장된 데이터들을 한 곳으로 모으는게 필수적입니다. 그래서 저희 팀에서는 이렇게 다양한 소스로 부터 발생해서 다양한 DB에 저장된 데이터를 어떤 과정을 통해 한 곳으로 모을 것인가에 대해서 고민하게 되었습니다. 그리고 고민 끝에 각각의 DB에 저장된 데이터를 하나의 큰 데이터 스토리지에 모을 수 있는 ‘데이터 파이프라인’을 구축하는 계획을 세우게 되었습니다. 하지만 다양한 소스로부터 수집된 수많은 데이터들을 잘 유지해가며 하나의 큰 DB에 모을 수 있는 데이터 파이프라인을 구축하는 것이 쉽지 않았는데요. 이 포스팅을 통해서 버즈빌에서는 어떻게 각각의 데이터들을 수집하고 저장하는지 또 이런 데이터들을 통합하기 위한 파이프라인을 어떻게 구축했는지 공유하고자 합니다. 본격적인 이야기에 앞서 현재 버즈빌에서 모든 데이터가 모이는 데이터 스토리지로 사용 중인 RedShift에 대해 이야기하고 싶습니다. 개인적으로는 정말 쓰면 쓸수록 감탄이 나오는 데이터 스토리지라고 생각합니다. Redshift는 AWS에서 관리하는 SQL기반의 열기반 스토리지(SQL based columnar data warehouse)이며 복잡하고 대규모의 데이터 분석에 적합합니다. 고객들로부터 생성된 수많은 종류의 데이터를 기반으로 다양한 인사이트를 얻고자 하는 많은 기업들(Yelp, Coursera, Pinterest 등)이 사용하고 있는 솔루션 이기도 합니다. 버즈빌에서는 여러가지 특징을 고려하여 Redshift를 도입하게 되었는데요. 그 이유는 아래와 같습니다.  Performance Performance Performance.     Column 기반 스토리지 -> 필요한 Column에만 접근한다.   Join이나 aggregation이 많은 복잡한 쿼리도 쉽게 계산할 수 있다.   분산 저장 방식 (Distributed Storage)   Date Ingestion이 빠르다. (Ingest first, index and clean later)     Horizontal Scalability   sharding이나 clustering에 추가적인 complexity가 필요하지 않다. 데이터가 원래 노드에 저장되기 때문에 horizontal scaling을 위해서는 그냥 추가적인 노드만 붙이면 된다. 다른 AWS서비스들과 쉽게 연동이 가능하다. (장점 이자 단점)    하지만 몇 개의 아쉬운 점들도 있습니다. :  다른 RDBMS와 달리 Mutilple indice를 지원하지 않는다.  1 Distribution Key and 1 Sort Key   MySQL이나 다른 RDBMS처럼 uniqueness나 foreign key constraint를 걸 수 없다.     모은 데이터를 어떤 방식으로 Redshift로 옮겨야 할까요? 버즈빌이 구축한 데이터 파이프 라인은 크게 3갈래의 메인 루트가 있습니다.   1) Athena Preprocessing Batch job을 통해서 (잠금화면 활동, 광고 할당) Why? 전처리 작업(Preprocessing)이 필요한 가장 큰 이유는 들어오는 데이터의 어마어마한 크기 때문입니다. 또 어떤 데이터들은 너무 raw하기 때문에 애널리스트나 데이터 사이언티스트가 분석에 활용할 수 있는 형태로 바꾸기위해 전처리가 필요하기도 합니다. 버즈빌에서는 이런 데이터들을 처리하기 위해서 AWS Athena를 사용하고 있습니다. Athena는 과금 방식이 Athena 쿼리로 읽은 데이터의 사이즈를 기반으로 하기 때문에 다른 EMR이나 MapReduce solution들을 사용했을때보다 상대적으로 적은 비용으로 활용할 수 있다는 장점이 있습니다. How?  먼저 S3로 데이터를 보냅니다. 그 후, Athena를 활용하여 데이터를 가공/처리합니다. 가공된 데이터를 읽어서 Redshift로 보냅니다. (COPY command 활용)  Pros?  서버를 따로 가질 필요가 없습니다. (EMR 클러스터나 서버를 관리할 필요가 없음) 경제적입니다. (S3에서 1TB를 읽을때마다 $5 정도의 비용)  Cons?  사용량이 몰리는 시간대 (12:00 AM UTC)에는 일부 쿼리가 실패할 수 있습니다. -> 중요하고 필수적인 데이터는 Athena가 아닌 다른 방법을 통해 처리하는것이 적합합니다. PRESTO DB의 기능을 (아직은) 온전히 활용할 수 없습니다.     2) Firehose를 통해서 (Impression, Clicks, Device, Events) Why? Kinesis Firehose는 Redshift, Elasticsearch, S3와 같은 최종 목적지까지 다양한 데이터들을 안정적으로 옮길 수 있는 파이프라인을 제공할 뿐 아니라 Fluentd와 매끄럽게 잘 연동된다는 점에서 굉장히 뛰어난 서비스 입니다. Fluentd는 서버로부터 firehose까지 데이터가 안정적이고 꾸준하게 전달 될 수 있도록 도와줍니다.  따라서 firehose와 fluentd의 연동을 통해서 따로 두개의 파이프라인 ( SERVER -> S3, S3 -> Redshift) 을 관리할 필요 없이 데이터 소스부터 최종 저장소까지 이어지는 하나의 파이프 라인만 관리할 수 있게 됩니다. How?  (https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html)  적절한 data format과 원하는 ingestion period를 설정하여 Firehose delivery stream을 만듭니다.   conf["user_activity"] = { "DataTableName": "user_activity", "DataTableColumns": "user_id, app_id, activity_type, timestamp", "CopyOptions": "FORMAT AS JSON "s3://buzzvil-firehose/sample/user_activity/jsonpaths/user_activity_log-0001.jsonpaths" gzip TIMEFORMAT AS "YYYY-MM-DDTHH:MI:SS" ACCEPTINVCHARS TRUNCATECOLUMNS COMPUPDATE OFF STATUPDATE OFF", "jsonpaths_file": "buzzvil-firehose/sample/user_activity/jsonpaths/user_activity_log-0001.jsonpaths", } configuration = { "RoleARN": "arn:aws:iam::xxxxxxxxxxxx:role/firehose_delivery_role", "ClusterJDBCURL": "jdbc:redshift://buzzvil.xxxxxxxxx.us-west-2.redshift.amazonaws.com:5439/sample_db", "CopyCommand": { "DataTableName": sample_table, "DataTableColumns": conf[type]["DataTableColumns"], "CopyOptions": conf[type]["CopyOptions"], }, "Username": db_user, "Password": db_password, "S3Configuration": { "RoleARN": "arn:aws:iam::xxxxxxxxxxxx:role/firehose_delivery_role", "BucketARN": "arn:aws:s3:::firehose_bucket", "Prefix": "buzzvil/user_activity/", "BufferingHints": { "SizeInMBs": 64, "IntervalInSeconds": 60 }, "CompressionFormat": "GZIP", "EncryptionConfiguration": { "NoEncryptionConfig": "NoEncryption", } } }  2. Fluentd docker containers을 각각의 서버에서 세팅하고 실행합니다.  @type tail path /var/log/containers/buzzad/impression.json pos_file /var/log/containers/td-agent/impression-json.pos format none tag firehose.impression @type kinesis_firehose region us-west-2 delivery_stream_name "prod-buzzad-impression-stream" flush_interval 1s data_key message  3. Firehose에서 데이터를 잘 모아서 Redshift 문제없이 보내고 있는지 모니터링 합니다.  Pros?  빠르고 안정적인 데이터 전송이 가능합니다. 모니터링이 편합니다.  Cons?  Schema가 자동으로 바뀌지 않습니다.( Redshift의 Schema를 수동으로 일일히 변경해주어야 합니다.)     3) MySQL Asynchronous Loads를 통해 (Ads, Contents, Ad Provider, Ad Publishers) Why? 여러대의 RDS MySQL DB로부터오는 데이터간의 sync를 맞춰가며 Redshift로 데이터를 복제하기 위해서는 3가지의 테크닉을 활용해야만 합니다. (이 방법은 소개하고 있는 세 메인 루트 중에서 가장 매력도가 떨어지는 방법입니다..) How?  FULL_COPY  MySQL 테이블 전체를 복사해서 SQL insert를 통해서 Redshift에 복사합니다.     INCREMENTAL_COPY  이전에 복사한 가장 마지막 Primary key부터 시작해서 새로생긴 row들을 읽어서 Redshift로 복사합니다.     UPDATE_LATEST_COPY  이전에 복사한 가장 마지막 타임스탬프부터 시작해서 새로 생성되거나 업데이트된 row들을 Redshift로 복사합니다.(중복된 값은 삭제).    Pros?  데이터의 특징에 맞게 잘 조정된 방법입니다. binary log를 통한 Replication보다 훨씬 다루기 쉽습니다.  Cons?  MySQL을 잘 조정하기 위해 여러대의 서버나 lambda를 다루어야만 합니다. -> Redshift sync task를 위해서 안정적인 schema altering을 할 수 있을 만큼 Redshift의 ORM이 발전된 상황은 아닙니다..    어떤 데이터를 다루는지에 따라서 위에서 소개한 3가지 방법 중 어떤 방법을 활용해야할지가 달라진다고 할 수 있습니다. 예를 들어 Transactianl log 같은 데이터들의 경우에는 firehose를 통해 전달하는 방법이나 먼저 aggregate하는 과정을 거친 후에 Redshift에 저장하는 식으로 처리를 해야 합니다. 그리고 MySQL에 저장된 fact table같은 데이터들은 CDC (change data capture) sync method를 통해서 Redshift에 데이터를 전달하고 동기화를 하는 과정이 필요합니다. 버즈빌에서는 위에서 소개해드린 3가지 방법을 적절히 조합해가면서 BD 매니저나 애널리스트들이 서비스간 플랫폼간의 데이터분석을 쉽게 할 수 있는 데이터 환경을 구축하기 위해서 노력하고 있습니다.
조회수 9059

왜 SQLite 에서 Realm 으로 옮겼는가?

SQLite 와 Realm잔디 앱은 2015년 중반부터 앱 내에 Offline Caching 기능이 포함되면서 본격적으로 Local-Databae 를 사용하기 시작했습니다.당시에 Realm 과 SQLite 를 검토하는 과정에서 다음과 같은 사유로 Realm 을 포기하였습니다.1.0 이 아직 되지 않은 미성숙된 상태의 라이브러리사용 사례에서 리포팅되는 버그들 (CPU 지원 등)Data 의 상속을 지원하지 않는 문제Robolectric 미지원 (안드로이드 팀 당시 테스트 프레임웍은 Robolectric 이었으며 현재 Android Test Support Library 입니다.)위의 문제로 인해 SQLite 를 선택하였고 여러 SQLite-ORM Library 를 검토한 후 ORMLite 를 선택하였습니다.누구보다 가볍고 빠르게2016년 6월경 앱의 핵심 데이터에 대해 개선작업이 되면서 그에 따라 기존의 Cache Data 로직도 많은 부분이 변경되었습니다. 그에 따라 실시간성으로 DB 를 대상으로 Read-Write 동작이 발생하게 되었습니다. Locking 등에 대한 처리가 되면서 성능에 대한 이슈가 계속적으로 발생할 수 밖에 없었습니다.간헐적인 성능 이슈는 사용자에게 나쁜 UX 로 다가갈 수 있기 때문에 다음과 같은 병목지점들에 대해 성능 향상을 꾀하였습니다.서버와의 통신 향상비지니스 로직 개선내부 DB 로직 향상서버와의 통신 향상병목 지점이 되는 것으로 판단되는 API 를 찾아 원인을 분석하여 개선요청을 서버팀에서 개선할 수 있도록 하였습니다.비지니스 로직 개선불필요한 객체 생성, 비동기로 처리해도 되는 동작들에 대해서는 로직 수정, 최소한의 검증 후에만 앱 실행, 네트워크 동작 최소화, 캐싱 활용 등 다양한 전략을 시도하였습니다.내부 DB 로직 향상SQLite 를 대상으로 빈번한 쿼리 작업을 최소한으로 하기 위해 2~3개의 쿼리로 이루어진 부분에 대해서 최소한의 쿼리만으로 동작하도록 여러 시도를 하였습니다.ORMLite 의 한계점ORMLite 를 대상으로 여러가지 시도를 하였습니다. 쿼리를 최소한으로 하고 1:N, N:M 동작에 대해서 로직 중간에 Query 가 발생하지 않도록 애초에 Join Query 를 하도록 하는 등 여러가지 전략을 시도하였으나 궁극적으로 ORMLite 자체에 대한 성능을 개선하는 것은 불가능하다는 결론이 도출하였습니다.여러 시도를 하였으나 고작 10~20% 정도의 성능향상밖에 없었으며 이는 사용자 관점에서 여전히 느릴 수 있다고 느끼기 충분한 수준이었습니다. 기존에 목표했던 100ms 이하의 쿼리를 기대하기엔 어려운 상황이었습니다.그래서 GreenDAO, Requery 라이브러리를 검토하였습니다.GreenDAO 의 문제점GreenDAO 를 검토하는 과정에서 겪은 가장 큰 문제점은 실제 Object 코드에 GreendDAO 코드가 생성이 붙으면서 유지보수에 큰 걸림돌이 될 수 있다는 것이 예상되었습니다.Requery 의 문제점성능면에서 ORMLite 에 비해서 큰 개선을 가져오지 못했습니다. Requery 는 JPA 를 가장 잘 채용한 것으로 알려져 있지만 그렇다고 SQLite 자체의 성능을 극적으로 개선했다고 보기엔 어려운 부분들이 있었습니다.SQLite vs RealmSQLite 가 가진 자체적인 성능 이슈를 SQLite 기반 라이브러리 범위안에서는 개선할 수 없다는 결론에 도달하였습니다.검토 방법 : 기존의 Object 를 대상으로 ORMLite 와 Realm 을 대상으로 성능을 검토합니다.데이터는 1:N / 1:1 관계가 되어 있는 여러 Object 의 집합으로 구성되어 있다.Database 에서 데이터를 가져올 때는 Eager Loading 방식으로 택한다.Write : 20회, Read : 20회 를 수행했고 그에 대한 평균 성능을 비교한다. SQLiteRealm성능 향상Write4039ms1142ms3.5xRead6010ms2450ms2.5x(Realm 의 벤치마크 정보와 너무 상이하여 재테스트한 결과 수정하였습니다.)위의 비교차트에서 봤듯이 Realm 은 무시무시한 성능이 입증되었습니다.도입 검토시에 Realm 버전은 2.0 이었기 때문에 충분히 신뢰할 수 있을 만큼 성숙되었다고 판단하고 최종적으로 도입을 결정하였습니다.Realm 도입 과정에서 문제점Realm 을 도입한다고 해서 여전히 잠재적인 문제가 해결된 것은 아니었습니다.파악된 다음 문제를 해결 해야 했습니다.Primitive 타입에 대해 Collection 저장을 지원하지 않는다.RealmObject 에 대한 호출 Thread 를 유지해야 한다.상속을 지원하지 않는다.Primitive 타입에 대한 Collection 관리를 해결하기이 문제는 ORMLite 에서 이미 겪었기 때문에 의외로 쉽게 구할 수 있었습니다. long, int 등에 대한 Wrapper 를 만들고 Json Convert 등의 과정에서 Post Processing 과정에서 Wrapper 로 데이터를 이관하도록 처리하였습니다.// example class Data extends RealmObject { private transient List refs; private List refIds; } class RealmLong extends RealmObject { private long value; } RealmObject 에 대한 호출 Thread 분리Realm 은 Object 에 대해 query 후 객체를 받는다 하더라도 실제로 객체 내 데이터르 접근할 때는 다시 Query 로 접근하기 때문에 실제로 Object 전체에 대해서 Eager Loading 방식으로 접근해야 합니다.Jandi 는 싱글톤 객체를 통해 데이터베이스에 접근하며, Background Thread 에서 진행하고 UI Thread 에서 객체 내 변수에 접근해서 UI 에 그리는 작업이 빈번하기 때문에 Thread 독립을 반드시 해야했습니다.Realm 에서는 Eager-Loading 을 지원하고 있습니다. Realm.copyFromObject() 를 사용하면 Return 값이 Eager-Loading 된 Object 가 반환됩니다.단, Realm 의 가장 큰 특징이로 보는 ZeroCopy 를 포기하는 것이기 때문에 신중하게 생각해야 합니다.// example public Chat getChat(long chatId) { return execute((realm) -> { Chat it = realm.where(Chat.class) .equalTo("id", chatId) .findFirst(); if (it != null) { return realm.copyFromRealm(it); } else { return null; } }); } 상속을 지원하지 않는다.가장 큰 문제였는데 해결방법을 찾을 수 없어 결국 상속을 포기하고 모든 Data 를 1개의 Object 에 표현하기로 하였습니다.위의 3가지 문제를 이렇게 해결해서 안드로이드팀에서는 1차적으로 도입을 완료하였습니다.결론현재까지 Realm 전환에 있어서 성공적인 도입으로 판단되어 차후에 다른 데이터에 대해서도 하나씩 DB 이전을 할 예정입니다.Realm 은 이제 충분히 신뢰할 수 있을만큼 성숙되었다고 생각이며 Realm 에서 처음부터 강조하던 성능또한 믿기 어려울 정도로 빨라졌습니다. 더 빠른 Mobile Database 를 원하신다면 Realm 을 적극 추천합니다.#토스랩 #잔디 #JANDI #개발 #개발환경 #업무환경
조회수 13593

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

스포카에서 다년간 일하면서 나에게는 몇 가지 별명이 생겼다. 그 중 하나는 봇맘(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년 전 스포카의 슬랙에서 활발히 쓰였다가 현재는 잘 사용되지 않는 경우도 있다. ↩#스포카 #개발 #개발자 #사내문화 #조직문화 #인사이트 #꿀팁
조회수 1049

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

 DevOps의 시작언제나 그랬듯이 소프트웨어 개발 트렌드는 계속 변화하고 있다. A부터 Z까지 모든 것을 새롭게 개발했던 것과 달리 아키텍처나 사용하는 용도에 따라 개방형 플랫폼이나 오픈소스 등을 활용하여 원하는 소프트웨어를 쉽게 개발할 수 있게 되었다. 또한 클라우드로 인해 애플리케이션과 서비스 개발에 대한 새로운 패러다임이 나타나고 있다. 기존의 온-프레미스 환경에서는 물리적 서버 준비, 운영체제 설치, 서비스 배포 등에 수많은 시간이 걸렸지만, 클라우드를 활용하면서 단시간에 원하는 자원을 준비하고 배포할 수 있게 되었다.이러한 변화로 개발자의 영역이 좀 더 넓어지는 계기가 되었다. 이는 전통적인 비즈니스 환경에서 개발, 빌드, 테스트, 배포, 운영에 이르는 프로세스를 효율적으로 운용할 수 있게 되어 고객의 요구사항을 빠르게 반영할 수 있게 되었다. 이것이 바로 DevOps의 시작이다. 하지만 다양한 오픈소스의 탄생과 클라우드 환경의 확산 등으로 인해 정말로 새로운 기능에 대한 개발이 빨라졌을까? 그렇다면 이에 따른 문제는 없을까? 개발 프로세스의 병목 구간DevOps의 필수 조건인 테스트 및 배포의 자동화가 이뤄지면 운영 단계에서는 반영된 사항들에 대해 주기적으로 모니터링을 해야 한다. 만약에 반영된 소스코드에 장애를 발생시킬 수 있는 잠재적 버그가 존재한다면 이를 어떻게 운영 단계에서 찾을 수 있을까? 예를 들어 특정 서비스의 피크타임에 부하가 급증한다면 앞서 말한 상황에 대한 버그가 발생할 확률이 상대적으로 높아진다. 하지만 장애의 원인이 될 수 있는 요소는 매우 다양하기 때문에 단순히 트래픽 문제로 속단할 수는 없다.직접 개발한 소프트웨어만의 문제가 아닐 수도 있으며, 제품 개발시 생산성 향상을 위해 도입된 다른 종류의 오픈소스에서 문제가 될 수도 있다. 실은 이런 류의 프로젝트들은 상용 제품이 아니므로 문제가 발생하면 상당히 곤란한 경우가 생기곤 한다. DevOps를 위한 환경이 구성되고, 고객의 요구사항을 빠르게 반영할 수 있는 시스템이 갖춰졌더라도 결국에는 앞서 말한 다양한 종류의 잠재적, 환경적인 문제들로 인해 병목이 발생할 수 있다.  모니터링 단계에서 APM의 역할개발 프로세스의 마지막 관문인 모니터링 단계는 DevOps에서 매우 중요한 역할을 한다. 하지만 안타깝게도 이미 반영된 실제 서비스에서 모니터링을 성공적으로 마치고 피드백 수집 단계로 넘어가기 위해서는 앞서 말했던 장애의 원인을 빠르게 진단해야 한다. 경우에 따라 많은 시간이 소모되기도 하기도 하며, 이는 바로 생산성 저하로 이어진다. 또한 새로운 프로세스 진행을 더욱더 보수적으로 만드는 원인이 된다.DevOps를 완벽하게 실현하기 위해서는 모니터링 단계에서 서비스 배포 이후의 서버에 들어오는 트랜잭션에 대한 상태를 배포 전과 비교할 수 있어야 하며, 응답을 지연시킬만한 요소들을 빠르게 인지할 수 있어야 한다. 그리고 배포된 소스코드로 인해 서비스 장애가 발생하는 상황이 온다면 이를 처리하기 전까지 어떻게든 서비스 장애를 지연시켜야만 한다. 이러한 이유로 DevOps 진영에서는 APM의 역할은 매우 중요한 이슈이다. 우리는 제니퍼를 통해 앞서 말한 기능들을 활용하는 방법에 대해 알아볼 것이다. 모니터링 프로세스모니터링 단계는 아래 그림과 같이 문제의 발견 및 조치, 문제해결시 재배포 단계로 나눌 수 있다.  제니퍼 대시보드를 통해 액티브서비스 상태와 트랜잭션 변화 추이를 모니터링 할 수 있는데, 만약에 새로 배포된 소스코드에 문제가 있다면 처리 중인 액티브서비스가 쌓이게 되고 , 트랜잭션 분포도 차트는 기존에 그려졌던 패턴과 다르게 보여지게 된다.이런 시점에 운영에서는 설정 여부에 따라 이벤트를 발생 시킬 수 있다. E-Mail이나 SMS, Slack과 같은 메신저 등으로 각각의 담당자들에게 서비스 상태를 알려줄 수 있으며, 담당자에게 이벤트 메시지가 전달되었다면 제니퍼를 통해 두가지 조치를 할 수 있게 된다. 먼저 개발자는 스마트 프로파일링 기능을 통해 원인분석을 하고, 운영에서는 서비스가 최악의 상태가 되기 전에 트랜잭션 유입을 차단하여 다른 화면으로 리다이렉트 시켜주는 PLC 기능을 사용할 수 있다.제니퍼에서는 서버에서 하나의 요청에 대한 처리가 끝나면 곧바로 수집되는 데이터를 트랜잭션이라하며, 현재 수행 중인 상태에 대한 실시간 데이터를 액티브서비스라고 정의한다.   모니터링 기준 값 설정서비스를 배포하기 전에 모니터링 단계를 원활하게 수행하기 위해서는 제니퍼 관리 화면에서 몇가지 설정을 해야한다. 먼저 서비스 장애 발생시 이벤트 알림 및 서비스 부하량 제어 설정의 기준이 되는 값인 전체 에이전트의 평균 액티브서비스 개수를 알아야 한다. 하지만 서비스가 운영되는 환경에 따라 기준 값이 너무 다르기 때문에 어느 정도 안정적으로 서비스가 운영되고 있다고 생각하는 시점에 대략적으로 기준 값을 정하면 된다.에이전트란 모니터링 대상 애플리케이션에 기생하여 성능 데이터를 수집하고, 이를 서버로 전송하는 역할을 하는 모듈을 말한다. 참고로 모니터링 대상 애플리케이션은 플랫폼 환경에 따라 차이가 있을 수 있는데, 일반적으로 WAS(Web Application Server)나 웹 서버를 말한다.  액티브서비스는 처리가 완료되지 않은 상태이므로 서비스 장애의 원인분석을 위한 데이터로는 적합하지 않다. 그렇기 때문에 액티브서비스 개수는 기준 값이 될 수 없으며, 개발자는 처리가 완료된 트랜잭션 데이터의 응답시간을 기준 값으로 제니퍼의 프로파일링 관련 설정을 해야 한다. 설정된 값을 기준으로 트랜잭션 분포도 차트에서 가상의 선을 긋고, 그 선 위에 있는 트랜잭션을 대상으로 스마트 프로파일링 기능을 수행할 수 있다.  본문에서는 모니터링 단계에서 직면하게 되는 문제점과 이를 해결하기 위한 APM의 역할과 필요성 대한 이야기를 했다. 다음 편에서는 본격적으로 제니퍼를 활용하여 모니터링 프로세스를 어떻게 수행하는지에 대해 알아볼 것이다.2편에서 계속...
조회수 961

[Tech Blog] Software architecture: The important stuff

마틴 파울러는 Software architecture 를 “무엇이건 간에 중요한 것들(The important stuff whatever it is)” 이라고 정의합니다. 조금은 재미있는 정의지만, 그 정의를 도출하기 위해 제시한 다른 정의를 들어보면 고개를 끄덕이게 합니다.  Software architecture 는 전문 개발자들이 같은 생각을 가지고 이해하는 시스템 디자인입니다. Software architecture 는 이른 시기에 정해져야 하는 디자인 결정들입니다. 혹은 여러분이 “아, 처음부터 좀 더 잘 생각하고 할 껄”이라고 후회하는 바로 그 결정들입니다. Software architecture 는 또한 바꾸기 어려운 결정들의 집합입니다.  결국 무엇을 중요하게 생각할 것인가, 그것이 Software Architecture 라는 의미입니다. Why is it important? 왜 중요한지 설득하지 못한다면 사실 중요하지 않은 것일지도 모르죠. 그래서 왜 Software Architecture 이 중요한지 짚어보고자 합니다. 쿠팡은 Microservice architecture 로 전환하는 여정을 글로 남겼는데요. 블로그 글의 제목을 “행복을 찾기 위한 우리의 여정” 이라고 지었습니다. (좋은 글이니 읽어보시길!) 다시 말해서, Software Architecture는 개발가자 더 좋은 제품을 만들 수 있는 길이기 때문에 중요하다고 말합니다. 그러나 좋은 Software Architecture를 만드는 일은 쉽지 않습니다. 블로그 글을 인용 해보겠습니다: “여기 저렴한 제품과 비싼 제품이 있습니다. 비싼 제품은 software architecture 가 잘 고려되어 있고, 저렴한 제품은 시스템 디자인에 대한 고민 없이 구현되어 있습니다. 하지만 두 제품은 겉으로 보기에 차이가 없습니다. 소비자가 보기에 똑같이 보이고, 똑같은 기능이 있으며, 성능 또한 같습니다. 어떤 제품을 사야할까요?” 소비자는 제품을 만든 개발자의 행복을 위해 더 비싼 제품을 선택하지는 않습니다. 개발자 역시 동료들에게 “내가 행복하려면 시간과 돈이 좀 더 들더라도 좋은 software architecture 를 구성해야 해.” 라고 주장하기엔 설득력이 부족하죠. Software architecture 가 왜 중요한지 모두가 공감하려면 경제적인 입장에서 그 중요성을 설득해야 합니다. “내부 품질을 좀 포기하더라도 이번 릴리즈에 더 많은 기능들이 들어가야 해.” 라는 의견에 “안돼 우리(개발자)는 더 전문적으로 구성해야 해.”라는 의견으로 대응하면 항상 질 수 밖에 없습니다. 장인 정신과 경제 논리 사이의 싸움에서는 경제 논리가 항상 이겨왔거든요.   Cumulative functionality over Time Software architecture 를 고려하지 않으면서 제품을 개발하면 초기에는 기능 추가 속도가 빠를 수 있지만, 시간이 흐름에 따라 제품의 기능 증가 속도는 점차 느려집니다. 이미 구현된 기능들과 코드가 새로운 기능을 추가하는데 걸림돌이 되기 때문입니다. 한편, 좋은 설계를 지속적으로 건강하게 유지하고, 주기적으로 리팩토링을 하고, 코드를 깨끗하게 유지한다면 시간이 흘러도 기능 추가가 느려지지 않을 수 있습니다. 오히려 기능을 추가하기 위해 수정해야 할 곳들이 명확하고 모듈화 또한 잘 되어있기 때문에 시간이 갈 수록 기능 추가가 더욱 빠르게 진행될 수 있습니다. 새로운 개발자가 참여하는 시점에도 시스템을 더욱 빠르게 이해하고, 더 빠르고 안전하게 기능을 추가할 수 있게 됩니다. 결국 장기적으로 더 많은 기능을 생산하고 빠르게 고객에게 전달하기 위해서 개발팀은 좋은 디자인과 설계에 대해 깊게 고민해야 합니다. What is the best software architecture? 옳은 software architecture 는 없습니다. 상황에 따라 해답은 다를 수 있습니다. Microservice architecture 가 좋다고 해서 모든 것에 대한 답이 microservice architecture 인 것은 아니고, 마찬가지로 어떤 시스템이 monolithic architecture 로 구현되어 있다고 해서 뒤쳐져 있는 것도 아닙니다. 모든 선택에는 Tradeoff 가 있기 마련이니까요. 유선 통신 시스템을 구성한다고 생각해 볼까요? 우리 나라처럼 인터넷이 잘 구성된 상황에서 Skype 로 할 수 있는 통화는 무료이고, 품질도 좋고, 영상 통화까지 됩니다. “Skype 만세! 인터넷을 통한 통신이 항상 옳습니다!” 라고 외치려던 시점에 정전이 되었습니다. 방금 외친 외침은 멀리 가봐야 옆집 정도 닿겠죠. 한편 기존 유선 전화 시스템은 느리고 화상 통화도 안되지만, 전화선 자체에 전원이 공급되고 있기 때문에 정전 시에도 통화가 가능합니다. 전쟁 상황이나 기타 재난 등에도 반드시 통신이 가능해야 하는 곳은 유선 전화 시스템이 꼭 필요할 것 같습니다. 은행 시스템도 적절한 예시가 될 수 있습니다. 비밀번호 입력, 전화 인증, OTP 확인하는 등 은행 업무는 왜이리도 복잡할까요? 그냥 비밀번호 기억해주고 로그인 유지해주면 참 편할텐데 말이죠. 안전하기 위해서겠죠. 여러분의 자산은 소중하니까요. 사용성(Usability)과 안전성(Security)은 종종 둘 사이를 조절해야 하는 Tradeoff 입니다. 만들려는 제품과 시스템, 환경, 시기와 조건 등에 따라서 적절한 architecture 는 달라집니다. 좋은 architecture 를 선택할때 개발자는 선택한 것의 대척점에 있는 무언가를 포기 해야합니다. 그렇기에 software architecture 는 기술적인 범주 안에서만 고려되면 안되고, 구현하고자 하는 비지니스를 매우 잘 이해하고 고려해서 적용해야 합니다. What are you going to do? 이미 구성된 software architecture 를 변경하는 것은 굉장히 어렵습니다. 이미 구성되어 있는 것들을 상세하게 알고 있어야 하고, 비지니스의 요구 사항을 수용해야 하며, 이미 존재하는 기능이 변경 도중 문제 없이 동작해야 합니다. 또한 기존 시스템에 기여한 개발자들과 변경 사항에 대한 공감대를 이뤄야 하며, 겉으로 보기에 당장 변화가 없는 것에 대한 비용에 대해 많은 사람들을 설득해야 합니다. 최근 Buzzvil 에서는 Architecture Task Force 팀을 구성하였습니다. 이를 통해 전체적인 설계를 정비하고 모든 개발팀이 구조적으로 같은 이해를 할 수 있도록 분석, 조사, 계획 수립, 실행에 옮길 예정입니다. 지속적인 공유를 통해 전사적인 공감대를 유지하고 체계적인 문서화와 가이드라인을 통해 모든 팀원이 함께 실행하며 성장할 수 있는 기반을 준비하게 될 것입니다. 궁극적으로 전사 프로젝트와 모든 팀이 더욱 빨리 움직일 수 있는 software architecture 를 구성하고, 이를 통해 더 많은 기능을 더 빠르게 전달할 수 있게 할 것입니다. 아직 해야할 일들이 많이 남아있지만 제대로 계획하고 빠르게 움직인다면 충분히 좋은 결과를 만들 수 있을 것 같습니다. 당장은 눈에 보이는 변화가 없을지라도, 좋은 디자인에 대한 고민과 실행이 우리가 궁극적으로 바라는 비전과 목표에 한 걸음 더 빠르게 다가가는 올바른 길이라고 믿습니다.   *버즈빌에서 개발자를 채용 중입니다. (전문연구요원 포함)작가소개 Whale, Chief Architect “Keep calm and dream on.”
조회수 4071

[Tech Blog] Go 서버 개발하기

Go 서버 개발을 시작하며   특정 API만 다른 언어로 구현해서 최대의 성능을 내보자! 저희 서버는 대부분 Django framework 위에서 구현된 광고 할당 / 컨텐츠 할당 / 허니스크린 앱 서비스 이렇게 나눌 수 있는데 Python 이라는 언어 특성상 높은 성능을 기대하기가 어려웠습니다. 하지만 세가지 서비스에서 락스크린에서 어떤 컨텐츠나 광고를 보여줄지 결정하는 Allocation(할당) API 가 가장 많이 호출되고 있었는데 빈도로 보면 80% 정도로 높은 비중을 차지하고 있어서 이 Allocation API 들을 성능이 좋은 다른 언어로 구현하면 어떨까 하는 팀내 의견이 있었습니다. Why Go? 저는 예전부터 Java,  C# 등의 컴파일 언어에 익숙해서 기존 Java 와 C, 그리고 Go 라는 최근에 새로 나온 언어 중에서 아래 블로그글과 같이 여러 reference 들을 통해 성능이 좋다는 Go 로 이 API 들을 포팅하는 작업을 시작하게 되었습니다. Go 에 대한 첫 인상은 Java, C계열 언어보다 덜 verbose 보였고 python 보다는 strongly-typed, encapsulated 하다보니 자유도를 제한해서 코드를 보기 쉽게 하는 것을 선호하는 저의 성격과도 잘 맞는 언어였습니다.     출처: Carles Mateo, Performance of several languages서버 개발 환경   Server design How to import libraries  GVT (https://github.com/FiloSottile/gvt) – Go 는 vendering tool 을 통해 dependency 를 관리할 수 있습니다. GVT 의 경우 처음 도입했을 때 별로 유명하지 않았는데 사용법이 간단해서 도입하게 되었습니다. 아래와 같이 참조하고 있는 revision 을 관리해주며 update 통해서 최신 소스를 받아 올수 있습니다.   { "version": 0, "dependencies": [ { "importpath": "github.com/Buzzvil/go-env", "repository": "https://github.com/Buzzvil/go-env", "vcs": "git", "revision": "2d8489d40184a12c4d09d09ce1ff717e5dbb0745", "branch": "master", "notests": true }, ....  Design pattern  Go 언어에서는 package level cycling dependency 를 허용하지 않아서 좀더 명확한 구조를 만들기 좋았습니다. 예를들어 Service 에서는 Controller 를 참조할수 없고 Model 에서는 Controller / Service / DTO 등을 참조할수 없도록 강제했습니다. 모든 API 요청은 Route 를 통해 Controller 에게 전달되고 이 때 생성된 DTO (Data transfer object) 들을 Controller 가 직접 혹은 Service layer 에서 처리하도록 하였고 DB 에 접근할 때는 모델을 통해 혹은 직접 접근하도록 했지만 추후 구조가 복잡해지면 DB 쿼리 등을 담당하는 DAO (Data access object) 를 도입할 계획입니다   Libraries                  요소이름선택 이유NetworkGinWeb 서버이다 보니 네트워크 성능을 최우선으로 고려, 벤치마크 표를 보고 이 라이브러리를 선택Redis & cachego-redis역시 성능을 가장 중요한 지표로 보고 이 라이브러리 선택MysqlGormORM 없이는 개발하기 힘든 시대이죠. 여러 Database를 지원하고 ORM 중에서도 method chaining 을 사용하는 Gorm 을 선택Dynamoguregu dynamoAWS에서 제공하는 Dynamo 패키지를 그대로 사용하면 코드 양이 너무 많아지고 역시 method chaining 을 지원해서 선택Environment variablescaarlos0 envGo 에서는 tag 를 이용하면 좀더 코드를 간결하고 읽기 쉽게 사용할수 있는데 이 라이브러리가 환경변수를 읽어오기 쉽도록 해줌   Redis cache  func SetCache(key string, obj interface{}, expiration time.Duration) error { err := getCodec().Set(&cache.Item{ Key: key, Object: obj, Expiration: expiration, }) return err } func GetCache(key string, obj interface{}) error { return getCodec().Get(key, obj) }  Mysql  var config model.DeviceContentConfig env.GetDatabase().Where(&model.DeviceContentConfig{DeviceId: deviceId}).FirstOrInit(&config)  Dynamo if err := env.GetDynamoDb().Table(env.Config.DynamoTableProfile).Get(keyId, deviceId).All(&profiles); err == nil && len(profiles) > 0 { ... }  Environment variables  var ( Config = ServerConfigStruct{} onceConfig sync.Once ) type ( ServerConfigStruct struct { ServerEnv string `env:"SERVER_ENV"` LogLevel string .... } ) func LoadServerConfig(configDir string) { onceConfig.Do(func() {//최초 한번반 호출되도록 env.Parse(&Config) } }    Unit test   환경 구성 Test 환경에는 Redis / Mysql / Elastic search 등에 대한 independent / isolated 된 환경이 필요해서 이를 위해 docker 환경을 따로 구성하였습니다. Test case 작성은 아래와 같이 package 를 분리해서 작성했습니다.  package buzzscreen_test var ts *httptest.Server func TestMain(m *testing.M) { ts = tests.GetTestServer(m) // 환경 시작 tearDownElasticSearch := tests.SetupElasticSearch() tearDownDatabase := tests.SetupDatabase() code := m.Run() // 여기서 작성한 TestCase 들 실행 // 환경 종료 tearDownDatabase() tearDownElasticSearch() ts.Close() os.Exit(code) }  Mock server는 은 http.RoundTripper interface 를 구현해서 http.Client 의 Transport 멤버로 설정해서 구현했습니다. 아래는 Test case 작성 예제입니다.  httpClient := network.DefaultHttpClient mockServer := mock.NewTargetServer(network.GetHost(MockServerUrl)) .AddResponseHandler(&mock.ResponseHandler{ WriteToBody: func() []byte { return []byte(mockRes) }, Path: "/path", Method: http.MethodGet, }) clientPatcher := mock.PatchClient(httpClient, mockServer) defer clientPatcher.RemovePatch()  Unit test 관련해서는 내용이 방대해서 추후 다른 포스트를 통해 자세히 소개하도록 하겠습니다.  Infra API 요청 분할 AWS Application load balancer 여러 API 중에서 할당 API 를 제외한 요청은 기존의 Django 서버로 요청을 보내고 할당요청에 대해서만 Go서버로 요청을 보내도록 구현하기 위해 먼저 시도 했던 것은 AWS Application load balancer (이후 ALB) 였습니다. ALB 의 특징이 path 로 요청을 구별해서 처리할수 있었기 때문에 Allocation API 만 Go 서버 로 요청이 가도록 구현했습니다.  출처: Amazon Devops Blog, Introducing Application Load Balancer   하지만 이렇게 오랫동안 서비스 하지 못했는데 그 이유는 서버 구성이 하나 더 늘어나고 앞단에 ALB 까지 추가되다 보니 이를 관리하는데 추가 리소스가 들어가게 되어서 어떻게 하면 이러한 비용을 줄일수 있을까 고민하게 되었습니다.   Using docker & nginx  Go로 작성된 서버가 독립적인 Micro service 냐 아니면 Django 서버에서 특정 API 를 독립시켜 성능을 강화한 모듈이냐 의 정체성을 두고 생각해봤을때 후자가 조금더 적합하다보니 Go / Django 서버는 한 묶음으로 관리하는 것이 명확했습니다. Docker 를 도입하면서 nginx container 가 proxy 역할을 하고 path를 보고 Go container / Django container 로 요청을 보내는 구성을 가지게 되었습니다.  글을 마치며   시작은 미약하였으나 끝은 창대하리라 하나의 API를 이전했음에도 불구하고 Allocation API 에 대해서는 약 1/3, 서버 Instance 비용은 1/2.5 수준으로 감소했습니다.   설명: 기존 4개의 Django 인스턴스의 CPU 사용률이 모두 13% 정도 감소, Go 인스턴스의 CPU 사용율은 17% 정도   17 / (13 * 4)  ≒ 1 / 3  충분히 만족할만한 성과가 나와서 그 뒤로 몇가지 API도 Go 로 옮겼고 새로 작성하는 API 는 Go 환경 안에서 직접 구현하는 중입니다. 처음에는 호출이 많은 하나의 API 를 다른 언어로 포팅하기 위해 시작한 작업이었는데 Container 기술을 도입하는 등 서버 Infra 까지 변경하면서 상당히 큰 작업이 뒤따르게 되었습니다. 하지만 이 작업을 하면서 많은 동료들의 도움과 조언이 있었고 결국 완성할수 있었습니다. 이렇게 실험적인 도전을 성공 할수 있는 환경에 여러분을 초대하고 싶습니다! Go언어에 대한 문의나 좋은 의견도 환영합니다.
조회수 2836

Node.js를 배우기 시작하다

안드로이드 개발자인 내가 항상 필요하다고 갈구하는 부분은 백엔드 개발이었다.기획에서부터 디자인, 안드로이드 개발까지는 혼자 진행하지만 대부분의 서비스에서 필요로 하는 서버를 전혀 다루지 못했기 때문에 혼자서 진행할 수 있는 프로젝트는 유틸성 어플리케이션까지로 굉장히 한정적이었다.그래서 매번 개인 프로젝트를 기획할 때마다 백엔드 개발의 필요성을 느꼈고 이제야 시작해보려고 한다.'안드로이드는 앱을 개발하기 위해서 배워야 하는 언어와 개발 툴은 Java와 Android Studio다.'라고 말할 수 있을 정도로 선택의 폭이 넓지 않은 것에 비해 (최근에서야 코틀린이나 리엑트 등이 생겨나 선택권이 많아 지긴 했지만 웹이나 서버에 비한다면..) 서버는 너무나 방대한 선택지에서부터 어려웠다. 그래서 검색과 주변의 추천을 통해 선택지를 추려나갔는데 주변에 물어보는 족족 Node.js(이후 '노드'로 통칭)를 언급하길래 어느 정도 노드로 가야겠구나 마음먹고 어떤 언어인지 알아보았다.먼저 노드의 장점이다.1. 노드의 가장 특징적인 부분인 이벤트 기반 비동기 방식으로 단 하나의 스레드만 생성하여 일을 처리한다. 그러므로 메모리와 같은 시스템 리소스 사용량에 큰 변화가 없어 대규모 네트워크 프로그램을 개발하기 적합하다.-> 사실 이 장점에 있어서는 아직 내가 서버 개발을 했던 사람이 아니기에 얼마나 큰 장점인지 체감되지는 않는다.2. 자바스크립트를 사용하여 개발할 수 있다.-> 이 부분이 내가 노드를 택하게 한 가장 큰 이유다. 이게 왜 큰 이유냐고 할 수 있겠지만 최근 자바스크립트 언어를 이용한 굉장히 다양한 프레임워크들이 등장하고 있다. 어차피 웹 개발이나 하이브리드 어플리케이션 개발을 시작할 때 배워야 하는 언어이기에 이왕 배울 거 활용성 높은 언어가 좋지 않은가. 효율을 가장 중시하는 나에게는 가장 큰 장점으로 느껴졌다.3. 노드는 구글이 만든 자바스크립트 엔진인 V8을 사용한다.-> 브라우저들끼리 경쟁하며 자바스크립트 엔진 속도를 발전시키는 과정에 있으며 구글 또한 V8 자바스크립트 엔진 속도를 위해 노력하고 있다. 이번엔 노드의 단점이다.1. 하나의 스레드만을 사용하기 때문에 하나의 작업이 지연된다면 시스템 전체의 성능이 저하된다.2. 에러가 발생할 경우 프로세스 자체가 죽어버리므로 주의해야 한다.아직 잘 모르기 때문에 얼마나 크리티컬 한 단점인지는 잘 실감이 나지 않는다. 단점에 대해서는 직접 개발해보면서 느껴봐야 할 것 같다.아무튼 이러한 이유로(사실 자바스크립트의 이유로) 노드를 택해서 공부하기로 했다.이번 주 주말부터 마음 맞는 몇몇의 개발자분들과 같이 스터디도 시작!빠르게 노드를 배워나가면서 AWS로 서버 구축하는 방법까지 익히면서 실무 프로젝트를 진행할 수 있도록 방향을 잡았다.배워나가는 것과 과정들을 꾸준하게 포스팅할 예정이다. 화이팅하자!참고문헌:모던 웹을 위한 Node.js 프로그래밍 - 윤인성개발자로 살아남기 (http://118k.tistory.com/197)티스토리 블로그와 동시에 포스팅을 진행하고 있습니다.http://madeitwantit.tistory.com#트레바리 #개발자 #안드로이드 #앱개발 #Node.js #백엔드 #인사이트 #경험공유
조회수 1282

[인공지능 in IT] 맥락인식, 말하지 않아도 알아요

오전 6시 30분. 휴대전화 알람이 울리기 시작한다. 부랴부랴 샤워를 끝내고, 나갈 채비를 하고 있으니, 5분 후 집 앞 버스 정류장에 회사로 향하는 100번 시내버스가 도착한다는 메세지가 나타났다. 버스에 몸을 싣고 사무실 근처 정류장에 내려서 걸어가는 도중, 필자가 즐겨 마시는 커피를 맛있게 내린다는 동네 카페에 대한 정보를 받았다. 어느새 다가온 점심시간에는 어제 이태원에서 과음한 것을 어떻게 알았는지, 휴대폰 잠금화면에 주변 해장국집 추천이 뜬다.그저 영화 속 이야기가 아니다. 실제 사용자의 취향과 행동 등을 분석하고, 시간, 날씨, 교통 등과 같은 외부적 환경요소를 정교하게 더한 시나리오다. 각 개인에게 필요하고, 일상을 윤택하게 만들 수 있는 유의미한 정보를 제공하는 것. ‘맥락인식’ 혹은 ‘상황인지 기술’이라고 불리는 ‘Context Recognition’의 궁극적인 목표 중 하나다.맥락인식 기술은 여러 센서로부터 수집한 데이터를 통해 사용자의 상황을 인지하고, 실시간으로 맥락을 이해하는 데 초점을 맞춘다. GPS, 와이파이, RFID, 모션 센서, 소리 등 여러 시그널을 수집해 분석하며, 사용자의 일정, 문자 메시지나 행동 정보 등을 가져와 ‘사용자가 어떤 사람인지’, 그리고 ‘현재 어떤 상황인지’ 등을 추론한다. 이와 같은 맥락인식 기술을 구현하기 위해 필요한 몇 가지 주요기술은 다음과 같다.1. 상황정보 수집사용자 인터페이스 또는 센서, 센서 네트워크 등를 통해 사용자의 위치, 활동, 생활 패턴 등 다양하고 복잡한 정보를 수집하는 기술.2. 상황정보 모델링상황정보를 가공, 저장 및 공유하는 모델링 기술.3. 상황정보 융합 및 추론사용자의 상황정보를 다른 기술과 융합해 높은 수준의 추론 기능을 제공하는 기술.4. 상황정보 교환센서, 장치 및 객체와의 상호작용을 지원하기 위해 이벤트 기반의 통신 메커니즘을 제공하는 기술.5. 지능형 에이전트사용자의 단순한 의도뿐만 아니라 감정이나 감성을 고려해 전체 상황을 자율적으로 판단, 사용자에게 적합한 서비스를 제공하는 기술.기업 입장에서 생각했을 때, 맥락인식 기술은 소비자 개인에게 특화된 서비스를 제공할 수 있는 날카로운 검이다. 간단한 예로 맥락인식을 활용한 맞춤형 광고에 대해 알아보자. 소비자 A와 소비자 B는 서울에 사는 30대 남성이고 스포츠를 좋아한다. 일반적인 검색이나 구매 히스토리에 기반한 광고와 달리 맥락인식 기술을 활용하면, 이들의 라이프스타일이나 행동패턴을 바탕으로 더 깊은 디멘션까지 분석해 세분화된 광고를 제공할 수 있다. 두 소비자 모두 스포츠를 좋아한다고 가정했을 때, A는 한강 근처에서 매일 저녁 7시 정도에 조깅하는 것을 좋아할 수 있고, B는 남산에서 새벽 6시부터 등산하는 것을 좋아할 수 있다. 미묘한 차이겠지만, 분명 다른 카테고리의 소비자로 정의할 수 있는 것이다.스켈터랩스에서 진행하고 있는 맥락인식 기술 프로젝트를 예로 들어보자. 앞서 언급한 것처럼 다양한 기기로부터 측정하는 저레벨 데이터를 수집하는 것으로 맥락인식 프로세스는 시작된다. 측정 데이터는 서버에 전송되어 시간 순으로 변경 및 취합되고, 기계학습을 통해 필터링 후 수집되며, 고레벨의 맥락으로 추상화된다. 시간, GPS, 와이파이, 모션센서, 소리, 문자메시지, 일정 등 여러 데이터를 처리해 사용자의 맥락을 이해한다. 이러한 일련의 과정 역시 맥락인식 기술의 한 부분인지라 메시지 스트림 프로세서를 기반으로 확장할 수 있는 인프라를 설계, 구축했다.실시간으로 데이터를 처리할 수 있는 파이프라인이다. 처리한 데이터는 좀 더 상위 레벨의 이벤트와 행동으로 인식되어 ‘의미‘를 지니는 데이터로 표현되는데, 예를 들어 GPS 정보를 와이파이 및 시간 등과 같은 다른 데이터와 결합하고, 방문 장소와 행동반경 등을 포함해 사용자의 장소를 식별하는 방식이다. 이러한 사용자의 행동 히스토리는 패턴인식 기술을 활용해 사용자 특정 행동을 학습하고, 이를 기반으로 ‘언제 집으로 돌아갈지‘, 혹은 ‘언제 식사를 하는지’ 등 행동을 예측할 수 있다. 결국, 맥락인식을 통해 사용자의 다음 활동을 예측할 수 있는 기술을 개발, 사용자에게 필요하고 유용한 정보와 서비스를 제공하는 것이 목표다.< 맥락인식 기술을 적용한 큐 앱 화면, 출처: 스켈터랩스 한지예, 이해연 디자이너 >얼마 전, 스켈터랩스의 맥락인식 기술 프로젝트 팀은 해당 기술을 활용해 사용자들이 일상 속에서 가볍게 사용할 수 있는 서비스가 무엇일까 고민하고, ‘큐(Cue)’라는 앱을 개발했다. 큐는 사용자가 직접 명령할 필요가 없다. 큐가 먼저 사용자의 생활을 돕기 때문이다. 날씨를 예를 들면, 사용자가 날씨를 알아보기 전에 비가 올 것 같으면 우산을 챙기라 알려주고, 덥거나 미세먼지가 많을 경우 도움 되는 정보를 알려준다. 사용자에게 전달하는 정보는 카드 메시지를 통해 잠금화면으로 표시된다.큐 프로젝트의 이민학 시니어 프로덕트 매니저는 큐를 통해 사용자가 ‘내'가 누구인지 파악할 수 있을 것이라고 말한다. 예를 들어, 나는 내가 운동을 좋아하는 액티브한 라이프스타일을 살고 있는 줄 알았는데, 실제로는 집에 누워서 영화보는 것을 더 좋아하는 사람에 가깝다는 것. 개인의 삶이 매우 중요해지는 시대이지만, 정작 내가 누구인지 확인하기 어렵기 때문에 맥락인식 기술은 다양한 용도로 사용될 수 있다.< 사용자 패턴을 분석한 유형 결과 예시, 출처: 스켈터랩스 한지예, 이해연 디자이너 >이민학 매니저는 맥락인식 기술에 대해 이렇게 말한다. 그는 “누가, 언제, 어디서, 무엇을, 어떻게, 왜로 구성된 사용자의 육하원칙을 파악하고, 더 나아가 ‘Next-육하원칙’을 파악하는 것이 진정한 맥락인식 기술입니다. 앞으로 기업 특히, 마케터들은 타겟 고객을 잡는데 굉장히 유용하게 사용할 것이라고 생각합니다”라며, “소비자 입장에서는 일상, 문화, 생활 등 세분화된 영역에서 자신의 삶을 더 윤택하게 영위할 수 있습니다. 맥락인식 기술이야말로 인간에게 정말 도움될 수 있는, ‘피부에 와닿는' 인공지능 기술이 아닐까 생각합니다”라고 설명했다.이호진, 스켈터랩스 마케팅 매니저조원규 전 구글코리아 R&D총괄 사장을 주축으로 구글, 삼성, 카이스트 AI 랩 출신들로 구성된 인공지능 기술 기업 스켈터랩스에서 마케팅을 담당하고 있다#스켈터랩스 #기업문화 #인사이트 #경험공유 #조직문화 #인공지능기업 #기술기업

기업문화 엿볼 때, 더팀스

로그인

/