스토리 홈

인터뷰

피드

뉴스

조회수 3383

Next.js 튜토리얼 2편: 페이지 이동

* 이 글은 Next.js의 공식 튜토리얼을 번역한 글입니다.** 오역 및 오탈자가 있을 수 있습니다. 발견하시면 제보해주세요!목차1편: 시작하기2편: 페이지 이동  - 현재 글3편: 공유 컴포넌트4편: 동적 페이지5편: 라우트 마스킹6편: 서버 사이드7편: 데이터 가져오기8편: 컴포넌트 스타일링9편: 배포하기개요이제 간단한 Next.js 애플리케이션을 만들고 동작시키는 법을 알았습니다. 이 간단한 애플리케이션은 하나의 페이지를 가지고 있지만 원하는 만큼 페이지를 추가할 수 있습니다. 예를 들어 pages/about.js에 다음 내용을 추가하여 "About" 페이지를 만들 수 있습니다:그러면 http://localhost:3000/about를 통해 About 페이지에 접근할 수 있습니다.이제 이 페이지들을 연결시켜야 합니다. 이를 위해 HTML의 "a" 태그를 사용할 수 있습니다. 그러나 a 태그를 사용하면 클라이언트 사이드를 통해 이동하지 않습니다. 원하지 않게도 서버 사이드를 통해 페이지가 이동합니다.클라이언트 사이드 이동을 지원하기 위해 next/link를 통해 export된Next.js의 Link API를 사용해야 합니다.설치이번 장에서는 간단한 Next.js 애플리케이션이 필요합니다. 이전 편을 수행하거나 다음의 샘플 애플리케이션을 다운받아주세요:아래의 명령어로 실행시킬 수 있습니다:이제 http://localhost:3000로 이동하여 애플리케이션에 접근할 수 있습니다.Link 사용하기두 개의 페이지를 연결하기 위해 next/link를 사용할 예정입니다.pages/index.js에 다음과 같은 코드를 추가해주세요.next/link를 Link로 import하여 다음과 같이 사용하였습니다:http://localhost:3000에 방문해주세요.그런 다음 "About Page" 링크를 클릭하면 "About" 페이지로 이동합니다.이것은 클라이언트 사이드 이동입니다. 이 동작은 서버 요청없이 브라우저 안에서 수행됩니다.브라우저의 네트워크 상태 검사 툴에서 확인할 수 있습니다.자 지금 간단한 과제가 있습니다:- http://localhost:3000에 방문하세요.- 그런 다음 "About Page"를 클릭하세요- 브라우저의 뒤로가기 버튼을 클릭하세요.뒤로가기 버튼을 클릭했을 때 어떤 일이 일어나는지 가장 잘 설명한 것은 무엇인가요?- 뒤로가기 버튼이 동작하지 않았다.- 뒤로가기 버튼이 브라우저 콘솔에 에러를 발생시켰다.- 클라이언트 사이드를 통해 인덱스(home) 페이지로 이동했다.- "뒤로가기 버튼을 지원하기 위해 'next/back'를 import하세요"라는 알럿창이 띄워졌다클라이언트 사이드 히스토리 지원뒤로가기 버튼을 클릭하면 클라이언트를 통해 인덱스 페이지로 이동합니다. next/link는 모든  location.history를 처리합니다.클라이언트 사이드 라우팅에 대한 코드를 단 한 줄도 작성할 필요가 없습니다.간단하게 페이지들을 연결하세요. 그래도 잘 동작합니다!Link 스타일링하기대부분의 경우 링크에 스타일을 지정하고자 합니다. 스타일을 지정하는 방법입니다:위와 같은 코드를 추가하면 스타일이 올바르게 적용된 것을 볼 수 있습니다.위의 코드 대신 아래의 코드처럼 작성하는면 어떨까요?위의 코드처럼 변경했을 때 어떤 일이 일어났나요?- 원하던 스타일이 올바르게 적용되었다.- 링크에 어떤 스타일도 적용되지 않았다.- 전체 페이지가 다시 로딩된 후에 스타일이 적용되었다.- 스타일이 적용되었지만 콘솔에 에러가 나타났다.Link는 래퍼 컴포넌트입니다사실 next/link에 있는 스타일 prop는 아무런 효과가 없습니다. 왜냐하면 next/link는 단지 "href"와 다른 라우팅 관련 props만 받아들이는 래퍼 컴포넌트이기 때문입니다. 스타일을 적용해야 한다면 하위에 있는 컴포넌트에 지정해야 합니다.Button이 있는 Link링크의 앵커 대신에 "button"을 사용해봅시다. 다음과 같이 코드를 수정해야 합니다:인덱스 페이지의 버튼을 클릭하면 어떤 일이 일어날까요?- 아무 일도 일어나지 않는다- "링크 안에 버튼이 올 수 없습니다"라는 에러가 발생한다- 페이지가 다시 로딩된다- about 페이지로 이동한다Link는 어떤 것과도 동작합니다버튼과 같이 커스텀 React 컴포넌트나 div 등을 Link 안에 배치할 수 있습니다.Link 안에 있는 컴포넌트들의 유일한 요구 사항은 onClick prop를 받을 수 있어야 한다는 것입니다.Link는 간단하지만 강력합니다이번 편에서는 next/link의 기본적인 사용법을 살펴보았습니다. Link를 사용하기 위해  몇 가지 재밌는 방법들이 있습니다. 다음 편들에서 배울 예정입니다.그동안 Next.js Routing documentation를 살펴보세요. 유용합니다.#트레바리 #개발자 #안드로이드 #앱개발 #Next.js #백엔드 #인사이트 #경험공유
조회수 1618

[앵커리어랩]연구보고서 개발자 '노선빈'

오늘 만나본 앵커리어의 팀원은!바로 앵커리어의 숨겨진 하드캐리어 개발자 노선빈(a.k.a 메-쓰:수학)군 입니당!컴퓨터와 대화하는 것을 가장 좋아하는 줄 알았던 그와인터뷰를 빌미로 오랜시간 이야기를 나누었습니다!그 결과... 의외로 수다떨기를 좋아하는 타입의 선빈씨!(나 촉 되게 좋아~~~ 선빈씨 다 들켰어~~~)그럼 앵커리어랩 네번째 인터뷰 시작합니다!(ps. 내일(10월 13일)이면 예비군을 떠나시는 선빈씨에게 이 포스팅을 바칩니다! 예비군 화이팅!)INTRO. 인사밍케터) 간단한 자기소개 부탁드려요^^메-쓰) 자기소개? 이럴 수가.어려워요. 아무렇게나 하면 되나요? 양식이..? 음….팀에서 개발을 하고 있으며, Front-end를 맡고 있고, 아주 약간의 Back-end를 맡고 있습니다.밍케터) 임하는 각오는요?메-쓰) 각오는… 각오라기보다는 지금의 마음 상태가 무섭네요.밍케터)) 마케팅팀이 무서우신 건가요?!메-쓰) 아니 아니 아닙니다.인터뷰가 무서운 거죠.아시다시피 저는 말을 많이 하는 사람이 아니라서. 이런 자리가 익숙하지 않죠. 제1장. 안경_★po코딩wer★밍케터) 하시는 일 소개 부탁드려요.메-쓰) 앵커리어에서의 저의 업무!위에서 한 것 같지만, 다시 하죠. 조금 더 구체적으로.웹 사이트를 만들고, 페이지를 구성하는 일을 합니다.디자이너께서 결과물을 만들어 냈을 때,실제로 웹 사이트를 그렇게 보이게 만드는 일을 하고 있습니다. 밍케터) 선빈 씨는 코딩 언제부터 시작하셨나요?메-쓰) 음. 그게 초 6 때죠.대표께서 초 5 때부터 혼자 코딩을 했었어서, 근데 제가 친구 였어서, 저를 꼬셔서,'같이 해보지 않을래?' 해서 하게 됐죠?(선빈씨 음성지원 中)6학년 때 정보 올림피아드 나가고 하면서 컴공과에 가서 프로그래머를 해야겠다라고 생각했었는데, 고등학생때 수학이 재미있어서 물리학과로 진학했습니다.그런데 올해 초에 새해를 맞아 오랜 친구인 대표께 전화를 했는데, ‘새해 복 많이 받아라’라는 말씀과 함께 '개발자 필요한데 같이할래?' 이러셨죠.그래서 올해부터 갑자기 다시 직업으로 삼게 되었습니다.   밍케터) 공백기가 길었는데 감을 잃지는 않으셨나요?메-쓰) 예전이랑 컴퓨터 언어도 다르고 분야도 달라서 “완전 능숙해” 이 정도는 아닙니다.밍케터) 코딩이 가장 즐거운 순간은 언제인가요?메-쓰) 1. 버그 없이 잘 돌아갈 때.2. 어떻게 해야 할지 바로 떠올랐을 때.3. 알 수 없는 버그가 날 괴롭히지 않을 때.밍케터) 물리 vs 코딩. 어떤 것이 더 재미있나요?메-쓰) 물리가 재밌습니다…아 각각의 재미가 다르죠(다급).물리는…..네이쳐를 알아가는 것은 흥미롭잖아요? 안 그렇습니까?밍케터) (.....전 아닌 것 같습니다만….)메-쓰) 개발은 문제를 해결해 나가는 재미가 있습니다. 이런 방식으로 하고 싶은데 이럴 때는 어떻게 해야 할까 같은 문제들이요. 둘 다 재미있습니다. 흥미롭죠. 밍케터) 게임 좋아하신다고 하던데, 인생게임 있나요?메-쓰) 인생게임이라…. 도타라는 게임이 있는데, warcraft3 라는 게임의 mod 같은 건데…밍케터) 그럼 이 인터뷰는 어떠세요? 핵심을 찔러서 평가해주세요.메-쓰) 분위기는 좋습니다. 굉장히 자유롭네요. 자유분방. 편한 분위기. 밍케터) 모드요? 모드…???메-쓰) 스타크래프트를 해봤으면 유즈맵이라고 하면 딱 아실텐데… 뭐 어쨌든.DOTA(‘디-오-티-에이’라고 친절하게 풀어서 읽어주는 선빈 씨)라는 게임이 있습니다. 지금 롤과 같은 장르의 AOS의 시초가 된 게임입니다. 밍케터) 가장 자랑하고 싶은 코딩 결과물 알려주세요.메-쓰) 없으면 안 되는 거죠?밍케터) 웬만하면 있으시면 좋겠습니다.메-쓰) 제가 솔로로 만든 것 중에 ‘오 굉장해. 오 훌륭해’ 이런 것은 없고, 참여한 것 중에 훌륭한 것은 지금 만든 자소설닷컴이죠?개인 작업물 중에 생각나는 것은…예-엣날에 코딩 처음할 때. 야구게임이라고 아시나요?야구게임 프로그램 예시(feat.다른 개발자).jpg고1 때 굉장히 유행했는데 옛날에 하던 코딩이 생각나 심심할 때 만들어서 학교에서 풀었죠.사실 코딩하는 사람들이 보면 굉장히 별거 아닌데 학생들이 “오 신기해. 쩔어. 있어보여” 이랬던 기억이 나네요. 밍케터) 대표님과 친구인지 얼마나 되셨죠?메-쓰) 18년 이죠.밍케터) 네 그리고 초, 중, 고 계속 같이 다니셨고 한 공간에서 코딩하시고...혹시 라이벌 의식…?메-쓰) 아, 전혀 없습니다.저는 예전부터 라이벌 의식 뭐 이런 것을 가져본 적이 없어서. 좀 있었어야 할 것 같은데.밍케터) 근데 굳이 필요가 없어 보이네요. 다 잘하시니까…알아서 좋은 학교에 입학하시고...(...조용히 먼 산을 바라보며 반성하는 마케터들)제2장. 입_난 핵심만 찌른다밍케터) 팀원들이 선빈 씨에 대해 핵심을 찌른다는 평가를 했습니다. 혹시 본인만의 남다른 기준이 있으신가요?메-쓰) 팀에 합류했을 때, 대표님이 저에게 날카로운 평가를 많이 기대하는 것 같았는데... 합류하고 보니 이미 굉장히 잘하는 분이 있으셔서. (조용히 pm님을 쳐다본다.) 서로 뿌듯해하는 하드캐리어들.jpg메-쓰) 하드캐리어 이십니다. 굉장히 날카로운 분이세요.상위 호환이 가능합니다.밍케터) …...네? 상위호환이요? 그게 뭐죠?메-쓰) 음…..밍케터)(상위호환을 이해하지 못하는 것은 나의 잘못일까, 선빈씨의 잘못일까, 고급언어를 사용할 줄 아는 능력의 차이인가….또 다시 먼 산을 바라보는 밍케터...)메-쓰) 여기저기서 쓸 수 있는 성격이라는 말입니다. 더 나으신 분이죠.상위 호환이 가능한 pm님) 선빈씨 시사잡지도 계속 주기적으로 사서 보시잖아요?메-쓰) 주기적이진 않지만 내킬 때…?상위 호환이 가능한 pm님) 주변에 보면 시사 잡지를 구독하는 이공계생을 본 적이 별로 없어요.시사에 관심이 많으신가요? 나아가서 정치 사회적인 부분까지 관심이 많으신가요?메-쓰) 음, 관심이 없진 않죠. ...왜 관심이 생겼을까요?시사주간지는 딱히 주기적으로 사진 않지만 내킬 때 사는데...지하철 편의점 지나다니다 보면 ‘이번 주는 저런 이슈가 있군.. 사볼까?’ 이럴 때 삽니다.뭔가 인생, 삶에 있어서 충실함이 떨어지거나 나태함이 차오를 때?열심히 사는 사람의 느낌을 낼 때 사는 것 같네요.밍케터) 그럼 이 인터뷰는 어떠세요? 핵심을 찔러서 평가해주세요.메-쓰) 분위기는 좋습니다. 굉장히 자유롭네요. 자유분방. 편한 분위기.제3장. 피카츄_개발팀의 핵심멤버밍케터) 선빈 씨 방에는 피카츄 친구들이 많잖아요? 혹시 피카츄가 최.애.캐(최강 애정 캐릭터)인가요?메-쓰)  캐릭터로 말할 것 같으면... 딱히 딱 떠오르는 것은 없습니다.밍케터) (당황… 최.애.캐인줄 알고 질문을 준비했는데…!)메-쓰) 피카츄는 포켓몬에서 상품 제작이 많이 되고 프로모션이 많잖아요?그래서 가보니까 귀여워서 사온거죠.밍케터)그럼 질문을 좀 바꿔서 드립니다.만약 살아있는 피카츄를 얻을 수 있다면 대표님과 피카츄 중 누구를 선택하시겠어요?세상에 단 하나 뿐이고, 100만 볼트도 쓸 줄 아는 피카츄라면?그런데 살아있는 피카츄를 얻으려면 대표님과 연을 끊어야 한다면?메-쓰) 이게 직장이 걸린 문제라서 다른 직장을 찾을 수 있는가가 문제인데요.밍케터) 그럼.. 대표님 자리에 앉아서 일하다가 퇴근할 때면 고개를 돌려 “피카!!!”하고 인사를 해주는 피카츄라면요?퇴근하는 직원들에게 인사하는 대표님_피카츄.jpg상위 호환이 가능한 pm님) 전 피카츄요.인터뷰 당일 대표님께 명품 벨트를 선물받은 문케터 ) 아 저도 피카츄로 하겠습니다. (대표님보다 피카츄)메-쓰) 음… 대표님이 양산에서 잘 살고 계시는 상태에서 연을 끊는 거라면…. 제4장. 마요 시리즈_에너지의 원천밍케터) 선빈 씨의 점심엔 항상 빠지지 않는 것이 있습니다. 한솥 마요네즈 시리즈.특별히 좋아하시는 이유가 있나요?메-쓰) 좋아해서가 아니라 싸서 먹고 있습니다.밍케터) (당황… 마요 시리즈를 좋아하는 줄 알고 질문을 준비했는데…이 인터뷰 호락호락하지 않다)그래도 가장 베스트 마요 하나만 말씀해주세요.인터뷰 당일 대표님께 명품 벨트를 선물받은 문케터 ) 그러지 마요.메-쓰) (무시) 제가 먹어본 것들이 치킨, 치킨샐러드, 닭가슴살 샐러드 등이 있는데 다 그놈이 그놈입니다.재료가 아니라 마요 맛이에요.싼 것을 먹어야 돈을 모을 수 있으니까 싼 걸 먹는 거죠.그래야 건물을 사서 임대를 줄 수 있고 ‘난 이렇게 돈이 많은 남자다’ 이러면서 사치도 부리는 거죠.빅치킨마요를 사 먹는다던가.밍케터) 그럼 우리 점심시간때 빅 치킨마요 사 먹는 분들은 선빈 씨 기준에서 사치 하는 사람이네요? ㅋㅋㅋㅋㅋ인터뷰 당일 대표님께 명품 벨트를 선물받은 문케터 ) 주연 씨? ㅋㅋㅋㅋㅋ상위 호환이 가능한 pm님) 선빈씨 “쟤는 건물 있나?”이러겠네요. ㅋㅋㅋㅋㅋ메-쓰) 최신게임도 풀 옵션으로 돌리고, 뭐 농담이고 돈 많으면 좋잖아요?   밍케터) 평소 과자 간식, 마요 시리즈, 콜라 등등 고칼로리를 즐겨 드시는데 날씬한 몸매 유지 비결이 무엇이죠?메-쓰) 마요가 고칼로리인가요? 먹을 때 칼로리 생각 안 하는데, 왜 살이 안 찔까...많이 안 먹어서 그런 것 아닐까요?저는 사실 먹을 만큼 먹는데 옆에서는 잘 안 먹는다 이런 평이 있긴 하더라고요.메-쓰) 그리고 저는 신체와 관련해서 그런 것을 해보고 싶긴 해요. 마사지? 교정? 교정이겠네요.요가라던가. 필라테스?이것들을 하면 나의 오랜 신체 불균형이 좀 개선되지 않을까 이런 생각이 있습니다.어멋_뒷사람을 못가렸네.jpg  제5장. 키. 손. 팔. 속눈썹… 메이비 전신_가장 자신 있는 부위밍케터) 마지막으로 가장 자신 있는 부위 알려주세요.메-쓰) 부위? 신체? 허….글쎄요.저는 막 몸이 이렇게 자신있는 스타일은 아닌데…그런데 살면서 들어본 신체에 대한 칭찬이 몇 가지가 있는데.밍케터) 몇 가지? (분명 몸이 자신 있는 스타일은 아니라 해놓고 천역덕스러우시군) 메-쓰) 네 몇가지는 누구나 있죠.우선, 키가 크다. 근데 이건 부위라고 하기엔 뭐하네요.왠지 전신을 이야기하는 것 같아서. "너는 손이 이쁘네. 손가락이 이쁘네. 손톱이 이쁘네."이런 이야기도 좀 들어 봤구요. 팔이… 이건 칭찬인지 모르겠지만, "여자들이 원하는 팔 형태네." 아니면 "속눈썹이 기네."  상위 호환이 가능한 pm님) 맞아요. 선빈씨 속눈썹 꼭 찍어야 해. 진짜 길어요. 장난 아니죠.메-쓰) 중학교 때 부터 여자애들이 “어우 속눈썹 굉장하다.” 이런 이야기를 몇 번 들었습니다. 메-쓰) 추가로 다리가 길다 정도?결론. 앵커리어 공식질문 1. 나에게 앵커리어란?뭐. 직장이죠.2. 자소설닷컴을 한 마디로 표현하자면?뭐. 우리 회사 서비스죠.#앵커리어 #팀원소개 #인터뷰 #팀원자랑 #기업문화 #조직문화
조회수 2304

