스토리 홈

인터뷰

피드

뉴스

조회수 4758

“디자인과 기술을 이어주는 존재, 마크업 개발자를 함께 알아볼까요?” - 유저플로우셀 오혜진

'마크업 개발자', 아직은 우리들에게 다소 생소한 직군이죠. '마크업 개발자'는 디자이너와 개발자 사이에서 '오작교' 같은 역할을 하는 아주 중요한 포지션이에요. 오늘은 코인원의 마크업 개발자로 활약 중인 혜진님과 이야기를 나눠보려 해요. 자신의 위치에서 묵묵히 유저 친화적인 웹 환경을 만들어나가고 있는 혜진님을 만나러 가보시죠!사실 이미 혜진님은 지난 4월 13일(토), 테크 업계 여성들의 목소리에 집중하는 소중한 행사 ‘Women Techmakers Seoul 2019’에서 ‘스타트업에서 마크업 개발자로 살아남기’를 주제로 자신의 이야기를 널리 알리고 왔답니다. 스타트업 그리고 코인원에서 마크업 개발자로 살아남는 혜진님만의 방법은 무엇일까요? :-)Q. 혜진님 안녕하세요, 자기소개 부탁드립니다.안녕하세요, 코인원 유저플로우셀에서 마크업 개발자로 일하고 있는 오혜진입니다. 유저플로우셀은 암호화폐 거래와 프로차트와 같은 트레이딩 영역을 제외한 전반적인 서비스 영역을 담당하고 있어요. 특히 ‘셀'이라는 목적조직으로 개편된 이후 PM, 디자이너, 개발자가 한곳에 모여 누구나 코인원에서 거래를 하고 싶은 마음이 들도록 매력적인 곳으로 탄생시키고 있답니다. 저는 셀안에서 마크업 개발자로 일하며 디자이너와 프론트엔드 개발자를 이어주는 다리 역할을 하고 있습니다.Q. 지난 ‘Women Techmakers Seoul 2019’에서 마크업 개발자를 널리 알리는 발표를 했다고 들었어요. 어떤 내용인지 소개해주세요!감사하게도 ‘스타트업에서 마크업 개발자로 살아남기' 라는 주제로 300명이 넘는 관중들 앞에서 발표를 하고 왔습니다. (사실, 많은 분들이 와주셔서 땀이 좀 나기도 했고요;) 마크업 개발자는 스타트업에서 발견하기 힘든 직군이기도 해요. 보통은 웹 에이전시에 많이 속해 있거든요. 제가 마크업 개발자로 일한지 6년이라는 시간 동안 스타트업에서 어떤 방식으로 일해왔는지 알리고 싶었어요. 그래서 지금까지 이런 일들을 해왔고, 앞으로도 더 활발하게 할 것이라고 속시원하게 말하고 왔습니다.Q. 마크업 개발자는 구체적으로 어떤일들을 하나요?마크업 개발자는 한마디로 디자인(Design)과 기술(Tech)의 오작교 같은 존재입니다. 디자인의 의도가 개발과 충돌하는 부분은 없는지 파악하고, 개발에 잘 녹아들 수 있도록 프론트엔드의 앞단을 맡고 있어요. 코인원 웹 서비스에서 제공하는 신규 기능의 마크업 개발을 담당하고, 운영하면서 생긴 이슈들을 처리합니다. 또한 마크업 레거시에 대한 유지보수 작업도 병행하죠.예를 들어, 코인원의 회원가입 페이지를 제작할 때 디자인 작업을 먼저 들어갑니다. 그럼 디자인 작업을 바탕으로 개발자들이 기능을 만들어 넣게 돼요. 이 때, 기능적인 개발을 제외하고 UI(User Interface)적인 부분을 제가 담당합니다. 회원가입 페이지에는 이메일 인증, 휴대폰 인증 등 여러가지 개발요소들이 많아요. 그래서 개발하기 전에 기능이 들어가는 기본적인 레이아웃을 만들어 개발자에게 전달합니다. 마크업 작업이 바탕이 되어 그 위에 기능 개발이 이뤄진다고 보시면 돼요.디자이너가 레시피를 만드는 사람이라면, 마크업 개발자는 레시피 재료를 세팅해 주는 사람이에요. 개발자들은 세팅된 레시피를 끓이고 버무려 요리를 완성시키고요. 저는 좋은 요리가 탄생할 수 있도록 중간과정을 도와주는 역할인거죠. ▲ 'Women Tachmakers 2019'에서 발표에 열중한 혜진님!Q. 디자인과 기술의 중간 역할을 담당하고 계시군요, 사실 중간자의 역할이라고 하면 이어주는 과정에서 고충(?)이 생길 것 같아요.아무래도 디자이너와 개발자, 양쪽과 다 소통해야하는 부분입니다. 디자이너 입장에서는 ‘왜 프론트엔드에서 이 디자인이 안되는걸까?’ 라는 불만이 생길때도 있고, 프론트엔드에서는 ‘왜 디자인이 이렇게 들어가야 하는걸까?’ 라고 이해를 못할 때도 있어요. 서로의 이해관계를 잘 전달해야 한다는 점이 나름의 고충이죠. 코인원에서는 ‘디자이너 - 마크업 개발자 - 프론트 개발자’의 협업 프로세스를 정립해서 각자가 맡은 분야에 집중 할 수 있는 초석을 다졌어요. 무엇보다도 배경이 다른 세 개의 직군이 원활하게 소통할 수 있는 체계가 잡혀 고충이 해결되고 있습니다 :) Q. 그렇다면 마크업 개발자는 어떤 부분을 기여한다고 볼 수 있나요?코인원 메인 화면에 기능 개발을 추가하지 않고도 마크업단에서의 처리만으로도 쉽게 변화를 줄 수 있습니다. 메인화면의 배너 이미지는 유저들이 코인원에 접속해 제일 먼저 마주하는 부분이죠. 그래서 유저들이 코인원의 시각화된 정보를 빠르게 접할 수 있도록 이미지를 교체합니다. 웹 페이지의 운영 측면에서 비주얼 개편을 빠르게 할 수 있는 환경을 만들어 놓고 대응하는거에요.곧 코인원 마이페이지 화면이 개편될겁니다. 웹 페이지를 새로 만든다는 것은 무에서 유를 창조하는 과정과 같아요. 제가 마크업 개발을 잘 해놓으면 다른 직군에게도 도움이 됩니다. 개발 속도도 더 잘 붙고, 디자인에서도 빈공간이 없는 페이지가 탄생하는거죠. 최대한 밑바탕을 꼼꼼하게 만들어 모두가 일에 더 집중할 수 있는 환경을 만든다고 보시면 돼요.Q. 코인원 마이페이지에서 새롭게 바뀌는 부분은?기존의 마이페이지는 유저들이 보기에 정리가 잘 안되어있다는 느낌이 있었어요. 어떤 인증과정을 끝마쳐야 하는지 한눈에 들어오지 않는 부분이 있었거든요. 이번에 개편될 마이페이지는 좀 더 명확해졌습니다. 이전의 인증페이지가 도돌이표의 느낌이었다면, 이번에는 UX(User experience)를 생각해서 flow 개선도 많이 이뤄졌습니다. 편리한 암호화폐 거래 경험을 코인원에서 느낄 수 있어요. (새롭게 바뀔 마이페이지 많은 기대 부탁드립니다! 물론 편리한 암호화폐 거래도 언제나 코인원!)Q. 유저들에게 편리한 거래경험을 선사하기 위해 어떤 가치를 가장 중요시 여기나요? 저는 중간자이므로 유저들 뿐만 아니라 개발까지 두 가지 측면을 모두 고려합니다. 유저의 입장에서 사용성과 접근성이 용이한 마크업을 짜려고 하고, 개발측면에서는 유지보수가 편리한 마크업을 최대한 짜려고 해요. 개발하기 편한것과 사용하기 편한 것은 다른 맥락이거든요. 요새는 코인원 디자인시스템을 적용하고 있어요. 디자이너 분들이 정리해주신 디자인 시스템을 잘 적용시켜서 코드적으로도 재사용성이 용이하게 관리가 되도록 하고, UI도 정돈이 되어가는 과정을 진행 중입니다. 이런 과정을 계속 거치면 유저들에게 편리한 거래 경험을 선사하는 부분은 놓치지 않을 것 같아요.▲ 마크업에 열중하고 있는 혜진님 (약간의 설정샷 +_+)Q. 코인원 크루로 일하면서 장점을 뽑자면?유저플로우셀은 코인원이 셀이라는 목적조직으로 개편되고나서 만족도가 높은 셀이라고 알고 있어요. 업무도 많은 편인데, 톱니바퀴처럼 잘 맞물린다는 느낌이거든요. 특히 일에 대해서 선긋지 않고, 이슈가 발생했을 때 해결할 수 있는 부분들을 빠르게 파악해주는 부분들이 정말 좋아요. 속도랑 효율성 측면에서 이만큼 해낼 수 있는 팀은 앞으로 만나지 못할 것 같아요. 항상 원활한 업무 소통을 위해 힘써주시는 셀원들에게 감사 드립니다!Q. 앞으로 이루고 싶은 목표가 무엇인가요?회사 안 뿐만 아니라, 바깥에서의 활동도 꿈꾸고 있어요. 마크업 개발자들이 모두 모여 이야기할 수 있는 CSS 컨퍼런스를 열어 좀 더 커뮤니티를 활성화 시키고 영향력을 높이고 싶습니다. 아직 마크업 개발자들만이 모여서 이야기 할 수 있는 곳이 부족하거든요. 저의 이야기도 차곡차곡 쌓아서 여러 창구를 통해 들려드리고 싶고요.코인원에서는 지금 하는 것 이상으로 마크업 개발도 열심히 할거에요. 우선 단기적인 목표로, 프론트엔드에서 사용하고 있는 angular에 대한 이해력을 높일 겁니다. 마크업 컴포넌트 단위에 최적화 된 CSS로 개편해서 사용하지 않는 스타일 리소스가 최소화가 되도록 만들거에요.▲ 마크업 개발자에 많은 관심 부탁드려요 :)디자이너가 디자인에 집중할 수 있게, 개발자가 개발에 집중할 수 있게 ‘일잘러’로 통한다는 혜진님. 혜진님의 인터뷰를 통해 ‘마크업 개발자’에 좀 더 친해지는 시간이길 바라봅니다. 그리고 이렇게 멋진 코인원 크루와 함께 성장하고 싶지 않으세요?  현재 코인원은 멋진 크루들과 함께 크립토갤럭시를 헤쳐나갈 분들을 기다리고 있습니다 :-)
조회수 767

블록체인 진짜 하나도 모르는 디자이너의 독학일기(1)