(개발자)가 !(개발자)와 일하는 방법

 이 포스트는 제가 개발팀에게 했던 세미나를 정리한 것입니다. 개발자와 기획자, 개발자와 디자이너 사이에 의사소통에 대해서 얘기하는 글이 너무나 많습니다. 디자이너(기획자)가 개발자와 일하기 위해 알아야하는 최소한의 개발 용어, 기획자와 개발자가 절대 하지 말아야 할 말들 등등 재밌는 포스트들이 인터넷에 떠돌고 여러 담당자들의 공감과 비판을 사고 있지요. 언제 이야기해도 농담을 주고 받으며 할 수 있는 좋은 주제인 것 같습니다. 그러나 그런 글들은 해당 개발자 또는 기획자가 쓴 글이기 때문에 바이어스가 걸리기 마련이지요. 우스갯소리로 넘기기에는 껄끄럽고 진지하게 받아들이기에도 껄끄럽죠. 왜 이런 말들이 이렇게 많이 나올까요? 왜냐하면 실제로 그들이 대화하는 방식이 너무나 다르고 서로가 하는 일을 이해하기 힘들기 때문입니다. 서로간에 말이 정말 잘 통했다면 그럴 일이 없겠지요. 심지어 화성에서 온 개발자 금성에서 온 기획자라는 말이 한 때 많이 나돌아 다녔지요.UI/UX도 모르면서...결국 게시판 만들라는 거잖아요이런걸 기획서라고 써오다니...아니 그걸 다 된다고 하면 어떡해요이거 하나 바꾸는게 그렇게 어려운가요?언제까지 가능한지만 얘기해주세요여기서는 되는데 우리는 왜 안되나요?개발 공부 할거에요! 공감 하시나요? 저는 개발자이지만 한번 기획자의 입장에서 왜 그렇게 할 수 밖에 없었는지 핑계를 대보겠습니다. 도대체 기획자는 저딴 방구인지 말인지 모를 말들을 할까요? 와이컴비네이터의 폴 그래햄의 유명한 에세에인 Do things that don’t scale의 한국어 요약본입니다. 영어가 싫고 1분1초가 아까운 여러분을 위해서 준비했습니다 :) 읽어보시면 스타트업에서 처음부터 규모가 큰 작업을 하거나 그것을 자동화하는 일이 얼마나 위험한 일인지 간접적으로 느끼실 수 있을것 같아요. 그 중에 일부만 발췌하여 말씀드리면1. 모집 : 사람들은 많은 선택권을 가지고 있기 때문에 우리 제품을 써야할 필요가 없음그들을 선택하려면 빠른 프로토타입이 필요하고 요구사항에 맞춰 변화할 필요가 있음2. 황홀감 : 모든 유저들에게 황홀한 수준의 경험을 제공해야하는데 엔지니어 교육과정중에 유저 만족에 기울어야한다는 내용이 없어서 생각하기 힘듬3. Meraki : 하드웨어 벤처의 경우 수동으로 기계를 생산/조립하면서 기존에는 알지못했던 핵심 요인들을 발견할 수 있음4. 수동 : 초기에는 소프트웨어가 할일을 사람이 직접하는게 좋을 수도 있음.수동으로 해결하다가 해결책을 자동화하는 것은 확실한 고객을 확보할 수 있지만, 처음부터 자동화된 해결책으로 아무런 문제도 해결하지 못한다면 확실한 실패로 이어짐5. 대형 : 처음부터 큰 스케일로 일을 벌인다고해서 성공으로 이어지는 건 아님. 수동을 싫어하기 때문에 크게 일을 벌리는 것은 큰 실패로 이어짐.큰 버그가 아니고 시장 진입 타이밍이 중요하다면 바로 출시할 수도 있다 이 중에서도 저는 4번의 수동이라는 덕목을 가장 중요하게 생각합니다. 개발자라는 족속들이 수동을 굉장히 싫어하는 경우가 많습니다. 수동은 쿨하지 않거든요. 그래서 모든 것을 자동화시키려고 하죠. 자동은 쿨하니까요. 어떤 포털사이트의 랜딩 페이지를 개발해야하는 프로젝트가 생겼다고 예를 들어봅시다. 개발자는 생각합니다.매일매일 갱신되는 랜딩페이지를 만들자. 좋아요와 댓글이 많은 글들을 최신순으로 정렬하여 보여주는데 매일 자정에 랜딩 페이지가 새로운 내용으로 갱신되는게 좋겠다. 이미 한번 게시되었던 글은 다시는 게시되지 않도록 구성해야겠군. 좋아요와 댓글의 가중치는 1:2 정도가 좋겠지? 이렇게 랜딩 페이지를 하나 구성하는데 엄청난 노력과 시간을 투자합니다. 기획자 또는 마케터는 왜 이렇게 일이 오래걸리는지 답답해하죠. 빨리 출시해서 고객들의 반응을 보고 싶은데 개발이 늦어지니까요. 사실 고객들은 포털 사이트의 메인 컨텐츠가 자동으로 구성되던 수동으로 구성되던 관심이 없어요. 그건 기획자 또한 마찬가지지요. 그들에게 어떤 컨텐츠를 보여줘야 좋아할까 고민하지요. 심지어 그전에 랜딩 페이지라는 기능이 유효한지 증명되지도 않았지요. 실제로 이전에 제가 만들었던 시크릿차트라는 서비스에서 병원의 랭킹을 계산하여 유저들에게 보여주는 기능을 만들 때도 비슷한 일이 있었습니다. 병원 랭킹 기능이란 각 병원이 언급된 블로그와 카페 글을 스크레이핑하여 몇 개인지 세고 데이터베이스를 쌓고 블로그와 카페 글이 많은 순서대로 정렬하여 보여주는 기능입니다. 처음에 저도 욕심이 생기는 겁니다. 검색 포털의 API를 이용하여 스크레이핑 봇을 만들고 데이터베이스를 구축해주는 프로그램을 만들고 싶었습니다. 그 프로그램을 만드는데는 테스팅까지 약 1주일이라는 시간이 꼬박 들겠지요. 그래도 굉장히 쿨하고 재밌어 보였습니다. 그러나 그 욕망을 꾹 참고 수동으로 세서 데이터베이스를 구축하기로 결심합니다. 검색 포털에서 검색하여 나온 숫자를 눈으로 직접 보고 데이터베이스에 직접 접근하여 수동으로 입력하는 방식입니다. 저는 기획자와 다른 개발자에게도 입력하는 것을 도와달라고 협조를 요청했습니다. 그렇게 2일만에 우리는 데이터베이스를 구축했고 빠르게 배포하여 고객의 반응을 살폈습니다. 고객의 반응을 살펴보던 기획자들은 그 기능이 정말 잘 작동하고 고객들이 좋아한다는 것을 증명해냈고 저는 그제서야 API를 이용하여 모든 것을 자동화했지요. 우리는 자동화의 욕심을 버려야합니다. 물론 시간과 비용, 효율을 따져서 해야겠지요. 효율을 따지는 것은 여러분이 더욱 능숙하실거라고 생각합니다. 우선은 간단한 예로 비개발자들이 왜 요상한 말과 행동을 하는지 알아보았습니다. 그러면 개발자인 우리는 그들에게 어떻게 이야기해야할까요? 어떻게 해야 싸우지 않고 일할 수 있을까요? 애자일 개발방법론 중에 하나인 익스트림 프로그래밍에서도 이야기하듯이 지식 섬 현상(Islands of Knowledge)은 굉장히 위험한 요소입니다. 서로가 이해하는 것이 다르기때문에 계속적인 커뮤니케이션을 통해 지식 섬을 없애야합니다. 저는 그 지식섬을 없애기 위한 실질적인 방법을 소개하려고 해요.조카에게 설명하듯이1. 훈민정음 아시겠지만 개발 용어는 절대 금지입니다. 정말로 필요한 경우가 아니면 절대 개발 용어를 쓰지마세요.2. ABC 제목만 보면 훈민정음 룰과 반대되는 내용인 것 같죠? 예를 들어서 설명할게요. 태그 기능을 만든다고 합시다. 그런데 거기서 기획서에 나오지 않은 허점을 우리는 발견했습니다. 손가락을 이리저리써가며 태그가 여러개가 되었을 때 꼬이는 현상을 설명하려 하지마세요. 태그A, 태그B, 태그C 이렇게 설명하세요, 또는 "가나다"도 좋겠군요.3. 연필 & 종이 미팅을 할때 무조건 연필과 종이를 챙겨가세요. 그리고 말보다는 그림을 그려가며 설명하세요. 종이를 아끼지 말고 최대한 자세하게요. 또는 미리 정리한 문서를 준비해가세요. 문서를 보면서 설명하면 빼먹지않고 더 잘 설명할 수 있지요.4. 메타포를 사용하라 익스트림 프로그래밍에도 나오듯이 시스템 전체 또는 기능 전체를 하나의 메타포로 정의하여 설명하는 방법입니다. 현재 제가 만들고있는 IoT 관제 솔루션의 뒷면에는 기획자 또는 디자이너가 절대 이해하지 못할 프로토콜이라고 불리는 부분이 있습니다. 우리는 프로토콜을 어떻게 개발자가 아닌 사람에게 설명해야 할까요? 저는 커피머신을 메타포로 사용하여 설명하겠습니다. 우리는 제품으로부터 raw data라는 가공되지 않은 커피빈을 받습니다. 그냥 겉으로만 보면 어떤 유용한 데이터를 가지고 있는지 전혀 모르죠. 커피빈을 볶고 갈아서 사람이 마실만한 에스프레소를 만듭니다. 거기에 우유, 크림, 초콜릿 등을 더해서 다른 사용자가 좋아할 만한 또다른 커피도 만들 수 있겠죠. 데이터베이스를 모르는 사람들이 보는 깔끔한 그래프가 나오는 화면은 아메리카노, 라떼 등으로 비유할 수 있겠군요. 정말 조카에게 설명하듯이 쉽게 친절하게 설명하시면 됩니다. 그럼 다음으로 여기서 한발짝 더 나아가서 심화학습을 해보죠. 우리는 개발자로서 비개발자인 그들에게 어떻게 해주면 더 좋을까요?1. 기획의도를 이해하기 왜 이렇게 기획했는지 이해하면 좋습니다. 유저의 요구사항이 무엇이고 왜 그런 요구를 했는지 Back-log를 알면 개발이 더 쉬울 뿐만 아니라 빠르게 배포할 수 있을지도 모릅니다. 예를 들어 배포 30분전에 버그가 발견되었습니다. 개발자는 "헉, 버그다."이러면서 열심히 고치겠지요. 그러면서 기획자에게 배포를 내일해도 되냐고 물어봅니다. 기획자는 안된다고 하고 또 싸우겠죠. 만약 기획의도를 이해한다면 이 싸움이 필요하지 않을지도 모릅니다. 해당 기능을 작동시키는데 있어서 크리티컬한 것이 아니면 서비스를 우선 배포하고 이 후에 고쳐도 되겠지요. 또는, 마케팅이나 시장은 타이밍이 중요하기 때문에 기능 구현의 우선순위를 기획자가 잡아줄 수도 있습니다.2. 프로토타입을 빠르게 개발자는 코드로 이야기합니다. 그러나 비개발자는 이해 못합니다. 움직이는 프로토타입은 고객뿐만 아니라 동료의 이해도를 드라마틱하게 높일 수 있지요.3. 계속해서 점검받기 점검받는다고 그들의 아래에 있는 것이 아닙니다. 우리는 프로젝트를 완수하기 위해 각자 다른 역할을 수행하고 있는 동등한 존재임을 잊지맙시다. 개발자는 비개발자에게 계속해서 움직이는 프로토타입을 보여주고 피드백 받으면서 지식의 섬을 없애나가야 합니다. 고객들이 원하는대로, 기획자들이 기획한대로, 디자이너 디자인한대로 구현하는 것이 프로젝트에서는 무엇보다도 중요하니까요.4. 데드라인은 꼭 지키기 데드라인을 지키는 것은 개발자와 비개발자간에 신뢰관계를 높이는 방법 중에 개발자가 할 수 있는 가장 효과적인 방법입니다. 또한 고객과도 마찬가지죠. 약속을 지키지 못하는 회사의 제품을 사가는 사람은 없습니다.  우리는 서로에 대해 너무 조금만을 알고 있습니다. 그래서 서로의 입장을 모르고 문제가 생기기 마련이지요. 당연히 서로에 대해 자세히 알 필요는 없지요. 우리팀에서 프로젝트를 망치고 싶어하는 사람은 없습니다. 그러나 상황이, 그리고 오해가 프로젝트를 망치게 하지요. 그리고 누구나 똥을 쌉니다. 서로 부족한 점이 있으니 부족한 점을 욕하기보다는 부족한 부분을 채우기위해 영역을 넓혀가는 건 어떨까요? 저건 내 일이 아니니 알아서 되겠지라는 태도보다는 다 같이 고민하며 빈 공간을 채우는 편이 좋다고 생각합니다. 서로를 비난하면서 프로젝트를 할 것인가, 서로를 이해하는 마음가짐으로 즐겁게 프로젝트를 할 것인가... 선택은 당신의 손에 달렸지요.#비주얼캠프 #인사이트 #경험공유 #조언 #개발자 #개발팀 #협업 #팀워크
조회수 1368

스켈티인터뷰 / 스켈터랩스의 금손 이주현 님을 만나보세요:)

Editor. 스켈터랩스에서는 배경이 모두 다른 다양한 멤버들이 함께 모여 최고의 머신 인텔리전스 개발을 향해 힘껏 나아가고 있습니다. 스켈터랩스의 식구들, Skeltie를 소개하는 시간을 통해 우리의 일상과 혁신을 만들어가는 과정을 들어보세요! 스켈터랩스의 하드웨어팀 금손 이주현 님을 만나보세요:)사진1. 스켈터랩스의 하드웨어 엔지니어 이주현 님Q. 자기소개를 부탁한다.A. 스켈터랩스의 하드웨어 엔지니어로 일하고있는 이주현이다.Q. 스켈터랩스에서 구체적으로 어떤 일을 맡고 있는가.A. 현재는 스켈터랩스의 레고(L.ego)팀에서 곧 출시 예정인 스마트 미러, 샘(Samm)을 만들고 있다. 레고 팀은 스켈터랩스가 가진 원천 기술을 소비자가 쉽고 편하게 접할 수 있도록 디바이스(Device) 형태로 구현하는 팀이다. 우리의 원천 기술이 다양하다 보니, 이 기술을 어떻게 활용하여 어떤 제품을 만들어야 할지부터 고민한다.Q. 매번 새로운 기획을 하고 아이디어를 내는 것이 쉬운 일은 아닐 것 같다.A. 그래서 다양한 소스를 참고하고 많은 사람에게 의견을 구하려고 한다. 킥스타터(Kickstarter)나 와디즈(Wadiz)와 같은 크라우드펀딩 플랫폼을 들여다보거나 DIY 상품을 여러가지 찾아보며 영감을 얻는다. 최근에는 레고팀 PM(Product Manger)이신 아영님의 소개로 산업디자인과 수업을 청강했다. 산업디자인이 내가 일하는 분야와 아주 밀접한 것은 아니지만 학생들이 아이디어를 개진하여 그것을 발전시켜나가는 것을 보며 나 또한 아이디어를 얻을 수 있었다. 이런 과정을 통해 제품이 구체화되면 성공 가능성에 연연하지 않고 일단 개발을 시도하려 한다.Q. 실제로 제작하는 과정에서도 예기치 못한 문제에 많이 부딪히지 않나.A. 맞다. 참신해보였던 아이디어도 기능을 구체화하는 단계에 접어들면 자잘한 이슈가 생기기 마련이다. 사람마다 생각이 다르기 때문에, 고객에게 제품의 어떤 기능이 유용할 지 예상하기도 쉽지 않다. 때문에 소프트웨어 엔지니어와 디자이너, 마케터와 같은 다른 포지션의 동료들과 자주 미팅을 갖는다.제품의 구체화가 성공적으로 완료되더라도, 실제 구현이 녹록치 않다. 가령 곧 출시를 앞두고 있는 스마트 미러 제품, 샘(Samm)의 경우 사용자의 제스처(Gesture)를 인식하여 작동하는데 생각보다 카메라의 한계가 있더라. 그래서 요즘은 카메라 뿐만 아니라 다양한 센서를 활용하는 방법을 찾고있다.Q. 내가 상상했던 ‘일반적인 하드웨어 엔지니어'의 업무와는 조금 달라보인다. 기획자 역할까지 겸비하는 것으로 보이는데, 맞나.A. ‘일반적인 하드웨어 엔지니어'의 역할을 무엇이라고 정의하는지에 따라 다른 것 같다. 나는 오히려 스켈터랩스에서 하는 업무가 내가 생상했던 ‘하드웨어 엔지니어'의 업무다. 보통 엔지니어들은 직접 만들어보는 것을 좋아한다. 그렇지만 만들고 싶은 디바이스가 늘 회사의 방향성과 일치하는 것은 아니기 때문에, 집에서 홀로 개발하기에는 시간과 돈이 늘 부족하다는 하소연을 많이 듣곤 한다. 또한 회사의 규모가 커질수록 하드웨어 엔지니어는 하나의 제품을 깊게 들여다보기 때문에 전문가로 성장하는 반면, 내가 하고싶은 개발을 할 수 있는 기회는 줄어들기 마련이다. 하지만 스켈터랩스에서는 내가 상상한 디바이스를 구현하기 위해 각종 부품을 조립하여 테스트하고, 응용하여 새로운 디바이스를 만들고 있다. 그래서인지 이곳이 내게는 딱딱한 회사의 느낌이 아니다. 정확히 내가 꿈꾸고 하고싶었던 일을 할 수 있게 도와주는 곳이라고 느낀다.Q. 최근에는 어떤 디바이스를 만들고 있는가.A. 흔히 인공지능이라고 하면 일종의 어시스턴트를 많이 떠올리는 것 같다. 개인적으로는 이 ‘어시스턴트'라는 것이 너무 범위가 넓고 거대한 느낌이다. 나는 조금 더 작고 가벼운 기술, 그리고 특정한 범위 내에서 나의 일상에 정말 도움을 주는 제품을 개발하고 싶었다. 처음에는 방에 무드 조명이 있는데 ‘이 조명이 좀더 스마트하다면’이라는 생각을 가지고 확장시켜나갔다. 피터팬에 등장하는 “팅커벨”이라는 캐릭터가 생각이 났고 원하는 분위기에 따라서 혹은 알람을 제공하기 위해 예쁘게 불빛을 밝혀주는 것이 초기 모델이었다. 가정에서 인공지능 스피커를 사용하는 사용자들은 스피커를 실상 똑똑하게 쓰지 못하는 경우가 많다. 심지어 꺼놓는 경우도 많이 보았다. 나 또한 구매 초기에는 열심히 사용하다가 요즘은 알람 기능 만을 사용하고 있다. 개인적으로 인공지능 스피커를 잘 사용하지 않는 이유가 현재의 사용성과 음성으로 정보를 전달한다는 한계 때문이라고 생각했다. 스피커는 음성 명령을 잘 알아듣지도 못할 뿐더러, 내게는 스피커의 부자연스러운 음성이 시끄럽게 느껴지기조차 했다. 이런 불편함을 개선하기 위해 무드 조명의 색 조합을 통한 정보 전달을 구상했다. 조명의 색깔로 전달한다면, 스피커처럼 음성이 다 끝날 때 까지 기다리지 않아도 되고, 더욱 빠르고 덜 성가신 방법으로도 정보를 전달할 수 있다고 생각한다. 프로젝트를 구체화하며 조명과 사물인터넷(IoT)에 대해 공부하고, 컨셉을 발전시키다 보니 사물인터넷을 통한 조명 컨트롤이라는 새로운 방향성이 생겼다.사진2. 이주현 님은 다양한 실험을 통해 최적의 디바이스를 개발하고 있다.Q. 스켈터랩스에 어떻게 입사하게 되었는지.A. 어릴 때 부터 아이디어를 내고, 그것을 실제로 구현해보는 다양한 활동을 좋아했다. 학부 시절에는 아이디어를 발제하고 이를 직접 만들어보는 소모임에도 참여하였다. 학부 전공이 전자공학이지만 인공지능 기술에 대한 관심도 컸다. 사실 인공지능은 소프트웨어 분야 아닌가. 그래서 졸업작품을 인공 지능 관련 디바이스로 정했을 때도 소프트웨어 관련 강의를 찾아 들어야했다. 그러다 현재 우리회사 하드웨어 엔지니어 파트의 리더를 맡고 있는 재경님을 만나게 되었다. 처음에는 아이디어를 실현하기 위한 기술 자문을 구하기 위해 뵈었는데, 재경님이 근무하고 계신 회사 얘기를 들으면서 입사에 대한 꿈을 키우게 되었다. 그렇게 우연히 스켈터랩스에 대해 알게된 것 같다.Q. 자발적으로 인공지능 관련 공부를 했다지만, 스켈터랩스에서 일하며 인공지능 기술 회사에 하드웨어 엔지니어로 근무하기가 녹록치않을 것 같다.A. 인공지능 기술을 비롯한 소프트웨어 전반의 공부를 계속 해야하는 것은 맞다. 그렇지만 스켈터랩스는 자발적으로 공부하기 좋은 문화를 갖추고 있고, 자연스럽게 최신 기술을 접할 수 있는 기회도 많다. 너와 나의 일을 규정짓고 나누기보다는, 무엇이든 스스럼 없이 질문하고, 함께 답변을 찾아 가는 분위기가 조성되어있다. 그래서 기술 하나를 물어보면 열을 가르쳐주려고 한다. A를 물어볼 때, 시간이 된다면 A부터 Z까지는 알아서 답변해주는 분위기 같다. Tech-Talk와 같은 사내 세미나를 통해서 강의 형태로 인공지능 기술에 대해 접하기도 한다. 또한 하드웨어 팀 내부적으로도 공부에 대한 필요를 느끼고  자체 세미나를 진행한다. 거창한 것은 아니지만, 우리가 스켈터랩스 기술에 대해 알아야 할 부분을 각자 공부하고 공유하는 자리였다. 이러한 과정이 버겁기 보다는 좋아하는 분야를 더욱 심층적으로 접할 수 있어 좋다.Q. 스켈터랩스에서 일하며 느끼는 좋은 점을 자랑한다면.A. 스켈터랩스는 ‘일단 해보자'라는 분위기가 있다. 아이디어를 내면, 시간과 재화를 제공해주고 시도해볼 것을 권장한다. 작은 실패에 연연해 할 필요도 없다. 해보고 아니다 싶을 때, 그 때 가서 접어도 늦지 않다, 라는 쿨한 문화가 있다. 나와 같이 새로운 것을 생각하고 만드는 것을 좋아하는 이들이라면, 이곳이 정말 이상적이다. 집에서 혼자 하던 것을 ‘일'로서 지원받으며 할 수 있으니까 말이다. 그리고 정말 눈치보지 않는 문화라는 점을 강조하고 싶다. 일하다 지칠 때면 블루룸(스켈터랩스에서 가장 큰 룸인데, 게임방으로 활용되고 있다)에서 게임을 할 수도 있고, 쇼파로 편하게 자리를 옮겨 일하기도 한다. 입사 초창기에 휴가에 대해서 미리 양해를 구하곤 했는데, 그럴 때마다 들은 말은 ‘알아서 할테니 걱정하지 말아라. 휴가썼다고 말도 하지 말고 떠나라' 였다. 이처럼 자율적인 문화에서도 각자 알아서 제 몫을 톡톡히 해내고 있다는 것이 스켈터랩스의 가장 멋진 점이라고 생각한다.Q. 반대로 가장 힘든 점은.A. 아무리 하드웨어 엔지니어 파트에 대한 지원이 있더라도, 우리는 어디까지나 ‘인공지능 기술’ 회사다. 그렇기 때문에 소프트웨어 엔지니어가 훨씬 많고, 프로그램 개발이 회사의 메인 테스크(Main Task)로 인식될 때가 많다. 전자공학을 전공했는데 인공지능 회사에 다닌다고 하면 의아해 하는 엔지니어들도 많다. 하지만 최근 하드웨어 단에서 인공지능을 작은 저전력 디바이스에 옮기려는 연구는 계속해서 진행되고 있다. 소프트웨어팀이 멋지게 구현한 어플리케이션 등의 서비스를 100퍼센트 전달할 수 있는 디바이스를 만드는 것을 목표로 하고 있다.사진 3. 스켈터랩스의 블루룸에는 각종 게임이 구비되어있고 밴드부 연습실로 활용된다.Q. 스켈터랩스에서 업무 외에 어떤 활동을 하고 있나.A. 밴드, 축구, 헬스동아리까지 하고 있다. 취미가 음악이라 대학교 때부터 밴드부로 활동했는데, 그때마다 공간의 필요성을 절감했었다. 악기 대여비도 만만치않게 들지 않나. 스켈터랩스 밴드인 Terkels는 공간과 악기를 모두 갖추고 있다. 심지어 PA(Public Address) 앰프와 공연용 스피커까지 구비되어 있다. 축구 동아리에서 매주 1회 풋살 대결을 펼치고, 점심 시간마다 헬스 동아리원들과 함께 헬스장에 간다. 이렇다보니 부모님한테 ‘놀려고 회사가냐'라는 핀잔을 들을 정도다.Q. 많은 동아리와 업무를 병행하는 것이 힘들지는 않은가.A. 전혀. 오히려 동아리 활동으로 더욱 친해진 팀원과 함께 머리를 맞대고 하는 업무이다보니 ‘일'이 아니라 일종의 ‘놀이'처럼 인식될 때가 있다. 그리고 스켈터랩스 특유의 문화가 겉으로는 느릿느릿 여유롭더라도 내부적으로는 치열한 부분이 있다. 축구동아리에 처음 참여했을 때 동아리원들이 ‘살살 뜁시다' 하더니 막상 경기 시작되자마자 엄청나게 공격적이더라. 살살 뛰는 사람은 한 명도 없었다. 무섭게 뛰고 공격하면서 골이 계속 터졌다. 헬스동아리는 최근에 생긴 동아리다. 여름맞이 몸을 만들기 위해서 여럿이 뭉쳐서 헬스장을 함께 간다. 헬스 자체가 함께 할 수 있는 운동은 아니지만, 그래도 시간을 정해서 함께 이동하다 보니 ‘오늘은 좀 운동하지말고 먹을까' 싶다가도 다른 분들이 가면 자극을 받게 되고, 더 열심히 운동하게 되더라. 일도 마찬가지다. 처음에는 ‘회사가 이렇게 놀게 해줘도 되나'했지만, 내부적으로 탄탄하게 서로 함께 놀고 일하며 자극과 영감을 받는 문화다.회사는 딱히 데드라인을 촉박하게 주지도 않고, 압박을 하는 경우도 없다. 그런데 다들 게임방에서 신나게 게임을 하다가도 다음 날이면 개발을 마친 결과물을 들고 온다. 자율적이지만 확실하게 자신의 업무에 대해 책임을 지는 문화가 형성되어 있다. 그렇다보니 나 또한 자연스럽게 동아리 활동을 하다가도 오늘 하루 내가 끝내야할 일로 정해놓은 것들은 마치고 퇴근하려 한다.Q. 회사에 게임방이라니, 게임방 얘기를 듣고싶다.A. 게임을 좋아하는 사람들이 많다 보니 닌텐도를 비롯해서 엑스박스(Xbox), 플레이스테이션(Playstation)을 비롯한 각종 게임기가 마련되어 있다. 다트와 탁구대, 당구대까지 준비되어 있다. 사무실을 성수로 이사하면서 테드님(Ted Cho, 스켈터랩스의 대표인 조원규 님은 사내에서 테드님으로 불린다)이 ‘모두가 놀 수 있는 공간을 만들겠다'라고 했었는데, 정말 놀이터를 만들어주시더라. 덕분에 점심시간마다 삼삼오오 모여서 각종 게임과 탁구, 당구를 즐기고 있다.Q. 하드웨어 엔지니어로서 최종 목표가 있다면.A. 테드님이 우리에게 자주 하는 말 중 하나가 ‘Don’t be evil’이다. 이 말은 사실 구글의 모토인데, 스켈터랩스의 모두가 공감하는 얘기다. 기업이 이윤을 추구할수록 소수에 대한 외면이 발생하기도 하고, 기술 기업으로서 수익 창출 만을 목표로 하면 정작 일상을 어떻게 더욱 편리하고 윤택하게 만들어줄 수 있는지를 쉽게 망각하는 것 같다. 사악해지지 않으면서, 정말 우리의 삶을 나아지게 하는 방법을 계속해서 고민하고 싶다.#스켈터랩스 #사무실풍경 #업무환경 #사내복지 #기업문화 #팀원인터뷰 #팀원소개 #팀원자랑
조회수 1898

빠른 프로토타이핑을 위한 도구 소개