독학을 시작했습니다. 스터디를 가려고 했는데 수많은 전문용어들이 제 영혼을 피폐하게 만드는 바람에 정신건강이 염려되었거든요. 포토샵도 혼자 배웠으니 이것도 못할까! 라고 자신있게 책을 폈는데 못할 것 같습니다.......그래도 산 책 값이 아까우니 읽고 공부한 내용들을 하나하나 정리해보고자 합니당! 블록체인 전문가님들이 혹시 이 글을 보신다면 노잼과 지루함내지는 유치함을 느끼실 수 있으니 엄빠미소로 지켜봐주시면 감사하겠습니다. 잘못된 부분이 있다면 바로 잡아주세요!!글을 쓰면서 5가지 원칙을 지킬겁니다.1. 꼭 써야하는 고유명사가 아닌 이상 어려운 단어는 쓰지 않습니다. 중학생 정도가 이해될 수준이길 제발 바랍니다...저는 블록체인을 이제 이틀 째 공부하고 있거든요.2. 가급적 팩트체크된 내용만 쓸겁니다.3. 제대로 공부하려면 경제사, IT기술, 코딩 등등..수많은 요소가 복잡하게 들어가지만 여기선 꼭 필요한 쏘옥 뽑아서 얘기할 겁니다. 4. 짧게 쓸 겁니다.5. 가끔 쓸 겁니다.(자주 쓰기 힘든 주제임..)시작합니당 :)블록체인이 왜 태어났는지 얜 뭔지부터 알아야 할 것 같아요. 그러자면 시간을 조금 되돌려서 우리는 어떻게 사고파는 경제활동을 해왔는지 살펴볼께요.1. 아주 오래전 = 기억하기종이란게 나타나기도 전 우리는 사과5개를 빨간집에서 해가 질 무렵에 씨앗10개와 교환했다. 는 걸 기억해야 했어요. 문제는 서로가 잘못 기억하거나 한 쪽이 다르게 우겨버리면 할 말이 없다는 거죠..철저히 신뢰와 기억에 의존한 거래였어요.2. 오래 전 = 나무나 가죽에 새기기원래 사람은 두 발로 직립보행 하기 전부터도 그림을 좋아했어요. 동굴에도 그리고 돌에도 그리고, 나무나 땅에도 곧잘 그림을 그렸죠. 뭔가 주고받는 물품이 많아지면서 기억하기가 힘들어지자, 이젠 가죽이나 나무 등등에 갯수를 남기기 시작했죠. 문제점은 그 가죽이나 나무가 훼손되거나 도난당하면 증명할 방법이 없다는 거에요.'동쪽 언덕 마을에서 온 또박이가 가죽3개를 사갔다.'3. 조금 오래전 = 종이에 적기(단식부기)종이가 발명되고 아라비아 숫자와 알파벳, 한글, 한자, 인도어 등등이 발달하기 시작하면서 문서를 남길 수 있게 되었어요!!! 문서를 남긴다는 건 굉장했죠!!!오랜 시간이 지나도 기록들을 잘 보관할 수 있었어요!! 거래를 할 때에도 수입과 지출을 한 번에 (가계부처럼) 적으면서 작은 종이에 많은 내용을 남길 수 있었답니다. 하지만..여전히 문제는 사람이었어요. 이를 위조하거나 없애버리면...? 또는 불에 다 타서 없어지면??4. 얼마 전 = 적은 걸 나눠가지기(복식부기)그래서 서로 함께 같은 내용을 공유하기로 했어요. 너 하나 나 하나. 그리고 그 과정을 감시하는 회계사. 이런 과정은 우리 조선시대에서도 아주 엄격했답니다. 특히 계문화가 발달했던 우리나라는 다양한 장부를 기록했는데 '용하기'라는 계의 장부기재는 정말 엄격한 원칙이 있었답니다!!1. 임시장부를 2부 작성해요. 이 때 회계담당자 이외 심지어 2명이 더 감시하고 있어요.2. 기재를 시작해요.3. 계원들이 다 모여야 하고 적은 내용을 크게 읽어요. 이 때 의심스러운게 있으면 이의제기나 수정을 해요.4. 계장과 두 명의 감시원이 있는 상태에서 최종수정해요. 그리고 계장이 서명해요.5. 중복된 장부가 있는지 확인하고 새 장부를 넣어 보관해요.엄청나죠???..놀라운 건 현재의 블록체인의 원리도 위와 비슷해요!! 다만 사람이 일일이 적고 감시하는 게 아니라 명령어에 의해 챡챡 처리되는 것 뿐이랄까요. 하지만 이것도 결국 '물질' 이다 보니....화재나 전쟁으로 인해 소실되어 버리면 그걸로 끝이었어요.5. 요즘 = 기관이나 중앙에 맡기기왕정체제가 아니라 민주주의와 시장경제가 도입되면서 은행이나 보험사, 카드사와 같이 경제활동을 담당하는 기업과 중앙기관이 생겨나기 시작했어요! 엄청나게 거대한 정보를 크으으은 서버나 금고에 보관할 수 있었어요. 그것은 영원해보이고 사람들은 오래도록 보관할 수 있다고 생각하니 관심을 끄기 시작했죠. 내 돈은 금고에 잘 있을 거니까요.하지만, 자본주의는 그런게 아니었어요. 은행은 내 돈을 다른 사람에게 대출로 빌려주고 그 이자로 돈을 벌어요. 그리고 다른 사람이 갚은 돈으로 다시 내 예금을 채우죠. 졸라 돌려막기인 거에요. 사람들이 끊임없이 돈을 빌리고 다시 갚을 수 있게 다양한 상품들을 만들어요. 이 방식은 굉장히 효율적이고 아무 문제가 없을 것 같이 보였어요.하지만, 해킹을 당했어요.은행을 털렸어요서브프라임 모지기론 사태처럼, 무리한 상품의 실패는 수백개의 기업을 무너뜨렸어요. 수많은 사람들의 돈이 한 순간에 날아갔어요.서버가 먹통이 되어 거래가 안되는 경우도 있어요.지진 등의 천재지변이 나면 내 기록은 사라지고 말아요.단순히 큰 사옥을 지닌 곳이니까 영원불멸할 것 같았던 중앙기관도 하루 아침에 무너질 수 있단 사실을 우린 수 차례 경험했어요. 그럼에도 우린 뭘 어떻게 해야할 지 몰랐어요. 우리가 할 수 있는 건 사고가 터지면 변호사를 써서 소송을 하는 것 뿐이었어요. 우린 은행의 상품이 정확히 어떤건지, 보험약관이 뭔지... 카드사는 어떤 원리로 움직이는지...내 세금은 어떻게 쓰이고 있는지...우리 돈이 어떻게 거래되고 내 돈을 가지고 그들이 무엇을 하는지 하나도 몰라요. 그냥 속수무책으로 그들만 믿고 있는 거예요. 6. 블록체인의 탄생 = 모두가 장부를 가질 수 있게그래서 생각해봤어요. 한 곳에 모여있으니 문제가 생긴다면, 쪼개면 되지 않을까? 은행 한 곳을 터는 것은 쉽지만 1,000여명을 한꺼번에 터는 것은 불가능할테니까. 계모임에서 쓰던 그 장부를 엄청나게 많이 만들어서 모두가 가지면 어떨까? 누굴 못 믿거나 위조하거나 털리거나 불나서 사라질 일이 없을 거 아냐?? 라는 생각을 말이죠. 그런데 친구가 질문을 하네요!!친구 : 그런데 어떻게??나 : 인터넷이 있잖아!! 내가 온라인상에서 거래하면 그 기록이 남잖아~ 그걸 모두가 공유하는거지! 친구 : 모두가 누군데?나 : 응 그건 이제부터 모아야해!!친구 : 그럼 어쨌든 모인 사람들에게 모두 공유하면 내가 어제 김치한포기 시킨것도 다른 사람이 알게 되는거야??나 : 아니지;;; 니가 뭘 시켰는지 그딴 건 관심없어..그냥 얼마 거래를 언제 몇시몇분몇초에 어떻게 했는가만 기록에 남는거야! 그리고 다른 사람은 그걸 직접 눈으로 볼 수 있는 게 아냐.생각해봐. 넌 브런치 로그인한 기록을 눈으로 다 볼 수 있어? 며칠 몇시에 얼마나 로그인했는지 알 방법이 없지? 하지만 그 기록이 있을까 없을까? 그렇지, 반드시 있다구. 범죄수사할때도 그러자나. 우리 화면에는 시간/내용밖엔 안뜨는 문자메시지지만, 실제로 서버에는 발신위치, 수신위치, 번호정보 등등이 모두 숨겨져 있잖아. 또 하나! 너가 네이버에서 틴트를 검색하면 나중에 페북에서 틴트광고가 뜨지 않아? 우리의 방문기록이나 클릭한 기록들이 모두 남아있기 때문이야.이렇게 우리가 눈으로 보는 화면 뒤에는 수많은 정보들이 컴퓨터만의 전기신호로 저장되어 있어. 우리가 말하는 장부도 이런 식으로 저장되어 있는거라구.  물론 필요하다면 그걸 화면으로 띄울 수 있는 명령어를 만들 수도 있겠지.친구 : 그건 이해했어, 내가 직접 볼 순 없지만 마치 사이트 방문기록처럼 어딘가에 거래내역이 다 남아있다는 얘기지?... 그런데 아까 지금부터 모아야 한다는 사람들은 어떻게 모으는거야??나 : 그건!!..바로!!!! 다음에 설명해줄께!!또 공부해서 돌아올께용!!
조회수 3273

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

Elasticsearch로 느린 쿼리 분석하기

응당 인덱스가 있으리라 생각한 칼럼에 인덱스가 없고 인덱스를 걸자마자 응답속도가 평균 10배 가까이 좋아지는 모습을 지켜보니 여러 생각이 들더라. 통계와 지표가 제공되는 곳은 주기적으로 검토하고 문제가 커지기 전에 손을 쓰는데 그렇지 않은 곳이 문제이다. 주기적으로 Slow query 로그를 훑어볼 수는 있다. 하지만 특정 시점에 일부 로그만 훑어봐서는 엉뚱한 문제를 해결하기 일쑤다. 예를 들어 1초짜리 쿼리보다 10초짜리 쿼리가 문제라고 생각하기 쉽지만 이 1초짜리 쿼리를 10초짜리 쿼리보다 1000배 많이 실행한다면 이야기가 달라진다. 요는 느린 쿼리를 지속적으로 수집하고 통계를 낼 필요가 있다는 것이다.이러한 모니터링 도구를 어떻게 구현할까? 우리 손에 있는 도구를 검토하는 일부터 시작했다.통계분석은 MySQL 또는 Elasticsearch 를 쓰면 된다.Elasticsearch를 쓴다면 Kibana를 이용해 시각화하기 편하다.느린 쿼리 로그를 Elasticsearch에 보내는 일은 Fluentd를 쓰면 된다.그러니까 Fluentd, Elasticsearch, Kibana 조합이라면 데이터를 눈으로 보고 문제를 해결하기 좋을 것이다. 그렇다면 어떻게 구현할 것인가?우선 RDS에서 느린 쿼리를 뽑아서 Fluentd에 보내는 방법을 찾아야 한다.Fluentd를 이용해 Elasticsearch에 데이터를 보내는 건 쉬우니 대시보드만 잘 구성하면 끝!문제는 RDS에서 느린 쿼리를 뽑아서 Fluentd에 보내는 것인데 크게 두 가지 방법이 있다. RDS 설정에 따라 느린 쿼리 로그를 테이블 또는 파일에 저장할 수 있는데 이에 따라 구체적인 구현방법이 달라진다. 하지만 기본적으로는 동일한 과정을 거치는데 대충 이런 식이다.느린 쿼리 로그를 읽는다.같은 쿼리라도 매개변수 값이 다를 수 있으므로 mysql_slow_log_parser 또는 pt-query-digest 같은 도구를 사용해 쿼리를 일반화한다.Fluentd를 통해 해당 로그를 ES로 보낸다.새로 추가된 로그만 읽어서 다시 ES로 보낸다.이와 관련해서는 AWS RDS Mysql SlowQuery monitoring on Kibana using Logstash 등의 글이 잘 설명한다.다행히 테이블에 저장한 로그를 읽어들이는 Fluentd 플러그인을 구하기는 쉽다. 변형체가 많은데 대부분은 kenjiskywalker/fluent-plugin-rds-slowlog에서 파생됐다. 파일에 저장한 로그의 경우는 in_rds_mysqlslowlog_stream.rb를 써서 처리하면 된다. 우리는 테이블에 저장하기 때문에 전자를 선택했다.이쯤 조사를 마치고 나니 진행방향은 매우 명확하다. 적당히 잘 만든 Fluentd 플러그인을 골라서 적용한 후에 ES에 대시보드를 만들면 된다. 물론 우리는 Kubernetes 위에 모니터링 도구를 띄워야 하니 Dockerize할 필요도 있다. 이쯤에서 또다시 구글링을 하니 무시무시한 게 나온다. inokappa/rds-slowquery-log-demo는 방금 설명한 모든 과정을 하나로 정리해서 제공한다. Docker로 만든 Fluentd와 ES 대시보드 설정을 한데 묶어놓았다. 거기에 파일 로그, 테이블 로그 둘 다 예제로 제공한다. 덕분에 일이 쉽게 끝날 줄 알았다. 하지만!개발한지 꽤 시간이 지난 지라 최신 버전의 Fluentd와 ES에서 계속 문제를 일으켰다. 문제점에 대해 구구절절 설명할 생각은 없고 DailyHotel/rds-slowquery-log-demo를 참고해서 적용하면 된다는 점만 이야기하고자 한다. 일어로 된 README 파일은 구글 번역기를 돌리면 적당히 읽을만해진다.삽질을 약간만 하면 아래와 같이 간지!나는 대시보드를 얻을 수 있으니 해볼만 할 것이다.참! DailyHotel/rds-slowquery-log-demo는 테이블 로그인 경우만 테스트했으니 파일 로그를 사용하는 경우라면 이 점을 주의해야 한다.더 읽을거리Collecting and Analying Slow Query Logs for MySQLRDS(MySQL) のスロークエリを EFK スタック + Docker で出来るだけ手軽に可視化する考察(2)〜 log_output: FILE の場合 〜#데일리 #데일리호텔 #개발 #개발자 #개발팀 #Elasticsearch #엘라스틱서치 #꿀팁 #도입후기 #일지
조회수 4628

100일 간의 챗봇 디자인 실패기-1편