새로운 아이디어를 검증하는 방법은 여러 가지가 있습니다. 비슷한 도구들을 사용하면서 간접체험을 해보기도 하고, 종이, 혹은 목업 도구를 활용한 프로토타입을 만들어보기도 합니다.스포카 팀은 새로운 아이디어를 검증하기 위해 더욱 직접적인 프로토타입을 만들어야 했습니다. 매장에서의 오프라인 경험에서부터 Facebook, Twitter 등의 온라인 경험까지 이어지는 총체적인 경험 선을 시험하기 위해선 실제로 어느 정도 동작하는 프로토타입을 만드는 것이 제일 확실하였기 때문이죠.하지만 막상 그럴싸하게 동작하는 프로토타입을 만드는 것은 생각보다 시간이 오래 걸리는 일입니다. 최소의 UI 디자인, 빠른 기능 개발, 배포 환경이 제대로 준비되어있지 않다면 실제로 유효한 수준까지 만드는 것이 많은 시간이 필요하게 될 것입니다.스포카 팀은 아이디어가 떠오를 때 어떻게 하면 그것을 빠르게 구현해서 확인할 수 있을지에 대해 많이 고민하였습니다. 그러면서도 해당 아이디어가 좋을 때 제대로 된 서비스로 확장하거나 기존 기능에 통합하는 것도 수월하게 가능하다면 더 좋겠지요. 이번 글에서는 제대로 작동하면서 확장성도 고려한 고 수준의 프로토타이핑을 빠르게 할 수 있게 도와주는 도구들을 모두 소개해보고자 합니다.어떤 언어를 고를까?특별히 교육의 목적이 있는 것이 아니라면 언어는 자신이 가장 잘 활용할 수 있게 미리 교육된 언어가 효과적입니다. 새로운 언어를 공부하면서 프로토타이핑을 한다면 지엽적이고 모르는 문제에 부딪혀 시간을 허비하는 상황이 많아 프로토타이핑 속도가 지연되기 쉽기 때문입니다. 다만 컴파일 가능한 언어와 불가능한 언어 중 선택해야 한다면 대부분 컴파일 과정이 필요없는 언어를 선택하는 것이 큰 효과를 경험하실 수 있습니다.스포카 팀은 서버 개발에 Python을 주 언어로 활용하며, 그 외에 Ruby나 Node.js 같은 언어도 추천합니다.마이크로 프레임워크를 활용하자규모가 커지면 구조에 손을 대야 하지만, 다양한 기능을 빨리 구현해서 넣고자 할 때 마이크로 프레임워크로 시작하는 것이 좋습니다. 간편하면서도 초기 구조를 아주 간결하게 들고 갈 수 있기 때문입니다.웹 서비스나 앱 서비스의 서버로 이용할 HTTP 프로토콜 서버를 구축한다면 Sinatra 스타일의 마이크로 프레임워크를 활용하는 것이 효과적입니다.아래는 주요 언어에서 볼 수 있는 마이크로 프레임워크입니다. 이 외에도 Sinatra style microframework을 검색해보시면 여러 언어에서 비슷한 형태로 구현된 마이크로 프레임워크를 보실 수 있습니다.Sinatra (Ruby)Flask (Python)Express (Node.js)스포카팀에서는 Flask를 즐겨쓰고 있습니다. Flask에 관심이 있으시다면 지난 기술 블로그의 소개글을 참조해주세요.디자인을 빠르게 하는 툴킷들기본적인 기능들을 빠르게 구현하였다면 이를 활용할 사용자 인터페이스를 만들어야 합니다. 하지만 웹 서비스나 웹뷰를 기반으로 하는 서비스를 만든다면 HTML/CSS/JS 기반의 디자인을 하는 일도 상당히 시간이 많이 필요한 일입니다. 이 때, 각 목적에 맞는 툴킷들을 이용한다면 디자인을 크게 고민하지 않으면서도 보기 좋은 서비스를 만들어 볼 수 있습니다.Bootstrap from Twitter는 디자인에 대한 여러 가지 기초적인 고민을 상당히 잘 흡수해주는 훌륭한 툴킷입니다. 크로스 브라우징을 지원하며, 우리가 쓰는 컴포넌트 대부분에 대해 심미적으로, 기능적으로 우수한 디자인을 제공합니다. 그리드 인터페이스를 제공해서 레이아웃도 간편하게 잡을 수 있으며, 곧 출시 예정인 2.0에선 반응형 디자인도 정식으로 지원하고 있습니다.Bootstrap은 LESS로도 제공해주기 때문에, 디자인 튜닝이 간편하고 Mixin을 활용해 의미적인 HTML 마크업을 하면서 디자인을 적용할 수도 있습니다.위의 툴킷과 같은 인터페이스를 가지고 디자인만 Facebook 형태로 바꾼 Fbootstrapp도 있습니다. Facebook 앱을 만든다면 이쪽을 쓰시는 편이 더 좋을 것 같습니다.터치 환경에 한정한 서비스를 디자인 중이라면 범용성이 조금 떨어지지만 jQuery Mobile을 추천합니다. 여러 기기의 웹뷰 환경을 지원하는 다양한 컴포넌트를 제공하고 있습니다.서비스를 최대한 쓰기모든 기능을 직접 전부 구현할 필요는 없습니다. 여러 회사에서 한 두 줄의 추가만으로 사용할 수 있는 서비스를 제공하고 있습니다. Google은 특히 Maps API, Chart Tools, QR Code, Font API 등 개발에 도움이 되는 수많은 기능들을 간단한 API로 쓸 수 있게끔 공개하고 있으며, Facebook 또한 소셜 플러그인으로 다양한 소셜 도구들(Like Button, Comments, Registration 등)을 제공하고 있습니다. 이런 서비스들을 잘 알고 있다면 가끔은 단지 여러 서비스 기능을 연결하는 것만으로 새로운 서비스를 만들 수 있기도 합니다.서비스 배포는 Platform as a Service(PaaS)를 활용하자위 도구의 협력으로 서비스를 만들었다면 이제 배포를 해야 합니다. 어디서나 접근할 수 있는 공용 서버에 서비스를 올리고, 서버를 세팅하고, 도메인을 연결해야 합니다. 이 과정들 또한 시간을 많이 필요로 하는 일들입니다.최근 Heroku를 시작으로 미국에서 Amazon Web Service를 기반으로 한 많은 Platform as a Service가 출시되고 있습니다. 이 서비스들은 대체로 Failover System, 쉬운 서비스 규모 스케일링, 잘 설계된 서버 스택, 편리한 배포환경을 강점으로 내세우고 있으며, 특히 처음 사용자가 가입부터 서비스 배포까지 아주 간편하고 빠른 속도로 진행할 수 있게끔 도구를 제공하고 있습니다. 게다가, 대부분 무료 플랜이 존재하기 때문에 비용 부담이 없다는 장점도 가지고 있습니다.Heroku의 서비스 배포 과정을 보시면 그 과정이 얼마나 편리한지 쉽게 알 수 있습니다.$ heroku createCreated sushi.herokuapp.com | [email protected]:sushi.git$ git push heroku master-----> Heroku receiving push-----> Rails app detected-----> Compiled slug size is 8.0MB-----> Launching... done, v1http://sushi.herokuapp.com deployed to Herokuview rawgistfile1.sh hosted with ❤ by GitHub단 두 줄로 git에 의해 관리되는 애플리케이션을 서버에 배포하고 접근 URL을 받았습니다.아래는 다양한 플랫폼에서 쉽게 이용 가능한 PaaS 목록입니다.저장소 이용아무리 빠르게 하고 싶다고 해도 저장소는 두고 하세요. 개인이 작업하는 것이라면 로컬에서도 저장소 관리가 가능한 분산형 버전관리 시스템 (git, mercurial)로 바로 이용하시고, 2명 이상이 동시에 작업한다면 반드시 저장소 호스팅 서비스를 이용해서 작업하시기 바랍니다. 변경사항을 공유하는 방법에 대해 버전관리 시스템보다 빠르고 깔끔한 방법은 아직까진 없기 때문입니다.저장소 호스팅은 많은 곳에서 제공해주고 있지만, 돈을 조금 투자해서 Github를 쓰시는 것을 추천해 드립니다. 저장소뿐만이 아닌 훌륭한 협업 플랫폼을 제공해주고 있기 때문입니다. 당장은 무료로 시작해야 한다면 Bitbucket의 무료 비공개 저장소를 이용하는 것도 좋은 방법니다.실제 케이스아래는 최근 사내에서 이루어진 아이디어 서비스 프로토타이핑이 이루어진 과정을 나열해보았습니다.Github에 저장소 생성. 팀원들에게 전달한 명은 Flask로 서버 사이드 개발QR코드 생성이 필요한 부분을 Google API로 해결한 명은 Bootstrap from Twitter로 뷰 작업을 진행작업이 되는대로 Github, Heroku에 배포개발에 필요한 시간은 약 5시간 정도였으며, 사실 이 기간은 그 이전에 해당 아이디어의 가치에 대해 토론하는 데 쓴 시간과 비슷한 시간이었습니다. 토론에선 답이 나오지 않은 채로 끝났지만, 프로토타입을 이용해보고 답을 내는 것은 그리 오랜 시간이 걸리지 않았습니다.마치며실용 가능한 프로토타이핑은 앱의 첫인상과 인터페이스 전반에 대한 이해를 넘어 아이디어의 가치평가를 확신할 수 있는 좋은 방법입니다. 우리가 토론에서 의견이 많이 갈리는 이유는 사실 보지 못한 것에 관해 이야기하기 때문인 경우가 많아서, 만약 토론하는 시간보다 더 짧은 시간 안에 말하는 것을 볼 수 있다면 의사 결정을 더 빠르고 정확하게 할 수 있습니다. 이 글은 그 방법에 대해 구체적으로 설명하였습니다.이번에 소개한 도구와 방법은 단지 돌아가는 것을 확인하는 것을 넘어 장기적인 확장성도 갖추고 있습니다. 언급한 언어들 모두 대형 서비스에서 실제 이용 중인 언어들이며, 마이크로 프레임워크들도 모두 커지는 구조에 대한 대응법을 준비하고 있습니다. 디자인은 Bootstrap의 일부 코드를 재작성하거나 튜닝하는 것으로 서비스에 최적화시킬 수 있으며, PaaS는 애초에 Fast scaling이 주요 강점이기 때문에 손쉽게 커지는 서비스의 사용량에 유연하게 대처할 수 있습니다.새로운 아이디어를 준비하고 계신다면, 이 글에서 소개한 도구들을 십분 활용하여 빠르게 실용할 수 있고, 확장 가능한 프로토타입을 반복해서 만들어 보시는 것을 적극 추천해 드립니다.#스포카 #개발 #개발자 #꿀팁 #스킬스택 #스택소개 #조언
조회수 1097

[Buzzvil People] Jen Yoon, Technical Account Manager

 Buzzvil People에서는 다양한 배경과 성격 그리고 생각을 지닌 버즈빌리언들을 한 분 한 분 소개하는 시간을 갖습니다. 어떻게 버즈빌에 최고의 동료들이 모여 최고의 팀을 만들어가고 있는 지 궁금하시다면, 색색깔 다양한 버즈빌리언들 한분 한분의 이야기가 궁금하시다면, Buzzvil People을 주목해주세요.1. 간단한 자기 소개 부탁드립니다. 안녕하세요, 버즈빌에서 기술지원 업무를 담당하고 있는 Jen입니다. 본명은 윤진 (Yoon Jeen) 인데요, 입사 당시 ‘본명이 매일 불리면 일상과 회사가 구분되지 않지 않을까’라는 생각에 이름에서 한 자를 줄여 Jen으로 결정했습니다. 그런데 얼마 지나지 않아 프로덕트 팀의 윤진한 매니저가 Jin 이라는 이름으로 입사했지요. 덕분에 매일 제 이름을 제 입으로 부르고 있습니다. 버즈빌에 입사하기 전에 소셜 스타트업, 푸드 스타트업, 인테리어 O2O 스타트업 총 세 곳에서 인턴으로 근무한 경험이 있습니다. 그리고 2017년 중순 버즈빌에 입사하여만 1년 3개월 동안 BD(Business Development)팀의 전략 매니저로 일했으며, 올해 초부터 BD팀 업무와 TAM(Technical Account Manager) 업무를 겸하다가 올 10월에 정식으로 TAM 업무를 전담하게 됐습니다. 2. 어떻게 버즈빌에 오시게 되셨나요? 지인의 추천으로 버즈빌에 대해 알게 됐고, 미래에 제가 사업을 할 때 도움이 될 좋은 회사라고 판단해 입사하고자 마음먹게 됐습니다. 몇 번의 인턴 경험을 통해 세운 ‘회사를 고르는 기준’ 중 1순위는 나중에 사업을 할 때 도움이 될 만한 곳에 가자는 것이었습니다. 세부적으로는 1) 리더가 능력 있고 2) 사람들에게서 많은 것을 배울 수 있고 3) 서로의 의견을 경청하는 곳이어야 한다는 것이었어요. 지인이 버즈빌을 추천하면서 해준 말들이 이 모든 것에 너무나 아름답게 부합했답니다. 더해서 CEO인 John이 대학교 특강에 연사로 와서 해준 설명을 듣고 입사에 대한 더욱 강한 열망을 품게 됐습니다. 그래서 학기 중에 면접을 보고, 여러 우여곡절 끝에 감사하게도 합격하게 됐어요. 면접을 보는 기간 과제 때문에 엄청나게 힘들어하기도 했고, 합격하지 못할까 봐 얼마나 노심초사했는지 모르겠습니다. 뽑아주신 덕에 8학기에 교환학생을 가려 했던 계획을 내던지고 지난 8월에 졸업해 완전한 직장인이 됐답니다. 3. 버즈빌에서 어떤 업무를 담당하고 계신가요? Technical Account Manager 의 업무는 크게 3가지입니다.  연동문서 관리 – 버즈빌에서 보유하고 있는 모든 프로덕트 및 기능에 대한 문서를 관리하고 있습니다. 문서를 작성하고 적절히 연결 짓고 업데이트하고 이에 대해 내외부에 설명하는 부분까지 포함됩니다. 파트너사와 개발 미팅이 있으면 문서를 설명하기 위해 참석하기도 하고요. 내외부 이슈 해결 – 업무시간의 가장 큰 비중을 차지하는 부분은 외부 파트너의 기술 관련 이슈 해결입니다. 버즈스크린 등의 SDK를 연동한 퍼블리셔(Supply 단) 및 버즈빌이 제공하는 광고 트래킹 기능을 연동한 광고주(Demand 단)까지가 모두 파트너에 포함됩니다. 우선 연동하면서 이상이 없도록 잘 안내하고, 이후 연동이 마무리되어 출시된 이후의 이슈를 처리하며, 추가 작업이 필요할 경우 개발팀에 전달하는 것까지 모두 이에 해당합니다. 내부 프로세스 개선을 위한 요청을 관리하는 것 또한 이 업무에 포함됩니다. 프로세스 세팅 및 개선 – 위 모든 것이 수많은 커뮤니케이션을 통해 이루어지기 때문에, 효율적으로 진행될 수 있도록 유관 팀과 협력하여 프로세스를 세팅하고, 현재 비효율적인 부분을 개선해나갑니다. 그리고 세팅하는 것보다 더 중요하게 이러한 프로세스가 잘 지켜지도록 안내하는 것도 업무의 일부입니다.  얼마 전까지는 하루 대부분을 문의와 이슈를 받아 이를 해결 or 전달하고, 있었던 커뮤니케이션에 대해 기록을 남기고 유관 팀에 공유하는 것에 할애해왔어요. 버즈빌의 사업 규모가 상당해서 모든 이슈를 관리하고 프로세스를 만들고 기록까지 하다 보면 하루가 늘 빠듯하더라고요. 감사하게도 최근에 좋은 분들이 팀에 참여해주셔서, 연동문서 체계화 및 문서화 쪽에 보다 집중할 수 있는 시간이 생기고 있습니다. 업무를 하면서 가장 곤란한 순간은 ‘이게 왜 이렇게 되어있지?’ 하게 되는 때입니다. 주로 개별 적용 되어있는 부분에 대해 히스토리가 남아있지 있거나, 기능 등이 실제로 어떻게 작동하는지 또는 사용되는지 몰라서 나오는 의문들입니다. 다행히 BD팀에서 파트너사를 운영하면서 알고 있었던 히스토리와 경험이 있어서 많은 도움이 되는 것 같아요. 이를 저뿐 아니라 다른 분들이 궁금하면 언제든지 아실 수 있도록 기록을 남기는 일에 힘쓰고 있습니다. 4. 스타트업에서 혹은 광고업계에서 일하는 느낌이 어떠세요? 스타트업으로서는 모든 것을 내 손으로 빚어나가는 느낌이에요. 이건 이전 회사들에서도 많이 느꼈던 부분이네요. 물론 버즈빌은 제가 입사할 당시부터 규모가 꽤 큰 상태였고 갖춰져 있는 시스템이 많아 매우 놀랐지만, 그런데도 많은 것들을 직접 만들어나가야 하는 ‘스타트업’이에요. 그래서 할 것이 너무 많아 버겁고 힘들 때도 있지만, 결국 제가 원하는 그림을 그려나가며 최대한 완벽하게 만들어나갈 수 있어서 매일 도전적이고 스릴 넘치는 하루를 보냅니다. 저뿐 아니라 버즈빌리언 모두 각자의 자리에서 본인에게 주어진 도전들을 클리어해나가는 것 같아요. 광고업계의 스타트업으로서는 변화와 적응의 결정체랄까요. 제가 모든 업계에 종사해본 것은 아니지만, 광고업계 특성 상 변화의 속도가 더 빠른 것 같아요. 수요와 공급 쪽의 요구가 계속해서 넘쳐나고, 그 안의 플레이어들도 계속해서 나타나서 변화와 혁신이 끊이지 않는 것 같습니다. 그 와중에 플랫폼 별 정책도 변화하게 되니 그야말로 내일을 점칠 수 없는 업계인 것 같아요. 그래서 저의 업무도 매일 변화하고 새로운 상품이나 퍼블리셔에 적응하는 과정의 일부입니다. 저는 이런 역동성이 좋아서 버즈빌에서 만족하며 일하고 있어요. 버즈빌에서 일하면서 받는 느낌은, 일이 제 삶 대부분을 차지해버렸다는 점이겠네요. 하루 대부분을 회사에서 보내고 그 외의 시간에도 회사나 일 생각을 하는 것 같아요. 이것의 장단점이 있다보니 이제 워라밸도 생각하려 하고는 있지만, 여전히 제 생각의 대부분을 차지하고 있는 것이 바로 버즈빌이랍니다. 5. 이것만큼은 버즈빌이 참 좋다! 어떤 게 있으실까요? 일단 사람들이 본인 일과 다른 사람에 대한 애정을 품고 있어요. 그 덕에 무엇 하나 대충 넘기는 일 없이 다 같이 힘을 모아 일을 해낼 수 있습니다. 다들 사소한 질문에도 답을 찾기 위해 적극적으로 도와주시고, 짜증 내지 않고 웃으며 대해주세요. 그래서 크고 작은 문제를 맞닥뜨렸을 때 혼자 끙끙대는 일 없이 헤쳐나갈 수 있고, 저도 질문을 받았을 때 더 신나게 도와드릴 수 있는 것 같습니다. 두 번째로는 회사가 커뮤니케이션을 굉장히 중시한다는 점이에요. 솔직히 저는 우리나라에서 나이에 따른 꼰대질이 없는 회사는 정말 희귀할 거로 생각하는데요, 버즈빌은 그 희귀한 곳 중 하나입니다. 제가 언제 어디서든 적극적으로 의견을 낼 수 있고, 아닌 것에 대해 아니라고 말할 수 있는 회사가 얼마나 있을까요. 말만 번지르르하게 하는 것이 아니라 실제로 모두의 의견을 존중하려는 버즈빌의 문화는 버즈빌의 큰 동력 중 하나라고 생각해요. 마지막으로 사람들이 끊임없이 자기발전을 위해 노력합니다. 기본적으로 사람들의 성향이 그런 것도 있고 회사도 적극적으로 지원해줘서 더 시너지가 나는 것 같아요. 그 덕에 저도 많은 자극을 받고 더 실력 있는 사람이 될 방법은 무엇일까 고민하게 돼요. 매일매일 기분 좋은 압박감 같은 것을 느끼고 있답니다. 6. 개인적인 목표나 꿈이 있으신가요? 있다면, 버즈빌에서의 경험이 어떻게 도움이 된다고 생각하시나요? 저는 ‘기댈 수 있는 존재’가 되고 싶습니다. 누군가 힘들 때 제게 말하거나 의지해줄 때 제 존재의 의미를 느끼거든요. 개인적으로는 누군가 힘들 때 찾아올 수 있는 사람이 되고 싶어요. 한때 ‘따뜻한 사람이 되고 싶다’ 정도로 마음에 품고 살았는데, 최근에 마냥 따뜻한 것을 넘어서 누군가 찾아올 수 있는 사람이 되고 싶다고 생각이 바뀌었어요. 그리고 삶의 큰 목표로서도 마찬가지로 즐거울 때든 힘들 때든 기댈 수 있는 상품이나 서비스로 사업을 하고 싶습니다. 사실 삶에서 힘이 되는 것들이 엄청 대단한 건 아닌 것 같아요. 아침에 눈을 떠서 오늘 좋아하는 사람들과 점심 약속이 있다는 사실에 벌떡 일어나기도 하고, 아무리 새벽까지 힘들게 일하고 집에 가도 고양이가 품에 안겨있으면 피로가 사르르 녹는 것처럼요. 그래서 일확천금의 기회를 준다거나 인생을 반전시킬 만큼의 서비스는 아니라도, 잔잔한 일상 속에서나 마음이 벼랑 끝에 몰리고 지친 순간이나 머릿속에 떠오를 만한 그런 사업을 하고 싶습니다. 아무래도 관심사가 음식, 동물, 심리 이런 분야이다 보니 그 교차점에 있는 무언가를 꼭 하고 싶어요. 아침마다 고양이들에게 둘러싸여 오늘의 요리를 준비한다면 더할 나위 없이 행복할 것 같네요. 일단 버즈빌에서의 직무가 저의 이런 꿈과 관련하여 참 잘 맞는 것 같아요. 누군가가 저를 필요로 하고 불러주는 게 정말 진심으로 너무 좋답니다. 그걸 잘 처리해드리지 못할 때는 매우 힘들지만, 제 이름을 불러주실 때마다 “넵!!” 하고 대답하는 게 항상 행복하고 감사해요. 그런 점에서 현 상태만으로도 제가 되고 싶은 제 모습을 만들어나가는 데에 도움이 많이 됩니다. 두 번째로는 나중에 사업을 할 때 도움이 될 인사이트를 많이 얻어가고 있어요. 특히 사업의 확장성에 대한 것인데요, 어릴 때 단순 자영업을 꿈꾸다가 더 많은 사람에게 도움이 되면 좋지 않을까 생각해서 기업가로 꿈을 바꾸었어요. 그와 유사하게, 버즈빌에 들어와 B2B 사업을 경험하면서 파트너사가 지닌 경험과 사용자를 leveraging하여 투자하여 더 큰 확장성을 가질 수 있다는 것을 절절히 느꼈습니다. 해서 나중에 사업을 하면서 다른 주체와 협업하고 소통하는 과정에서 지금 버즈빌에서 BD매니저, 그리고 현재 TAM으로서의 경험이 아주 큰 도움이 될 거라고 확신합니다. 이에 더해서 좋은 회사란 무엇인가 고민하고, 그 고민을 통한 액션 아이템이 도출되고 실행되는 과정에 함께하는 것 또한 나중에 제 일을 할 때 큰 도움이 될 것 같습니다. 마지막으로 모든 것을 다 떠나서 너무나 좋은 사람들과 함께 웃고 이야기하고 일할 수 있다는 것 자체가 제 인생을 풍요롭게 해줍니다. 단 하루도 쉬이 넘어간 적이 없지만, 동시에 즐겁게 웃지 않았던 날도 없어요. 앞으로 버즈빌에서 제 삶이 어떻게 될지 모르지만, 여기에서 시간과 경험과 인연은 제 삶에 보석 같은 존재로 남을 것 같습니다. 
조회수 2750

PHP CI 환경에서 완전한 Vue 사용하기

편집자 주Vue 또는 VUE로 혼용하나 공식 사이트의 표기에 맞춰 아래와 같이 통일함-Vue-Vuex-Vue-Router목차1.Controller2.VIEW3.webpack Vue 소스 진입점4.webpack 설정5.Package.json6.Vue-Router7.Vuex8.공통 처리 mixin9.요약10.마치며시작하며드디어 브랜디 관리자 서비스에 Vue를 도입하고자 떠났던 여정의 마지막 장입니다. 브랜디 관리자 서비스는 PHP Codeigniter와 jQuery로 구성되어 있습니다. 사실 잘 운영되고 있는 서비스에 리스크가 큰 신기술을 도입하는 것은 도박에 가깝습니다. 몇 시간만 운영이 정지되어도 회사에 엄청난 피해를 안겨줄 수도 있으니까요. 하지만 여러 번의 검증과 실험으로 도박에서 이길 확률을 100%에 가깝게 끌어올린다면 한번 도전해볼 만하지 않을까요?이전 글인 PHP Codeigniter 환경에서 VUE 사용해보기에서 기본적인 webpack + Vue + Codeigniter 환경 구축 방법을 알아봤는데요. 하지만 단순히 webpack과 Vue만 적용했다고 해서 “우리 시스템은 UI 프레임워크로 Vue를 사용하고 있습니다.”라고 말할 순 없습니다. 아주 중요한 숙제가 남았죠.Vue에는 활용도를 대폭 끌어올려주는 Vue-Router와 Vuex Store1)가 있는데 그중 Vue-Router를 이번 글에서 자세히 다루려고 합니다.2) Vue-Router는 Vue.js의 공식 라우터입니다. 공식 홈페이지의 소개는 아래와 같습니다.중첩된 라우트/뷰 매핑모듈화된, 컴포넌트 기반의 라우터 설정라우터 파라미터, 쿼리, 와일드카드Vue.js의 트랜지션 시스템을 이용한 트랜지션 효과세밀한 내비게이션 컨트롤active CSS 클래스를 자동으로 추가해주는 링크HTML5 히스토리 모드 또는 해시 모드(IE9에서 자동으로 폴백)사용자 정의 가능한 스크롤 동작한마디로 정리하면 입력된 URL에 반응해 부분에 해당 URL의 view를 보여주는 기능인 것입니다. 다시 말해 URL이 변경될 때 한 페이지에서 화면 전체를 갈아끼우거나, 화면의 일부분(부분)을 치환해주는 역할을 한다는 것이죠. 더 나아가 해당 화면이 로드되기 전후로 전처리, 후처리 기능까지 가능합니다.착안점Vue와 Vue-Rotuer를 알게 되었을 땐 PHP 기반 프로젝트에 Vue-Router를 적용할 수 없으니 처음부터 새로 만들어야 한다고 생각했습니다. 로그인 인증 문제, 메뉴의 권한 관리 등 모든 것이 Vue 아래에 있어야 한다고 생각했기 때문입니다.어느 날 관리자 서비스에 TDD를 구현해보려고 Python Flask + webpack + Vue 프로젝트를 구성하고 있었습니다. 그러던 중 우연히 Flask + Vue-Router에서 404 페이지를 처리하려면 Flask Fallback 페이지를 Vue-Router 메인 페이지(가 있는 페이지)로 보내고, Vue-Router에서 진짜 매핑된 URL이 없으면 404 처리를 하는 식으로 구성한다는 글을 읽고 문득 호기심이 생겼습니다.‘관리자 서비스에서도 컨트롤러로 여러 URL을 한 가지 페이지로 보낸다면?’PHP를 거쳐 페이지로 이동한 것이므로 권한 관리와 메뉴 트리까지는 PHP에서 처리되면서 URL이 변할 것이고, 실제로 화면을 보여주는 Contents 영역만 를 사용한다면 어떻게 될지 궁금해졌습니다. 바로 하던 일을 멈추고 관리자 소스에 Vue-Router를 활용한 테스트 소스코드를 작성해봤습니다.예상했던 대로 PHP의 로그인 인증 처리를 거치면서 실제로 보이는 부분에는 부분만 정상적으로 치환되었습니다. 이 간단한 실험을 바탕으로 통계 시스템의 일부를 구현하는 데에 Vue-Router와 Vuex Store, 공통 처리 Mixin을 추가해 제작했습니다.1.Controller4개의 페이지를 가진 통계 시스템의 Codeigniter 컨트롤러 모습입니다. 기존의 서비스 URL들이 존재하기 때문에 Fallback을 통으로 Vue-Router로 보낼 순 없었고, 라우터를 사용할 페이지들을 하나의 페이지로 보냈습니다.1-1) /application/controllers/[컨트롤러 경로]... 생략 /* [라우터 view]에서 태그를 포함하고 있습니다. */ public function salesAnalysisProduct() { $this->load->view('[라우터 view]'); } public function salesAnalysisSeller() { $this->load->view('[라우터 view]'); } public function trendAnalysisProduct() { $this->load->view('[라우터 view]'); } public function trendAnalysisSeller() { $this->load->view('[라우터 view]'); } ... 생략 2.VIEWCodeigniter 환경에 반영하는 것이므로 CI에서 인식시킬 PHP view와 webpack에서 빌드 결과를 자동으로 바인딩할 html 파일로 구성됩니다.2-1)/application/views/[Vue용 view 경로]/index.php// [index.php] Vue 를 매핑할 php파일 컨트롤러의 view로딩용 [라우터 view]입니다. ... header, menu 생략 ... //바인딩될 부분 //자동매핑 html 인클루드 <?php include('index.html'); ?> ... footer 생략 ... 2-2)/application/views/[Vue용 view 경로]/index.html webpack의 빌드 결과로 자동으로 생성되는 파일입니다. [removed][removed] 위는 webpack의 HtmlWebpackPlugin에 의해 자동으로 바인딩된 모습입니다. 빌드되기 전 index.html은 다음 항목에 있습니다.3.webpack Vue 소스 진입점관리자에서는 프로젝트 폴더 안에 webpack과 Vue 용 서브 폴더를 두고 webpack.config.js에서 output 옵션을 통해 빌드 결과를 삽입하는 구조입니다. webpack 루트 폴더는 application 폴더와 같은 레벨에 위치하며, 폴더 구조나 파일 위치는 어디에 둬도 상관없습니다. webpack.config.js에서 entry 속성으로 잡아주시면 됩니다.3-1)/[webpack루트]/index.html// HtmlWebpackPlugin으로 스크립트를 삽입하기 위한 빈 템플릿 파일 3-2)/[webpack루트]/index.js/** * 진입용 index.js */ import Vue from 'vue' import axios from 'axios' import router from './router' import App from './App.vue' Vue.prototype.$http = axios new Vue({ el : '#app', router, components : { App }, template : '' }); 3-3)/[webpack루트]/App.vue [removed] import mixin from './common/common-mixin.js' import store from './vuex/store' export default { store, name : 'App' } [removed] Vuex와 통신 모듈 axios, Vue-Router 등을 루트 Vue 객체에 추가해줍니다. 브랜디 관리자의 webpack은 babel을 사용하고 있기 때문에 위의 store처럼 축약해서 작성하면 빌드된 파일에는 store: store와 같이 입력됩니다.Vue-Router는 태그에 자동으로 매핑되며, 위와 같은 구조로 상위 컴포넌트에서 할당되어 있어야 합니다. Vuex와 Vue-Router 설정은 글 아래에서 다루겠습니다.4.Webpack 설정이번에 Vue-Router와 Vuex를 도입하면서 webpack의 설정도 실제 서비스용과 개발용으로 분리했습니다. 폴더는 편의상 추가하였으며, package.json에서 자신이 설정한 경로로 설정하면 됩니다.Webpack 설정 파일은 Webpack의 시작과 끝이라고도 할 수 있습니다. Webpack 설정 파일에서 빌드할 소스의 경로와 빌드 결과 파일의 명명 규칙을 정하고, html 파일에 스크립트파를 자동으로 주입시키거나, Babel 플러그인을 통해 최신 스크립트 작성법을 브라우저를 신경쓰지 않고 사용할 수도 있습니다.그중에서도 중요한 옵션이 있는데 바로 Code Splitting에 관련된 옵션입니다.관리자 초기 Vue 모델에는 Vue-Router가 없었기 때문에 js 번들 파일의 크기가 그렇게 크지 않았습니다. 하지만 Vue-Router를 사용해 싱글 페이지 어플리케이션이 되거나 화면의 UI가 복잡해 컴포넌트 수가 많아지면 번들 js 파일의 크기가 매우 커집니다. 즉, 캐시를 사용하지 않는 익스플로러라면 소스에서 한 글자만 바뀌더라도 모든 페이지에서 거대한 번들 js를 새로 로딩하게 되고, 상당한 서버 자원을 소모합니다.Code Splitting 적용 전위의 이미지는 Code Splitting을 적용하기 전의 번들 js 정보입니다. 실제로 완성된 Vue 프로젝트의 번들 js는 더욱 큽니다. 정말 단순한 페이지 하나를 띄우는데 매번 뚱뚱한 js를 로딩해야 하는 것은 서비스 제공자와 서비스 사용자를 모두 괴롭게 할 것입니다.Code Splitting 적용 후하지만 위처럼 작은 조각으로 나눠 필요한 시점마다 필요한 번들 js만 로드하면 매우 빠른 페이지를 제작할 수 있습니다. 따라서 Code Split 기능은 매우 중요한 이슈입니다.물론 개발을 진행하다 보면 역시 어느 것 하나 쉽게 넘어가지지 않습니다. 관리자의 웹팩은 4.x 버전대를 사용하고 있습니다. 예전에 TF에서는 Webpakc 3.x 버전대를 사용하였는데 당시에는 CommonChunkPlugin 설정을 통해 Code Splitting을 사용할 수 있었습니다. 그대로 관리자에 적용하려 했는데..Removed라고 쓰여 있습니다. 찾아보니 CommonChunkPlugin이 옵티마이즈 옵션 하위의 splitChunk 속성으로 들어가면서 설정 방법이 바뀌었더군요. 머리를 싸매고 설정을 잡습니다.4-1) /[webpack루트]/build/webpakc.config.js : 공통 설정파일'use strict' const HtmlWebpackPlugin = require('html-webpack-plugin'); const { VueLoaderPlugin } = require('vue-loader'); const path = require('path'); module.exports = { entry: { //string, object, array 가능 - 기본은 ./src app: path.join('[스크립트 파일 경로]', 'index.js') //진입점 스크립트 파일입니다. }, output: { path: '[빌드된 js 목적지 경로]', publicPath: '[이미지등의 웹상 리소스 경로]', filename: './[name].[chunkhash].js', // 엔트리 파일명명규칙 chunkFilename: '[id]_[chunkhash].js', // chunk파일 명명 규칙 // --mode development에서는 [id]에도 chunkName들어갑니다. }, //vue와 js, css 로드 규칙을 설정합니다. module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', include: [ /[Vue 소스 경로]/ ] }, { test: /\.js$/, use: { loader: 'babel-loader?cacheDirectory', }, include: [ /[Vue 소스 경로]/ ] }, { test: /\.css$/, oneOf: [ { use: [ 'vue-style-loader', 'css-loader' ] } ] } ] }, resolve: { alias: { '@': '[Vue소스 경로]', // 편의상 소스단축경로를 설정합니다. }, //파일 확장자 자동인식 임포트시 해당 확장자는 생략가능합니다. extensions: ['.js', '.vue', '.json'], }, plugins: [ // Vue 파일 로더 new VueLoaderPlugin(), // html 자동 바인딩 // 아래의 플러그인으로 인해 index.html에 해시네임으로 빌드된 index.js가 자동으로 매핑됩니다. new HtmlWebpackPlugin({ // index.php에서 include할 파일이 생성될 경로와 파일명 입니다. filename: path.join('[View경로]', 'index.html'), // 자동으로 매핑할 진입점파일을 지정합니다. template: path.join('[Vue소스 경로]', 'index.html'), inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true } }), ], optimization: { //웹팩 4.x 버전에서 옵티마이즈 속성으로 추가된 CodeSplitting 기능입니다. splitChunks: { //initial - static파일만 분리, async - 동적로딩파일만 분리, all - 모두 분리 chunks: 'async', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, //병렬 요청 chunk수 maxInitialRequests: 3, //초기 페이지로드 병렬 요청 chunk수 automaticNameDelimiter: '_', //vendor, default등 prefix 구분문자 (default : '~') name: true, //development모드일때 파일에 청크이름 표시여부 cacheGroups: { default: { minChunks: 2, //2개 이상의 chunk priority: -20, reuseExistingChunk: true //minChunks이상에서 사용할경우 공통사용 }, //axios, vue 같은 공통 모듈은 vendor로 관리합니다. vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 } } } } }; 4-2) /[webpack루트]/build/webpack.dev.config.js 개발용 설정 파일 (네이밍은 자유)'use strict' const merge = require('webpack-merge') const webpack = require('webpack') const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin const baseWebpackConfig = require('./webpack.config') const config = require('../config').dev //개발용설정 const devWebpackConfig = merge(baseWebpackConfig, { //mode는 chunk[id], 디버깅 코드 등에 영향을 줍니다. webpack 3.x 버전에서는 Env 속성을 통해 관리했다고 합니다. mode: 'development', plugins: [ new BundleAnalyzerPlugin(), //번들 무게 분석기 제대로 스플릿 되었는지 확인할 때 사용합니다. new webpack.DefinePlugin({ env : config.env }), ], watch: true, //코드의 변화를 감지해 자동으로 재빌드해주는 옵션입니다. cache: true, //캐시 사용을 활성화하면 변경사항이 있는 코드만 재빌드합니다. optimization: { //uglify 플러그인 코드 압축 여부를 설정합니다 압축 시 용량을 매우 줄일 수 있으나 빌드 속도가 크게 저하되므로 개발 시에는 꺼줍니다. minimize: false, } }) module.exports = new Promise((resolve, reject) => { resolve(devWebpackConfig); }) 4-3) /[webpack루트]/build/webpack.prod.config.js 서비스용 설정파일 (네이밍은 자유)'use strict' const merge = require('webpack-merge') // 설정파일 결합에 사용합니다. const webpack = require('webpack') const baseWebpackConfig = require('./webpack.config') //베이스 설정파일 const config = require('../config').prod //서비스용 설정 const prodWebpackConfig = merge(baseWebpackConfig, { mode: 'production', //chunk[id], 디버깅 코드등 영향 있음 plugins: [ new webpack.DefinePlugin({ env : config.env }), ], //개발용과 반대로 용량은 줄이고 필요 없는 기능은 꺼줍니다. watch: false, cache: false, optimization: { minimize: true, } }) module.exports = prodWebpackConfig 5.package.json웹팩 설정 파일이 분리되면서 package.json의 런 스크립트도 변경했습니다.... "scripts": { "build": "webpack --config build/webpack.prod.config.js --progress", "build-dev": "webpack --config build/webpack.dev.config.js --progress" }, ... 6.Vue-RouterVue-Router는 위에서 설명한 대로 Vue의 컴포넌트와 밀접하게 결합된 라우터입니다. 그런데 여기서 webpack의 Code Split을 사용하려면 컴포넌트 import 방법이 매우 중요한데요.import './testComponent' 위처럼 import 구문을 사용해 컴포넌트를 불러오면 코드가 쪼개지지 않고 한 덩어리로 빌드되므로 아래와 같은 형태로 사용해야 합니다.const testComponent = () => import('./testComponent') webpack 공식 문서에도 나와있듯이 위처럼 ES2015 Loader spec에 있는 import()를 사용하여 컴포넌트를 생성해야 번들 js가 제대로 분리되며, Dynamic Import가 가능해집니다.Vue-Router를 쓰는 순간 싱글 페이지 어플리케이션이 되기 때문에 이곳에서 설정을 잘못 잡아주는 순간 육중한 컴포넌트 한 덩어리가 튀어나오면서 Code Splitting은 물거품이 되어버립니다. 조심합시다!또한 import 함수 안쪽엔 아래와 같은 주석을 달아야 청크 이름이 적용됩니다.const testComponent = () => import( /* webpackChunkName: '[청크이름]'*/ './testComponent') 라우터 경로 속성인 path 와 Codeigniter의 컨트롤러 경로를 맞춰주는 것이 포인트입니다!6-1) /[webpack루트]/router/index.js - 경로와 파일명은 자유입니다!import Vue from 'vue' import Router from 'vue-router' // 주석의 webpackChunkName = 코드 스플릿 chunk Name으로 사용됩니다. // 꼭 컴포넌트와 청크 이름을 같게 설정할 필요는 없습니다. const SalesAnalysisProduct = () => import(/* webpackChunkName: "salesAnalysisProduct" */ '[컴포넌트 파일 경로]') const SalesAnalysisSeller = () => import(/* webpackChunkName: "salesAnalysisSeller" */ '[컴포넌트 파일 경로]') const TrendAnalysisProduct = () => import(/* webpackChunkName: "trendAnalysisProduct" */ '[컴포넌트 파일 경로]') const TrendAnalysisSeller = () => import(/* webpackChunkName: "trendAnalysisSeller" */ '[컴포넌트 파일 경로]') Vue.use(Router) const router = new Router({ mode: 'history', routes: [ /* 통계 */ { path: '[CI컨트롤러 url]/salesAnalysisProduct', name: 'salesAnalysisProduct', component: SalesAnalysisProduct }, { path: '[CI컨트롤러 url]/salesAnalysisSeller', name: 'salesAnalysisSeller', component: SalesAnalysisSeller }, { path: '[CI컨트롤러 url]/trendAnalysisProduct', name: 'trendAnalysisProduct', component: TrendAnalysisProduct }, { path: '[CI컨트롤러 url]/trendAnalysisSeller', name: 'trendAnalysisSeller', component: TrendAnalysisSeller }, ] }) // 아래의 함수로 전처리 후처리도 가능합니다! router.beforeEach((to, from, next) => { // ... }) router.afterEach((to, from) => { // ... }) export default router 7.Vuex앞서 Vue와 Vuex, 컴포넌트간 통신과 상태 관리에서 소개했던 상태 관리와 통신을 위한 Vuex도 추가합니다. Vuex는 하나의 Store만 쓸 경우 상태 변수의 과포화로 인해 유지 보수가 어려워질 수 있으므로 namespace: true 옵션을 통해 도메인별로 관리합니다.7-1) /[webpack루트]/vuex/store.js - Vuex 진입파일import Vue from 'vue' import Vuex from 'vuex' // 각 도메인별 store들이 들어있는 modules 를 임포트해줍니다. import * as modules from './modules/index' Vue.use(Vuex) export default new Vuex.Store({ state : { }, getter: { }, mutations : { }, actions : { }, modules : modules.default }) 7-2) /[webpack루트]/vuex/modules/index.js - 도메인별 Store 자동 바인딩 스크립트const files = require.context('.', false, /\.js$/) const modules = {} //자신(index.js)를 제외한 파일들을 파일이름을 Key로 modules에 담습니다. files.keys().forEach((key) => { if (key === './index.js') return modules[key.toLowerCase().replace(/(\.\/|\.js)/g, '')] = files(key).default }) export default modules 7-3) /[webpack루트]/vuex/modules/statistics.js(통계 store 파일) - 예시입니다.export default { namespaced : true, //해당 속성을 통해 파일명을 namespace로 사용합니다. state: { /* 상태값 및 데이터 */ ... }, getters: { }, mutations: { /* state 변경처리 */ ... }, actions: { /* 통신처리 */ ... } } namespace: true로 되어있으므로 파일명인 statistics를 namespace로 사용하게 됩니다. 따라서 store 각 항목에 대한 접근은 다음과 같이 이뤄지며 computed 속성에 state: this.$store.state.statistics 처럼 정의해두면 편리합니다.dispatch는 this.$store.dispatch(‘statistics/[action 이름]’)commit은 this.$store.commit(‘statistics/[mutation 이름]’)state 변수 접근은 this.$store.state.statistics.[state 이름]8.공통 처리 mixinapi 통신에 사용되는 통신 라이브러리와 그 라이브러리의 복잡한 설정 코드, 단순한 Toast 출력 함수, 로딩 이펙트를 보여주는 함수 등 모든 항목들이 매 페이지마다 있으면, 통일되지 못한 UI, 페이지마다 일관되지 못한 설정 등으로 휴먼 에러가 발생할 확률이 높아집니다. 유지 보수 측면에서도 비용이 높아집니다. 이러한 단순 반복 코드들은 한번만 정의하고 재사용하는 것이 바람직합니다. 나중에 수정할 때도 용이하죠.공통사항을 묶어 Vue 전역 믹스인으로 Vue 루트 객체에 추가합시다. 단, global 옵션인 만큼 조심해서 써야 합니다. 시스템에 영향을 줄 것 같으면 하위 컴포넌트 mixins 속성에 넣어 해당 스코프에서만 사용하는 것이 바람직합니다.8-1) /[webpack루트]/common/common-mixin.js (파일이름, 경로는 자유입니다!)import Vue from 'vue' import Vue from 'axios' import Cookies from 'js-cookie' const TIMEOUT = '[타임아웃 시간(ms)]' /* mixin의 기본 형태는 Vue 컴포넌트의 형태와 동일합니다. 주로 전역 통신과 상태 관리는 vuex store에서, 전역 data 속성과 전역 함수는 mixin에서 관리합니다. */ Vue.mixin({ /* 전역 사용 data속성 선언 */ data: () => { return { ... //이곳에 선언하는 data 속성은 전역에서 this로 접근 가능합니다. } }, created: function() { // 공용 axios 객체 생성 this.axios = axios.create({ timeout: TIMEOUT, withCredentials: true, //공통해더는 여기에 headers : { } }); //axios 의 success와 error를 mixin method에서 처리 하도록 등록 this.axios.interceptors.response.use(this.onSuccess, this.onError) }, /* 전역 사용 함수 선언 */ methods: { /* axios의 response handling 함수*/ onSuccess : response => { }, onError : function (error) { }, /*GET, POST 등의 통신 함수, Toast(alert) 표출함수, 에러핸들링함수 등 선언*/ /*... 내용이 너무 길어서 생략 ...*/ } }); 9.요약지금까지의 내용은 파일 경로를 토대로 요약하면 다음과 같습니다. 참고로 아래의 폴더 구조는 절대적인것은 아닙니다. 모든 폴더 구조는 자율이며, 폴더 구조에 맞게 webpack.config.js에서 조정해주면 됩니다.[프로젝트 루트] └ [웹팩 루트] └ package.json └ [Vue 소스 루트] └ [common] └ [router] └ index.js // 라우터 설정파일 - CI 컨트롤러와 url 맞춰줘야함 └ [vuex] └ index.js // 도메인별 store module export 스크립트 └ [modules] └ 도메인별 store.js └ [컴포넌트 폴더] //예시에서는 ststistics └ App.vue //진입점 vue파일 Vuex와 전역 mixin 세팅 └ index.html //index.js가 주입될 껍데기 └ index.js //진입점 js Vue-Router와 App.vue 세팅 └ [build] // 빌드파일경로 └ webpack.config.js //베이스 설정파일 └ webpack.dev.config.js //개발용 설정파일 └ webpack.prod.config.js //서비스용 설정파일 └ [application] //Codeigniter 루트 └ [controllers] └ [컨트롤러 경로] // 예시의 통계부분 └ [views] └ [웹팩빌드 결과 폴더] └ [index.php] // CI 에서 로드하는 view (index.html include) └ [index.html] // js 번들이 자동 주입된 빌드결과 파일 └ [include] └ [scripts] └ [빌드결과 js 경로] //public path 속성 경로 └ 빌드 결과 js chunk들 마치며관리자 서비스에서 완전한 Vue를 사용하기 위해 꽤 험난한 과정을 거쳤습니다. 지금도 잘 돌아가는 서비스에 리스크를 감수하면서도 새로운 것을 도입하려는 이유를 찾아야 했고, 한동안은 레거시와 Vue로 된 소스를 2중으로 개발해야 했습니다.게다가 이 글을 작성하기 시작했을 땐 Code Splitting 설정 방법이 바뀌어 적용하지도 못한 상황이었기 때문에 사실 Code Splitting 내용이 없었습니다. 그런데 글을 작성하면서 splitChunk옵션을 성공해버렸어요! 덕분에 이 글도 모두 수정해야 했죠. Vue의 도입을 고려하는 개발자분들에게 도움이 되길 바라는 마음으로 글을 마칩니다.참고1)Vuex Store는 Vue와 Vuex, 컴포넌트간 통신과 상태 관리에 자세히 정리해두었다.2) 브랜디 관리자 서비스는 jQuery로 작성되어 있다. 따라서 jQuery를 베재할 수만은 없는 상황이었다. 이에 따라 기존 jQuery 컴포넌트들에 대한 해결책은 천보성 팀장님이 작성한 JQuery 프로젝트에 VUE를 점진적으로 도입하기를 참고했다. props와 emit 기능을 이용해 jQuery로 제작한 컴포넌트를 깔끔하게 Wrapping 하는 방법에 대해 자세히 기술되어 있으며, 이를 활용하면 레거시 UI 플러그인을 마치 네이티브 Vue 플러그인처럼 사용할 수 있다.글강원우 과장 | R&D 개발2팀[email protected]브랜디, 오직 예쁜 옷만
조회수 968