디자인 학도로서 4년 넘게 학교에서 UI/UX를 공부했다. 또래에 비해 학교를 오래 다녔으며 해당 분야에 대한 관심도 남달랐거니와, 심지어는 UI 디자인 소프트웨어를 만드는 회사에 다닌 경험이 있는 만큼 실무적으로는 아직 많이 부족할 지라도 이론만큼은 이제 어느 정도 자신이 있다고 생각했다.그런데 대체 이 녀석은 또 뭐지. 챗봇이라니.   지난 1월, 새로운 사업을 결심한 팀원들과 사업구상을 하며 챗봇이라는 아이템을 마주하게 되었다. 우리가 챗봇에 대한 무한 신뢰를 했던 이유는 한 가지였다. '일상적 편리함에 있어 메신저만 한 것은 없다'는 것.한때 SNS에 화제가 되었던 '엄마의 메모장'챗봇은 이미 한 차례 미국 본토를 강타하고 조금씩 국내 시장에 진입하고 있던 상황이었고, 새로운 기술에 호기심을 가진 우리 팀은 챗봇에 희망을 품고 해당 분야에 대한 학습을 진행하기 시작했다.  자연어 처리, 형태소 분석 등 기술적인 부분들을 개발팀원들이 검토하고 있는 동안 디자이너로서 챗봇에 대한 리서치를 시작하려는 찰나, 아무리 검색을 해도 평소에 비해 아무것도 나오지 않는 매우 당황스러운 시추에이션이 발생했다.  일반적인 웹이나 어플리케이션 기획의 경우 이미 레퍼런스 삼을 만한 사례가 충분히 있었고, 설령 국내 자료 중에 없다고 한들 영어로 조금만 검색해보면 해외 자료들을 금세 찾을 수 있었다. 그러나 챗봇은 상황이 달랐다. 영어권 챗봇 또한 이제 막 성장하는 단계인 만큼 해외 챗봇 사례 중에서도 이렇다 할 벤치마킹 대상을 찾는 것이 쉽지 않았다.우선 우리가 만들고자 한 챗봇은 '일정' 관련 봇이었다. '자연스러운 대화를 이해하여 사용자의 일정 입력을 돕는 챗봇이 있다면 어떨까'라는 것이 우리의 가설이었다.괜찮지 않을까?지난 4년 간 학교에서 배운 과정대로라면 브레인스토밍, AEIOU, 컨셉맵핑, 유저 인터뷰, 포커스그룹 인터뷰 등에 걸친 여러 기법들을 통해 디자인을 시작해야 했다. 하지만 현 상황은 우리가 대체 정확히 무엇을 만드는 것인지에 대한 정의조차 내려지지 않은 상태였다.이 챗봇의 기능은 무엇이며, 타겟은 누구이고, 어떻게 구현될 수 있는 걸까. 너무나 생소한 분야였던 만큼 우선 첫 한 달 동안은 챗봇 관련 국내외 글을 꾸준히 읽기 시작했다. 4차 산업혁명, 완전자동화 등 챗봇에 대한 여러 이론적인(쓸데없는) 내용들이 있었지만 그중에서도 유독 눈에 띄는 글이 하나 있었다.https://chatbotsmagazine.com/bots-hype-or-glory-656f4d614efb#.g6s68jvkgI was an undercover-bot for 2 months. Here is what I learned.Bots: hype or glory?chatbotsmagazine.com 해당 글의 주요 내용을 번역 및 요약하자면 이러하다.- UX 매니아로서, 그 수많은 챗봇 중에 쓸만한 게 없더라.- 그래서 챗봇을 개발하기 전 직접 실험을 해보기로 했다.- 약 2달간 직접 서비스 내에 사용자를 돕는 봇인'척' 했다(틈틈이 사람이라고 힌트는 줬다).- 우리 서비스를 사용하는 사용자들은 컴퓨터나 기술을 좋아하는 사람들이 아닌, 일반인이었다.- 봇이 아닌 사람이 실시간으로 응대한다고 인지는 시켜주었지만 사실 신경 쓰는 사람은 없었다.본문은 '아직 챗봇은 기술적으로도, 시대적으로도 준비가 되지 않았다'로 최종 결론을 지으며 마무리되는데, 이미 챗봇에 콩깍지가 씌여 있던 나에게는 그저 앞부분의 내용이 중요할 뿐이었다."사람이 챗봇인 척 테스트를 한다고?"서비스 기획 및 디자인에 갈피를 못 잡고 있었던 우리 팀은 긴말할 것 없이 곧바로 실행에 들어갔다. 대학교 게시판에 피실험자 알바 구인 글을 올리고 약 30명의 캘린더 유저를 확보했다. 실험에 대한 대략적인 안내사항은 이러했다.1. 우리는 현재 일정 관련 챗봇을 만들기 위해 수동으로 실험 중이며, 주 기능은 '일정등록' 이다.2. 구글 또는 네이버 캘린더 작성 권한을 사용자로부터 공유받아 일정을 입력한다(캘린더 공유 기능 활용).3. 사용자는 최소 주 1회 이상 카톡을 통해 캘린더에 일정을 입력하여야 한다(페이 지급 조건).4. 사용자는 챗봇에게 일정 등록뿐만이 아닌 일정 관련 어떠한 요청도 할 수 있다.5. 이에 대한 예시로 문자/메일 분석, 공개 캘린더 추가, 키워드 일정 추천 등을 제시한다.6. 대화의 형태는 정해져 있지 않으며 원하는 어떠한 형태(말투, 축약어, 신조어)로든 가능하다.응대에 사용한 옐로아이디 관리자 툴지금은 플러스친구로 업데이트된 카카오톡 옐로아이디 관리자 툴을 활용하여 사용자들과 대화(채팅)를 진행했다. 데스크탑용 웹 인터페이스를 통해 대화를 입력할 수 있었기에 입력 속도는 빨랐지만 사용자가 언제 무슨 말을 걸어올지 도저히 예측이 불가능했다. 팀 내 개발자들이 자연어 처리에 대한 공부를 지속하는 동안 운영을 맡은 팀원과 함께 2명이서 상시 대기하며 사용자들의 요청에 응대했다.운영 초기 우리가 기대했던 이상적인 요청들은 이러했다.하지만 현실은 아래와 같았다.목적어 및 각각의 형태소가 매우 명료하고 명확한, 챗봇 개발 시 자동화가 가능한 텍스트들을 기대하고 있었지만 실상 대부분의 요청은 실제 사람이 개입하지 않는 이상 과연 처리가 가능할까 싶은 내용들이 태반이었다.텍스트 입력 시간도 사용자마다 다 제각각이었다. 아침 일과를 시작할 때 일정을 입력하는 사용자들이 있는 반면 하루를 정리하며 다음날 일정을 계획하는 사용자들도 있었다. 밥을 먹다가도, 샤워를 하다가도 옐로아이디 알람이 울리면 컴퓨터로 달려가 응답을 했다. 아무리 상시 대기를 한다 해도 잠은 자야 했기에 결국 자정부터 다음날 아침 8시까지는 옐로 아이디의 자동 응답기능을 활용하여 '잠시만 기다려주세요'를 출력하였다.(물론 잠시는 아니었지만)여러 시행착오를 거쳐 약 한 달 간의 기나긴 응대 끝에 실험이 종료되었고, 우리는 사용자들을 대상으로 설문 및 인터뷰를 진행하였다.우선 가장 중요하게 생각한 전체 캘린더 일정 입력률(데스크탑/모바일 캘린더를 포함한 모든 입력) 대비 카톡을 통한 일정 입력률은 약 절반 정도로 확인되었다.카톡을 통한 일정 입력률 / 전체 일정 입력률  = 51%이와 더불어 '카톡을 통해 캘린더에 일정을 등록하는 방식에 대해 불편한 점'을 질문한 결과1. 즉각적이지 않은, 늦은 응답 - 40%2. 개인 일정 정보 유출에 대한 불안 - 20%3. 익숙하지 않은 카톡 입력의 불편함 - 13.3%순으로 응답함을 확인하였다.생각보다 나쁘지 않은 결과였다.비록 입력 된 내용들을 정형화 하기가 쉽지는 않았지만, 기대했던 것에 비해 카톡을 통한 입력률이 높은 편이었고 가장 큰 문제점으로 지적된 '늦은 응답'과 '개인 정보 유출'은 챗봇 개발을 통해 개선할 수 있을 것으로 기대했다. 자동화를 통해 즉각적으로 응답할 수 있을뿐더러 사람의 개입을 없애 개인 일정 정보 유출을 방지할 수 있을 것이라는 판단 하에 챗봇 개발을 진행하였다.그렇게 한달 간 입력받은 텍스트 데이터를 활용, 약 2주 간의 개발 끝에 간단한 일정 등록 기능을 갖춘 일정 관리 챗봇, 린더봇이 탄생하게 되었다.https://www.youtube.com/watch?v=zSRYRYfzTFo2편에서 계속...#히든트랙 #챗봇 #기술기업 #개발자 #개발팀 #인사이트 #경험공유
조회수 2027

레진 기술 블로그 - IntersectionObserver를 이용한 이미지 동적 로딩 기능 개선

구글 크롬 51 버전부터 DOM 엘리먼트의 노출 여부를 비동기로 처리하는 IntersectionObserver API를 사용할 수 있게 되었습니다. 이 기능을 이용하면 이미지의 동적 로딩이나 광고 배너의 노출 측정 등을 효율적으로 사용할 수 있다고 구글 개발자 블로그에서 소개하고 있습니다. 이 글에서는 기존의 이미지 동적 로딩에 대한 문제점을 짚어보고 여러 예제를 통해 IntersectionObserver의 사용 방법을 익혀 기존 기능을 개선할 수 있도록 합니다. 사용한 예제들은 브라우저의 호환성을 고려하지 않고 구글 크롬을 기준으로 작성하였습니다.기존의 이미지 동적 로딩 구현이미지의 개수가 많거나 용량이 큰 페이지를 불러올 경우 쓸데없는 네트워크 비용이 증가하고 이미지를 불러오는 과정에서 서비스 속도에 문제가 발생할 소지가 있어서 이미지가 사용자에게 보일 때만 불러오는 동적 로딩 기능이 필요합니다. IntersectionObserver를 소개하기 전에 먼저 기존 라이브러리들이 이미지 동적 로딩을 어떤 방법으로 구현하고 있는지 간단하게 알아보도록 합니다.엘리먼트 가시성 판단이미지 동적 로딩에서 가장 중요한 코드는 해당 엘리먼트가 현재 화면 내에 보이는지 알아내는 것입니다. 이를 위해 엘리먼트의 크기와 위치 값을 돌려주는 Element.getBoundingClientRect 함수를 사용하는 경우가 많습니다. 아래는 이 함수를 사용한 간단한 구현 예제입니다.function isInViewport(element) { const viewportHeight = document.documentElement.clientHeight; const viewportWidth = document.documentElement.clientWidth; const rect = element.getBoundingClientRect(); if (!rect.width || !rect.height) { return false; } var top = rect.top >= 0 && rect.top < viewportHeight; var bottom = rect.bottom >= 0 && rect.bottom < viewportHeight; var left = rect.left >= 0 && rect.left < viewportWidth; var right = rect.right >= 0 && rect.right < viewportWidth; return (top || bottom) && (left || right); } 이벤트 처리위에서 구현한 isInViewport 함수는 언제 호출해야 할까요? 먼저 문서를 처음 불러왔을 때 호출해야 합니다. 그 후에는 동적 로딩이라는 단어에 맞게 사용자의 동작에 따라 보이지 않던 엘리먼트가 보이게 되는 이벤트를 감지해야 합니다. 마우스나 터치로 스크롤을 통해 문서의 위치가 바뀌거나 브라우저의 크기가 바뀔 수도 있고 모바일 기기의 화면을 돌려서 볼 수도 있습니다. 데스크톱의 경우 scroll, resize 이벤트를, 모바일의 경우 orientationchange 이벤트의 처리를 생각해야 합니다.const images = Array.from(document.querySelectorAll('img')); document.addEventListener('scroll', () => { images.forEach(image => { if (isInViewport(image)) { image.onload = () => images.splice(images.indexOf(image), 1); image.src = 'original_image_path'; } }); }); 간단하게 위 코드와 같이 구현할 수 있습니다. 물론 실제 서비스를 위해서는 수정할 점이 몇 가지 있습니다. 동적 로딩의 대상이 되는 이미지를 구분하기 위해 해당 엘리먼트에만 특정 클래스를 부여하거나 HTML5에서 지원하는 data 속성을 이용하기도 합니다. 스크롤이나 리사이즈 이벤트가 과도하게 발생하는 경우가 많으므로 throttle 또는 debounce 등을 사용해 실행 빈도를 조절할 수도 있습니다. 일부 라이브러리에서는 requestAnimationFrame을 이용해 이벤트 핸들러를 처리하기도 합니다.TADA레진코믹스에서는 이미지 동적 로딩을 위해 서비스 초기에 Unveil 라이브러리를 사용했었습니다. 그러나 적용 후 몇 가지 아쉬움이 있어 따로 TADA 라이브러리를 제작했습니다. 먼저 마크업 구조상 이미지를 태그가 아닌 다른 태그에 배경 이미지로 사용하는 경우를 지원해야 했습니다. 그리고 모바일 웹에 주로 많이 적용하는 수평 스크롤 구역에 대한 처리도 필요했습니다. 문서의 스크롤 이벤트로는 처리가 되지 않기 때문에 특정 엘리먼트를 받아 그 엘리먼트의 스크롤 이벤트 핸들러를 등록할 수 있도록 해야 했습니다. 이를 해결하기 위해 만든 라이브러리를 현재 서비스에 적용 중이지만 이 라이브러리 역시 아래와 같은 문제점들을 가지고 있습니다.</> < id>기존 이미지 동적 로딩의 문제점getBoundingClientRect 함수의 문제점위 코드에서 특정 엘리먼트가 현재 화면 내에 보이는지 검사할 때 사용하던 Element.getBoundingClientRect 함수에는 치명적인 단점이 있습니다. 이 함수를 호출할 때마다 브라우저는 엘리먼트의 크기와 위치값을 최신 정보로 알아오기 위해 문서의 일부 혹은 전체를 다시 그리게 되는 리플로우(reflow) 현상이 발생한다는 점입니다. 호출 횟수가 적을 경우에는 부담이 되지 않지만, 이 함수는 위에서 구현한 것처럼 스크롤이나 리사이즈 이벤트가 발생할 때마다 등록한 모든 엘리먼트를 순환하면서 호출하게 됩니다. 이 코드들이 하나의 메인 스레드에서 실행되기 때문에 스크롤을 할 때마다 실행 속도가 눈에 띄게 느려질 수도 있습니다.외부 도메인 문서를 사용하는 iframe최신 브라우저들은 동일 도메인 정책에 따라 iframe 내의 외부 도메인 문서에서 현재 문서에 접근하지 못 하게 막고 있습니다. 이 제한은 서비스 개발에서 겪게 되는 문제는 아니고 외부 광고 플랫폼 개발자의 입장에서 발생하는 문제입니다. 광고 이미지의 표시나 클릭 이벤트의 처리 등은 iframe 내에서 처리할 수 있지만 광고 이미지를 지연 로딩한다거나 이 광고가 사용자에게 노출이 되었는지 기록하는 등의 기능은 iframe 내에서 불가능합니다. 그래서 광고를 적용하는 서비스 개발자에게 스크립트를 제공하고 서비스 문서 내에 삽입하는 방식으로 처리하고 있습니다. 이러한 외부 광고가 여러 개라면 삽입해야 하는 코드가 늘어날 뿐만 아니라 코드 내에서 스크롤이나 리사이즈 이벤트 등을 각각 사용하기 때문에 위에서 언급한 문제점들이 배가될 수 있습니다.기타 이벤트에 대한 처리대부분의 동적 로딩 라이브러리들은 적용할 엘리먼트에 특정 클래스 또는 data 속성을 부여하면 코드를 추가 작성하지 않더라도 쉽게 사용할 수 있습니다. 하지만 화면에서 보이지 않던 엘리먼트가 갑자기 나타나는 현상은 스크롤이나 리사이즈 이벤트에서만 발생하는 것이 아닙니다. 더보기 버튼을 눌렀을 때 숨겨져 있던 엘리먼트를 노출할 수도 있고 AJAX 호출 후 엘리먼트를 생성한 후 보여줄 수도 있습니다. 이런 경우 일괄적으로 처리하기가 어렵우므로 해당 이벤트가 발생할 때 수동으로 처리하는 수밖에 없습니다.IntersectionObserver위에 나열한 문제들을 효과적으로 처리하기 위해 크롬 51/엣지 15/파이어폭스 55 버전부터 IntersectionObserver를 지원하기 시작합니다. 우리말로 번역하면 교차 감시자 정도가 될 이 기능은 등록한 엘리먼트가 보이는 영역에 나타나거나 사라질 때(용어에 충실하자면 대상 엘리먼트의 영역이 루트 엘리먼트 영역과 교차하기 시작하거나 끝났을 때) 비동기로 이벤트를 발생시켜 줍니다. 기본적인 사용법은 아래와 같습니다.const intersectionObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { // do something observer.unobserve(entry.target); } }); }); intersectionObserver.observe(element); 먼저 IntersectionObserver 생성자에 콜백 함수를 인자로 넘겨주고 생성한 인스턴스의 observe 메소드를 통해 동적으로 처리할 엘리먼트를 등록합니다. 콜백 함수는 IntersectionObserverEntry 객체 목록을 전달받으므로 순환문을 통해 각 엘리먼트에 대한 처리를 완료하고 필요한 경우 unobserve 메소드를 이용해 감시 대상에서 해제할 수 있습니다.IntersectionObserver 예제아래 예제들은 기본적으로 아래 코드를 바탕으로 작성되었습니다. 각 예제들의 최상단에 엘리먼트에 짝을 이룬 표시등을 두었고 콜백 함수가 호출될 때마다 파동 효과를 주었으며 이 때 isIntersecting 속성을 기준으로 표시등을 켜지거나 꺼지게 되어 있습니다.const io = new IntersectionObserver(entries => { entries.forEach(entry => { // isIntersecting 속성으로 해당 엘리먼트가 보이는 지 표시 }); }); Array.from(document.querySelectorAll('.box')).forEach(box => { io.observe(box); }); 스크롤 이벤트를 다루지 않더라도 엘리먼트의 가시성 여부를 isIntersecting 속성을 통해 알 수 있습니다.<iframe class="demo" data-fr-src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/basic-verticalscroll.html" width="600" height="400" frameborder="0">수평 스크롤의 경우에도 overflow 속성이 적용된 컨테이너 엘리먼트의 스크롤 이벤트를 처리하지 않더라도 상관없습니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/basic-horizontalscroll.html" width="600" height="200" frameborder="0">더보기 버튼에 대한 클릭 이벤트를 따로 등록하지 않아도 동작합니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/basic-unfold.html" width="600" height="240" frameborder="0">리사이즈 이벤트 역시 따로 처리할 필요가 없습니다. 새 창을 띄운 후 창 크기를 조절하면서 확인할 수 있습니다.위의 모든 예제들은 <iframe> 태그 안에서 실행되고 있습니다. 이처럼 작성한 코드가 외부에서 실행이 되더라도 IntersectionObserver API는 문제없이 동작합니다.IntersectionObserver 생성자 옵션rootroot 옵션에는 가시성의 판단 기준이 될 HTML 엘리먼트를 지정합니다. observe 메소드로 등록하는 엘리먼트들은 반드시 이 루트 엘리먼트의 자식이어야 합니다. 이 옵션을 지정하지 않을 경우 브라우저 화면에서 현재 보이는 영역인 뷰포트가 기본이 됩니다. 아래 예제에서 알 수 있듯이 루트 엘리먼트를 지정하면 현재 화면과는 상관없이 루트 엘리먼트와 등록한 엘리먼트들의 영역이 교차하는 지 판단하게 됩니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/option-root.html" width="600" height="400" frameborder="0">rootMargin루트 엘리먼트의 마진값을 지정할 수 있습니다. CSS에서 사용하는 형식과 같기 때문에 “10px”, “10px 20px”, “10px 20px 30px 40px” 형태가 모두 가능하며 음수값으로 지정할 수도 있습니다. 기본값은 0이고 루트 엘리먼트를 지정한 상태라면 퍼센트값을 사용할 수도 있습니다. 이 옵션을 이용하면 이미지 동적 로딩에서 해당 엘리먼트가 화면에 나타나기 전에 이미지를 불러오기 시작해 이미지 공백을 줄이는데 유용하게 이용할 수 있겠습니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/option-rootmargin.html" width="600" height="400" frameborder="0">위 예제에서는 root 옵션은 지정하지 않고 rootMargin 옵션을 각각 0, 100px, -100px, 50%로 지정했습니다. 하지만 iframe 내에서 실행을 하게 되면 이 옵션이 정상적으로 동작하지 않습니다. 프로젝트 페이지의 이슈 댓글에는 동일 도메인의 프레임 안에서는 동작하는 것으로 논의되고 있지만 뷰포트에는 해당하지 않거나 버그 또는 아직 크롬에 반영이 되지 않아 보입니다.이 예제는 새 창을 띄워 프레임을 벗어나면 정상적으로 동작합니다. 스크롤을 내리다보면 엘리먼트마다 IntersectionObserver 콜백 함수가 다른 위치에서 호출됨을 알 수 있습니다.thresholdthreshold 옵션은 엘리먼트가 콜백 함수의 호출 시점을 정하는 옵션입니다. 0과 1을 포함한 그 사이의 숫자 또는 숫자 배열을 지정할 수 있는데 이 숫자는 엘리먼트의 전체 영역 중에 현재 보이는 영역의 비율입니다. 이 비율의 경계를 넘나들 때마다 콜백 함수가 호출됩니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/option-threshold-value.html" width="600" height="400" frameborder="0">위 예제에서는 threshold 옵션을 각각 0, 0.5, 1, [0, 1]로 지정했습니다. rootMargin 예제처럼 엘리먼트마다 콜백 함수가 다른 위치에서 호출됩니다. 두 번째와 세 번째 상자는 콜백 호출 시점에 isIntersecting 값이 항상 참이기 때문에 표시등이 정상적으로 표시되지 않습니다. isIntersecting 속성을 기준으로 처리해야 할 작업이 있다면 반드시 threshold 속성에 0을 포함시켜야 정상적으로 동작합니다. threshold 속성은 아래 예제처럼 콜백 함수의 인자로 받는 IntersectionObserverEntry 객체의 intersectionRatio 속성과 같이 사용하기에 유용합니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/option-threshold-ratio.html" width="600" height="400" frameborder="0">위 예제에서는 threshold 옵션을 각각 [0, 1], [0, 0.5, 1], [0, 0.25, 0.5, 0.75, 1]로 지정하고 콜백이 호출되면 intersectionRatio 값을 기준으로 표시등의 배경 투명도를 바꾸도록 했습니다.IntersectionObserver의 활용이미지 동적 로딩지금껏 알아본 IntersectionObserver를 이용해 이미지 동적 로딩을 간단하게 구현해봅니다. 이미지 엘리먼트를 구성할 데이터가 배열로 존재한다고 가정하고 ES6에서 지원하는 템플릿 문자열을 사용해 배열을 순환하면서 이미지 목록을 생성합니다. 그 후 IntersectionObserver를 초기화하고 만들어진 엘리먼트들을 등록합니다. 콜백 함수에서는 엘리먼트가 보이는 상태일 때 이미지를 로딩하고 해당 엘리먼트를 감시 해제합니다. id="comics"> const comics = [ { alias: 'eunsoo', id: 6080299074584576, title: '은수' }, ... ]; const template = comics => ` ${comics.map(comic => ` ${comic.id}"> ${comic.alias}" class="info">${comic.title} `).join('')} `; document.getElementById('comics').innerHTML = template(comics); const io = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (!entry.isIntersecting) { return; } const target = entry.target; const id = target.dataset.id; target.querySelector('.info').style.backgroundImage = `url(https://cdn.lezhin.com/v2/comics/${id}/images/wide?width=600)`; observer.unobserve(target); }); }); Array.from(document.querySelectorAll('.comic')).forEach(el => { io.observe(el); }); 아래 예제를 실행하면서 브라우저의 개발자 도구를 열고 네트워크 탭을 살펴보면 이미지 엘리먼트가 보이기 시작할 때 불러오기 시작하는 것을 확인할 수 있습니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/demo-lazyload.html" width="600" height="400" frameborder="0">무한 스크롤IntersectionObserver 기능을 이용하면 무한 스크롤 역시 쉽게 구현할 수 있습니다. 아래 예제에서는 스크롤의 끝부분에 감시를 할 엘리먼트를 두고 그 엘리먼트가 노출이 될 때마다 콘텐츠를 추가로 불러오도록 작성하였습니다. id="items"> id="sentinel"> const count = 20; let index = 0; function loadItems() { const fragment = document.createDocumentFragment(); for (let i = index + 1; i <= index + count; ++i) { const item = document.createElement('p'); item.classList.add('item'); item.textContent = `#${i}`; fragment.appendChild(item); } document.getElementById('items').appendChild(fragment); index += count; } const io = new IntersectionObserver(entries => { entries.forEach(entry => { if (!entry.isIntersecting) { return; } loadItems(); }); }); io.observe(document.getElementById('sentinel')); loadItems(); 실행 결과를 아래 예제에서 확인할 수 있습니다.<iframe class="demo" src="https://cdn.rawgit.com/fallroot/intersectionobserver-examples/master/demo-infinitescroll.html" width="600" height="400" frameborder="0">마무리IntersectionObserver API는 아직 몇몇 브라우저의 최신 버전에서만 사용할 수 있지만 지원하지 않는 브라우저를 위해 Polyfill을 제공하고 있습니다.IntersectionObserver API는 웹 광고 플랫폼 제공자와 사용자 모두에게도 좋은 소식이라 봅니다. 이 API가 정착된다면 광고 노출 여부를 측정하기가 쉬워지고 서비스에 더해졌던 리소스 낭비를 줄일 수 있을 것이라 생각합니다.레진코믹스는 크롬 브라우저 사용자의 비중이 높은 편이기 때문에 빠른 시일 안에 적용해 볼 예정입니다. 이미지 동적 로딩 기능의 개선과 정주행 기능과 같이 현재 스크롤 이벤트를 과하게 사용하고 있는 코드에 대한 부담을 덜 수 있기를 기대하고 있습니다.참고자료Intersection Observer API SpecificationIntersectionObserver’s Coming into ViewIntersection Observer API
조회수 1618

우리는 비정상인걸까?

필자는 스팀헌트라는 스팀 블록체인 기반 댑 프로젝트를 진행하고 있다. 스타트업을 하면서 저마다의 관점과 철학이 다른 문제이겠으나, 내가 지금까지 약 1년간 경험해본 이놈의 "블록체인"이라는 업계는 뭔가 정상적이지 않다. 그간 나름 "스타트업"이라는 업계 전반의 경험에 비추어 봤을때 이바닥 관행들이 뭐가 내게는 비정상적으로 보이는지 간략히 살펴보면 다음과 같다.1.대부분의 "블록체인" 태그를 달고 나오는 프로젝트들은 가장 처음 하는 일이 펀딩이다. 아직 제품은 커녕 그냥 프로젝트 소개하는 랜딩페이지에 수십명의 팀원, 어드바이저 리스트, 현실성이 있을까 싶은 각종 기업 로고들이 파트너사로 나열되어 있다.2.그들에게 "제품"이란 마치 수십 수백페이지의 엄청난 공을 들인 "화이트페이퍼"인듯 하다. 왜냐하면 위에서 얘기한 랜딩페이지 맨 위에 항상 가장 대문짝 만한 자리를 차지하고, 이미 3개국어는 기본, 5개국어 버전까지 준비해 놨기 때문이다.3.이런 제품도 없고 요상한 랜딩페이지만 있는 프로젝트들이 수십, 수백억의 ICO, IEO, 프라이빗 세일 등등의 단어로 치장된 "토큰 세일"을 진행한다. 이들이 초기에 들이는 자원중 99% 이상은 카톡방 관리, 텔레그램방 관리, 코인판 (사이트 이름이다) 마케팅, 각종 밋업, 컨퍼런스 참여, 유투버들 마케팅 등등이다. 물론 이런 행동들은 성공적인 펀딩을 위해 필요한 일들이긴 하다. 다만, 일반적인 스타트업이라면 초기에 99%의 자원이 제품과 유저들에게 쏟아야 마땅한 단계에 그게 아니라는게 내겐 비정상적인걸로 보일 뿐.4.아직 제품도 없는 팀이 팀원 리스트를 꾸린걸 보면 거의 중견급 스타트업 레벨이다. 아직 유저도 없고 비즈니스도 없는 팀이 CEO, CTO, CMO, CSO, C.... 레벨이 5명은 기본, 개발자 5-6명을 리스트에 박아놓는다. 일반적인 스타트업에서는 MVP가 어느정도 검증되고 나서 스케일을 낼때 하는 일들이다. 마치 삽도 뜨기 전에 삽질할 사람들 수십명을 모아놓은 그림이다. 이 중 십중팔구는 삽을 뜨려고 보니 땅바닥이 콘크리트 바닥이라 팔 수가 없거나, 애초에 팔 의지도 없었던게 대부분이지만...5.어드바이저 리스트... 내가 가장 요상하게 여기던 관행인데, 어느 프로젝트를 들어가도 이력이 화려해 보이는 어드바이저들 5명 이상은 기본으로 갖고 들어가더라. 내가 맨 처음 이바닥 들어갈때는 나름 "뭐, 아무도 가본 길이 아니니 조언해줄 사람들이 많이 필요할수도 있겠지.."라고 착각했었다. 알고보니, 그들은 그저 위에 자리를 채워주는 역할과 아주 약간의 투자자+거래소 인맥을 소개시켜주는 역할을 하는 사람들이더라. 이렇게 이름만 팔아주고 대부분 총 발행량의 0.5 ~ 2, 3%까지 토큰을 받아가는데, 대부분 상장과 함께 가장 먼저 덤핑될 토큰들이라는게 업계의 공통된 시각이다. 사실, 이 바닥이 그리 넓지 않아서 거래소 인맥 소개시켜주는건 인맥이 넓으신 1-2명으로도 충분히 커버 가능하다. 아예 제대로된 엑셀러레이터 들어가면 그들이 백배는 더 전문적으로 잘 해주는 영역이기도 하다. 아무리 생각해도 삽도 안떠본 스타트업이 저 많은 어드바이저 리스트를 꾸려야 할 이유를 지금도 못찾았고, 앞으로도 모를것 같다.6.지금이야 STO니 해서 증권형 토큰들이 하나둘씩 나오지만, ICO하는 대부분의 코인들은 본인들이 "유틸리티" 코인이라고 주장한다. 뭐, 토큰 모델 디자인상 유틸리티 토큰일 수 있다. 그런데 문제는, 이를 배포할 때 초기 토큰 홀더들은 100% "투자자"라는데에 있다. 그들이 주장하는 토큰의 유틸리티, 유저 페르소나와 1도 관계 없는 사람들이 대부분 토큰을 갖게 되고, 시장 상장 후 차익 실현을 위해 보유하는 경우가 거의 백프로다. 마치 사탕 사먹으라고 발행한 백원짜리 동전을 손에 쥔 백명의 사람들이 사실 사탕 사먹으려는게 아니고 모두 이백원, 삼백원에 팔기위해 손에 쥐고 있는것과 같은 논리다. 이러니, "유틸리티" 토큰이라는게 작동할리가 없다.7.백서... 어드바이저와 함께 내가 가장 요상하게 여기는거다. 대부분의 프로젝트가 삽도 뜨기 전에 수십, 수백장짜리의 백서부터 쓴다. 읽어보면 완전 세상을 바꿀 의지가 넘쳐 흐르는 철학적 도입부 + 본인들의 기술이 세상에 없던, 혹은 현존하는 기술은 거의 쓰레기 수준이라는 설명 + 삽도 떠본적 없는데 3-5개년 중장기 계획이 세워져 있고, 3년후에는 이미 이 시장을 평정해 있는 이야기들로 점철되어 있다. 제품도 없고 유저도 없는 상태에서 쓰여지는 수십페이지짜리 백서라는건, 그냥 대학교에서 팀플 리포트 A학점정도 맞을 만큼 잘 써진 그냥 소설 페이퍼정도인데, 이걸 무슨 신주단지마냥 만들어서 돌리는지 도무지 이해할수가 없다.8.투자자 생태계가 진짜 엄청나게 요상하게 꾸려져 있다. 일반적인 스타트업에서 보통 시드펀딩을 위해 VC들을 만나보면, 그들은 이 제품이 진짜 어떤 문제를 해결중인건지, 그 문제 해결에 열광하는 유저들이 얼마나 존재하는지, 이게 스케일이 가능한 형태인지, 스케일 했을때 시장규모가 얼마나 될건지, 이놈들이 그중 얼마나 먹을 수 있는 팀원들인지... 보통 이런걸 본다. 이런걸 봐야 나중에 스케일에 성공해서 엑싯이 되든 상장이 되든 해서 투자 수익을 얻을 수 있기 때문이다. 한편, 이바닥 투자자들이 가장 중요시 여기는 것들을 나열해 보면 다음과 같다.1) 백서가 얼마나 있어빌리티하게 작성되어 있는지 (본인들이 잘 모르는 개념들이 잔뜩 들어가 있을수록 높은 점수를 받는다)2) 흥행성 - 이 프로젝트가 얼마나 "호재"를 잘 타서 토큰 가격 펌핑이 가능한 구조인건지. 파트너사들, 각종 MOU, 화려한 이력이 있는 팀, 어드바이저 등등이 보통 활용된다.3) 토큰 분배 - 프라이빗 세일에서 디스카운트 먹은 투자자들 규모가 얼마나 되는지, 팀/어드바이저들은 얼마를 던질 준비가 되어 있는지4) 토큰 상장 - 소위 "대형" 거래소에 처음부터 상장될건지, 얼마나 많은 거래소에서 유통될건지...이 어디에도 "제품"이나 "유저"와 관련된 내용은 하나도 없다. 즉, 투자자들이 진짜 그들 제품의 성공 가능성에 대해 점쳐보며 투자할 분위기도, 그럴 생태계도 아닌게 이 판이다.9.원래 비트코인도, 이더리움도, 이런 탈중앙화 퍼블릭 블록체인 프로젝트의 강점은 오픈소스 프로젝트라는데에 있다. 모든 소스코드가 깃헙에 투명하게 공개되어 있고, 누구나 개발에 기여할 수 있다. 그런데, 이 후에 쏟아진 수 많은 블록체인 프로젝트들이 개발이 이루어지지 않거나, 본인들 소스코드는 비공개라고 하는 경우가 허다하다. 심지어 깃헙 링크가 아예 없는 프로젝트도 수두룩 하다.10.글로벌 프로젝트라는데 물론 아직 "글로벌" 유저도 없고, 레딧이나 트위터 등의 활동도 전무하고, 공식 커뮤니케이션 채널은 카카오톡 오픈챗이나 텔레그램 채널이란다. 가끔 싱가포르나 어디 글로벌 컨퍼런스에서 머리 노란 사람들과 사진 몇방 찍고 이걸 블로그나 신문기사로 찍어내면 글로벌 프로젝트가 되는 분위기다.이렇게 요상한 관행들이 어떤 결과를 가져왔는지 한번 살펴보자. 뭐, 가격 폭락하고 거품 빠지고... 이딴걸 얘기하려는게 아니다. 일반적인 스타트업 업계에 비해 이바닥의 현 성적표가 얼마나 초라한지를 보는거다.1. 전체 ICO의 78% 이상은 스캠으로 판명, 7%는 실패하거나 프로젝트가 사멸하였다 (블룸버그).2. 가장 큰 네트워크 규모를 자랑하는 이더리움 블록체인에서 돌아가는 1,375개의 댑 (DApp - 블록체인에서 돌아가는 앱을 뜻하는 단어)들 중 86%는 유저가 단 한명도 없으며, 93%는 아예 온 체인 트랜잭션이 단 한 건도 발생하지 않은 댑이다 (크립토글로브).3. 이더리움 지갑 보유자 전체의 고작 2%만이 이더리움 댑을 사용하는 유저이다 (dapp.com)4. CoinGecko에 리스팅 되어 있는 전체 4,139개의 프로젝트 중 과거 30일 동안 단 한번이라도 개발 커밋이 이루어진 프로젝트는 단 64개 밖에 없다 (2019년 2월 28일 기준).이걸 스타트업 상황에 비교해서 설명해보면 이렇다.전체 스타트업 중 78%는 사기를 쳤고, 7%는 삽도 못떠보고 망했다. 86%는 유저를 1명도 못만들었고, 93%는 유저는 있는데 유저들의 사용 이력이 1도 없다. 특정 운영체제를 쓰는 스마트폰 보유자들의 고작 2%만이 실제 앱 스토어에서 앱을 다운받아 사용하는 유저이다. 전체 스타트업 중 고작 1.5%만이 과거 30일동안 단 한번이라도 개발 커밋이 이루어졌다. 정말 요상하지 않는가? 그런데 더 충격적인건... 이걸 요상하게 여기는 우리 팀이 더 비정상이라고 보는 이 업계 시각이다. 내가 하는 스팀헌트라는 프로젝트에 대해서는 다음 글에서 상세히 소개할 예정이지만, 우리는 처음에 제품부터 만들어서 유저를 모으고, 가설을 검증하고, 사업모델을 모색하고... 그 다음 펀딩을 추진하는, 지금까지 스타트업에서 있었던 아주 일반적인 트리를 타고 있었다.백서? 물론 없었다. 제품 운영도 안해보고 저런 소설을 내 스스로 쓰는거에 대한 오글거림도 있었고, 솔직히 수만명의 커뮤니티 유저들을 상대하다 보면 그런짓에 시간을 쓸 여유도 없었다.웹사이트에는 그냥 이렇게 끄적여 놨었다...ㅎㅎ그런데, 우리는 아주 일반적인 단계라고 여기며 요즘 펀딩을 준비하고 있는데, 거의 모든 관계자들이 그놈의 "백서"를 요구한다. 제품부터 열어봅시다, 유저부터 한번 봅시다 하고 말꺼내는 사람들이 거짓말 안보태고 10에 1명 찾아볼까 말까였다. 우리도 얼마전까지는 "우린 그런 소설책 쓸 시간이 없어요~~" 이랬었는데... 결국 우리도 백기를 들고 일주일만에 백서를 써버렸다. 근데 사실 써보고 나니, 우린 제품도 1년이나 운영하면서 나름 가설 검증을 많이 해 놓은 단계라 그런지 백서가 쉽게 써지긴 하더라. 로드맵도 3-5년 후 이야기는 있지도 않다. 1년 앞에 어떻게 될지 모르는게 일반적인데 굳이 3-5년후를 쓸 가치를 못느낀다.사실, 위에서 소개한 뭔가 이 바닥에서는 "비정상"처럼 여겨지는 일반적인 스타트업들이 타는 트리를 타고 있는 블록체인 프로젝트들이, 스팀헌트가 만들어진 스팀 블록체인에는 수두룩하게 많다. 아니, 스팀에서는 오히려 위에서처럼 백서만 들고와서 펀딩하는 프로젝트들을 더 까는 경향이 있다.스팀이 코인의 시총만 따지면 40-50위권 수준이라 유명새를 타지 못한 상태이지만, 그 블록체인을 기반으로 움직이는 60여개의 댑들은 이미 실제 유저들을 어마어마하게 거느리고, 이더리움이나 EOS마냥 메타마스크나 스캐터를 깔지 않으면 로그인조차 할 수 없는 상태가 아닌, 일반적인 앱을 쓰는것과 동일한 UX에 모바일에서도 100%로 돌아간다. 코인판의 수 많은 사람들이 거래소에서 pump and dump에만 열을 올리고 있는 사이 스팀에서는 실제 소셜 앱들을 만들기 위한 스타트업 다운 스타트업 생태계가 만들어지고 있던 거다.출처 - https://stateofthedapps.com (2019년 1월 7일 기준)https://stateofthedapps.com라고, 이더리움, EOS등 2,500개 이상의 댑들의 유저수, 트랜젝션을 기반으로 순위를 매기는 공신력 있는 사이트가 있다 (무슨 돈만내면 별점 매겨주는 ICO레이팅 그딴 사이트가 아니다). 거기 차트에 들어가보면 이미 스팀기반 댑들이 상위권을 차지하고 있다. 스팀헌트도 항상 상위 10-20위사이에서 왔다갔다 하면서 최상위권을 유지중이다. 또한, 대부분이 도박, 게임등인 이더리움/EOS와는 달리 스팀기반 댑들은 소셜 서비스라는게 엣지이다. 스팀헌트 역시 테크 얼리어답터들의 "커뮤니티" 플랫폼이다.오늘을 기점으로 다시 브런치 활동을 시작하려고 한다. 내가 직전에 연재하던 시리즈가 "기획돌이의 스타트업 고군분투기"였는데, 이건 일반적인 스타트업에서 좌충우돌하던 깨달음에 대한 글들이였다면, 오늘부터 연재할 글들은 이 "비정상"이 "정상"처럼 여겨지는 블록체인판에서 내가 스팀헌트 프로젝트를 운영하면서 겪게되는 좌충우돌에 대한 이야기들을 소개할 예정이니, 많은 관심과 구독 부탁드린다.글쓴이는 스팀헌트 (Steemhunt) 라는 스팀 블록체인 기반 제품 큐레이션 플랫폼의 Co-founder 및 디자이너 입니다. 비즈니스를 전공하고 대기업에서 기획자로 일하다가 스타트업을 창업하고 본업을 디자이너로 전향하게 되는 과정에서 경험한 다양한 고군분투기를 연재하고 있습니다.현재 운영중인 스팀헌트 (Steemhunt)는 전 세계 2,500개가 넘는 블록체인 기반 앱들 중에서 Top 10에 들어갈 정도로 전 세계 150개국 이상의 많은 유저들을 보유한 글로벌 디앱 (DApp - Decentralised Application) 입니다 (출처 - https://www.stateofthedapps.com/rankings).스팀헌트 웹사이트 바로가기
조회수 1733