[맛있는 인터뷰 4] 잔디의 헬스보이, 안드로이드 개발자 Steve를 만나다

[맛있는 인터뷰] 잔디의 헬스보이, 안드로이드 개발자 Steve를 만나다                                         미소, 승리의 V, 로맨틱, 성공적                                       삶은 생각보다 심플한 것 같아요.                              인생은 결국 생각하는 대로 풀리게 되더라고요.                                     잔디에서 제 목표를 이뤄가고 있어요.                                      – Steve, 잔디 안드로이드 개발자편집자 주: 잔디에는 현재 40명 가까운 구성원들이 일본, 대만, 한국 오피스에서 일하고 있습니다. 국적, 학력, 경험이 모두 다른 멤버들. 이들이 어떤 스토리를 갖고 잔디에 합류했는지, 잔디에서 무슨 일을 하고 있는지 궁금해하시는 분들이 많았습니다.  이에 잔디 블로그에서는 매 주 1회 ‘맛있는 인터뷰’라는 인터뷰 시리즈로 기업용 사내 메신저 ‘잔디’를 만드는 사람들의 이야기를 다루고자 합니다. 인터뷰는 매 주 선정된 인터뷰어와 인터뷰이가 1시간 동안 점심을 함께 하며 다양한 이야기를 나누며 진행됩니다. 인터뷰이에 대해 궁금한 점은 댓글 혹은 이메일([email protected])을 통해 문의 부탁드립니다.오늘의 ‘맛있는 인터뷰’ 장소는 어디인가요?‘롱브레드’라는 빠니니집이에요. YB와 같이 버디런치할 때 갔었는데 맛있었어요. 강남이라는 위치 특성 상 보통 식당들이 혼잡한데 여긴 조용한 편이에요.                                       빠니니 앞에 우리는 겸손해진다.잔디 블로그가 유명해지면 그리되겠죠? 자기소개 좀 부탁드릴게요안녕하세요? 스타트업을 동경해 안정적인 삶을 뒤로 하고 잔디에 조인한 안드로이드 애플리케이션 개발 담당자 Steve입니다.안드로이드 개발 중에서 어떤 일을 맡고 계신가요?지금은 전체적인 부분을 다 하고 있어요. 안드로이드 쪽으로 가장 먼저 입사한 사람이라 요즘 들어오는 개발자분들 OJT도 하고, 주요 개발 포인트에도 열심히 참여하고 있습니다.그렇군요. 헬스 트레이너 자격증을 갖고 계신단 얘길 들었어요.사실 운동을 전문적으로 하려 그런 건 아니었고, 옷 맵시를 잘 살리고 싶어 운동을 시작했어요. 제가 과거에 개그 콘서트 ‘헬스보이’에 나오는 김수영 같았담 몸매였다면 믿기시겠어요? 인생의 암흑기였던 그 시절, 어떤 옷을 입어도 멋있지 않았어요. 딱 한 번이라도 좋으니 뭘 입어도 간지가 났으면 좋겠단 생각을 했어요. 그게 제 생활 습관을 바꾼 계기였어요.트레이너 자격증 따는 게 쉽지 않을 것 같아요트레이너 자격증 준비할 당시엔 장기적으로 꾸준히 운동했어요. 아침 6시에 일어나 운동하고 오전, 오후 일과를 보낸 뒤 오후 5시부터 다시 운동하고 11시에 자곤 했어요. 식단은 하루에 5끼를 한 가지 종류의 메뉴로 구성해 1년 동안 먹었는데요. 정말 힘들 때는 한 달에 한 번 피자를 먹기도 했습니다.참기 힘든 유혹의 순간이 있진 않았나요?음.. 실기 시험 일주일 전이었어요. 여긴 특이하게 짧은 바지만 입고 몸을 보여주는 테스트를 통과해야 필기 시험을 볼 수 있었는데요. 실기 시험 전 참석했던 친한 동기 생일에서 술을 마다하고 최대한 절제하고 있었어요. 근데 친구가 자기 생일인데 왜 안 마시냐 핀잔 아닌 핀잔을 주더라고요. 그 때 조금 마셨는데 순간 고삐가 풀리더라고요. 이후 3시간 동안 미친 듯이 술과 안주를 먹었어요. 정말 다행히 실기 시험에 통과했지만 그때 한번 제대로 이성을 잃었던 적이 있습니다.헬스를 하면서 얻은 수확이 있다면?1년 정도 운동을 하니 규칙적인 생활이 몸에 뱄어요. 언제, 무엇을 할지 계획을 세워 생활하다 보니 어떻게 하면 효율적으로 시간을 사용할 수 있을지 알게 되었는데요. 운동을 통해 스스로 인내하고 제어하는 방법을 그 때 다 배웠어요.그 습관이 업무에 도움이 되셨나요?업무 관련 이야기는 아니지만 잔디에 합류하기 전 이직 준비를 1년 넘게 했어요. 이직에 필요한 사항을 정리해 최선을 다해 준비해보자 마음먹었어요. 이때 운동을 통해 다진 규칙적인 생활 습관이 큰 도움이 되었는데요. 꼬박 1년 동안 밤낮을 가리지 않고 개발 공부에 매달렸어요. 덕분에 ‘함께 일해볼 생각이 없냐?’는 제의를 많이 받았어요.                                 일할 땐 진지 모드, 밥 먹을 땐 샤방 모드.그런 제의를 고사하고 잔디를 선택하신 이유가 있다면?몇 가지 이유가 있는데요. 스타트업에 계시는 다른 분들을 보고는 비전이 있는 곳으로의 이직을 결심했어요. 5년 차 엔지니어로서 1년이라는 시간을 가지고 승부수를 던진 거예요. ‘생각하면서 살면 생각한 대로 살지만, 살면서 생각하면 사는 대로 생각하게 된다.’는 말을 인상 깊게 봤어요. 이 말대로 실천하려고 노력해 온 게 시간이 지나니 확실히 남들과 차이가 커지더군요.  그래서 생각하면서 사는 게 얼마나 중요한지 알고 있어요. 그중에서도 직장은 하루에 큰 부분을 차지하니까 신중하게 직장을 선택하는 건 인생의 중요한 전환점이죠.잔디에서의 생활은 만족스러우세요?기대했던 모든 게 다 잔디에 있는 것 같아요. 업무에 대한 자율성과 책임감이 적절히 섞여 있어요. 일반 회사의 수직적 구조도, 팀장급 이상에게만 주어지는 의사 결정권도 잔디에선 찾아볼 수 없어요. 덕분에 다양한 시각과 방법으로 개발 업무를 할 수 있기 때문에 전 개인적으로 만족하며 일하고 있습니다.쉬는 날에는 보통 어떤 활동을 하세요?업무 관련 공부를 하거나 친구들을 만나곤 해요. 개인적으로 회사 근처에 사는 걸 선호해 현재 강남 쪽에 살고 있는데요. 덕분에 친구들과의 약속이 잦아졌어요. 약속이 없는 날에는 주로 혼자 공부하고 있어요.이전 인터뷰이인 Jay님이 오늘 인터뷰이에게 ‘좋은 프로덕트란 어떤 것인지’ 물어봐달라고 하셨는데요. 이 질문에 대한 Steve의 답변은?좋은 프로덕트란 ‘복잡한 설명이 없어도 모든 동작을 깔끔하게 작동할 수 있게 만드는 것이다’ 라고 정의하고 싶습니다. 이를 위해선 개발자들이 모든 프로세스를 다 자동화해야겠죠? 생각보다 매우 꼼꼼한 업무가 필요한 과정이라 개발자들에게는 스트레스가 될 수 있을 거에요. 하지만 이건 개발자의 몫이고 사용자에게는 ‘편리함’과 ‘익숙함’을 제공해야 한다고 생각합니다. 제품 사용을 위한 프로세스를 최대한 단순화시켜 사용자가 자신이 원하는 동작 이외의 행동에 대해 생각하지 않게 만드는 게 최고의 프로덕트인 것 같습니다.미리 준비하셨나요? 인상적인 답변이네요. 마지막으로 다음 인터뷰를 위한 릴레이 질문이 있으시다면?다음 인터뷰이 분에게 ‘일과 사랑 어느 쪽이 우선인지’ 꼭 물어봐 주셨으면 좋겠습니다. 보통 스타트업을 다니면 연애하기 힘들다고 하잖아요. 왠지 다음 분께서 어떤 대답을 하실지 궁금하네요.열정적인 Steve와의 인터뷰 이후 ‘잔디의 안드로이드 개발 부분은 걱정 없겠구나’ 란  생각을 하게 되었습니다. 앞으로도 잘 부탁해요 Steve! 다음 주 인터뷰도 많은 기대 부탁 드려요.#토스랩 #잔디 #JANDI #개발자 #앱개발자 #애플리케이션 #모바일 #팀원 #팀원소개 #팀원인터뷰 #인터뷰 #사내문화 #조직문화 #기업문화 #팀원자랑
조회수 4056