잔디 팀에서 가장 자유로운 영혼을 가진 그녀! 고객 경험(CX)팀의 Soo를 만나다

맛있는 인터뷰: 고객 경험(Customer Experience) 매니저 Soo ▲ 점심엔 역시 맥주 한 잔이죠? 알코올과 함께 하는 맛있는 인터뷰 먼저 인터뷰를 제안해 온 사람은 처음이다. 본인 소개를 부탁한다Soo(이하 ‘S’): 반갑다! 잔디 팀에서 고객 경험: CX(Customer Experience) 업무를 담당하고 있는 Soo라고 한다. 고객 응대뿐 만 아니라 서비스 번역이나 비즈니스 팀에서 사용되는 제품 메뉴얼 작성, 영상 작업 등 고객 경험에 연관된 다양한 업무를 수행하고 있다. 하는 일이 꽤 많은 것 같은데?S: 잔디 팀원이라면 당연히 이 정도는! 타이 음식은 오랜만이다. 이 곳을 오게 된 이유가 있다면?S: 우리가 온 곳은 망고플레이트에서도 평이 좋은 태국 음식점 ‘알로이 타이(Aloy Thai)‘다. 개인적으로 동남아 음식을 너무 좋아한다. 미국에 있을 때 먹었던 쌀국수 맛이 늘 그리웠는데.. 수소문 끝에 알아낸 인생 맛집이다. 선릉역 2번 출구에서 도보 5분 거리에 있다. 정확한 주소는 서울시 강남구 대치동 8… 잠깐! 광고비를 받은 건가? 맛있는 인터뷰는 원칙적으로 협찬을 금지하고 있다S: 무슨 소리. 인생 맛집이라 이렇게라도 알리고 싶었다. 아님 말고..S: ..^^ 음식과 함께 술을 주문한 인터뷰이는 Soo가 처음이다S: 평소 술을 즐기는 편이다. 하지만 오해하지 않았으면 좋겠다. 술을 좋아하는 거지 잘 마시는 건 아니다. 가끔 집에서 혼술하는 것도 좋아한다. 술 말고 좋아하는 건?S: 게임을 좋아한다. 미국에 있을 때는 집에서 혼자 농구게임을 엄청 많이 했고, 친구들과 철권을 즐겼다. 한국에서는 롤을 무척이나 많이 했다. 아침부터 새벽까지 랭겜을 돌리곤 했다. 티어가…?S: 그것은 비밀이다. (웃음) 술, 게임, 쌀국수까지. Soo의 미국 생활이 진심 궁금하다S: 남들과 크게 다르지 않다. 중학교를 제외한 학창 시절을 모두 미국에서 보냈다. 한국에서 이렇게 오래 지내보는 건 처음이다. 잔디 팀에 조인하면서 한국 생활을 시작한 격인데 처음엔 무척 낯설었다. 2년 지난 지금은 꽤 괜찮아졌다. ▲ 미국에 있을 당시의 Soo 모습. 왼쪽에서 화사하게 웃고 있는 사람이 Soo다.어떻게 잔디 팀을 알고 지원했는지 궁금하다S: 대기업에서 인턴을 해보니 수직적인 기업 문화가 맞지 않았다. 때마침 지인에게 잔디 팀을 추천 받게 되어 입사하게 되었다. 스타트업은 뭔가 열정이 넘치다 못해 폭발하는 사람만 가는 곳이라 생각했는데, 지금은 그 ‘스타트업’ 중 한 곳에서 일하고 있다. 묘한 감정이 든다. (웃음) 잔디 팀의 업무 문화는 마음에 드는가?S: 잔디 팀에서 일하면서 가장 좋은 점은 내 직무에서 풀어야 할 숙제를 스스로 한다는 점이다. 개인적으로 가장 재미있고 신나는 경험이다. 너무 교과서적인 대답이다. 신박한 답변을 원한다S: 역으로 질문하고 싶다. 잔디 팀의 업무 문화가 마음에 드는가? 소중한 말씀 감사합니다..S: ^^ 주말에는 무엇을 하고 지내는가?S: 보통 술을 마신다. (웃음) 아니면 집에서 영화를 본다. 뭔가 #술 #알코올 #혼술 #집스타그램 해시태그를 붙여야 할 것 같은 인터뷰다. 다른 이야기를 해보자!S: 언제든지! 잔디 표지모델은 어떻게 하게 되었는지?S: Product 팀의 DL이 부탁해서 촬영하게 되었다. 사진을 본 내 친구들이 이게 뭐냐며 비웃었던 게 가장 기억에 남는다. DL이 보정을 해준다고 했는데 실제로는 목주름만 보정해줬다. 뭔가 슬펐다. ▲ 잔디 홍보 자료에 자주 등장한 Soo 일하는 자리를 보면 아기자기한 물건들이 많다. 애착이 가는 물건이 있다면?S: 내가 기르고 있는 식물이다. 귀엽기도 하고, 물만 줘도 조용히 잘 자라는 녀석들이 기특하다. 펫을 기른다는 기분으로 정성스레 기르고 있다. 이름도 지어주었다. 이름이?S: 밝힐 수 없다. 맛있는 인터뷰를 통해 공개하기엔 부적절한 이름이다. (웃음) 대학교에서 신문방송학을 전공했다고 들었다. 전공과 무관한 고객 경험 업무를 하게 된 계기가?S: 고객 응대만을 하는 CS(Customer Service)가 아니라 총체적인 ‘고객 경험’에 참여하는 CX 라는 점이 끌렸다. 제품과 고객을 잇는 브릿지 역할을 한다는 점이 매력적이었고, 잔디를 이용할 때 퍼널(Funnel) 최전방에서 가장 먼저 접하는 사람이 나라는 점도 흥미로웠다. 그리고 주 전공인 영상 제작 업무도 CX 일을 하며 할 수 있어 좋았다. 업무를 하다 보면 재미있는 에피소드가 있을 것 같다S: 연령대가 높은 사용자 중 생각보다 컴퓨터 사용법을 잘 모르는 경우를 종종 볼 수 있다. 그럼에도 불구하고 최근 많은 이슈가 되고 있는 협업 트렌드를 배우고자 열심히 노력하는 모습이 너무 인상적이었다. 더욱 더 도와주고 싶다는 생각이 자연스레 들 정도다. 협업툴에 대한 요구가 많아졌음을 직감하는지?S: 협업툴에 대한 요구도 많아졌지만 그보다 더 피부에 와닿는 변화는 고객의 인식이 확연히 바뀌었다는 점이다. 처음 CX 업무를 시작했을 때 접한 잔디 사용자들은 돈을 주고 서비스를 사용한다는 개념을 생소하게 여겼다. 반면 지금은 다르다. 최근 잔디 도입을 문의하는 고객 대다수는 서비스 요금부터 문의한다. 잔디 도입 문의 어디에 하는 게 효과적인가?S: 잔디 웹사이트 우측 하단에 있는 파란색 버튼을 클릭하거나 도입 문의 폼을 남기면 CX팀과 세일즈 팀이 바로 도움을 드린다. ▲ 인형과 식물이 가득한 Soo의 업무 공간잔디 팀에서 배운 점이 있다면?S: 사람과 소통하는 방법을 가장 많이 배웠다. 아무래도 한국 문화에 익숙하지 않아 ‘한국식 소통 방법’이 낯설었는데 사회 생활을 통해 자연스레 학습할 수 있어 좋았다. 잔디 팀에서의 경험 덕분에 자신감이 생겼다. 다른 곳에 간다고 해도 잘 할 수 있을 것 같다. 첫 직장으로서 잔디 팀의 생활이 만족스럽다는 걸로 들린다S: 물론이다. (웃음) 정말인가?S: 물론이다. 건배나 하자. 태국 음식엔 역시 맥주가 짱이다. (웃음) 어떤 꿈을 가졌는지 궁금하다S: 사실 무엇을 해야할 지 정한 건 없다. 막연하지만 나만의 것을 해보고 싶다. 사무실에 앉아서 일하는 것보단 무언가 발로 뛰며 성취하는 경험을 해보고 싶다. 이전 인터뷰이였던 잔디 HR 담당자 Amy의 질문이다. 자신의 인생에서 가장 행복했던 순간은?S: 행복했던 순간이 너무 많아 한 가지만 고르기 힘들다. 뭔가 성취감을 느꼈을 때 행복을 느끼는 것 같다. 그 외에는 맥주 한잔하면서 집에서 뒹굴뒹굴할 때가 행복하다. 일상의 소소한 것에서 느끼는 즐거움이 진짜 행복은 아닐지 생각해본다. 다음 인터뷰이를 위한 질문을 부탁한다S: 올해 꼭 이루고 싶은 목표는? ▲ 술과 음식으로 점철된 맛있는 인터뷰가 열린 선릉역 맛집 ‘알로이 타이’마지막 질문이다. 왜 맛있는 인터뷰가 하고 싶었는지?S: 잔디 팀과 함께 한 시간이 어언 2년이다. 팀의 일원으로서 잔디 이름을 가진 어딘가에 내 흔적을 남기고 싶었다. 맛있는 인터뷰가 그 흔적으로 적합하다고 생각하는가?S: 물론이다. 맛있는 인터뷰를 보면 그간 잔디 팀과 함께 했던, 그리고 함께 한 멤버들의 모습을 꺼내볼 수 있다. 일종의 추억 보관함이라고 해야할까? 내 이야기도 잔디 팀의 누군가에게 추억이 될 거라 생각해 내 이름을 꼭 남기고 싶었다. 인터뷰 해줘서 너무 고맙다. (웃음) #토스랩 #잔디 #JANDI #팀원소개 #인터뷰 #기업문화 #조직문화 #팀원자랑
조회수 1049