제니퍼5 기능 소개

JENNIFER 5의  유용한 기능을 소개해 드리는 시간. 새로운 기능을 검토해 보시고, 지금 바로 사용해 보세요. 제니퍼소프트는 제품을 사용하는 고객이 최적의 환경에서 모니터링 할 수 있도록 하는데 최고의 가치를 두고 모든 제품을 개발합니다.제니퍼(JENNIFER)는 웹 애플리케이션 (Java EE, .NET, PHP) 시스템 모니터링을 위한 APM(Application Performance Monitoring) 솔루션입니다. 제니퍼는 경량화(Light-Weight), 실시간(Real-Time), 그리고 개별 트랜잭션 모니터링(Individual Transaction Monitoring) 등 기술기반의 '직관적인 통합 성능관리 솔루션'으로 이미 국내외 1200여 개 고객사를 통해 검증된 바 있습니다.  또한, 시대의 요구 사항인 모바일, 클라우드, 그리고 빅 데이터 시장의 온전한 모니터링 체계를 위하여, 웹 서비스 사용자 모니터링 (Web Service Real-User Monitoring), 웹 서비스 중심의 토폴로지 뷰(Web Service Topology View), 클라우드(대규모 시스템) 환경을 고려한 아키텍처, HMTL 5기반의 N스크린(N-Screen)까지도  지원하는 APM 제품입니다.웹 서비스 중심 토폴로지 뷰 (Web Service Topology View)제니퍼 토폴로지 뷰(Topology View)는 기업의 웹 서비스를 중심으로 연결된 서비스에 대한 가시성(Visibility)을 확보하는 것이 핵심 기능입니다. WAS를 중심으로 연결된 서비스(DB, 외부 연계 서비스, HTTP 등) 사이에 발생하는 트랜잭션, 즉, 구간에서 처리되는 트랜잭션까지 실시간으로 모니터링 할 수 있습니다.구간 엑티브 서비스 모니터링: 구간에서 처리되고 있는 엑티브 서비스를 실시간 모니터링 하여 병목 지점과 그 원인을 분석할 수 있습니다.X-view 연계 분석: 병목 지점이 되는 구간에서 처리되는 모든 트랜잭션에 대한 분석을 할 수 있습니다.구간 실시간 모니터링: 실시간 차트를 통해 원하는 구간에 대한 모니터링이 가능합니다.웹 서비스 사용자 응답시간 모니터링(RUM)클라이언트 구현 기술의 발전과 모바일 기기의 대중화로 인해 기업의 서비스는 복잡해졌습니다. 사용자는 모바일을 통해 언제, 어디서든 기업의 서비스를 이용할 수 있게 되었고, APM은 이제 서버사이드 영역의 모니터링뿐만 아니라, 실제 사용자의 만족도를 높일 수 있는 사용자 중심의 성능 모니터링 기능을 요구하고 있습니다. 이러한 변화에 따라 제니퍼는 프런트 앤드(Front-End) 영역의 모니터링을 위한 실제 사용자 모니터링, 즉 RUM(Real User Monitoring)을 지원합니다.이 기능은 웹 표준 조직 기구인 W3C의 Timing Navigation API를 사용하여 별도의 모듈 설치 없이 브라우저에서부터 서버사이드까지 전 영역에 대한 응답시간 측정이 가능하며, 서버와 네트워크로 이어지는 애플리케이션 수행 경로를 시각적으로 표시하여 애플리케이션 성능에 대한 깊이 있는 분석이 가능합니다.제니퍼 for CLOUD최근 IT 흐름의 큰 변화 중 하나는 클라우드(대용량 시스템)입니다. 클라우드 환경의 큰 특징은 트랜잭션의 양에 따라 하드웨어의 제약을 받지 않고 필요에 따라 서버 수를 조절하며 운영할 수 있어야 한다는 것입니다. 제니퍼는 자동감지(Agent Auto Detection), 일괄 설정(Central Configuration), 일괄 배포 (Central Deployment) 기능을 통하여 클라우드 환경에서의 애플리케이션 성능 모니터링을 지원합니다.스마트 프로파일링(Smart Profiling)제니퍼의 개별 트랜잭션의 응답시간을 활용한 엑스 뷰 기반의 분석은 이미 수많은 고객사에서 검증된 트랜잭션 모니터링 기법입니다. 하지만, 프로파일링 분석은 개발자 혹은 성능 튜닝의 전문가가 아니면 어려움을 겪는 것이 사실이었습니다. 이에 제니퍼는 누구나 쉽게 프로파일링 데이터를 분석 할 수 있는 스마트 프로파일링(Smart Profiling)을 제공합니다. 이 기능을 통해 사용자는 Method, SQL, 외부 서비스 중 응답시간이 느린 구간을 선택하여 해당 시점의 프로파일을 쉽게 분석할 수 있습니다.실시간 Connection Pool 모니터링실시간 Connection Pool 모니터링은 Instance별 Connection Pool을 실시간으로 모니터링하는 기능입니다. 이 기능은 액티브 서비스 차트와 함께 모니터링하며 액티브 서비스 점유가 주로 DB Connection에 있을 경우 Connection Pool 설정을 조정할 수 있어 서비스 성능을 개선할 수 있다는 것입니다. 다른 측면에서 DB Connection을 특정 애플리케이션에서 많이 사용할 경우 현재 Connection을 사용하고 있는 Active Service를 찾아내어 원인을 분석할 수 있습니다.실시간 애플리케이션 변경 이력 모니터링기업에서 운영하는 서비스는 수많은 고객의 요구사항을 반영하고 서비스 개선을 위해 하루에도 여러 번 애플리케이션을 변경합니다. 모니터링 관점에서 애플리케이션 변경 시점은 곧 서비스 장애가 일어날 가능성이 가장 많은 시점입니다. 그렇기에 모니터링이 가장 필요한 시점이기도 합니다. 애플리케이션 변경 감지 기능은 변경 전후의 성능 변화를 실시간으로 모니터링하고, 변경 시점에 변경된 소스코드를 추적하여 어떤 소스코드가 변경되었는지 추적할 수 있습니다.  이를 통해 개발자와 운영자 모두가 쉽고 빠르게 서비스의 변화를 감지하고 대응할 수 있는 장점이 있습니다. 엑스 뷰(X-View) > 애플리케이션 연계 분석애플리케이션 연계 분석은 검색한 X-View의 개별 트랜잭션을 기반으로 애플리케이션 단위 호출건수, 평균 응답 시간, 최대 응답 시간, 평균 SQL 시간, 평균 CPU 시간을 함께 분석할 수 있는 기능입니다.  또한 이러한 성능 수치들이 높은 애플리케이션의 개별 트랜잭션을 분석하여 성능에 영향을 미치는 애플리케이션을 튜닝 할 수 있습니다.엑스 뷰(X-View) > 연계 트랜잭션 분석제니퍼는 하나의 요청으로부터 시작된 다수의 트랜잭션 간의 상관 관계를 모니터링하거나 분석할 수 있습니다. 하나의 서버에서 처리된 서로 다른 업무 트랜잭션들을 연계할 수 있으며, 다른 서버에서 발생된 트랜잭션을 연계할 수 있습니다. 프로토콜 후킹 방식(HTTP, RMI)과 GUID를 활용한 연계방식을 지원합니다.엑스 뷰(X-View) > 자동 스택트레이스제니퍼를 포함한 대부분의 APM은 트랜잭션이 느린 원인을 분석하기 위해 매서드 프로파일링 기능을 제공합니다. 하지만 매서드 프로파일링 기능은 잘못된 설정으로 성능에 영향을 주거나 실제 느린 매서드를 찾지 못할 경우가 많습니다. 또한, 로직을 잘 알아야 하므로 성능 전문가가 아닌 이상 사용이 매우 어려운 단점이 있습니다.제니퍼는 이런 제약사항을 없애고 좀 더 쉽게 사용하기 위해 자동 스택트레이스 기능을 제공합니다.  이 기능은 성능 전문가가 아니더라도 느린 트랜잭션이 발생했을 때 해당 시점에 자동적으로 스텍트레이스(Stacktrace)를 남겨서 원인을 쉽고 빠르게 분석할 수 있습니다. 제니퍼소프트는 항상 제니퍼 고객의 모니터링 환경을 좀 더 쉽고 유용하게 할 수 있도록 고민하고 있습니다.  더 좋은 기능을 제공할 수 있도록 노력하겠습니다. 
조회수 2157

레진 기술 블로그 - 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
조회수 1127

Vue, 어디까지 설치해봤니?

Overview새로운 사용환경 구축에 도전하는 건 개발자의 운명과도 같습니다. 오늘은 여러 장점을 가지고 있는 Vue (프론트엔드 자바스크립트 프레임워크)를 도전해보겠습니다. Vue는 다른 프레임워크에 비해 가볍고, 개발하기에 편합니다. 그럼 우선 Vue를 설치합시다! Vue 설치CDNhttps://unpkg.com/vue 주소를 script 태그에 직접 추가 Vue.js 파일다운개발용, 배포용 버전을 다운 받아 script 태그에 추가개발용 버전은 개발에 도움이 되는 모든 경고를 출력하기 때문에 개발 중에만 사용하고, 실제 서비스에서는 배포용 버전으로 사용해야 한다. NPM 설치규모가 큰 프로젝트 경우 컴포넌트별 독립적으로 관리할 수 있는 싱글 파일 컴포넌트 방식 추천 Vue를 설치하는 방법은 여러 가지가 있습니다. 각자 특성에 맞게 편리한 방법으로 설치해주세요. 이번 글에서는 싱글 파일 컴포넌트 방식을 사용할 것이므로 NPM vue-cli 를 설치해 프로젝트를 구성하겠습니다. # vue-cli 전역 설치, 권한에러시 sudo 추가 $ npm install vue-cli -global vue-clivue-cli를 사용하면 뷰 애플리케이션을 개발하기 위한 초기 프로젝트 구조를 쉽게 구성할 수 있습니다. 다만, 싱글 파일 컴포넌트 체계를 사용하려면 .vue 파일을 웹 브라우저가 인식할 수 있는 형태의 파일로 변환해 주는 웹팩(Webpack)이나 브라우저리파이(Browserify)와 같은 도구가 필요합니다. vue-cli 설치 명령어 vue init webpack : 고급 웹팩 기능을 활용한 프로젝트 구성 방식. 테스팅,문법 검사 등을 지원vue init webpack-simple : 웹팩 최소 기능을 활용한 프로젝트 구성 방식. 빠른 화면 프로토타이핑용vue init browserify : 고급 브라우저리파이 기능을 활용한 프로젝트 구성 방식. 테스팅,문법 검사 등을 지원vue init browserify-simple : 브라우저리파이 최소 기능을 활용한 프로젝트 구성 방식. 빠른 화면 프로토타이핑용vue init simple : 최소 뷰 기능만 들어간 HTML 파일 1개 생성vue init pwa : 웹팩 기반의 프로그레시브 웹 앱(PWA, Progressive Web App) 기능을 지원하는 뷰 프로젝트여러 설치 명령어 중에 특성에 맞는 초기 프로젝트를 생성하세요. 1) vue init webpack 실행# 해당 프로젝트 폴더에서 실행 $ vue init webpack   # 현재 디렉토리에서 프로젝트 생성 여부 ? Generate project in current directory? (Y/n) # 프로젝트 이름 ? Project name (vue_ex) # 프로젝트 설명 ? Project description (A Vue.js project) # 프로젝트 작성자 ? Author (곽정섭 ) # 빌드 방식 ? Vue build (Use arrow keys) # vue-router를 설치 여부 ? Install vue-router? (Y/n) # 코드를 보완하기 위해 ESLint를 사용 여부 ? Use ESLint to lint your code? (Y/n) # ESLint 사전 설정 선택 ? Pick an ESLint preset (Use arrow keys) # 단위 테스트 섧정 ? Set up unit tests (Y/n) # 테스트 러너 선택 ? Pick a test runner (Use arrow keys) # Nightwatch로 e2e 테스트를 설정 여부 ? Setup e2e tests with Nightwatch? (Y/n) # 프로젝트가 생성 된 후에`npm install`을 실행해야합니까? ? Should we run `npm install` for you after the project has been created? (recommended) (Use arrow keys) 2) 고급 웹팩 기능을 활용한 프로젝트 구성 방식으로 설치3) 설치완료4) package.json 파일에 설정된 라이브러리 설치$ npm install 5) 개발모드 실행# 해당 프로젝트 폴더에서 실행(소스수정시 자동 새로고침) $ npm run dev 6) http://localhost:8080/ 브라우저 실행7) Yeah, You got it!!!!추가 도구: Vue Devtools(크롬 확장 플러그인)Vue Devtools(크롬 확장 플러그인)은 Vue를 사용할 때, 브라우저에서 사용자 친화적으로 검사하고 디버그할 수 있습니다.크롬 개발자 도구에 Vue 탭이 추가됨ConclusionVue를 설치하는 여러 방법 중 고급 웹팩 기능을 활용한 프로젝트 구성을 알아봤습니다. 다음 글에서는 Vue 인스턴스 및 디렉티브(지시문) 사용법을 다뤄보겠습니다.참고설치방법 — Vue.js 글곽정섭 과장 | R&D 개발1팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발문화 #개발팀 #업무환경 #인사이트 #경험공유 #Vue
조회수 4046