S/W 공학과 실전과의 거리감

학교에서 배우는 소프트웨어 공학이 왜? 실제 업무에서 사용이 안되는가?그동안 후배들에게 멘토링을 할 때에 가장 많이 받았던 질문 중의  하나이다. 평소에 답변하던 것들을 글로 옮겨 본다.소프트웨어를 전공하는 많은 후배들은 대학생활 4년 동안 배우는 다양한 이론들과 소프트웨어공학들의 수많은 이론을 배운다. 하지만. 대부분의 선배들은 사회생활의 실제 프로그래머로 취업을 한다고 해도, 프로그래밍을 실제 업무에서 하지만, 실제 관련된 이론과 기술. 수많은 가이드라인과 품질 관련 이슈에 대해서 실제 적용하기 어렵거나, 거의 사용하지 않는다고 선배들에게서 이야기를 듣는다.물론, 이 경향은 많이 바뀐 것은 사실이다. 이제 대부분 공학적인 접근법을 사용한다. 하지만, 그럼에도 불구하고 실제 현장에서는 이 현상이 그다지 바뀌지는 않았다.과연 우리가 학창 시절 배우는 그 많은 이론들은 도대체 왜? 만들어졌는데, 실제 사용이 안 되는 이유는 무엇인가? 학창 시절에는 자바나 C와 같은 프로그래밍 스킬만 높이면 되는 것인가? 도대체, 학생 시절 배우는 그 많은 이론과 공학, 품질 관련 이슈들은 실제 업무에서 그렇게 쓸모없는 것이라고 대부분의 선배들이 이야기하는가?실전과 대한민국의 현실. 그리고. 소프트웨어 프로그래밍에 대해서 학생들에게 삽질의 대가가 한마디 하려 한다. 왜? 우리는 학교에서 배우는 이론을 실제 사용할 기회가 없는 것일까?필자는 소프트웨어 공학을 학창 시절 배운 것이 아니다. 오히려, 실제 소프트웨어 개발 활동을 하면서, 공학적인 것이나 소프트웨어의 시각화를 해야만, 소프트웨어의 품질을 관리할 수 있다는 것을 몸으로 느끼고, 이것이 실제 소프트웨어를 상품이나 서비스의 명목으로 사용자들에게 제공하는 경우에 정말 필요하다는 것을 20년의 실제 개발자 생활을 하면서 그 필요성에 대해서 처절하게 느껴왔다.차라리, 필자가 핵심 서비스와 중요한 개발 내용을 직접 코딩하는 개발자의 역할을 할 때에는 이러한 공학적인 것이나, 작은 규모의 소프트웨어를 개발할 때에는 이러한 필요성을 느끼지 못했었다. 대부분의 작은 규모의 소프트웨어를 개발할 때에는 단기적인 일들이 많았다.사용자의 요구사항에 맞추어서 그 시기에 그때에 맞추어서 소프트웨어를 개발하였고, 해당 소프트웨어를 다시 유지 보수한다던가, 다시 수정 작업을 하지 않는 식의 작업을 하는 경우에는 이러한 공학적인 개념이나 그 배경으로 디자인하고 설계한다는 것에 대해서 매우 귀찮게 생각했었다.과거 첫 경험이었던 코볼이나 클리퍼 시절에는 해당 소프트웨어의 규모가 크지도 않았으며, 데이터의 구조 설계 또한 대부분 파일 중심의 데이터였었고, 화면의 구조 또한 수십 개를 넘지 않는 정도의 규모였다.오히려, 고속의 인덱스를 걸기 위한 테이블 접근법이나, 고속으로 화면에 출력하는 방법. 데이터를 조금 더 빠르게 구성하는 방법들에 집중할 시기에는 굳이 플로우 차트를 왜? 그리는 것이며, 파일 구조에 대해서 디자인해야 하는지에 대해서 의아함을 똑같이 가지고 있었으며, 굳이 설계나 디자인 없이 바로 코딩과 개발을 하던 시절이었다.하지만, 대규모 시스템을 주로 구사하는 웹서비스의 시대에 있어서, 단순한 로그 정보하나를 시리얼라이즈화시키는 것만 봐도 그 사람의 수준을 파악할 수 있고, 텍스트 중심의 구성 설계를 보면 향후 시스템의 성능에 대해서도 예측이 되는 경험을 축적하게 되면, 가장 중요한 것은 역시... 공학적인 접근법이다.필자가 소프트웨어 공학의 첫 번째 개념에 대해서 눈을 뜨고, 그 필요성을 절감하던 첫 번째가 바로, 고객에게 제공되는 소프트웨어가 지속적인 유지보수성을 가지기 시작할 때에 그 필요성을 처음으로 인지하기 시작하였다.처음의 요구사항이 변화되면서 사용자의 업무 흐름이 소프트웨어의 구조와 데이터베이스의 구조를 계속 변화하여 나가고, 이러한 상황을 미리 설계된 자료를 통해서 예측하거나, 소프트웨어 아키텍처적인 관점으로 조금 더 세밀한 환경에 대해서 메모가 되어있고, 그 구성에 대해서 서술해두었다면, 상당히 고속 개발을 하고, 소프트웨어 품질을 향상시키는데 매우 중요한 첫 번째 개발 행위가 되었을 것이라고 느꼈었다.또한, 개발자가 수십, 수백 명 단위로 소프트웨어의 설계가 대단위로 변화하고, 그 개발 품질에 대한 통제와, 적정한 수준의 개발 수준을 형성하게 하는 방법에 대해서 고민할 때에도 똑같이 이러한 소프트웨어 개발의 시각화에 대해서 인지하기 시작한 것이다.당시에는 공학적인 개념 없이 유사한 방법이나 표현방법을 고안하였으나, 관련된 내용을 찾아보고, 전문가들에게 조언을 구해보니, 상당 부분 그 부분에 대해서 전문가들 간의 협의가 있었고, 그 표준화되는 시각화 방법들과 방법론들이 매우 많이  연구되었다는 것을 알게 되었다.필자는 오히려, 이러한 개발과정에 있어서 필요한 것들을 개발하다가, 공학적인 베이스나 방법론들이 어떻게 실제 개발에 사용되어야 효과적인가에 대해서 실전에서 터득하고, 실전에 배치되는 것에 대해서 이해를 넓혔다.또한, 미국에서 개발되어진 개발 방법론이 국내의 실정이나 환경에 적합하지  않은다는 것을 깨닫고, 그러한 부분들을 어떻게 지식을 바꾸어야 하며, 실제 실천해야  하는지에 대해서 아키텍트 포럼이나 모임에서 역설하기 시작하였고, 그 부분을 실제 개발에 접목하려 애써왔다.그리고, 그 경험을 중심으로 소프트웨어 아키텍팅과 관련된 경험을 늘려왔고, 모바일과 웹서비스를 중심으로 하는 기업에서 개발 총괄을 하는 경우에는 그동안 축적한 소프트웨어 개발의 경험을 바탕으로 소프트웨어 형상관리 SCM(Software Configuration Management)을 중심으로 이슈관리, 개발, 테스트, 배포의 단계를 자동화하는 소프트웨어 개발의 비주얼라이제이션을 어떻게 실현할 것인가에 대해서 고민하고, 그 환경을 보다 쉽게 전파할 수 있는 공정과 형태를 미국 중심의 CMMI체계와 국내의 SP의 기준을 배경으로 상당 부분 고민하고 있다.그런데, 가끔 만나는 후배들이나 이제 막 개발자의 생활을 시작하려는 친구들에게서 많이 받은 질문 중의 대표적인 질문이 ‘도대체, 학교에서 배우는 소프트웨어 공학은 언제 사용하나요?’, ‘도대체, 대학 4년 동안 배우는 그 많은 이론들은 언제쯤 사용할 수 있는 것일까요?라는 질문들을  그동안 수십 번, 수백 번 받아왔다.심지어, 소프트웨어 개발 생활을 몇 년정도 한 후배들에게서 마저도 듣게 되니, 이 부분에 대해서 한 번쯤은 글로 남겨 두어야 하겠다고 생각하였다.과거, ‘서울 행복 직업박람회’에서  질문받은 내용은 이러했다.그 당시 필자에게 찾아온 대학생이 질문한 내용은 매우 간단하지만, 매우 어려운 답변일 수 있었다. 그것은, ‘왜 대학교 때 배우는 이론이나 원론과 같은 기본적인 내용들이 실제 사회생활 나가면 필요 없다고 자기의 선배들이 이야기하는 것일까요?. 실제. 취업하면 정말 그런가요?’이 질문은 이번 이야기의 주제이며, 필자가 20년을 넘게 소프트웨어 개발자 생활을 하면서 받아온 질문 중에 가장 빈도수가 높은 질문이라고 하겠다. 필자가 자부해온 삽질의 대가라는 점에서 그 친구는 그 친구는 정말 그 이야기를 잘 해줄 사람을 찾아온 것이라고 생각하면서 다음과 같이 설명했다.결과론적으로 '필요하지만, 필요없는 곳도 있다. 하지만, 가능한 필요한 곳을 찾아봐라.'라는 식의 이야기를 해주었다.자, 그렇다면. 필자가 이런 선문답 식의 답변을 하게 된 내용을 하나씩 풀어서 설명해보자. 도대체, 대한민국의 소프트웨어 개발을 하는 곳에서 왜? '소프트웨어 공학'적인 개념이나 이론들이 사용이 안되고 있는 것일까?물론, 정답은 간단할 수 있다. 국내의 대부분의 소프트웨어 개발회사의 경우에는 소프트웨어 공학쯤은 없어도, 아무런 문제(?) 없이 소프트웨어 개발이 가능한 경우이다.실제, 그런 회사도 그런 개발 조직도 상당히 많다는 것을 필자는 경험으로 알게 되었다. 그렇다면, 그렇게 소프트웨어 공학쯤은 필요 없는 기업이나 개발 조직은 어떤 곳들일까? 그곳들부터 알아보자.개발 총괄 책임자의 대우가 형편없는 회사필자는 개발자의 생활을 시작하는 어린 친구들이 첫 번째 직장을 가지는 곳에 대한 선택에 대해서 조언을 해왔을 때에 가장 먼저 해주는 조언은 이것이다. 면접을 보려는 회사의 개발 총괄 책임자나 리더에 대한 대우와 회사 내에서의 위치를 먼저 살펴보라는 것이다.대부분 대우가 형편없거나, 매일 야근과 반복된 개발 일정의 반복이 계속되는 회사의 경우에는 그 대우가 형편없는 것 이상으로 개발의 공정이나 개발의 방법이 정형화되어있지 못할 가능성이 매우 높다.물론, 소프트웨어 개발이 시각화가 되면, 요구사항의 변동폭이 보이게 되고, 해당 정량적인 지수가 도출되므로, 해당 부분에 대해서 대응이 가능하지만, 개발 총괄 책임자의 지위가 낮거나 대우가 형편없다는 이유는 다음의 두 가지의 경우에 해당이 된다.하나. 공학적인 방법이나 정형화된 방법을 제안하는데, 회사의 최고책임자가 인정하지 않는 경우이다.이 경우에는, 보통은. 제대로 알고 있는 소프트웨어 개발자들은  해당되는 조직을 빠르게 떠나고, 별로 기대할 수 없다는 것에 대해서 자괴감이나 패배감과 같은 분위기가 개발 조직 내에 흐른다는 것을 곧 감지할 수 있을 것이다.둘. 실제 이러한 공학적인 방법 따위의 개발 방법론으로 통제할 수 없는 고객이 '슈퍼갑'인 경우이다.실제, 소프트웨어 개발 활동을 해당 '슈퍼갑'에서 영업적인 능력으로 얻어낸 경우의 회사의 경우에는 아무리, 옳은 이야기, 옳은 방법론으로 대응한다고 해도, 개발 막판에 개발의 방향성 자체를 손 뒤집듯이 바꿔버리는 상황이 빈번한 경우이다.대부분 이런 경우에는 소프트웨어 개발 총괄 책임자가 오히려, 공학적인 것을 알고 있거나, 똑똑한 사람이라면 멘붕에 빠지거나, 자괴감에 빠져서,  대충대충 소프트웨어 개발을 하거나, 자기가 먼저 자리를 뜨는 경우가 대부분이다. ( 버티는 사람은 몰라서 버틸 수 있다고 설명하는 것이 더 바람직하겠다. )물론, 이 경우에도 그런 것을 당연시하면서, 공학적인 개념도 모르는 리더가 고객과 같이 동조하는 경우가 오히려, 업무가 수월해지는 경우가 많은 것 또한 현실이다. 고객과 개발 책임자가 같이 '닭짓'을 하는데, 개발 조직이 온전할 리 없다. 공학 따위는 집어치우고, 프로세스나 정량화된 목표, 자동화된 방법과 같은 소프트웨어 품질은 그냥, '책'에만 나오는 단어이며, 개념일 뿐이다.실제, 똑똑하고 말 잘하고, 올바른 방향으로 이끄는 리더가 이 조직에 리더가 된다고 하더라도. 어쩔 수 없이, 버티지 못하고, 떠나게 되는 것을 흔히 보게 된다.그리고, 이러한 조직에 있는 대부분의 개발자들은 '소프트웨어 공학'따위의 '장난'은 실제 개발이 필요 없다고 역설하고, 이것을 당연하게 여긴다. 보통, 이렇게 만들어지는 소프트웨어의 품질은 보장할 수 없고, 이 보장할 수 없는 소프트웨어를 통해서, '슈퍼갑'에서 꾸준한 유지보수 비용과 일거리가 발생하는 방법은.. 아마도, '4대 강'처럼. 한번 만들어 두면, 끊임없는 유지보수 업무를 발생시키는 식의 문제 정의와 처리방법이라고 할 수 있겠다.당연한 것이지만, 결론적으로 이야기하자면, 이런 개발 조직에서 개발 총괄 책임자의 대우는 형편없고, 일정 조절이나 개발에 대해서 지휘할 수 있는 권리나 인사권 같은 것도 매우 부족한 상황으로 변화한다.그래서, 이런 회사일 수록, 소프트웨어 공학은 그냥, 뜬구름 잡는 이야기가 되는 경우가 일상다반사이다.실제, 소프트웨어 개발을 하지 않는 회사소프트웨어 개발 조직이 있지만, 실제 소프트웨어는 개발하지 않고, 심지어. 소프트웨어 유지보수마저도 관련 업체에 일임하거나 위임하는 경우의 조직이 해당되는 경우이다. 대부분의 슈퍼갑인 회사와, 어설프게 소프트웨어를 개발하는 기업들의 전산실에  해당하는 곳이 이런 환경에 해당된다.이 경우 소프트웨어의 공학적인 배경이나, 개발에 대한 스킬과 협조보다는, 일반 회사의 기획과 경영, 회계와 관리에  해당하는 업무들이 가장 중요하므로, 소프트웨어 개발의 시각화나 공정에 대해서는 그다지 관심이 없는 경우이다. 오히려, 제품을 선택하고, 유지보수 업체를 어떻게 관리하고 운용할 것이냐에 핵심과 초점이 있기 때문에, 소프트웨어 공학적인 배경은 가장 중요한 선택의 포인트가 되지 못한다.오히려, 투입 대비 효과에 대한 경영학적인 관점의 스킬과 개념이 더욱더 중요하다고 하겠다. 필자는 개인적으로 대부분의 대학에서 이러한 관점으로 교육을 하지 않는 것에 대해서 매우  불만족스럽다.분명, 소프트웨어 개발과 소프트웨어를 개발, 유지보수, 운영 및 관리한다는 것은 매우 연관성이 높기 때문에, 이와 관련된 과정이나 소통방법, 그리고. 윤리체계와 운영방법 등에 대해서도 충분하게 소프트웨어 관련학과에서 교육이 필요하다고 생각한다.이러한 회사에 입사하게 되는 개발자의 경우에는 소프트웨어 개발자가 된다기 보다는, 소프트웨어 개발과 운영을 관리하는 회사를 관리하는 업무를 더욱더 많이 배우고 경험하게 되므로, 소프트웨어 개발공학 따위의 뜬구름 잡는 이야기는 경력이 쌓여갈수록 더더욱 필요 없게 된다.사장이 직접 개발하는 소규모 개발회사이러한 경우도 몇 가지의 사례로 나눌 수 있지만, 대부분의 구성 형태는 정말 비슷해지는 점이 매우 특이하다. 그것은, 소프트웨어 개발회사에 있어서 개발 총괄 책임을 '사장님'이 직접 통제를 하는 경우이고, 실제, 중요한 코딩도 '사장님'께서 직접 하는 경우이다.이 경우에는 '소프트웨어 공학'적인 콘셉트보다는, '사장님'의 경험적인 바탕에 의해서 소프트웨어 개발의 시각화가 만들어지고, '사장님'의 지극히 개인적인 경험과 지식의 배 경위에서 '정량적'지수들이 결정되는 경우이다.이 경우에는 '사장님'의 스킬이 높은 파트의 경우에는 매우 느슨할 수도, 매우 강하게 조일 수 있고, 사장님의 경험이 부족하거나 어색한 지식을 가진 파트의 경우에는 매우 불완전하고, 매번 변경된다는 것을 개발 조직 전체가 느낄 수 있다.이러한 조직의 특성은 상당 부분 필요한 소프트웨어 품질을 유지하고 있기는 하지만, 특정 버그나 특정 형태, 특정 상황에 대해서는 포기하는 경우가 많다는 점이다. 또한, 개발 조직의 구성역시 특정한 방향으로 구성되어진 기형적인 개발 조직이 만들어진다는 것이다.물론, 이 방향이 완전히 틀린 것이 아니라는 점 또한 매우 중요한다. 해당 업무나 설루션, 패키지에 적합한 방향에 대해서 '사장님'의 경험에 의해서 구축되었기 때문에, 특정 공학적인 지식을 가지고 있거나, 개발의 경험이 풍부한 사람이 해당 조직에 들어와서 보기에는 매우 어색한 점이나, 매우 이상한 형태를 느끼게 된다.대부분 이러한 소프트웨어 개발 조직은 보통, 수년 이상 설루션이나 서비스를 진행해오고 있고, 특정한 형태로 발전되어 있고, 적당한 개발자들이나 서비스 운영조직과 내재화된 자체들의 경험들이 중첩되어 있어서, 정말 세밀하게 분석하고, 환경을 조절하기에는 정말 어려운 환경으로 진화된 경우가 많다.대부분, 급여와 업무, 직원들의 잦은 이탈과 특정 개발 조직에 대한 '사장님'의 편애가 눈에 뜨일 정도로 보이는 경우가 많다. 그것은, 해당 소프트웨어와 서비스가 그 환경에 가장 적합한 구조를 가지고 있기 때문에 발생하는 경우이기 때문에, 냉정하게 분석해보면, 그 조직의 형태가 매우 적합한 구조인 경우가 많다.그래서, 이러한 조직에 들어가는 경우에는 '이론적'인 소프트웨어 공학은 잠시 뒤로하고, '경험적으로 구축되어진 개발 프로세스'에 익숙해져야만 그 조직과 프로세스를 이해할 수 있게 된다. 이러한 회사의 경우에는 필요한 경험과 지식에 대해서 매우 제한적이기는 하지만, 나름대로의 규칙과 개발 철학, 향후. 발전방향에 대해서 어느 정도 구축하고, 이를 따라서 개발 조직을 운영하고 있다는 점이기 때문에, 어설픈 개발공학적인 개념으로 이러한 환경을 이해한다는 것은 매우 어려울 것이다.초보 개발자들의 경우에는 이러한 개발 조직에서 수년 이상을 지내야만, 이러한 방법을 이해하는 경우가 대부분이다. 그래서, 초기에는 '공학'따위는 없다고 푸념하거나, 필요 없다고 이야기하는 경우이다.소프트웨어 공학은 해당 개발 조직과 개발자들의 수준, 축적된 시각화 방법들을 종합화하여 보이는 활동이기 때문에, 이러한 개발 조직은 이러한 정착된 패턴에 대해서 한 번쯤은 시각화를 위한 종합진단과, 형태에 대해서 정립하고 자신들만의 개발 문화를 선언하는 방법을 택하는 것이 좋다. 그래서, 공학적인 방법에 대해서 고민하고, 품질에 대해서 조금은 더 발전적인 방법으로 진화할 수 있게 하는 방법이 될 것이다.하여간, 잘 모르는 사람들에게는 이러한 개발 조직은 매우 이상하게 보인다. 단, 이 조건에 가장 적합한 회사의 경우는 '적당한 수익을 시장에서 얻고 있으며, 그 시장에 맞추어 개발 조직과 문화가 발전한 회사의 경우'를 의미하는 경우이다.당연한 것이겠지만, 이러한 환경으로 '시장'에서는 버티기 매우 어려울 것이고, 곧 망할 가능성이 높은 경우이다. 물론, 영업적은 능력으로 개발 조직이나 회사가 운영되고 있다면, 자연스럽게, '개발 총괄 책임자의 대우가 형편없는 기업'으로 변화되기 때문이다.특정 개발 조직이 관습화 된 인사권을 행사하는 경우보통은 이러한 회사를 게임회사에서 잘 찾아볼 수 있다. 특정 서버의 기술이나 클라이언트의 개발팀에서 사람을  구인하는 데 있어서, 일반적인 구인의 방법보다는 인맥이나, 특정 방법에 의해서 인력을 수급하는 경우이다.이 경우에 중요한 개발 공정이나 프로세스와 개발경험들은 내부의 팀에서 내부의 팀원들을 통해서만 서로 간에 운영되는 형태이며, 보통은 게임회사나 특정 하드웨어 기술을 가진 업체들에게서 이러한 환경들이 빈번하게 나타난다.한편으로는 이러한 방법이 개발 조직 내에서의 테두리가 제한되기는 하지만, 어느 정도 회사가 성장하거나, 회사의 규모 이상이 되지 않는다면, 그렇게 문제가 되지 않는 경우가 된다. 필자의 경험에 의하면 매출 1조 원을 넘기는 기업이 되는 경우의 하드웨어 업체이거나, 매출 1천억을 넘기는 소프트웨어 기업의 경우에 이러한 개발 조직의 문화가 가장 큰 걸림돌이 되는 경우를 많이 보아왔다.이런 경우에 대부분의 중심 개발 조직이 아닌 조직에서는 자신들이 공정을 변화시키거나 제품의 중요 기능을 다룰 수 없고, 반복적인 유지보수나 무의미한 행위들이 연속되는 경우를 계속 경험하게 되므로, 소프트웨어 공학에 대해서 많은 의아심을 가지게 되는 경우이다.이상의 몇 가지 기업의 형태를 살펴보면서 필자가 알게 된 것은 소프트웨어 개발의 형식은 역시 무형식이며, 그 상황과 형태에 따라서 변화되고 진화한다는 것이다. 또한, 위에서 이야기한 몇 가지의 경우의 공통점은 바로, ‘소프트웨어의 품질’이 그다지 중요하지 않은 기업의 경우에 해당한다고 이야기할 수 있다.위에서 언급한 회사들의 공통점은 ‘소프트웨어의 품질’ 때문에 개발 조직을 변화시키거나, 개발 문화에 대해서 고민할 필요가 없는 회사라는 점이다. 당연한 것이겠지만, 소프트웨어 공학은 ‘뜬구름 잡는 이야기’를 하는 학창 시절 때에나 이야기한다고 이야기를 하는 선배들을 대부분 만날 것이다.대한민국에서 만날 수 있는 대부분의 소프트웨어 개발 활동들은 소프트웨어의 품질이 그다지 중요하지 않은 경우가 참 많다는 것이다.일단, 가동을 시작한 서비스가 죽게 되면 크게 문제가 되는 경우이거나, 해당되는 소프트웨어가 작은 문제로 인해서, 실제 비즈니스와 업무에 크게 문제가 되는 경우가 아니라면, 소프트웨어의 품질에 대해서는 그 중요성이 떨어지게 되는 것이 당연하다.충분한 소프트웨어 가치를 인정받을 수 있는 평가와 방향성에 대해서 충분하게 고민하고 있지 않은, 회사이거나 소프트웨어 개발 조직의 경우에는 당연한 것이겠지만, ‘소프트웨어 공학’은 그다지 중요하지 않다는 것이 결론이라고 하겠다.소프트웨어 품질이 정말 필요한 곳인가?이렇게 답변을 정의할 수 있다.소프트웨어 품질이 중요한 가치를 가지는 곳에서는 충분하게 소프트웨어 공학적인 이론과 배경이 가장 중요한 것이 될 것이다. 필자가 아는 어느 회사의 경우에는 소프트웨어의 기본적인 행위하나 가 실제 큰 비용으로 계산되는 경우가 있었다.단순한 하나의 물류이지만, 어떤 물류를 크레인을 사용하여 한 번 잘못 이동하게 되고, 해당되는 물품이 전혀 엉뚱한 나라에 가있거나, 해당 물품이 적재되고 내려지는 과정이 중첩되면서 만들어지는 비용을 단 한번 행위의 가치로 평가하였을 때에 1번 펑션이 1억 원 정도의 비용으로 계산되는 경우라면, 소프트웨어 개발의 펑션이나 개발 프로세스에 대해서 얼마나 고수준으로 설계하고 평가될 것인가에 대해서 생각해보면 될 것이다.이미, 은행에서 자금이 이체되고, 움직이는 과정에 대해서도 개별적인 가치에 대해서 평가를 할 수 있을 것이다. 과연, 내가 만드는 소프트웨어의 기본가치는 어떻게 되는 것일까? 에 대해서 생각해보면, 우리가 만드는 소프트웨어에 얼마나 고품질이 필요한 것인가에 대해서 설명할 수 있을 것이다. 그렇지만, 필자는 이렇게 이야기하겠다.슬프지만, 대한민국의 IT 중에서 소프트웨어 개발 분야에 있어서, 정말 고품질이나 고성능을 요하는 수준으로 요구하는 곳이 거의 없기 때문에 이러한 문제는 계속 발생할 것이며, 계속 이러한 질문은 만들어질 것이다.대부분의 학생 시절에 우리가 배우는 기본과 이론들은 쉽게 설명해서 죽지 않는 서버와 데몬을 만들고, 가능한 정해진 규칙 하에서는 다운되지 않는 웹서비스를 만들려고 그런 기본과 이론을 배운다.하지만, 대부분의 서비스들은 죽으면, 서버의 데몬 프로세스를 죽였다가, 다시 동작하면 되는 수준의 업무면 충분한 경우가 대부분이다. 더군다나, 외국에서 만들어진 프레임웍이나 만들어진 소프트웨어 위에서 동작되는 소프트웨어를 만드는 환경에서라면, 이러한 공학이나 이론 따위야 그다지 중요한 것이 아니게 될 것이 아니라는 점이다. ( 그 책임은 비싸게 구매한 DBMS나 프레임웍이 해결해야할 책임이라고 떠넘긴다. )결론적으로 마지막 이야기를 한다면, 과연 이러한 소프트웨어 가치를 충분하게 만들어 낼 수 있는 소프트웨어 개발 활동을 내가 하고 있는가에 대해서 고민해보자. 그리고, 그러한 행위를 할 수 있고, 발전 가능성이 있는 곳이야말로, 이러한 고수준의 품질활동이 필요한 곳이 될 것이다.그리고, 이러한 고수준의 소프트웨어 품질활동이 필요한 곳은, 바로. 아직은 단 한 번도 이러한 소프트웨어나 서비스가 만들어지지 않은 곳에서 이러한 활동이 더 많이 필요하다. 그것은 바로, 스타트업이나 이제 서비스를 개시하려는 곳일수록, 적절한 소프트웨어 품질활동이나 시각화가 필요하다고 이야기할 수 있겠다.소프트웨어 활동을  시각화한다는 것은 결론적으로 소프트웨어 개발자가 투입하는 행위에 대한 가치에 대해서 얼마나 고수준으로 끌어올린 것이며, 어느 정도 적절한 품질 수준을 고려할 것인가에 대한 활동을 의미한다.그러므로, 현재 스타트업을 꿈꾸고 있거나, 적적할 소프트웨어의 개발비용을 고민하고 있는 곳이라면, 소프트웨어 공학은 매우 중요한 활동이나 방향성에 대해서 정답에 근접하도록 도움을 줄 것이다. 소프트웨어 고품질의 세계와 소프트웨어 공학의 세계는 소프트웨어 개발자들이 어떤 생각을 하고, 개발에 참여하느냐에 따라서 결정되어진다. 그 선택은 역시, 각자가 하는 것이다.
조회수 2305