풀스택 개발자, 그것은 환상..

풀스택 개발자라는 용어가 가끔 등장한다. 죄송하지만, 한국에서는 이 용어가 정말 잘못 이해된 상태로 사용되고 있다. 처음에 만들어진 의미와 뜻이 한국에 들어오면서 변한 것을 보는 것이 이번만도 아니다.언제나처럼, 이 '단어'가 의미하는 뜻은 '귤이 회수를 건너면서 언제나 탱자가 되는' 한국적인 환경에서는 매우 이상하게 와전된 의미로 사용되고 있다. 특히나 비개발자들인 경영진들이 그러하고, 개발자들도 가끔 잘못된 의미로 사용한다.와전된 의미의 '풀스택 개발자(Full Stack Developer)'는 프런트엔드와 서버 엔드를 넘나드는 모든 것을 다 아는 전지전능한 개발자인 것처럼 쓰인다. 죄송하지만, 풀스택 개발자의 의미는 프런트-엔드부터 서버-엔드까지 모든 것을 다룰 줄 아는 개발자를 의미하는 것이 아니다.이 '용어'가 쓰이는 분야를 조금은 국한시켜야 할 필요가 있다.그것은 '웹'환경의 프론트 영역으로 국한시키는 것이 매우 현명할 것이다. 다음의 링크를 참조하기를 권한다.http://www.sitepoint.com/full-stack-developer/위의 사이트에 있는 이미지와 단어를 차용한다. 아래의 그림을 살펴보라.[이미지출처 : http://www.sitepoint.com/full-stack-developer/ ]OS부터 Database, WebServer, Server Side Code, Browser, Client Side Code를 아우르는 능력을 가진 사람을 Full-Stack Developer라고 부를 수 있다.좀 더 쉽게 이야기하자면, 'Web'환경은 서버사이드 코드와 클라이언트 사이드 코드를 모두 이해하고 작성되어야 한다. 브라우저( 특히나 변덕스러운 호환성 문제들.. )의 스크립트 환경이 효과적으로 가동되기 위해서는 웹서버의 API를 적절하게 디자인하고 구현된 상태에서 동작되어야 하며, 대부분의 코드들은 직접 Database에 영향을 주는 경우가 많다. 더군다나, 소프트웨어 개발을 하려면 형상관리부터 배포 처리를 위한 기술도 할 줄 알아야 한다.맞다. 'Web'개발 환경에서는 Full-Stack Developer가 되지 않으면 제대로 된 개발이 어렵다. 그래서, '웹'에서는 풀스택 개발자를 지향해야 하고, 매우 당연하게 해당 스킬들을 익숙하게 다루어야 한다.풀스택 개발자는 Web의 개발환경에서는 어쩔 수 없이 매우 당연한 기술적인 한계이고 해야 할 업무를 위해서는 필연적인 형태 인 것이다.이렇게 '웹 환경에서의 풀스택 개발자'는 한국에도 많이 존재한다. 상당수의 PHP개발자 분들이 그러한 '풀스택 개발자'인 경우가 많다.그렇지만, 이 풀스택 개발자의 용어는 '개발'이나 '소프트웨어'를 잘 모르는 경영자의 머릿속으로 잘못 들어가서 마치, iOS나 Android APP도 개발하고 Rest API 디자인이나 구현도 하면서, AWS의 분산 환경에 대한 이해나 개발도 모두 가능한 '전지전능한 개발자'와 같은 의미로 잘못 사용되기도 한다.( 더군다나, 디자인능력이 극도로 필요한 자바스크립트나 능동형 웹-UI를 만들어 내는 능력은 전혀 다른 능력이다 )원래 의미의 '풀스택 개발자'는 '혼자서 웹서비스 하나를 만들 수 있는 개발자'라는 좁은 의미로는 맞다. 하지만, 이를 과도하게 해석하거나 아전인수격으로 해석하는 것은 매우 곤란하다. 그것은 바로 한국적인 특수한 환경 때문에 그러하다.슬프지만, 한국적인 의미의 풀스택 개발자가 존재하기는 하고 있다.프로그래머가 기획도 하면서, 서버 구입부터 설치까지 다진 행하고, DB도 일부 다룰 줄 알면서, 웹이나 클라이언트 프로그래밍의 일부도 할 줄 아는 매우 한국적인 풀스택 개발자가 존재하기는 한다. ( 근데, 그런 개발자들을 풀스택 개발자라고 표현하지 않는다. 거의 기업의 잡부(?)처럼 부려지는 경우다. )노가다 - dokata, 土方 -'막일'을 하는 노가다를 하는 잡부가 한국형 풀스택 개발자라고 표현하겠다.하지만, 그런 테크트리로 형성된 한국형 풀스택 개발자들의 실력은 매우 볼품이 없는 경우가 대부분이다. 필자가 공공 SI현장에서 만난 수많은 한국형 풀스택 개발자들이 그러했다.그들은 컴파일러가 만들어내는 에러 메시지에 대한 이해는 없지만, 10년 넘게 업무를 배운 경험과 대충 Linux나 Windows Server의 기본적인 경험과 온통 스파게티 식으로 구성되어진 소스로 만들어진 더 이상 시장이 커지지 않는 한계가 다다른 시장에서 소프트웨어 개발을 하고 있다.태생적으로 '잡부'가 될 수밖에 없는 작업현장에서 진정한 의미의 풀스택 개발자는 거의 형성되기 어렵다. 이런 한국형 풀스택 개발자들은 실제 하나하나의 스킬들을 확인하거나 체크해본다면 거의 대부분 매우 부족하거나, 특정 기능에만 적합한 일반적으로 쓸모없는 기술들이 대부분일 가능성이 크다고 단언하겠다.이런 경향은 게임업계도 비슷하다. 한국형 풀스택 게임 개발자는 게임 기획부터 스프라이트의 2D부터, 포토샵이나 일러스트레이트도 다룰 줄 알며, 3D Max로 3D도 만들고, Auto-Cad로 도면 데이터도 다루고, DirectX에 Unity도 다루며, 서버나 iOS의 앱까지 만들 줄 안다고 하지만, 정작 그 어느 하나도 제대로 못 다루는 경우가 태반이다.물론, 전부 다루는 사람이 없는 것은 아니다. 있기는 있지만... 그분들 굉장히 유명하거나 특정 기술하나 가 대가의 수준이기 때문에 자신이 가진 다른 기술들을 포함해서 자신을 '풀스택 개발자'라고 포장하지 않는다.하지만, 한국에서 유독 '개발자 구인 광고'를 보면 '풀스택 개발자'를 찾는 곳이 많은 이유는 무엇 때문일까?그것은, 무지한 경영진이나 무지한 비즈니스 모델, 무지한 리소스 활용이 난무하는 헬게이트의 주인들이나 그런 단어들을 주로 사용한다고 보면 된다.100% 단언컨대 한 사람의 개발자가 완벽한 풀스택 개발자라고 하더라도, 요구사항이 발생하고 유지보수업무가 존재하는 업무를 하드웨어적인 서버 관리부터 서버 API, 앱 프로그래밍, 웹 프로그래밍을 하기 위한 스킬은 알 수 있다고 하더라도 그 복잡하고 어지러운 업무량은 모두 다룰 수 없다.만일 그런 것이 가능하다고 이야기하는 경영진이 있거나 무지한 영업맨이 있다면 정신 차리라고 조언해주자. 심지어 그렇게 만들 수 있는 서비스는 존재하지 않고, 존재한다고 하더라도.. 어마어마한 '기술적 부채'가 존재하며, 대부분의 가장 비싼 개발자의 리소스를 그 기술적 부채를 해결하기 위해서 사용되고 있을 것이라고.물론, 그렇게 동작하는 허접하고 쓰레기 같은 코드라고 하더라도, 특정 조건과 특정 환경에서는 서비스가 가능한 경우가 한국에는 많이 존재한다. 경영진이나 영업, 기획은 고객들을 설득하고 고객들이 해당 제품과 서비스를 사용하기 위해서 일부를 희생할 것이다. 그리고, 분명 다른 영역에서 누수가 발생하거나 희생되고 있는 것을 잊지 말자.특히나 경쟁이 없는 제품이거나 더 이상 리소스를 투입하기 어려운 소프트웨어나 서비스의 경우에는 이런 형태로도 동작은 할 것이다. 하루에 한두 번 서버의 Oracle 커넥션을 모두 종료하는 유지보수 행위를 하는 전산실의 업무가 그러한 경우 때문에 벌어진다.중견기업이거나 제조업체, 병원의 전산실에 '야간 당직'업무가 있고, 시스템 모니터링에 민감하다면 대부분 '기술적 부채'를 안고 허접하게 만들어진 것뿐이라고 판단하면 된다.말 그대로, 헬조선의 헬게이트, 헬(!)한 업무환경으로 소프트웨어 개발자로서 비전이 없는 영역이라고 생각하면 된다. 하지만, 그럼에도 불구하고... 스타트업 경영진이나 대기업, 중소기업 경영진들은 '풀스택 개발자'의 환상에 대해서 이야기한다.'모든 것을 다 하는 개발자'가 있으면, 복잡한 커뮤니케이션 비용도 안 들고, 인건비도 적게 들것이라는 착각을 한다. 다만, 이 부분만큼은 명쾌하게 이야기하겠다. '그런 회사 가지 말라'는 것이다.'풀스택 개발자'를 구인하고 있는 회사는 개발자의 무덤이라는 것이다. 대부분 그러하다. 그 이유를 다음과 같이 정리하겠다. 그들이 '풀스택 개발자'를 뽑고 싶은 이유는 간단하다. '돈'이 없어서다. 그리고, 다음의 이유들이 있는 경우이다.하나. 경영진이 요구사항 정의도 제대로 못하므로 개발자와 의사소통에 자신이 없다. 그래서, 풀스택 개발자를 구하려고 한다. 한 명 하고만 이야기하면 될 것이라고 착각한다.둘. 개발자의 인력이 몇 명이 투입되는지에 대해서 평가나 정의가 불가능하므로, 풀스택 개발자를 구하려 한다.셋. 개발자가 두 명, 세명이 있다면 팀 리더도 있어야 하고, 관리자도 있어야 하므로 그 비용을 줄이기 위해서 풀스택 개발자가 필요하다. 한마디로, 돈이 없다.넷. 현대의 웹서비스들을 가동하기 위해서는 최소한의 비용과 인건비가 투여된다. 이 비용을 투자할 정도로 비즈니스 모델에 가치가 없기 때문에 여러 명의 개발자를 고용할 수 없기 때문에 풀스택 개발자를 구하려 한다.다섯. 풀스택 개발자라면 막연하게 다 해줄 것 같은 환상을 가진 경영진이 있는 경우이다. 슬프지만, 전설의 개발자인 '제프 딘'을 고용한다고 하더라도, 삽질을 할 것이다.물론, 스타트업에 초기에 합류하면서 CTO의 역할을 부여받았다면 조금은 입장이 달라진다. 정당한 지분을 받고, 미래의 가치에 대해서 나눌 수 있다면, 해당 롤을 가진 사람은 알아서 '풀스택 개발자'가 될 가능성이 크다. 그러므로, 매우 당연하지만 CTO는 풀스택 개발자에 근접되면 좋기는 할 것 같다. 하지만, 현실적으로는 그렇게 세팅하지 못하는 경우가 대부분이다.그리고, 냉정하게 초기 개발이나 Lab수준, 시리즈 A를 투자받기 전의 '소프트웨어'나 '서비스'는 대부분 비즈니스 모델을 증명하는 수준에서 끝내는 것이 바람직하다. 굳이, 환상의 개발자나 풀스택 개발자가 아니라도 비즈니스 모델을 검토하고 증명하는 모델을 구현하는 것은 충분하게 가능한 경우가 대부분이다.사용자가 수백만 명도 아니고, 구현된 기능들도 수백 가지가 아니며, 아직은 스파게티 식으로 구성하더라도 무방하기 때문이다. 해당 기술적 부채는 서비스의 증명 후에 해당 코드는 버려지고, 다시 개발팀을 제대로 세팅하여 구현하면 되기 때문이다. 더군다나, 대부분의 스타트업은 고속 개발을 해야 하기 때문에 '풀스택 개발'이 가능한 '웹'만으로는 모든 것을 커버하기 어려울 것이다.좌우지간, 간단하게 이야기해서 '풀스택 개발자'타령하는 구인광고를 보게 된다면, 그 회사나 팀은 무언가 잘못 생각하고 있거나, '돈'이 없는 조직이라고 생각하면 된다. 거기에, '기술'이나 '개발'에 대해서는 아무것도 모르는 사람이 사장이 존재하는 곳이라고 생각하면 된다.헬게이트에 입성하고픈 개발자라면 '풀스택 개발자'를 구인하는 곳으로 가면 된다. 엄청난 '일'의 쓰나미를 경험하고, 인성이 피폐해지는 것을 경험할 것이다.필자는 국내 최고의 개발자들을 여럿 알고 있다. 하지만, 그분들은 자신들을 '풀스택 개발자'라고 이야기하지 않는다. 그 용어가 의미하는 것 자체가 '날림'이라는 것을 너무도 잘 알고 있기 때문이다. 물론, 10년 20년을 소프트웨어 개발을 하다 보면 얻어지는 경험과 지식들이 있다.궁극적으로는 풀스택 개발자가 이야기하는 비슷한 테크트리를 대부분 알고는 있게 된다. 하지만, 경력 20년 되고 하나의 도메인에 익숙하며, 특정 분야의 대가인 분들을 스타트업에서 고용한다는 것은 거의 불가능에 가깝다. 간혹, 그런 분들이 직접 스타트업을 하는 것이라면 모를까 말이다.이제 이야기를 마무리하겠다.'웹 개발'을 하려면 '풀스택 개발'을 지향하는 것은 맞다. 하지만, 그것 자체가 완벽한 풀스택 개발을 의미하는 것이 아니라는 것을 생각하기 바란다. 그리고, 경영진이나 비개발자들에게도 다시 한번 이야기한다. '풀스택 개발자'를 구인하겠다는 환상을 버리기 바란다.그런 사람 없고, 있다고 하더라도... '풀스택 개발자'를 구인하겠다는 발상으로는 절대 초빙하거나 모실 수 없다는 것을... 깨몽 하기 바란다.물론, '풀스택 개발자'처럼 이것 저것 다하는 정성스럽고, 일에 애정 넘치는 개발자들을 제대로 대우해주시기를... 기술로써의 풀스택 개발자가 아니라, 그 기업이 원하는 일을 풀스택 개발자처럼 일할 뿐이다. 그들에 대한 애정 넘치는 말한마디... 경영진들에게 부탁드린다.갑자기, '풀스택 개발자'에 대한 환상에 대해서 정리하고 싶어서 한 번에 글을 써 내려갔다. ~.~

기업문화 엿볼 때, 더팀스

로그인

/