사운들리 백엔드 이야기

사운들리는 '귀에 들리지 않는 소리'를 이용해서 컨텐츠를 전달할 수 있는 SaaS 플랫폼을 서비스하고 있습니다.제품의 구성요소는,음파를 송신할 수 있는 송신단음파를 모바일에서 수신할 수 있는 Android, iOS SDK그리고 컨텐츠를 제공하고 데이터를 수집, 분석하는 백엔드로 구성되어 있습니다.오늘은 구성 요소중 백엔드에 대해서 이야기 해보도록 하겠습니다.<그림 1. 사운들리 솔루션 구성도>사운들리의 인프라는 모두가 잘 아시는 아마존 웹 서비스를 이용하고 있으며, 크게 컨텐츠를 제공하는 API서버 부분, 로그를 수집, 분석하는 부분, 그리고 컨텐츠를 관리하는 CMS 부분으로 이루어져 있습니다.소프트웨어 스택Java : 현재 사운들리의 일부 시스템을 제외하고는 전부 자바로 작성되어 있습니다. Node.js로 시작하여 PHP를 거쳐 지금의 자바 기반의 시스템으로 구성하게 되었습니다. 다양한 사람들이 개발을 해오면서 각자 가장 잘할 수 있고, 빠르게 구현할 수 있는 언어로 개발되어 가다 현재의 자바로 통일되어 구성되게 되었습니다.Spring : API서버는 HTTP 기반의 REST API를 이용해 컨텐츠를 전달하고 있으며 스프링 프레임워크를 이용해 개발되었습니다. 이외에도 일부 분석에 스프링 배치를 사용하고 스프링을 편리하게 사용할 수 있게해주는 스프링 부트도 이용하고 있습니다.gRPC : 분산되어있는 서버들끼리 이기종 언어간 통신을 하기 위해서 Protocol Buffers 기반의 gRPC를 이용하고 있으며 서버들의 모니터링하는 서버와 에이전트들 사이의 통신 목적으로 사용합니다.Flume : 분산된 서버들에서 로그를 수집하는 역할을 합니다. 수집된 로그는 파일로 저장하며 실시간으로 볼수 있도록 엘라스틱서치에 같이 저장하고 있습니다. SDK에서 전송되는 로그 또한 웹서버의 엑세스 로그를 플럼 에이전트가 수집하는 방식으로 비동기로 처리하고 있습니다.ElasticSearch : 수집된 로그들을 실시간으로 확인하기 위해서 사용되며 Kibana를 이용해 시각화하고 있습니다.Angular.js : CMS의 프론트엔드는 Angular.js + Bootstrap을 이용해 개발되었으며, Bower를 이용한 라이브러리 관리, Grunt를 이용한 빌드 관리를 하고 있습니다.소프트웨어 개발/운영GIT : 소스코드는 git로 관리하며 Git-Flow를 이용한 브랜치 정책을 수립하여 가져가고 있고 저장소로는 깃허브를 이용합니다.Quality Practice : QA단계에서 제품을 테스트하기 전 개발자들은 QA 프로세스에 맞게 다음 3가지 기준으로 소스 코드의 품질을 관리합니다.코딩 컨벤션 : 사운들리 내부 코딩 컨벤션에 맞게 개발되었는지 확인합니다. Checkstyle의 규칙을 정의 및 자동화합니다.테스트 코드 : 단위 테스트 코드를 작성하며 테스트 결과는 모두 통과되어야 합니다.테스트 커버리지 : 단위 테스트 코드가 작성된 커버리지를 계산하며 현재 60%를 목표로 진행하고 있습니다.젠킨스 : 소스코드 저장소에 변동이 일어나면 젠킨스가 소스코드를 빌드하고 위에서 언급한 세가지에 대한 리포트를 작성합니다.소나큐브 : 무료 오픈소스로 코드 정적 분석을 해주며 및 QA 리포트를 같이 볼 수 있습니다.슬랙 : 인력이 적은 저희 팀도 슬랙을 적극적으로 개발/운영에서 사용하고 있습니다.팀 커뮤니케이션 : 팀원들 간의 의사사통을 위한 주요 수단으로 모든 팀원이 함께 사용하고 있습니다.분석 리포트 : 젠킨스나 배치를 통해 분석된 데이터들은 분석이 끝난 지표들은 슬랙으로 결과를 전송하여 모든 팀원이 볼 수 있도록 공유하고 있습니다.서버 모니터링 : 서버들의 이상 징후 감지나 배치 오류등을 슬랙을 통해 담당자에게 전송하여 조치할 수 있도록 합니다.애플리케이션 및 서버 모니터링 : 애플리케이션의 모니터링은 Naver에서 오픈소스로 공개한 핀포인트를 사용하고 있고, 서버 상태 모니터링을 위해 자체 개발한 모니터링 시스템을 사용하고 있습니다. 모니터링 데이터 수집을 하는 에이전트와 전체 시스템의 데이터를 관장 하는 서버간에는 gRPC를 이용하여 상태 체크를 합니다. 서버의 상태에 문제가 있을 때에는 slack을 통해 담당자들에게 알람을 주도록 시스템 설계를 하였습니다.개발 문화개발자들은 각각 개발을 할때 정해진 정책에 맞춰 브랜치를 만들어 개발합니다.각각 개발된 소스들은 저장소인 깃허브에 푸시된 후 깃허브의 댓글 기능을 이용하거나 오프라인을 통해 코드 리뷰를 진행합니다.리뷰가 끝난 후 합쳐진 소스는 QP 활동을 통해 분석이 됩니다.빌드가 실패할 경우 커피를 사야합니다 ^^ (커피를 얻어 먹으려는 것이 아닌 소스코드를 푸시하기 전 잘 확인하자는 취지입니다) AWSEC2 : 사운들리의 대부분의 구성 요소인 API서버와 로그 수집, 분석 서버, 엘라스틱서치, 플럼, CMS등이 모두 EC2에 구축되어 있습니다.RDS : 컨텐츠의 주 저장소로 데이터베이스 관리의 용이성을 고려하여 RDS의 Multi-AZ에 배포하여 Active-Standby로 구성되어 있으며 이 데이터들은 레디스와 로컬 캐시를 이용하여 API서버에서 활용하고 있습니다.S3 : 컨텐츠에 포함된 각종 정적 데이터들이 저장되며 수집된 로그들도 저장하여 보관됩니다. EMR : 로그 수집서버를 통해 S3에 저장된 로그들은 EMR을 이용해서 분석됩니다.Beanstalk : 개발 서버의 배포에 사용됩니다. 최근 IntelliJ의 플러그인이 업데이트 되면서 IntelliJ 15버전을 지원하게 되므로써 로컬에서 개발하고 개발 서버에 배포까지 편리하게 하고 있습니다. VPC : 인터넷이 필요 없는 서버들은 VPC 내부 private-zone에 배포 및 ELB를 통해 외부에서 접근하도록 구성되어 있습니다.<그림 2. AWS 배포 구성도>이상으로 사운들리에서 사용하고 있는 백엔드 소프트웨어들을 소개해 보았습니다. 적은 인력으로 빠르게 사업을 진행하는 스타트업에서는 비즈니스에 집중할 수 있도록 도와주는 다양한 툴이나 오픈소스를 이용하여 많은 도움을 받을 수 있는 것 같습니다. 또한 코드를 잘 작성하여 에러를 줄이는 것도 필요하지만 여유가 많지 않으면 최소한 제품의 에러에 빠르게 대응할 수 있도록 하는 방법도 필요한 것 같습니다.#사운들리 #개발 #개발자 #문제해결 #프레임워크 #스킬스택 #스택 #인사이트
조회수 948

Jeykll에서 플러그인 없이 sitemape 생성하기

오늘은 구글에서 블로그를 검색할 수 있도록 설정하는데에서 크게 삽질했다.. 구글 웹마스터에 사이트맵을 등록해야 했는데 그 사이트맵이 자꾸 테스트를 통과못해서 3시간이나 삽질했다.. ㅠㅠ계속 삽질하다가 찾은 이유는.. _config.yml 파일에 url 속성이 없어서 url을 가져오지 못해 생긴 문제였다. ㅠㅠ 정말 허무하고 신나고.. 아무튼 모든 문제를 해결하여 성공적으로 완료했으니 그 방법에 대해 정리하도록 하겠음.참고한 블로그: 스우의 게임서버와 클라이언트! 미친듯이 영어 검색어들로 오류를 찾으며 삽질했었는데 의외로 한글 블로그에서 이 부분에 대해 언급되어 있어 해결할 수 있었다. 감사합니다 ㅠㅠsitemap 생성하기1. sitemap.xml 파일 생성블로그의 root 디렉토리에 sitemap.xml 파일 생성.2. sitemap.xml 파일 작성하단의 코드를 복사하여 만들어준 sitemap.xml 파일에 붙여넣기.            3. url 설정추가_config.yml 파일에 url 설정이 없는 경우 url 설정을 추가하여 sitemap.xml에서 site.url 변수값을 사용할 수 있도록 해줌. (이 부분 때문에 무한 삽질 ㅠㅠ)4. 구글 웹마스터 툴에서 테스트 혹은 제출구글 웹마스터 툴에서 테스트 혹은 제출을 통해 만들어준 sitemap이 제대로 동작하는지 확인.여태 GA나 기타 여러가지를 설정하느라 공개하지 않았는데 이제서야 공개합니다.제 블로그는 https://heelog.github.io/about/ 입니다!#트레바리 #개발자 #안드로이드 #앱개발 #Jeykll #백엔드 #인사이트 #경험공유
조회수 6144

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

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

기업문화 엿볼 때, 더팀스

로그인

/