스토리 홈

인터뷰

피드

뉴스

조회수 1070

원하는 대로 뭉치는 GROUP BY

편집자 주전문 용어는 특정의 학술 용어나 기술 용어를 말하는데, 대개 둘 이상의 단어가 결합하여 하나의 의미 단위에 대응하는 말, 곧 합성어의 성격으로 되어 있다. 아래와 같은 전문 용어는 단어별로 띄어 씀을 원칙으로 하나, 편의상 붙여 썼다. 1) 수행 결과 > 수행결과2) 수행 시간 > 수행시간3) 실행 계획 > 실행계획Overview지난 글에서는 ORDER BY를 파헤쳤습니다. 이번에는 ORDER BY만큼이나 자주 쓰이는 GROUP BY를 알아볼 시간인데요. GROUP BY는 컬럼 값을 그룹짓고(중복을 제거하고) 이에 대해 건수나 값의 합을 계산할 때 사용합니다.지난 글 보기: 순서대로 척척, ORDER BY지난 글 보기: 단일 TABLE을 SELECT하자! 1.GROUP BY의 이해GROUP BY의 기본적인 문법은 아래와 같습니다.SELECT     MBR_NM FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 실행계획은 아래와 같습니다. 테이블을 전부 읽어서 temp를 만들고 GROUP BY를 수행하라는 의미죠. GROUP BY가 수행되는 것은 Extra에 Using filesort가 표시된 것으로 유추할 수 있습니다.참고로 Using filesort는 GROUP BY, ORDER BY, DISTINCT 등의 정렬과 관련한 작업을 수행하면 나타납니다. Query를 수행해볼까요?위와 같은 결과가 나왔는데, 수행시간은 3.77초가 걸렸습니다. 이 Query는 MBR_NM의 중복을 제거해서 화면에 표시한 것입니다. 이번에는 아래의 Query를 수행해보겠습니다.SELECT     MBR_NM      ,COUNT(*) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 바뀐 것이 있다면 SELECT 절에 COUNT(*) 가 추가된 것입니다. 실행계획은 다른 점이 없습니다.COUNT(*)는 레코드의 건수를 계산할 때 사용합니다. 위의 계획은 MBR_NM의 값이 같은 건수를 출력하라는 의미입니다. 수행해보겠습니다.수행시간은 3.64초로 비슷하게 나옵니다. 위의 내용을 보면 강나영 1437건, 강다은 1465건, 강도연 1445건 … 인 것을 알 수 있습니다. 만약 테이블의 전체 건수를 알고 싶다면 어떻게 할까요? 아래와 같이 수행해보세요.SELECT     COUNT(*) FROM test.TB_MBR_BAS  ; 수행결과는 다음과 같습니다.2.GROUP BY의 응용(1): 나이 구하기이번에는 나이 컬럼을 추가하고 이름별 나이의 합을 구해보겠습니다. 아래의 명령으로 컬럼을 추가합니다.ALTER TABLE test.TB_MBR_BAS ADD COLUMN AGE TINYINT UNSIGNED DEFAULT 0 COMMENT '나이'; 컬럼이 추가되고, 다음과 같은 구조를 갖출 겁니다.AGE 컬럼에 모두 0이 들어간 것을 알 수 있다.SELECT     * FROM test.TB_MBR_BAS ; 0으로 들어간 값을 1에서 100 사이의 임의 값으로 변경하겠습니다. 만약 내용을 변경한다면 아래 예시와 같이 UPDATE문을 사용하세요. UPDATE test.TB_MBR_BAS SET AGE = TRUNCATE(RAND()*100,0)+1 ; test.TB_MBR_BAS 의 AGE 컬럼 내용을 변경하라는 명령을 하기 위해 RAND() 함수를 쓰고 임의의 값을 발생시겼습니다. UPDATE 및 SELECT를 수행하면 값이 변경된 것을 알 수 있습니다.SELECT     * FROM test.TB_MBR_BAS  ; 변경된 값이번에는 이름이 같은 사람들의 나이 합을 구해볼까요? 합을 구할 때는 SUM 함수를 사용합니다. SELECT     MBR_NM     ,COUNT(*)     ,SUM(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM ; 실행계획은 AGE 컬럼을 추가하기 전과 바뀐 것이 없다는 걸 알 수 있습니다. 실행결과를 보겠습니다.수행시간은 4.3초 걸렸습니다. ‘강나영’이란 이름을 가진 사람의 건수는 1,437건이고, 나이의 합은 74,092인 것을 알 수 있습니다. 합산만 하면 의미가 없으니 평균 나이를 구해보겠습니다. 방법은 SUM / COUNT하는 방법과 AVG 함수를 이용하는 방법 두 가지가 있습니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 실행계획은 이전과 달라진 부분이 없습니다. 수행결과를 보도록 하죠.수행시간은 5.6초 정도 걸렸습니다. 좀 더 빨리 수행하면 좋을 텐데 말이죠. 시간을 단축시키려면 어떻게 해야 할까요?3.GROUP BY의 응용(2): 수행시간 단축하기기본적인 방법은 GROUP BY할 컬럼으로 INDEX를 생성하는 것입니다. MBR_NM으로 INDEX를 생성해보겠습니다.CREATE INDEX IX_MBR_BAS_02 ON test.TB_MBR_BAS (MBR_NM); 생성 후, 이전 Query를 수행합니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 아래의 실행계획이 달라진 것을 알 수 있습니다.실행계획을 보면 전체를 읽어서 처리하는 부분은 사라졌습니다. 대신 IX_MBR_BAS_02 INDEX를 사용하는 것으로 나옵니다. 이미 정렬된 구조를 갖추고 있는 INDEX에서는 GROUP BY 수행 시, 또 정렬하지 않아도 됩니다. 그래서 별도 정렬인 Using filesort가 Extra에 나오지 않은 것이고, GROUP BY에 INDEX를 사용하는 것으로 해석할 수 있습니다. 그렇다면 시간은 얼마나 줄었을까요? 수행해보겠습니다.0.5초 정도 걸렸습니다. 기존 5.6초보다 훨씬 많이 개선된 것을 알 수 있습니다. 시간은 단축되었는데 결과는 같습니다.이번에는 IX_MBR_BAS_02를 기존 MBR_NM에서 MBR_NM, AGE로 생성해 보겠습니다.DROP INDEX IX_MBR_BAS_02 ON test.TB_MBR_BAS; CREATE INDEX IX_MBR_BAS_02 ON test.TB_MBR_BAS (MBR_NM,AGE); INDEX를 생성하고 이전 Query를 수행합니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS GROUP BY     MBR_NM  ; 달라진 것이 있다면 Extra에 Using index가 표시된 것입니다. 기존에 INDEX가 MBR_NM으로만 구축된 Query는 IX_MBR_BAS_02 INDEX로 GROUP BY하고, TB_MBR_BAS에서 AGE 합을 구한 것입니다. 하지만 INDEX가 MBR_NM, AGE로 구축된 이번 경우는 IX_MBR_BAS_02 INDEX를 이용해 GROUP BY 와 AGE의 합까지 구한 것이죠. 물론 결과는 같았지만, 수행속도는 0.3초로 개선되었습니다.4.GROUP BY의 응용(3): 특정 조건의 결과 출력WHERE마지막으로 성이 김 씨인 경우에만 GROUP BY하여 값을 출력해보겠습니다. 위의 Query에서 WHERE로 조건만 더하면 되는데요.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS WHERE MBR_NM LIKE '김%' GROUP BY     MBR_NM  ; 위의 이미지처럼 WHERE 조건이 들어가면서 type이 index에서 range로 바뀐 것을 알 수 있습니다. 이것을 해석하면 ‘ IX_MBR_BAS_02를 WHERE조건의 범위만큼 처리하라는 것’입니다. 실행결과를 보죠.HAVINGHAVING 절은 GROUP BY로 SUM, COUNT, AVG한 값을 필터 조건으로 걸고 싶을 때 사용합니다. 예시로 위의 Query에서 AVG(AGE) 값이 50보다 작은 것을 출력해보겠습니다.SELECT     MBR_NM      ,COUNT(*)      ,SUM(AGE)      ,SUM(AGE)/COUNT(*)      ,AVG(AGE) FROM test.TB_MBR_BAS WHERE MBR_NM LIKE '김%' GROUP BY     MBR_NM HAVING AVG(AGE) < 50>결과를 출력하면 아래와 같습니다.AVG(AGE)가 50보다 작은 값들이 출력된 것이 보이는군요.글을 마치며간단한 예제를 소개해드렸지만 큰 규모로 GROUP BY를 하면 재미있는 결과들을 만날 수 있습니다. 예를 들어 대한민국 전체 국민을 대상으로 GROUP BY를 실행하면, 평균 나이가 가장 많은 성 씨를 찾을 수 있습니다. 인구통계학 분석에 적용하면 100년 안에 없어질 성 씨를 알 수도 있고요. 응용할 수 있는 범위가 아주 많겠죠? 이상으로 GROUP BY에 대한 소개를 마칩니다. 글한석종 부장 | R&D 데이터팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발자 #개발팀 #인사이트 #경험공유
조회수 2295

ZOYIFUL TALK (1) 사무실이 마음에 들어 왔다가 개발에 재미 들렸죠

유저 반응을 볼 때가 즐겁다는 프론트엔드 엔지니어 인턴 Mino조이에서 소프트웨어 엔지니어 인턴으로 살아간다는 것이 어떤지 궁금해 하시는 분들이 많아 4개월차 소프트웨어 엔지니어 인턴 미노(본명 천민호)를 Zoyiful Talk 첫 번째 주자로 모셨습니다.ZOYI: 미노 안녕하세요! 인턴으로 조인하신지 벌써 4개월이 지나셨다면서요. 우선 간단한 소개부터 해주세요. 회사에서 무슨 일을 하고 있나요?MINO: 안녕하세요, 채널(Channel)이라는 조이 신규 서비스를 개발하고 있는 엔지니어 미노입니다. 채널은 소비자와 커머스 기업을 연결해주는 소통 창구 같은 서비스인데요, 저는 그 중에 웹 프론트엔드를 개발하고 있습니다.ZOYI: 프론트엔드가 뭔가요? 좀 더 설명해 주세요.MINO: 프론트엔드는 흔히 ‘웹 개발자’라 하는데요, 웹이나 앱에서 서비스 이용자가 경험하는 부분을 개발합니다. 이용자에게 더 좋은 시각적 효과를 주고, 더 편리한 경험을 제공하기 위해 기술을 이용하죠. 이를 구현하기 위해 자바스크립트라는 언어를 사용하고, react.js를 프레임워크로 사용하고 있습니다.ZOYI: 원래부터 프론트 개발을 많이 하셨었나요?MINO: 프론트엔드는 HTML 작성할 수 있는 정도? 아니면 레일즈로 간단한 홈페이지 게시판 만드는 정도였어요. 자바스크립트는 조이에서 처음 배워봤고요.사실 개발 시작한 것 자체가 작년 9–10월이니 이제 반 년 좀 넘었네요. 코딩은 2년 전부터 시작했었는데 거의 알고리즘 공부가 위주였고 최근에야 제대로 개발을 한 것 같아요ZOYI: 조이에는 어떻게 조인하게 되신 거예요?MINO: 대학 개발 동아리 회장을 할 당시 대회 후원사가 필요해서 레드(CEO)한테 컨택한 적이 있거든요. 후원을 받고 나서 레드의 권유로 회사에 한 번 놀러왔는데, 사무실이 생각보다 좋더라고요. (웃음)스타트업 하면 좁은 공간에 다닥다닥 붙어있는 모습을 생각했었는데… 깔끔한 공간이 인상깊었어요.높은 천장과 통유리 채광을 자랑하는 조이 사무실에 반했다고 합니다.ZOYI: ㅎㅎㅎ 직접 일해보니 어때요? 실제로도 깨끗하던가요?MINO: 레드의 책상이 좀 더럽긴 하지만…은 농담이고요, 실제로 일해보니 더 좋은 것 같아요. 책상도 넓고… 제가 이렇게 하얀 느낌을 좋아하거든요.ZOYI: 조이에서의 4개월을 지내보니 어때요?MINO: 음… 4개월 지나고 나니, 이제야 내가 뭘 모르고 뭐가 부족한지를 알 수 있게 된 것 같아요. 잘한다고 말하긴 아직 부끄럽지만, 적어도 구글링으로 뭘 찾아야 할지는 알 수 있게 됐어요.ZOYI: 안해본 것들을 했잖아요, 주로 어떻게 습득을 했어요?MINO: 사람마다 좀 다를 수 있는데 저는 그냥 시간 날때마다 조이 오픈소스 프로젝트들을 하나하나 열어보면서 이게 어떻게 동작하나를 봤어요. 그래도 모르면 물어보면서 Follow up 받고… 동료들한테 부담없이 물어볼 수 있어서 좋았어요. 촉진제같은 역할을 해 준 것 같아요.한 번은, 전혀 새로운 분야이고 처음 접해보는 언어를 다루는 거라 익숙치 못해 하루종일 구글링을 한 적이 있어요. 그런데도 오늘 커밋 했냐, 뭐했냐 이런 얘기가 없고… 당신의 성장을 그냥 지켜보겠다는 태도인 거예요. 처음엔 익숙하지가 않았는데, 그런 분위기 덕분에 결과적으로 리서치를 잘 하고 일을 성공적으로 마무리 할 수 있었어요.ZOYI: 동료들과 교류가 많은 편인가요?저는 프론트엔드를 하다보니 주로 개발팀 멤버들과 많은 시간을 보내는데요, 업무 외적으로도 되게 재미있어서 친하게 지낼 수 도 있고 그래요. 꾸준히 소통하려 하는 게 느껴져요. 나를 막연히 6개월 후 나가는 인턴이 아니라, 함께 성장해 가는 동료로 생각하고 있구나. 하는 기분이 들죠.ZOYI: 푸스볼 중독이라는데?MINO: 푸스볼도 ZOYI에서 처음 배웠는데, 이건 정말, 최고의 레져인 것 같습니다 (목소리 톤 올라감). 가격 대비 효율이 최고예요. 하루 한 번 이상 꼭 하고 있습니다.10분만 해도 맥박이 빨라진다는 엄연한 스포츠, 푸스볼ZOYI: 본인의 푸스볼 랭킹은?MINO: 글쎄요, 디케이(하드웨어 디자이너)보단 잘하지 않을까요? ㅎㅎZOYI: 인턴 끝나면 생각나겠어요, 그러고 보니 인턴도 이제 두 달 남았네요. 돌아가면 하고싶은 일이 있나요?MINO: 아직 고민중이예요. 사실 조이 들어오기 전에는 프론트, 웹 개발자는 정말 안하겠다고 생각했었는데 지금은 이게 재미있다는 생각이 들어요.초반에 누가 “잘 하게 되면 점점 재미있어 질거다”라고 말해준 적이 있는데, 그 말이 공감이 돼요. 점점 배워가면서 지금은 어느정도 의도한 대로 구현이 되니까…이젠 재미있는 거예요. 새로운 분야를 알게 된 느낌? 그래서 앞으로 프론트엔드 개발자로 일해도 좋고, 뭐든 최대한 많은 경험을 하고 많은 지식을 습득해 보고 싶어요.ZOYI: 좋은 계기가 되었네요, 인턴 생활은 만족스러워요?MINO: 네, 생각하던 것 이상으로 좋았어요. 주도적으로 일을 해 나갈 수 있다는 점과, 하나하나 해 나갈 때마다 내가 성장하고 있는 느낌이 좋아요. 사실 처음 입사할 땐 단순히 반복작업만 할 줄 알았거든요. ZOYI엔 뭔가 ‘네 꿈을 펼쳐봐라~’하는 태도가 있는데, 저는 거기에 잘 맞았던 것 같아요.ZOYI: 그렇다면 향후 ZOYI 지원을 고민하시는 분께 어떤 조언 한마디 해주시겠어요?MINO: 주변에 많은 친구들이 ‘난 안될거야’라고 생각하고 지원조차 안하는 경우가 많은데, 저는 일단 지원해 보라고 말해주고 싶어요. 저도 지원할 당시 굉장히 걱정을 했었거든요. 나는 알고리즘 공부밖에 못해봤고, 서버도 용어 하나도 모르는데 내가 잘 할 수 있을까?하는 생각.막상 회사에 들어오고 난 지금은 생각이 많이 달라졌어요. 인턴에게 중요한 자질은 완벽함보다 가능성인 것 같아요. 그 가능성이란 게 대단한 스펙이 아니라, 기초를 탄탄히 가지고 있는 거예요. 그리고 나면 회사에 와서 충분히 성장할 수 있어요.그 좋은 사례가 션(CTO)인 것 같아요. 함께 일하면서 CTO가 되어가는 모습을 곁에서 보는 게 참 좋았어요. 내부에서 우리가 성장해 더 큰 역할을 맡을 수 있는 조직이란 게 참 좋아요.ZOYI: 조언 감사합니다. 남은 기간 ZOYI에서 기대하는 점이 있다면?MINO: 이번 주부터 시작될 개발팀 위클리 세션이 기대돼요. 각자가 알고 있는 기술을 다른 멤버들과 공유하는 시간인데요, 조이가 워낙 다양한 기술을 다루다 보니 제가 담당하지 않는 분야에 대해서는 잘 모르는 게 많거든요. 같이 일하는 사람들은 어떤 분야에 대해 일하고 있는지 기술적으로 알아보고 싶어요.ZOYI: 좋은 시도네요. 마지막으로 글 읽으시는 분들께 한마디 하시겠어요?MINO: ZOYI는 잘하는 사람들이 와서 더 잘하게 되는 곳이 아니라 가능성 있는 사람들이 와서 잘하게 되는 곳이라고 생각해요. 누구에게나 열려 있으니 편히 찾아와 주셨으면 좋겠어요 ^^#조이코퍼레이션 #개발팀 #개발자 #개발환경 #업무환경 #팀원인터뷰 #팀원소개 #팀원자랑
조회수 3814

[어반베이스 인턴일기] 전공의 벽을 뚫어낸 능력자들

                                                      ‘전공무관’. 많은 채용 사이트에서 볼 수 있는 이야기죠. 하지만 채용공고만 그렇지, 막상 개발이라면 컴퓨터 공학을 전공해야 할 것 같고, 마케팅이라면 경영을 전공해야 할 것만 같습니다. 하지만 어반베이스의 개발 인턴들은 컴퓨터공학을 전공하지 않았고, 마케팅 인턴도 경영학을 전공하지 않았다는 사실! 우리는 어떻게 어반베이스를 알게 되어 어반베이스를 선택하게 되었을까요? 이제 들어온 지 한 달, 타운홀 미팅을 통해 정식으로 인사도 드렸으니 진정한 어반베이스의 식구가 되었습니다. 한달 간 느낀 인턴들의 솔직한 이야기를 만나보세요!※ 타운홀이란 ? 매달 1회 전직원이 모여 자유로운 주제로 소통하고 네트워킹하는 어반베이스만의 토론 문화 Pt 0. 자기 소개 및 하는 일 왼쪽부터 민진, 수민, 윤아마케팅부문 인턴 _ 민진 (컨텐츠 제작)건축공학을 전공하고 마케팅 부문 인턴이 되었다.어반베이스의 SNS들을 관리하고, 그에 맞는 컨텐츠를 제작, 그리고 이번에 열리는 어반스니커즈 컨퍼런스의 진행을 돕고 있다.개발부문 인턴 _ 수민 (3D 도면변환)건축학을 전공하고 개발부문 인턴이 되었다. 지금은 3D로 변환된 도면을 산업에서 쓸 수 있도록 다양한 3D 포맷으로 바꾸는 일을 한다. 개발부문 인턴 _ 윤아 (머신러닝)생체의공학을 전공하고 개발부문 인턴이 되었다.공간을 찍으면 공간이 어느 곳인지 인식하여 분류해주는 작업이다. 머신러닝과 딥러닝을 사용해서, 연령, 성별, 취향 등으로 공간을 세분화하여 그 공간에 맞는 제품을 추천해주는 시스템까지 계획하고 있다Pt 1. 선택Q. 어반베이스의 인턴 셋은 모두 전공과 다른 길을 가고 있네요. 어떻게 선택하게 된 길 인가요?전공과 맞지 않음을 깨달은 인턴 3人수민 : 전공이 건축이잖아요. 그런데 설계에 대한 회의가 들었어요. 그리고 VR에 관심이 생겼고, 그래서 프로그래밍을 배우게 됐어요.윤아 : 생체의공학과는 주로 배우는 분야가 하드웨어 쪽에 가까워요. 근데 저는 하드웨어 쪽은 잘 안 맞는 것 같더라고요. 전자공학과를 복수 전공하면서 프로그래밍 수업을 듣다가 프로그래밍을 이용한 데이터 분석에 흥미를 갖게 됐어요. 민진 : 취직 준비를 하면서 느꼈는데, 건축업계 자체가 굉장히 폐쇄적이고 수직적이고 보수적인 문화를 가지고 있더라고요. 그런 곳에서 잘 적응하지 못할 것 같아 건축이라는 전공을 살려 할 수 있는 다양한 길을 찾아 봤고, 그런 과정 중에 어반베이스를 알게 됐어요.Q. 그렇다면 왜 어반베이스를 선택했나요? 윤아 : 데이터 사이언스 쪽으로 일자리를 찾다가 알게 됐어요. 수치나 텍스트 데이터를 사용해서 분석하는 공부를 많이 해서, 이미지 데이터를 사용하는 분야도 배우고 싶었는데, 어반베이스에서 그런 일을 하더라구요.수민 : VR에 관심이 있었고, 회사가 하는 일이 건축 전공이라면 잘 맞을 것 같아서 선택했고, 와서 겪어보니 실제로도 그런 것 같아요. 채용공고나 블로그에서 봤던 회사의 복지나 비전도 선택에 큰 영향을 미쳤죠. 민진 : 건축을 베이스로 하는, 4차 산업혁명의 흐름을 직접 느낄 수 있는 회사에서 일을 하고 싶었어요. 그래서 무모하지만 과감하게 마케팅 팀에 지원을 했습니다. 수민님에게 큰 영향을 주었다는 어반베이스의 꿀복지!Q. 대기업이 아닌 스타트업을 생각했던 이유가 있나요? 윤아 : 대기업의 획일화 된 채용 시스템이 싫었어요. 딱딱하고, 틀에 박혀있는 그런 형식들이요.민진 : 저두요. 그리고 저는 스타트업에서 일을 하면 바로 실무를 할 수 있다고 해서 욕심이 났어요. 바로 일을 해보고 싶었거든요.Q. 전에 일을 하신적이 있나요? 실제로 일을 해보니 어떤가요?수민 : 실무를 하는 것은 처음이에요. 저는 3D로 변환된 도면을 산업에서 쓸 수 있도록 다양한 3D 포맷으로 바꾸는 일을 해요. 설계할 때는 3D 툴을 직접 다루는 입장이었는데 지금은 파일만 다루니 생소하긴 하네요. 부담되기도 하지만, 사람들에게 많이 물어보거나 정보를 알아서 흡수하려고 해요. 3D 도면변환을 담당하고 계신 수민님윤아 : 마찬가지로 실무는 처음이에요. 저는 머신러닝 쪽인데, 쉽게 말해서 공간을 찍으면 공간이 어느 곳인지 인식하여 분류해주는 작업이에요. 일단 아직은 배우는 중이라 그런지 일이 재미있어요. 시간이 빨리 가는건 재밌다는 거 아닐까요? 사실 사수가 있을 줄 알았는데 없어서 되게 막막했어요. 가끔 일 하다가 막힐 때가 있는데, 모르는 것은 다른 분들에게 물어보기도 하고, 구글링하거나 다른 책을 찾아보기도 해요. 머신러닝 부분의 윤아님민진 : 타 회사에서 설계 관련 인턴을 했었어요. 마케팅 실무는 처음이라 모든 것이 새로워요. 채용공고와 면접에서 SNS 콘텐츠 기획 및 제작을 주로 맡게 될 거라고 했고, SNS나 블로그를 운영하고 있어서 자신이 있었어요. 그래도 확실히 실무는 다르더라고요. 사수분이 잘 가르쳐 주시는 덕에 잘 적응하고 있어요. 내 손으로 직접 무언가를 기획하고 컨텐츠를 제작한다는 것이 굉장히 재밌어요!SNS에 올라가는 컨텐츠를 만들고컨퍼런스 관련 컨텐츠를 제작하고 업무를 서포트 하고 있는 민진님Pt 2. 어반베이스의 첫 인상<인턴들이 뽑은 어반베이스의 좋은 점>1.윤아 : 사람들이 친절해요.민진 : 맞아, 뭐든 물어보면 되게 친절하게 알려주세요.2.민진 : 아, 그리고 유연 근무제 너무 좋아요. 아침에 지각하지 않으려 뛰지 않아도 되고, 사정이 있으면 빨리 퇴근할 수도 있고.수민 : 금요일에 2시에 퇴근하시는 분들도 많이 있어요. 짱이에요. 9시 13분, 사무실 풍경. 자율적으로 조절하는 업무 스케줄3. 수민 : 또, 식대 8000원! 선릉 맛집 점령! 이 정도면 굉장히 넉넉하지 않나요? 어반베이스 단체방에 올라오는 점심 사진들. 넉넉함 인정4.윤아 : 무제한 맥주가 있는 것, 그리고 근무시간에 먹어도 된다는 것! 민진 : 커피도 무제한이잖아요. 심지어 맥주, 커피 모두 밖에서 사먹는 것보다 맛있어요.사진 출처 : 스파크플러스Q. 반면, 당황했던 부분이나 힘들었던 점도 있나요?민진 : 저는 처음에 ‘ㅇㅇ님’ 이라고 부르는 것이 너무 어색했어요. 전에 하던 알바와 인턴, 모두 직급체계가 확실한 곳이었거든요. 근데 이젠 다 적응해서 아무렇지도 않아요.Pt. 3 채용 과정Q. 어반베이스를 어떻게 알게 됐어요? 수민 : 로켓펀치와 원티드에서 알게 됐어요. 그리고 유튜브나 관련기사들도 많이 검색해봤어요. 보도자료를 보니 어반베이스가 하고 있는 일이 미래를 널리 생각하고 있는 것 같아서 굉장히 좋은 영향을 줬어요.  윤아 : 저도 원티드에서 보고 알았어요. 블로그나 기사가 많아서 하나씩 다 살펴봤어요. 민진 : 저도요. 유튜브 계정에서 하나씩 다 살펴봤어요. 건축 AR에 관련된 영상이었는데, 굉장하더라고요. 그동안 제가 만들었던 허접한 모형들이 뇌리를 스쳐 지나가며.. 이런 신세계가 10년만 일찍 펼쳐졌다면 밤을 좀 덜 샜을 텐데.. 모형을 만드는 나도, 그걸 보는 교수님도, 서로 덜 괴롭지 않았을까.. 하는 생각이 들기도 했습니다 하하. 영상의 풀버전은 어반베이스 유튜브에 올라와 있습니다!Q. 자기소개서 및 포트폴리오 준비는 어떻게 했나요?수민 : 자기소개서는 다른 자기소개서들이랑 비슷했어요. 지원동기, 성장배경, 성격 등 기본적인 문항들로 채웠고 그동안 했던 프로젝트를 PPT에 정리해 제출했어요. 윤아 : 저도 거의 비슷해요. 민진 : 저는 자기소개서를 굉장히 짧게 적었어요. '왜 어반베이스에 지원했는지, 왜 나를 뽑아야 하는지' 딱 두 개만 적었어요. 포트폴리오는 건축 프로젝트, 공모전, 동아리 등 내가 했던 모든 활동을 정리해서 제출했어요. Q. 면접은 어땠나요?윤아 : CTO님이 이야기를 굉장히 잘 들어주시고 편한 분위기에서 면접이 진행되었어요. 면접을 진행하며 좋은 인상을 받았어요.수민 : 저는 조금 긴장했어요. CTO님께서 제 포트폴리오를 보고 질문을 하셨어요. 제 답변에 틀린 점도 있었는데 틀린 부분을 친절히 설명해 주시기도 했어요. 2차 면접도 역시 편안했고요.민진 : 저는 1차 면접을 마케팅팀 분들과 봤어요. 면접 자체가 제가 일방적으로 질문에 응답하는 것이 아닌, 서로 이야기를 주고 받는 '대화'에 가까웠어요. 그래서 저도 면접 이후로 더욱 좋은 인상을 받았어요. 두 번의 면접이 진행되면서 어반베이스가 하고 있는 사업들에 대해 더욱 자세히 알게되었는데, 진짜 꼭 붙고 싶더라고요. 붙어서 참 다행입니다. 마지막으로Q. 전공과는 조금 다른 길을 선택했는데, 후회는 없나요?수민 : 음, 그래도 어반베이스는 건축이 바탕이 되어 있으니까요. 건축산업이 좀 더 유연하게 바뀌고, 기술이 많이 도입 된다면, 지금 제가 보내는 이 시간들이 굉장히 값진 시간이 될 거예요. 프로그래밍과 건축 베이스의 지식이 굉장한 무기가 될 수 있다고 생각해요. 윤아 : 저도 후회는 없어요. 요즘 데이터 분석은 어딜가나 쓰이니까요. 전공을 살려 의료 쪽 데이터를 다룰 수도 있지 않을까요? 그런 의미에서 전공지식이 무용지물은 아니라고 생각해요. 민진 : 저도 후회 안해요. 건축을 전공했기 때문에 지금 어반베이스가 하고 있는 일을 훨씬 잘 이해할 수 있었어요. Q. 어반베이스를 들어오고 싶은 사람들에게?수민 : 어반베이스는 기술 집약적인 기업이라 생각해요. 프로그래밍의 아주 초입자라면 어렵겠지만 업무가 적성에 맞다면 즐겁게 일할 수 있을 거에요.민진 : 미래산업에 관심이 있다면  더욱 흥미롭게 다가올 것 같아요. 현재 국내에서 쉽게 접할 수 있는 사업이 아니기 때문에 굉장히 도움이 될 거라고 생각해요. 인터뷰 Behind 1어반베이스의 좋은 점에 대해 이야기하며 어반베이스 복지문화 중 하나인 ‘어반테이스트’의 얘기가 나왔습니다. 수민 : 아, 그 어반테이스트도 가신 분들 엄청 부러워요. 그 쓰리쁠 등심.. 나도 먹어보고 싶다. 윤아 : 나는 어반 테이스트 뽑히면 스시먹어야지. 수민 : 오마카세..!민진 : 아, 갑자기 배고프네. 다들 좋아하는 음식 있어요?윤아 : 아무거나 다 잘 먹어요.수민 : 저는 라멘이 먹고 싶네요.윤아 : 수민님 며칠전부터 라멘 얘기하셨어요. (웃음)민진 : 그럼 오늘 점심 때 먹으러 가요. 빨리 선릉역 라멘 맛집 찾아봐요. 선릉역 라멘집 호타루인터뷰 하다말고 맛집을 검색하더니 곧 우리의 행선지가 결정되었습니다! 점심으로 라멘을 먹고 셋이서 아주 뿌듯했다는 이야기. (ㅎㅎ) 인터뷰 Behind 2윤아 : CTO님과 면접보다가, 나중엔 자소서 잘 쓰는 법도 알려 주셨어요. 그래서 '아, 날 뽑지 않고 자소서 잘 써서 다른데 지원하라는 의미구나.' 싶었어요. 그래서 떨어질 줄 알았는데, 합격 전화가 와서 깜짝 놀랐어요. (웃음)수민 : 원래 공대생들이 글을 잘 못쓰잖아요. 모두 : 아, 완전 공감.선택한 길에 대해 후회는 없다는 인턴 3인방. 인터뷰를 하며 공통적으로 말했던 것은 ‘좋은 사람들과 멋있는 일을 할 수 있어 아주 즐겁고 재밌다!’는 것이었어요. 어반베이스도, 우리들도 더욱 발전할 수 있었으면 좋겠습니다. :) 어반베이스에 관심이 생기신 분들, 그래서 입사 지원을 하시는 분들 중 혹시 더 궁금한 점이 있다면 댓글에 남겨주세요. 담당자분에게 직접 물어봐 드릴게요.  그럼 이만 일하러 가보겠습니다 !출처: https://blog.naver.com/urbanbaseinc
조회수 1227

Humans of TODAIT : CTO 유병한을 만나다

어느 화창했던 3월, ‘Humans of TODAIT’ 의 첫 주인공인 투데잇 CTO 유병한을 만나봤습니다. 투데잇 핵심엔진인 그의 이야길 함께 들어볼까요?Q. 자기소개 부탁드려요.안녕하세요! 투데잇에서 CTO를 맡고 있는 유병한입니다. ‘SW 마에스트로’라는 과정에서 대표님과 좋은 인연이 되어 투데잇의 전신인 투데잇브레이커부터 지금까지 열심히 개발중입니다. 안드로이드분야에 관심이 많아서 시작하게 되었는데, 차츰 기술 스펙을 확장해 나가면서 서버개발부터 최근엔 iOS 개발까지 맡고 있습니다.Q. ‘꿈을 향한 오늘, 투데잇’ 이라는 슬로건처럼 CTO님의 꿈에 대해 들을 수 있을까요?제겐 두가지 꿈이 있는데요, 먼저 투데잇이라는 서비스 자체에 대해선 전국민 앱으로 거듭나고 싶어요. 기존 교육관련 산업에서 우뚝 솟을 수 있는 서비스가 되고 싶은데요, 공부하는 사람의 입장에서 처음부터 끝까지 도움을 줄 수 있는 서비스를 제공하고 싶어요. 그래서 ‘저 사람이 일하는 투데잇은 일하기 좋은 회사다!’ 라던가 ‘성장하기 좋은 회사!’라는 인식을 주고 싶어요! 여러사람들을 심쿵!하게 만들고 싶습니다(웃음)음.. 그리고 제 개인적인 꿈으론 진짜 언젠간 해보고 싶은건데, 다큐멘터리 내셔널 지오그래픽급의 사진작가가 되고 싶어요.이래저래 심쿵하는 사람이 되고, 심쿵하게 만드는 서비스를 제공하고 싶습니다.Q. ‘개발자’로서의 시작은 어땠나요?음 제가 처음부터 개발자가 되고 싶단 생각은 안했어요. ‘개발’과 인연의 끈이라고 되짚어본다면, 아마 어릴 적에 접했던 나모웹에디터로 홈페이지 만들기?였던 것 같아요.그리고 수시를 과감하게 버리고 제가 즐겁게 할 수 있었던 컴공이나 관련 학과로 찾다보니 지금의 과에 입학하게 되었어요. 대학교와서도 다양한 학교 수업 중 개발 관련 수업을 맛보면서 ‘아 이게 나한테 맞겠구나!’ 싶어서 본격적으로 공부했어요.(Q. 앗, 그럼 ‘개발자’라는건 갑작스러운 전환이었나요? )그렇다고 해서 아주 갑작스럽진 않았어요. 학생때 사진찍는걸 즐겨서 색감에 대한 거라던가 화면에서의 구도에 대한 이해같은게 높았거든요. 학과에서 배웠던 다양한 편집툴들이 지금의 UI 센스에 발판이 되지않았나 생각해요.어느 순간 하나가 쓸데없던 적은 없었던 것 같아요. 자그마한 순간순간들이 지금의 저로 만든 것 같아요.Q. 본인이 맡은 업무에 대해 어떻게 접근하나요?일단 맡은 분야에 대해서도 그렇고 제가 욕심이 좀 많아요(웃음) 내가 잘하고 싶은 욕심, 가지고 싶은 욕심이 여러 힘든 과정을 이겨낸 원동력이 아닐까 생각해요.Q. 예를 들면 어떤 경험이 있나요? 조금 더 자세하게 듣고 싶어요!음.. 아 이건 좀 비밀인데 중학교때 사진을 찍게 되었는데 보통 그냥 똑딱이카메라쓰던 시절이었거든요. 그런데 DSLR이 너무 가지고 싶어서 조르기도하고 한푼두푼 모으기도해서 결국엔 DSLR을 손에 넣었어요. 되게 사소한것 같지만 나름 원하는걸 얻어낸 뜻깊은 추억이죠. 뭐든 전문가처럼 해야겠단 욕심이 강한 것 같아요.(Q. 오.. 그런데 책상에 책이 되게 많이 쌓여있네요? )책을 쌓아두는게 사실 좀 최근 관심이 가진 프로그래밍 언어라던지 관심이 가는거 위주로 가져다 놓긴 했어요. 아이폰 관련 서적이 몇개 있는데, (이제 세달 정도) 레퍼런스로 많이 찾아보기 위해서 책들이 상시대기하고 있어요. 2–3권. 스위프트라는 언어를 배우면서 기존의 코틀린 자바 스크립트 등 다양한 관심이 생겨서 , 언어들에 대한 욕구가 좀 큰 요즘입니다~(웃음)Q. 일을 하다보면 힘든 순간도 많았을 것 같아요.힘든 순간은 매순간인것 같아요(하하) 그래도 진짜 엄청 힘든 순간이 있었는데 제겐 ‘아버지’가 되게 큰 힘이 되주셨어요. 아버지께서 목사님이시거든요. 평생 부산에서만 사셨던 분이 산골 깊숙히 들어와서 농촌교회를 준비하시면서 힘든 부분이 분명 클텐데도, 지금은 사회복지기관까지 운영하시는 걸 보면 정말 대단하신 것같아요. 홀로 타지에서 모든걸 감내하셨던 부분이, 그리고 하고자 하는 일에 대한 끊임없는 열정을 많이 배워요.그런 아버지를 보고 감명받아서인지 저도 모르는 사이에 창업가 마인드가 생겼던 것 같아요. “ ‘내’가 능동적으로, ‘내’회사를, ‘내’회사에서, ‘내’회사를 위해 일하는, ‘내’일을 한다. ”라는 생각 자체가 아버지의 영향을 많이 받지 않았나싶네요.음 그리고 역시나 빼놓을 수 없는! 우리 투데잇을 사랑해주시는 유저분들이 정말 큰 힘이되요. 실은 투데잇브레이커 당시에 제가 이일을 시작하게 된 이유자체가 ‘이 서비스를 사용하는 유저들이 있다’란 거였거든요. 제겐 그분들이 제 모든 이유인것 같아요. 제 스스로가 성장할 수 있는 이유, 투데잇이 인정받을 수 있는 이유, 그 모든 이유의 근간이라고 생각해요.Q. 항상 좋은 리뷰만 있진 않았을 것 같아요. 혹시 가장 기억에 남는 리뷰 있나요?되게 오래전 리뷰인데, 많이 부족했던 투데잇을 보고 ‘대체 언제쯤 기능 업데이트 되냐, 3D게임 만드냐’라고 하셨던 리뷰가 가장 기억에 남아요. 순간은 되게 기분이 상하면서도 점점 더 잘해내고 싶단 의지가 생기더라구요. ‘내가 3D게임 개발하는 것도 아닌데, 이정도라니. 더 개발 좀 열심히 해야겠다.’하구요. 지금은 그분께 감사하죠.그때 당시만해도 투데잇이란 서비스가 되게 부족했을텐데도 끊임없이 애정해주시면서 기다려주신 유저분 중 한 분이니까요.좋았던 리뷰들은 정말로 셀 수 없이 많아요. 저희가 매주 리뷰를 함께 공유하는 자리가 있는데, ‘성적이 올랐다는 리뷰’부터, ‘투데잇 덕분에 공부 스타일이 또는 생활 습관이 바뀌었어요’, ‘지금 수험생활을 하고 있는데 힘을 얻고 있어요.’ 그리고 ‘합격소식’까지. 진짜 큰 힘이 되죠. 제가 어떤 무형의 무언가를 하고 있단게 현실에서 드러난다는게. 그게 정말 큰 힘이 되요.Q. 나에게 ‘기술’ 이란?저는 아까 말씀드렸던 것처럼 욕심이 좀 많은 편인데, 그 중 제일 욕심 많은게 바로 ‘기술’이예요. 이 분야에서 전문가가 되기 위해서 하나하나 하면 하나를 깊게 파는 스타일이예요.그래서 다양한 분야의 기술을 심도있게 잘하고 싶은 욕심이 있었는데, 투데잇을 개발하면서 그런 욕심을 부릴 수 있는 기회가 주어졌어요. 당시만 해도 당장 없는 개발팀원 자릴 메우기 위해 열심히 욕심부렸던게 지금의 이 자리에 앉게되지 않았나 생각됩니다.제게 기술이란건, 기술 자체가 가지고 싶은 그 무언가예요. 끊임없이 욕심을 내서 계속해서 닿고싶은 그런 존재?(웃음)Q. 오픈소스활동에서 핫하다는 이야기가 있는데요~오픈소스 활동이 아주 거창하진 않아요. 아직은 걸음마단계 수준이죠. 음 처음엔 제가 필요한 오픈 소스를 사용하면서 발견한 에러나 버그 부분에 대해 피드백을 드렸어요. 되게 간단한 부분이었는데 그쪽에서 긍정적으로 받아들여주셨어요. 그런 상호 피드백이 오가면서 관심을 갖게되었습니다.제트브레인스라는 회사에서 근무하시는 분의 피드백을 받는 과정이 오픈 소스활동을 통해 서로 교류할 수 있단 점이 매력적이었어요.활동을 하게된 결정적인 계기는, 다른 회사에 다니는 친구와 함께 깃허브에 올리고 IOS 개발 커뮤니티에 올렸더니 반응이 핫하더라구요. 큰 이슈는 아니지만, 사람들이 긍정적인 피드백을 해줘서 즐거운 순간이었죠.앞으로도 작은것부터 하나씩 해나갈 예정이에요. 큰 규모의 기술은 아니더라도, 투데잇의 ANDROID/IOS에 필요한, 하지만 불편함을 해소해줄 수 있는 라이브러리나 툴들을 만들어나가려고 생각을 하고 있구요. 기존에 투데잇 안에서만 쓰던 걸, 조금씩 정리해서 공유해나갈 생각입니다.Q. 안드로이드 앱 개발을 하면서 소프트웨어 아키텍쳐에 관한 고민이 있다던데, 어떤 고민을 하고계신지 들어볼 수 있을까요?지금 저희 나름대로, 기존에 있던 MVVM, VIPER라든지 그런 아키텍쳐들을 많이 보고 차용을 해서, 투데잇에도 적용을 해나가고 있는 중이에요. 직접 해보니 학교에서 책으로 배운 “프로그래밍 구조가~” 나 “아키텍쳐 구조가~” 에 대해 필요성을 뼈저리게! 몸소 부딪혀가면서 느끼는 중입니다.개발을 하다보면, 사소한 버그나 문제점을 많이 발견하게 되는데, 이를 어떻게 미리 테스트할지 또 어떻게 검증할지에 대해 고민을 하고 있어요. 그런데 기존 소스코드는 각각 다른 기능을 하는 코드가 한데 뭉쳐있어서, 이걸 분리해서 테스트하기에 용이한 아키텍쳐에 대해 개선 및 적용해나가고 있습니다.또 안드로이드와 아이폰 버전을 개발 중인데, 각각 플랫폼에 종속적인 부분을 빼놓고 두 버전 모두 동일한 구조를 가지고 갈 수없을까에 대한 고민 중인데요, 이러한 고민을 함께 하실 분들이 오셨으면 좋겠어요. 이상적인 구조를 향해서 말이죠. (웃음)Q. 현재 일하고 있는 팀원이 7명이나 된다고!네! 대표님과 단둘이 끌어왔던게 엊그제같은데, 벌써 7명의 투데잇팀으로 구성되었네요. (웃음) 사실 제게 투데잇팀은 그냥 공기같은 존재예요. 같이 있을 땐 중요성을 모르다가도, 누구하나 자릴 비우게 되면 그 느낌이 진짜 오묘해요. 서로가 서로를 너무 당연하게 자리하고 있다고 느끼고 있어서요.언젠가 한번 기호형님(COO)이 자릴 비운적이 있었어요. 아직 일한지 1년도 채 안되는데도, 옛날 옛적부터 알고 있던 사람처럼 그때 그 공허감이 되게 크더라구요.사실 좋을 땐 다 좋죠. 중요한건 일하면서 분명 좋지 않은 순간이 올텐데, 이때 서로 어떻게 커뮤니케이션을 하느냐 인것 같아요. 부정적 피드백에 대해 받아들이는 자세가 우리 팀의 가장 메리트라고 생각해요.지금 팀원들은 일에 있어서 피드백이 오갈 땐, 감정적인 건 잠깐 내려놓고, 객관적으로 앞으로 더 발전 방향에 있어서 뭘 어떻게 해야할지를 생각하는 태도를 보이거든요. 이 부분에 대해 ‘서로 핏이 잘 맞는다’라는 문장이 딱 맞는 표현 같아요.그래서 전 “같이 있으면서 어색하지 않은 그런 사이”가 좋아요. 물론 시간이 지나면서 서로 맞춰가는거겠지만, 왜 그런거 있잖아요. 함께 일을 해도 계속해서 어색한 사람이 있고 조금 풀리는 사람이 있는거. 그런 점이 저희 팀의 메리트라고 생각합니다.Q. CTO의 입장에서, 같이 일하고 싶은 개발자는 어떤 사람인가요?당연한 거겠지만, 일단 서로 존중해줄 수 있는 사람이면 좋겠어요. 아무리 비즈니스라지만 서로가 서로에게 예의와 매너가 갖춰진 사람을 원합니다.업무적으론, 뭔가 새롭게 배우는거에 대해 두려움이 없는게 좋은 개발자의 기본 자세라고 생각해요. 그래서 바로바로 과감한 도전 정신이 있는 사람! 그리고 제게 없는 재능을 가져서 서로가 상호 보완해나갈 수 있는 파트너면 좋겠어요.Q. 지원하고 싶은, 지원을 생각하는, 이 글을 보고있는 사람에게 한마디 부탁드려요!“만약에 지원을 하신다면, 마음을 단단히 먹어야할겁니다.”초반만 하더라도, 스타트업에 대한 환상이 있었어요. 이상적인 모습, 장밋빛 회사생활만을 꿈꿨거든요. 언론에서 소위 말하는 ‘젊은 창업가!’의 그 이면엔, 장밋빛을 현실화 하기위해 매일매일이 고난의 길이란걸 잊지 않으셨음 해요. 스타트업이란게 자신의 한계를 확인하는 과정이기 때문에, 같은 출발선에서 함께 발전하기 위해 달릴 준비가 되신 분을 환영합니다.또 자기 나름의 미션이 있고, 그걸 회사의 가치 성장에 일치시켜 나가면서 함께 실현해나가실 분을 모십니다!우리의 이상을 위해 함께 이 현실을 헤쳐나가실 분을 찾습니다!#투데잇 #팀원소개 #팀원인터뷰 #팀원자랑 #기업문화 #조직문화 #개발자 #개발팀 #CTO
조회수 3208

야놀자 앱은 왜 자동실행 되나요?

pluu 04 JUL 2018저는 야놀자 CX서비스실의 Android 파트에서 레이아웃 깎기와 Kotlin과 새로운 Android 기술을 전파하는 노현석입니다. 야놀자에 합류하고서 경험한 가장 독특한 케이스에 대해서 이야기해 보려고 합니다.시작은 물음표부터언제부터인가 야놀자앱을 설치하거나 업데이트하면 앱이 자동으로 실행된다는 리뷰가 들어오기 시작했습니다.네?! 그게 무슨 말이에요?안드로이드 개발을 시작한 이래로 처음 들어보는 내용이라, 원인도 정확한 해결책도 떠오르지 않는 그런 리뷰였습니다. 그래서 자연스럽게 브라우저를 켜서 구글에 검색을 먼저 해봤습니다. Android, Auto Start, Install 등 다양한 검색 결과로 일정한 패턴의 내용을 확인할 수 있습니다.  Intent Action 관련 내용android.intent.action.PACKAGE_ADDEDandroid.intent.action.PACKAGE_CHANGEDetc.Broadcast Receiveretc.일반적으로 안드로이드 앱이 설치 및 업데이트될 때 발생하는 이벤트(이하 Broadcast)를 받는 방법에 대한 설명이 많습니다. Broadcast는 배터리 변화, 전화 여부, 와이파이 등 시스템의 상태 변화를 감지하거나 서비스 내부적에서 이벤트를 전달하기 위해 사용합니다. ???? 실질적인 해결책은 되지 않지만, 범위를 좁혀서 찾아볼 포인트로 Intent 의PACKAGE관련 액션을 포커스로 잡았습니다. 하지만, 야놀자앱에서는 마케팅 성과 측정을 위해com.android.vending.INSTALL_REFERRER를 광고 트래킹 SDK에서 사용하는 것 이외에는 별도의 작업을 하지는 않습니다. 그러나, 이를 알 리가 없는 사용자는야놀자 앱이 일으키는 문제라고 인지하기 쉽습니다.  일차적으로, 어느 경로를 통해서인지는 모르지만 누군가가 야놀자 앱을 실행하는 것이라고 생각했습니다.야놀자 앱 사용자의 기기에 설치된 모든 앱 리스트를 받아올 수도 있고, 리퍼럴에 따른 앱 실행경로를 모두 수집할 수도 있지만, 단순히 버그를 찾기 위해 사용자의 동의 없이 정보를 수집할 수는 없기 때문에 장기전으로 돌입하게 되었습니다. 하지만 동일한 리뷰는 계속되었고 여전히 뚜렷한 해결책이 없는 채로 시간이 흘러갔습니다.  저 재현되는데요증상이 나타나지만 재현은 되지 않고, 재현 경로를 단기간에 파악하기는 어려운 과제였습니다. 한두 명에 불과하던 제보가 시간이 지날수록 Android 파트의 목을 조르듯이 점점 유입되는 횟수가 늘어만 갔습니다. 그런데 어느 날, 다른 팀의 분께서저 재현되는데요라는 한 줄기의 빛과 같은 언급을 해주셨습니다.믿고 싶지 않은 일이 현실이 되었다네? 그게 … 정말로 일어났습니다.이제부터가진짜시작역시버그는재현이되어야제대로잡을수있겠죠! 저에게는재현되는 단말이 있어요!Android에서 디버깅을 할 수 있는 다양한 수단이 있습니다. 이번 사례의 경우는Log혹은Dump를 확인해보는 선택지가 있습니다.Log민감한 정보라고 판단되는 부분은 모자이크했습니다.앱 설치 후 광고 SDK가 수집하는 것으로 보이는 Log에는 다양한 항목들이 나열되는 것을 볼 수 있습니다. 이때 설치한 앱의 정보가 SDK를 통해 특정 API로 전송되는 것도 확인할 수 있습니다. 하지만 Log는 Log일 뿐입니다.  Dumpsys이렇게 Log만으로 추적이 어려울 때, 추가적으로 시스템의 상태를 얻어내 디버깅 할 수 있는 방법이 있는데 바로dumpsys입니다. dumpsys는 Android 단말에서 실행되며 시스템 서비스에 대한 다양한 정보를 제공하는 도구입니다. ADB(Android Debug Bridge)를 사용하여 dumpsys를 호출 시 해당 단말에서 실행 중인 모든 시스템 서비스에 대한 정보를 가져올 수 있습니다. 간단하게 말하면 배터리의 잔량, 메모리 소비량, 네트워크 통신 상태 등을 명령어로 확인할 수 있습니다. dumpsys의 기능에 대해서는 방대한 설명이 필요하므로, 자세한 내용은 아래 링크로 대체합니다.  Android Developers ~ dumpsyshttps://android.googlesource.com/platform/frameworks/native/+/master/cmds/dumpsys/dumpsys.cppActivity DumpDumpsys 에서 좀 더 Activity 와 관련된 정보를 얻기 위해서는 아래의 명령어를 적용해볼 수 있습니다.// Activity Log Dump adb shell dumpsys activity activities 결과를 확인해봅니다. 아래와 같은 Activity 의 활동 이력을 얻을 수 있습니다.Activity Dump에 나타난mCallingPackage값으로 야놀자 앱을 시작시킨 앱의 패키지를 확인할 수 있습니다. 해당 패키지를 실제 Play Store에서 확인해본 결과, 사진 보정 필터앱으로 유명한카메라 앱중 하나였습니다.???? 야놀자와는 전혀 연관성이 없는 앱인데, 호출하고 있네요… ????Process ID// 애플리케이션의 Process ID 취득 adb shell ps Activity Dump에서 확인한mCallingUid는u0a423였는데, 이는 Activity를 호출한 uid 값을 가리킵니다. 실제로 Process 가 호출되는 Application ID도 카메라 앱에서 호출한 ID 정보와 일치합니다.대상 앱 자료 분석단순하게는 APK 를 분석하여 추측하는 방법이 있습니다. Android Studio 에서 제공되는Analyze APK기능을 이용하여 해당 앱에서 사용되는 서비스의 정보를 파악할 수 있습니다. 이 방법을 이용하여 문제의 앱이 사용하는 광고 SDK 서비스에서 패키지 설치/제거 관련 Broadcast Receiver를 수집하는 것을 확인 할 수 있습니다.패키지 관련 Broadcast인android.intent.action.PACKAGE_ADDED, android.intent.action.PACKAGE_REMOVED를 앱이 사용하는 것은 잘못된 것이 아닙니다. 예를 들어 런처 앱의 경우 단말기 내부의 앱 정보가 변경되었다는 이벤트를 이용하여 화면 렌더링 및 동작을 변경하는 처리를 할 수 있습니다 해당 광고 SDK의 경우에는 앱을 설치 및 실행하는 것으로 사용자에게 포인트 및 여러 혜택을 제공할 것이라고 예상할 수 있습니다.개인적인 의견으로는 사용자의 액션과 상관없이 동작하는 부분에 대해서는 분명히 Android 의 개선도 필요하다고 생각됩니다. 이런 정상 동작과 어뷰징은 아슬아슬한 경계에 있지만, 자칫 어뷰징으로 이어지는 경우 서비스의 품질이 떨어지게 되면서 사용자와 개발사 모두에게 좋지 않은 경험을 줄 뿐입니다.설마 이것도 되려나?동일 패키지명이번 포스팅을 작성하게 된 카메라 앱과 야놀자 서비스 사이에 특별한 관계가 없다면, 왜 이런 현상이 발생하는지 고민해봤습니다. SDK도 연결하지 않았다면, 앱을 추적할 수 있는 유일한 키는패키지명이지 않을까라는 생각으로 패키지명만 야놀자 앱과 동일한 샘플 앱으로 테스트해봤습니다.동일 재현 성공!!그럼… 해결… 끝?많은 사람들에게 이름이 널리 알려진 여러 서비스에서조차 이번 포스팅에서 다룬 내용과 같은 현상이 발생하고 있습니다. 발생 유무에 따른 차이점이나 현상의 인과 관계를 명확히 판단하기엔 아직 정보가 많이 부족합니다. 그리고 이번 분석에서 발견한 문제의 앱을 비롯하여 또 다른 제2, 제3의 앱들이 등장할 거란 가능성도 배제할 수 없는것이 현재 상황입니다. 슬프게도 아직 이 현상은 지금도 계속되고 있으며, 불편을 호소하는 리뷰가 등록되어 서비스 전체의 이미지와 평점을 갉아먹고 있습니다. 안드로이드 생태계가 사용자 및 서비스 제공자에게 더 유익한 방향으로 나아갔으면 하는 바람을 담아 작성했습니다.도움 주신 분동일 증상을 발견하고, 단말을 빌려주신 R&D SF팀 전호숙님같이 추적해주신 R&D CX 서비스실 유관종님Dump/Log 관련 조언을 주신 Wind River의 차영호님 (????????????)국어가 많이 부족한 저를 도와주신 리뷰어 ???????????? R&D CX 서비스실 강미경님, 송요창님, 유관종님, 유용우님, 이미혜님이번 현상 추적에 도움을 주신 분들에게 감사함을 전합니다.#야놀자 #개발자 #개발팀 #문제해결 #버그수정 #안드로이드 #인사이트 #경험공유
조회수 1410

반복적인 모니터링 프로세스 구축

IT 서비스에 장애가 발생 할 경우 모니터링 프로세스는 장애를 찾는 것으로 끝나지 않습니다. 장애를 발견하는 것은 모니터링 프로세스의 시작 점이며 최종적으로 모니터링을 통해 장애의 근본 원인을 찾아낼 수 있어야 합니다. 그리고 찾아낸 원인들은 예측과 추론에서 확인까지 이르는 하나의 프로세스로 정착되어 다시금 모니터링 과정에 포함되어져야 합니다. 이렇게 서비스를 운영하는 과정에서 근본적인 장애를 찾기 위해 모니터링을 어떻게 이해해야 하는지 알아보겠습니다. 우리가 모니터링 해야 하는 지표어플리케이션 지표(WORK METRICS)- 처리량 지표(THROUGHPUT)- 성공 지표(SUCCESS)- 에러 지표(ERROR)- 성능 지표(PERFORMANCE)시스템 지표(RESOURCE METRICS)- 가동률(UTILIZATION)- 포화상태(SATURATION)- 에러 지표(ERROR)- 이용률(AVAILABILITY)이벤트(EVENTS)- 코드 변경(CODE CHANGES)- 경고 알림(ALERTS)- 규모 변경(SCALING EVENT)- 기타(ETC)IT 서비스를 운영하는 과정에서 발생하는 문제의 근본원인을 추적하기 위한 모니터링 데이터는 크게 3가지로 나눌 수 있습니다. 어플리케이션 지표(Work metrics)서비스의 흐름(트렌젝션)을 측정하여 시스템의 최상위 레벨의 이슈를 보여줍니다. 시스템 지표(Resource metrics)이용률, 상태, 에러 또는 시스템 의존적인 리소스의 이용률을 수량화합니다.이벤트(Events)코드변경, 내부 경고, 확장 이벤트와 같이 드물게 발생하는 불연속적이 이슈를 보여줍니다.일반적으로 IT 모니터링의 핵심 이슈는 어플리케이션 지표를 통해 확인할 수 있습니다. 하지만 다른 지표들 또한 어플리케이션의 지표에서 나타난 문제의 원인을 찾기 위한 중요한 요소이기 때문에 같이 모니터링 해야 합니다. 시스템 지표를 통한 모니터링인프라스트럭쳐는 대부분 시스템의 자원으로 구성됩니다. 최상위 수준에서 유용한 작업을 하는 각각의 시스템들은 다른 시스템들과 연동하기도 하는데요. 예를 들어, 여러분의 아파치 서버가 MySQL 데이터베이스를 자원으로 사용하여 요청을 처리하는 작업을 지원할 수 있습니다. 연관된 작업을 따라 들어가보면 MySQL은 제한된 커넥션 풀을 관리하기 위한 리소스를 가지고 있고 MySQL이 실행되는 서버의 물리적인 리소스 레벨에서는 CPU, Memory, Disk 같은 지표를 보게 됩니다.어플리케이션이 서비스를 제공하는 데 있어서 각각의 리소스가 그 작업을 지원한다면 우리는 장애가 발생한 경우에, 필요한 원인을 얻는 좋은 방법을 시스템을 통해서도 찾아볼수 있습니다. 이런 프로세스를 만들어 간다면 시스템에서 발생한 경고를 통해 장애의 원인을 체계적인 조사하는데 도움이 될 것입니다. 1. 최상위 어플리케이션 지표에서 시작하기첫번째 해야 하는 질문은 "발생한 장애를 설명할 수 있는가?" 이다. 처음부터 문제를 명확하게 정의하지 못하면 이슈를 분석하기 위해 파고들어가야 하는 시스템 패스를 잃어버릴 확률이 높다.다음으로 문제가 있을 것으로 보여지는 최상위 시스템의 작업 지표를 검사해라. 이 지표들은 종종 문제의 원인을 알아내거나 또는 적어도 추적해야 하는 방향을 알려 줄 것이다. 예를 들어 성공적으로 진행된 작업의 성공율이 한계치 이하로 떨어졌다면 에러 지표를 찾아보고 반환된 에러의 형러의 타입을 살펴봄으로써 문제의 방향을 찾아나갈 것이다. 반면에, 대기시간이 길고 외부 시스템에 의해서 요청된 작업처리량이 매우 높다면 시스템 과부하로 인한 문제일 확률이 높다. 다만 와탭의 어플리케이션 분석 서비스를 사용한다면 약간 방법을 달리해도 된다. 와탭의 성능 분포도(어플리케이션 히트맵)와탭의 어플리케이션 성능 분포도를 통해 문제가 발생한 트랜잭션을 드래그하여 선택하게 되면 실제 어플리케이션에서 발생하는 스탭들을 추적하여 문제 해결에 바로 도달할 수도 있다. 하지만 더 복잡한 형태의 장애라면 시스템의 리소스 정보를 찾아봐야 합니다.  2. 리소스 찾아보기최상위 work metrics를 조사하여 문제의 원인을 알수 없다면, 다음으로 시스템이 사용하는 리소스(물리적인 요소 뿐만 아니라 시스템의 리소스 역할을 하는 소프트웨어 또는 외부 서비스)들을 조사합니다. 해당 리소스가 높다면 리소스를 사용하는 하위 Application 지표를 찾아보는 방식으로 찾아나갑니다. 와탭의 데시보드(CPU, MEMORY)3. 변경 내용 찾아보기다음으로 지표에 연관된 경고와 다른 이벤트들을 살펴봅니다. 문제가 발생하기 직전 코드가 릴리즈 되었거나, 내부 경고가 발생하고나 다른 이벤트가 등록되었다면 문제와 연관된 부분을 찾아봐야 합니다. 4. 수정하기 (잊지 말기)문제의 원인을 찾았다면 문제의 원인이 되는 상태를 수정해보고 증상이 사라지는 것을 확인합니다. 증상이 더이상 나오지 않는다면 향후 유사한 문제를 피하기 위해 시스템을 어떻게 변경할지 고민해야 합니다.  서비스가 중단된 상황이 오면 1분이 중요합니다. 문제를 찾는 속도를 높이기 위해 눈앞에서 벌어진 상황에 대한 높은 집중력을 유지하면서 대쉬보드를 상황에 맞춰 재 조정합니다. 최상위 어플리케이션 데쉬보드와 각각의 서브시스템들을 위한 대시보드를 하나씩 설정합니다. 시스템 대시보드는 시스템 지표의 하위 시스템의 키 메트릭스와 함께 어플리케이션 메트릭을 확인 할 수 있어야 합니다. 이벤트 데이터도 이용가능한 상황이라면 연관 분석 차트에서 관련된 이벤트가 올라가 있어야 합니다. 와탭의 알림 서비스정리하기   서비스에 장애는 무조건 발생하지만 우리는 모니터링을 통해 빠르게 해결 할 수 있습니다. 이를 위해 표준화된 모니터링 프로세스를 만들고 대시보드로 연관관계를 만들어 놓는다면 문제를 빠르게 추적 조사할 수 있습니다. 가능하면 모든 지표는 어플리케이션 지표에서 부터 찾을 수 있도록 대시보드를 구성합니다.인프라스트럭처를 통해서도 문제를 분석할 수 있습니다. 시스템에 대해 대시보드를 설정하고 주요 지표들을 올려놓아야 합니다. 문제의 원인을 조사하는 것은 증세가 나타나는 최상위 시스템에서 부터 시작합니다. 문제가 되는 리소스가 발견되면 문제를 발견하고 수정할 때가지 리소스에서 발견되는 패턴을 조사하고 적용시키는작업을 반복해야 합니다. #와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 1198

채널 데스크 프론트엔드 기술 스택

오프라인 고객 분석 솔루션 워크인사이트를 개발해 온 조이는 최근 온라인 접객 서비스 채널을 런칭했습니다. 이 글은 채널과 관련된 기술 블로그의 첫번째 글로 채널 데스크 프론트엔드(웹, 윈도우, OSX)의 기술 스택 및 개발 환경을 소개하도록 하겠습니다.React채널 개발을 처음 시작할 당시 (지금으로부터 1년 전) 에 워크인사이트 대시보드 및 기타 사내 툴에서는 AngularJS 1을 사용하고 있었습니다. 비교적 적은 코드로 복잡한 애플리케이션을 빠르게 만들 수 있는 점에는 만족했지만 퍼포먼스면에서는 아쉬운 부분이 많았습니다. 따라서 새로운 프레임워크 및 라이브러리를 리서치 했고 매우 가볍고 렌더링 퍼포먼스 면에서 AngularJS 1 대비 우위에 있던 React 를 사용하기로 결정했습니다.컴포넌트의 설계 패턴은 Redux를 만든 Dan이 제안한 Container 와 Presentational 컴포넌트를 구분하는 방식으로 설계하고 있습니다. 따라서 Container 가 data fetch 및 update 등의 액션을 실행하고 Presentational 컴포넌트들을 조합하여 렌더링을 하게 됩니다.React를 실제 1년째 사용해 본 결과 저를 비롯한 팀원들은 매우 만족하고 있습니다. 구조, 스타일, 동작을 한 컴포넌트로 묶어 재사용성이 매우 높아졌으며 React의 휴리스틱한 Dom diff algorithm 덕분에 렌더링 퍼포먼스에서도 많은 이득을 얻을 수 있었습니다.Facebook Flux Utils아키텍쳐는 페이스북이 제안한 flux 철학에 따라 설계되었습니다. flux를 구현하기 위한 기본적인 유틸리티 기능을 제공하는 Flux Utils을 사용합니다. Flux의 많은 구현체 중에 요즘 가장 인기인 Redux도 고려했었습니다. 저희가 프로젝트를 시작할 당시에 Redux는 5~6개월밖에 되지 않은 프로젝트였고 거의 Dan의 1인 프로젝트였기 때문에 향후 메인터넌스를 장담할 수 없다고 판단했습니다. 그보다는 페이스북이 만든 Flux Utils가 그런 면에서는 더 안전할 거라고 생각했던 것이죠.약 1년 정도 Flux Utils로 개발해오며 몇 가지 문제를 겪게 되었습니다. 애플리케이션이 커지면서 관리해야할 State가 많아지고 그들 사이의 의존성 관리 때문에 Store의 복잡도가 빠르게 증가했습니다. 그에 따라 테스트가 어려워지고 올바른 유닛테스트를 위해서는 테스트 코드 역시 매우 복잡해지는 문제가 있었습니다.그래서 Redux를 다시 리서치하게 되었고, 결론적으로 “단일 Store, 다수Reducer” 라는 Redux의 철학을 통해 State 관리 로직(Reducer)을 단순하고 테스트도 쉽게 유지할 수 있겠다는 생각을 하게 되었습니다. 뿐만 아니라 그 동안 설계와 관련되어 고민하고 필요한 경우 저희 스스로 개발해서 사용하던 많은 부분이 Redux의 서브 프로젝트 형태로 (redux-actions, redux-thunk, reselect 등) 개발되어 사용되고 있는 것을 발견해서 Redux로의 마이그레이션을 결정했고 현재 진행 중에 있습니다.Electron이 글의 도입부에서 이야기한 것처럼 채널 데스크는 윈도우용, OSX용 애플리케이션으로도 제공됩니다. 채널 개발 초기 당시 윈도우, OSX 각각 네이티브로 만들 리소스가 부족했기 때문에 웹 기술 기반으로 네이티브 앱을 만들 수 있는 다양한 솔루션들을 리서치했고 그 중 Electron을 선택하게 되었습니다.Electron은 제가 정말 좋아하는 제품인 Slack, Simplenote에서 사용하고 알려져 있고 국내에서는 Remember 등에서 사용하고 있습니다. 초기 개발 당시에는 안정성에 의문을 제기하는 개발자들도 많았고 저희도 여러 문제와 삽질(인증, 패키징, 이슈 레포팅의 어려움, 메모리릭 등등)을 많이 겪긴 했습니다만 개인적으로는 충분히 프로덕션에 쓸 수 있을 정도 수준이라고 생각합니다. 무엇보다 프론트엔드 개발자가 매우 적은 노력으로도 네이티브 데스크탑 앱을 만들 수 있는 장점이 다른 모든 문제점을 상쇄하고도 남습니다.언어개발 언어로는 자바스크립트 ES6를 사용합니다. 언어를 선택할 당시에도 여러 옵션이 있었는데 가능하면 실험적이지 않고 표준을 사용하는 것이 미래 유지보수에 안전하다고 판단했습니다. 또한 다른 자바스크립트 대안 언어를 사용하지 않더라도 ES6 (일부 ES7 포함) 스펙도 충분히 효율적인 개발이 가능하다고 생각했습니다.코딩 스타일은 기본적으로 Airbnb의 코딩 스타일 가이드라인을 따르며 조이의 상황과 맞지 않는 부분은 엔지니어들과 상의 후 수정해서 사용하고 있습니다. 스타일 체크는 ESLint로 자동화한 뒤 Circle CI와 붙여서 모든 풀리퀘스트에 대해 점검하고 있습니다.테스트초기 개발할 때는 테스트 코드를 별도로 붙이지 않았습니다. 고객의 요구와 기타 상황에 따라 기획과 설계가 크게 변경되기도 했고 그 때마다 기민하게 반응하기 위해서, 어느 정도 확립된 제품이 되기 이전에는 테스트 코드는 작성하지 않는 것이 좋다고 판단했습니다. 이제는 많은 부분이 확정되었고 안정성이 중요해지기 시작했으며 애플리케이션이 커지면서 자동화된 테스트는 필수가 되기 시작했기에 최근에 도입을 하고 있습니다.테스트를 위한 도구는 Jest, Enzyme 등을 사용합니다. Presentational 컴포넌트에 대한 테스트는 props에 따라 원하는 형태로 렌더링이 이루어지는지, 이벤트에 따라 콜백이 잘 실행되는지 등의 Spec 을 작성합니다. Container 컴포넌트에 대한 테스트는 각종 이벤트 및 동작을 시뮬레이션하고 그에 따라 Action이 잘 발생하는지 또는 내부 state가 잘 변경되는지를 테스트합니다. 또한 Store (또는 Reducer), Action Creator, Model, Util 등 모든 구성 요소에 대한 테스트를 붙이려고 노력하고 있습니다. 유닛 테스트가 아닌 e2e 테스트 혹은 css 스타일 테스트 등은 하지 않고 있습니다.빌드 및 배포현재 채널 데스크는 Client-side rendering을 합니다. 초기 로딩 속도가 느리다는 단점이 있어서 Server-side rendering으로의 전환도 고려하고 있습니다. 이미 Node.js 를 사용하고 있어서 Isomorphic Javascript의 형태로 어렵지 않게 전환이 가능합니다.작성된 자바스크립트는 Babel로 컴파일되고 Webpack으로 번들화됩니다. css를 포함한 각종 리소스들 역시 Webpack을 통해 처리됩니다. 웬만한 작업은 npm과 Webpack으로만 자동화하려고 했으며, Electron과 관련된 작업(패키징, 인증 등)들만 gulp를 이용해 자동화됩니다. 모든 리소스들은 Node.js + express 서버로 Serving 되고, Node.js 앱은 Docker로 빌드되어 AWS EC2로 배포됩니다.마무리이상으로 채널 데스크 프론트엔드의 기술 스택을 소개해드렸습니다. 앞으로 각 부분 별로 저희 팀이 고민해 온 문제들과 해결 방법을 공유하고자 합니다. 뛰어난 개발자 분들의 많은 관심과 피드백 부탁드립니다!#조이코퍼레이션 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 10425

Next.js 튜토리얼 7편: 데이터 가져오기

* 이 글은 Next.js의 공식 튜토리얼을 번역한 글입니다.** 오역 및 오탈자가 있을 수 있습니다. 발견하시면 제보해주세요!목차1편: 시작하기 2편: 페이지 이동 3편: 공유 컴포넌트4편: 동적 페이지 5편: 라우트 마스킹6편: 서버 사이드 7편: 데이터 가져오기 - 현재 글8편: 컴포넌트 스타일링9편: 배포하기개요꽤 그럴듯한 Next.js 애플리케이션을 만드는 방법과 Next.js 라우팅 API의 모든 장점을 배웠습니다.대부분의 경우 데이터 소스에서  원격으로 데이터를 가져와야 합니다. Next.js는 페이지에 데이터를 가져오기 위한 표준 API를 제공합니다. getInitialProps라 불리는 비동기 함수를 사용하여 구현할 것입니다.주어진 페이지에 원격 데이터 소스를 통해 데이터를 가져오고 원하는 페이지에 props을 통해 전달할 수 있습니다. 서버와 클라이언트 둘 다 동작하도록 getInitialProps를 작성할 수 있습니다. 그래서 Next.js는 클라이언트와 서버에서 모두 사용할 수 있습니다. 이번 편에서는 getInitialProps를 사용하여 공개된 TVmaze API에서 가져온 데이터로 배트맨 TV 쇼에 대한 정보를 보여주는 애플리케이션을 구현할 예정입니다.설치이번 장에서는 간단한 Next.js 애플리케이션이 필요합니다. 다음의 샘플 애플리케이션을 다운받아주세요:아래의 명령어로 실행시킬 수 있습니다:이제 http://localhost:3000로 이동하여 애플리케이션에 접근할 수 있습니다.배트맨 쇼 데이터 가져오기데모 애플리케이션 내의 home 페이지에 블로그 포스트 목록이 있습니다. 배트맨 TV 쇼 목록을 표시할 것입니다.쇼의 데이터들을 하드코딩하는 대신에 원격 서버에서 그 정보를 가져옵시다.여기서는 TV 쇼를 가져오기 위해 TVMaze API를 사용합니다.TV 쇼 정보를 검색하는 API 입니다.먼저 isomorphic-unfetch를 설치해야 합니다. 데이터를 가져올 때 사용할 라이브러리입니다. 브라우저 fetch API 구현을 간단히 할 수 있도록 만들어진 것이지만 클라이언트와 서버 환경에서 모두 동작합니다.npm install --save isomorphic-unfetchpages/index.js를 다음과 같이 변경해주세요:위의 페이지에 있는 모든 내용은 아래에 표시된 Index.getInitialProps를 제외하고는 익숙할 것입니다:애플리케이션의 어떤 페이지에든 추가할 수 있는 정적 비동기 함수입니다. 이것을 사용하여 데이터를 가져오고 가져온 데이터를 props를 통해 페이지로 보낼 수 있습니다.보다시피 배트맨 TV 쇼 데이터를 가져오고 'shows' props를 통해 페이지로 전달합니다.위에서 보았던 getInitialProps 함수에서 가져온 데이터 숫자를 콘솔에 출력합니다.이제 브라우저 콘솔과 서버 콘솔을 살펴봅시다. 그리고 페이지를 새로고침 해주세요.페이지를 새로고침 한 후 출력되는 메시지는 어디에서 보였나요?- 서버 콘솔- 브라우저 콘솔- 둘 다- 어떤 콘솔에도 출력되지 않았다서버에서만 출력됩니다이 경우 메시지는 서버에서만 출력됩니다.이는 서버에서 페이지가 랜더링되기 때문입니다.이미 데이터를 가지고 있어 클라이언트에서 다시 정보를 가져올 필요가 없습니다.post 페이지 구현하기TV 쇼에 대한 자세한 정보를 보여주는 "/post" 페이지를 구현해봅시다.먼저 server.js를 열고 /p/:id 라우트를 다음과 같이 바꿔주세요.위처럼 바꾼 코드를 적용하기 위해 애플리케이션을 재실행시켜주세요.이전에는 title 쿼리 파라미터를 페이지에 매핑했습니다. 이제 id로 이름을 바꿔야합니다.다음과 같은 내용으로 pages/post.js를 변경해주세요.페이지의 getInitialProps을 살펴봅시다:여기에서 함수의 첫 번째 파라미터는 context 객체입니다. 정보를 가져올 때 사용할 수 있는 쿼리 필드를 가지고 있습니다.예제에서 쿼리 파라미터로부터 보여지는 ID를 선택하고 TVMaze API로부터 데이터를 가져옵니다.이 getInitialProps 함수에서 표시할 제목을 출력하는 console.log를 추가했습니다. 이제 어디에서 출력되는지 볼 수 있습니다.서버와 클라이언트의 콘솔를 둘 다 열어주세요.그 다음 홈페이지 http://localhost:3000로 이동하여 배트맨 쇼 제목을 클릭하세요.위에서 애기했던 console.log 메시지가 보여지는 장소는 어디인가요?- 서버 콘솔- 브라우저 콘솔- 콘솔 둘 다- 아무 콘솔에서도 출력되지 않는다클라이언트 사이드에서 데이터 가져오기브라우저 콘솔에서 메시지를 볼 수 있습니다.클라이언트 사이드를 통해 포스트 페이지에 이동했기 때문입니다. 그런 다음 클라이언트 사이드로부터 데이터를 가져오는 것은 가장 좋은 방법입니다.예를 들어 http://localhost:3000/p/975에 직접 이동한다면 클라이언트가 아닌 서버에서 메시지가 출력되는 것을 볼 수 있습니다.마무리데이터를 가져오고 서버 사이드에서 렌더링하도록 만드는 Next.js의 가장 중요한 기능 중 하나를 배웠습니다.대부분의 유스 케이스에서 충분히 사용할 수 있는 getInitialProps의 기본을 배웠습니다. 더 많은 것을 배우고 싶다면 Next.js의 문서 중 data fetching 문서를 참고할 수 있습니다.#트레바리 #개발자 #안드로이드 #앱개발 #Next.js #백엔드 #인사이트 #경험공유
조회수 2136

[인공지능 in IT] 인공지능 기업에서 하드웨어 엔지니어로 사는 법

인공지능 열풍이 거세게 불면서 이를 개발하는 엔지니어에 대한 수요도 폭발적으로 늘었다. 글로벌 IT의 중심이라 불리던 실리콘밸리를 포함해 중국에서도 막대한 자본을 바탕으로 엔지니어에게 기존 연봉의 2~3배를 제공하는, '인재 쟁탈전'에 돌입했다. 암흑기라 불릴 정도로 이공계 기피현상이 심했던 과거 일은 어느새 기억 속에서 잊혀질만큼 소프트웨어 엔지니어의 위상은 날이 갈수록 높아지고 있다. 심지어 교과 과정에 코딩 교육 의무화를 논의하는 단계다.AI 전문인력이란, 대게 원천기술을 개발하는 소프트웨어 엔지니어나, 학문적인 연구를 하는 리서치 인력을 많이 생각한다. 하지만, 실제로 핵심적인 역할을 담당하는 사람은 하드웨어 엔지니어다. 일반적으로 하드웨어 엔지니어라고 하면 많은 사람들이 납땜을 하고, 모터를 돌리는 등 '기계'를 만지는 엔지니어를 떠올리지만(물론 이 역시 하드웨어 엔지니어가 하는 일 중 하나다), 요즘처럼 인공지능이 적용되지 않은 곳이 없는 세상에서 하드웨어 엔지니어 역할은 그 이상이다.모두의 이해를 돕고, 인공지능 기술을 만드는 회사에서 하드웨어 엔지니어 역할이 얼마나 중요한지 알 수 있도록, 스켈터랩스 사내에서 시니어 하드웨어 엔지니어로 일하고 있는 오혁님과 질의응답 시간을 가졌다.< 스켈터랩스 오혁 하드웨어 엔지니어 >하드웨어 엔지니어로서 주로 하고 있는 일은?사용자가 실제로 만질 수 있는 기기, NVIDIA에서 생산하는 하드웨어 플랫폼과 운영체제(OS) 등을 막론하고, 소프트웨어 알고리즘을 실제 프로덕트로 구현하는 일을 한다. 이런 면에서 보면 소프트웨어 엔지니어링 서포터라고 생각할 수 있다. 하지만, 많은 사람이 더욱 더 심층적으로 인공지능을 연구할 수 있는 이유는 바로 하드웨어의 발전 때문이다.< '구글I/O 2017'에서 차세대 인공지능 전용 칩 'TPU'를 발표하는 모습, 출처: 구글 >예를 들어보자. 프로세서(CPU) 연산속도는 계속 빨라지고 있고, 그래픽 프로세서(GPU)가 프로세서 역할을 일부 담당하고 있으며, 대용량 메모리, 인공지능 가속기 등 모든 면에서 하드웨어 성능이 뒷받침되어야 한다. 하드웨어가 없다면, 소프트웨어 엔지니어가 열심히 만들어도 실제 구현하기가 어렵다. 간단하게 정리하면 하드웨어 엔지니어로서 리서처 역할을 하고, 눈으로 보이는 하드웨어도 만든다.일반인들이 알고 있는 것과 가장 큰 차이가 있다면?일반적으로 하드웨어 엔지니어라고 하면 많은 사람이 빛을 내거나, 모터를 돌리고, 부품을 조립하는 등 물리적인 제품을 만든다고 생각한다. 맞는 말이다. 하지만, 이 모든것을 컨트롤하기 위한 펌웨어, 미들웨어, OS, 디바이스 드라이버 등 소프트웨어가 돌아가기 바로 직전 단계까지, 하드웨어 엔지니어가 담당한다. 또한, 실제 제품 구현도 우리가 맡는다. 때문에, 놀랍게도 하드웨어 엔지니어도 소프트웨어 엔지니어의 전유물이라고 여겨지는 코딩을 많이 한다.< 'GTC 2017'에서 엔비디아 젠슨 황 CEO가 고성능 GPU 아키텍쳐 '볼타'를 발표하고 있다, 출처: 동아일보 >인공지능 붐이 일어나면서 어떤 점이 달라졌는가?인공지능 열풍이 불기 전 하드웨어 엔지니어는 제품을 목적에 맞게 실행하는 역할을 주로 했다. 제품을 구동되기 위해서는 대부분 순차적으로 프로세스를 진행한다. 땜질하고, 코딩하고, 각 부품에 연동하면 완성되는 형태다. 그러나, 지금은 이런 기본적인 프로세스 외에도 기계학습에 대한 알고리즘이나 인공지능 기술 전반에 걸쳐 소프트웨어적인 기술을 이해하지 못하면 절대로 원활하게 제품을 구현할 수 없다. 소프트웨어 엔지니어링을 서포트하는 역할에서 벗어나 인공지능 기술에 들어가는 소프트웨어가 어떻게 구현되는지 이해해야 적합한 제품을 만들 수 있기 때문이다.심지어 이제는 펌웨어를 코딩하는 것도 예전과 많이 달라졌다. 결과물만 놓고 보면, 모터를 돌리는 것은 같을 수 있다. 하지만, 예전에는 로봇 팔을 만들어 무언가를 잡기 위해, A 모터와 B 모터를 순차적으로 돌려서 잡는 것에 그쳤다면, 이제는 기계학습을 적용해 어떤 종류의 컵이라도 스스로 알아서 잡을 수 있도록 제작한다. 하나하나 펌웨어로 낮은 레벨에서 구현하는 것이 아니라, 로봇팔이 잡았을 때 이에 맞는 조건을 제공, 코드 하나로 학습하는 커스터마이징을 적용하는 것이다.< 국산 복강경 로봇수술기기 '레보아이'의 모습, 출처: 동아일보 >인공지능 기업의 하드웨어 엔지니어로서 가장 재미있는 점은?인공지능을 적용하면서 굉장히 재미있는 것을 많이 시도할 수 있다. 아이디어를 내고 무언가를 만들고 싶다면, 최종 제품으로 가는 길에 있어 여러 옵션을 선택할 수 있기 때문이다. 다시 말해 인공지능 소프트웨어를 통해 기존과 다른 방식으로 문제에 접근하고, 이를 해결할 수 있다는 점이다. 비유하자면, 지금까지 손으로 직접 돌리는 드라이버를 사용했다면, 이제는 앞의 부품을 언제든 바꿔낄 수 있는 전동드릴을 사용하고 있다고 보면 된다.반대로 힘든 점은 무엇인가?아무래도 인공지능이 너무 핫하다 보니 계속해서 새로운 기술이 등장한다. 인공지능 업계에서 종사하는 모든 사람들도 마찬가지겠지만, 신기술을 공부하고 연구해야 좋은 제품을 만들 수 있다. 또한, 하드웨어 엔지니어들이 열심히 만든 결과물이 너무나도 빠른 기술 발전속도로 잠시 거쳐가는 것에 불과할까 걱정되기도 한다.그럼에도 앞으로 기대되는 점은 무엇인가?하드웨어 엔지니어로서 세상을 이롭게 하는 제품을 더 많이 제작할 수 있다는 점이다. 인공지능 기술이 발전함에 따라 인간이 못 하는 영역도 조금씩 다가서고 있다.개인적으로는 로봇 쪽에 관심이 많다. 기술 발전속도가 빨라지는 만큼 다양한 제품이 등장해 사람들의 삶에 많은 혜택을 줄 것으로 기대한다. 예를 들면, 청각 장애인을 위해 음성인식을 시각적으로 바꿔주는 제품이나, 거동이 불편한 독거노인을 돕기 위한 기술 등이 있다. 삶을 윤택하게 해주는 기술을 개발하는 것이 점점 더 쉬워지고 있다는 점에서 많이 기대하는 중이다. 어떤 형태가 될 지는 예측할 수 없지만, 지금 단계에서는 소프트웨어든 하드웨어든 커다란 인공지능 플랫폼을 만들고 있다고 생각한다.이호진, 스켈터랩스 마케팅 매니저조원규 전 구글코리아 R&D총괄 사장을 주축으로 구글, 삼성, 카이스트 AI 랩 출신들로 구성된 인공지능 기술 기업 스켈터랩스에서 마케팅을 담당하고 있다#스켈터랩스 #기업문화 #인사이트 #경험공유 #조직문화 #인공지능기업 #기술기업 #하드웨어엔지니어
조회수 980

Node.js 이해하기

Understanding node.js 글을 번역한 글입니다. 부족한 영어 실력이지만 공부를 위해 번역하여 틀린 내용이 있을 수 있습니다. 이런 부분이 있을 경우 댓글로 알려주시면 감사하겠습니다!! 글이 문답형으로 진행되니 감안하시고 읽어주세요!Node.js(이후 '노드'로 통칭)를 소개했을 때 사람들은 일반적으로 두 가지 반응을 보인다. 바로 알았다고 하는 반응 혹은 매우 혼란스러워 하는 반응이다.만약 너가 후자의 경우라면 노드를 설명하기 위한 내 시도가 있다.노드는 command line tool이다. 너는 파일을 다운로드하고 컴파일하고 소스를 설치한다.노드는 JavaScript(이후 '자바스크립트'로 통칭) 프로그램들을 터미널에 'node my_app.js'를 입력함으로써 실행하게 한다.자바스크립트는 V8 자바스크립트 엔진으로 실행된다. (구글 크롬을 빠르게 만드는 것이다.)노드는 네트워크와 파일 시스템에 접근하기 위한 자바스크립트 API를 제공한다.나는 내가 필요한 모든 것을 Ruby, Python, PHP, Java에서 구현할 수 있어!너의 말이 맞다! 미안하게도 노드는 너를 위해 오고 너의 일을 하는 별난 유니콘이 아니다. 이것은 단지 툴이고 적어도 지금은 너가 보통 사용하는 완벽한 툴들을 대체하지 않을 것이다.요점을 알려줘!ㅇㅋ. 기본적으로 노드는 같은 시간에 여러 가지의 일들을 해야할 때 매우 좋다. 코드를 작성하고 "나는 이것들이 동시에 작동했으면 좋겠어"라고 말해본 적 있니? 노드에서는 너의 코드를 제외한 모든 것들이 동시에 작동한다.엥??정말이다. 너의 코드를 제외한 모든 것들이 동시에 작동한다. 이것을 이해하기 위해 너의 코드는 왕이고 노드는 왕의 하인들이라고 상상해보자.한 하인이 왕을 깨워 왕이 필요한 것들이 있는지 물어보는 것으로 하루가 시작된다. 왕은 하인들에게 해야할 일 목록을 주고 다시 오랫동안 자러 간다. 하인은 이 할 일들을 동료들에게 나눠주고 그들은 일을 시작한다.하인이 일을 끝내면 그는 왕의 쿼터 밖으로 보고서를 나열한다. 왕은 한 하인씩 따로따로 들여보내고 그들의 보고서를 듣는다. 때때로 왕은 나가는 길에 하인에게 더 많은 일을 준다.인생은 좋다. 왕의 하인들이 동시에 왕의 모든 일들을 수행하는 동안 왕은 하나의 결과가 있는 보고서에만 따로따로 집중할 수 있다.짱이다! 하지만 그 어리석은 비유를 그만두고 컴퓨터적으로 말해줄 수 있니?ㅇㅋ. 간단한 노드 프로그램은 아래와 같을 것이다:너의 코드는 노드에게 파일을 읽고 쓰는 두가지 일을 주고 자러 간다. 노드가 일을 완료했을 때 이것을 위한 콜백이 실행된다. 하지만 그들은 동시에 실행되는 콜백이 될뿐이다. 콜백이 실행을 완료하는 동안까지 다른 모든 콜백들은 라인에서 멈춰있어야 한다. 게다가 그 콜백들이 실행될 것이라는 보장도 없다.그래서 나는 동시에 같은 데이터 구조에 접근하는 코드에 관해 걱정할 필요가 없지않아?맞다! 그것이 자바스크립트의 싱글 쓰레드와 이벤트 루프 디자인의 아름다움이다. 좋긴 하지만 내가 왜 노드를 써야해?한 가지 이유는 효율성이다. 웹 어플리케이션에서 너의 메인 응답 시간 비용은 대개 너의 모든 데이터베이스 쿼리들이 실행하는데 전력하는 시간들의 합이다. 노드에서는 제일 느린 쿼리를 실행하는 동안 응답시간을 줄이기 위해 너의 모든 쿼리를 즉시 실행한다.또 다른 이유는 자바스크립트다. 너는 노드를 브라우저와 백엔드 사이에서 코드를 공유하기 위해 사용할 수 잇다. 자바스크립트는 정말 다방면성의 언어다. 너가 과거에Python, Ruby, Java, PHP를 써왔다하더라도 아마도 어떤 자바스크립트를 선택해왔을 것이다.마지막 이유는 로우 스피드다. V8은 계속해서 행성에서 가장 빠른 동적 언어 인터프리터의 하나로 경계를 밀고 있다. 나는 자바스크립트만큼 적극적으로 속도를 위해 푸시되는 다른 언어를 생각할 수 없다. 게다가 노드의 I/O 설비는 정말 가볍고 너의 시스템의 가능한 많은 I/O 능력을 활용하게 다가가는 것이다.그러면 너는 내가 당장 내 모든 앱을 노드에서 구현하라고 말하는거야?그렇기도 하고 아니기도 하다. 너가 노드 망치를 휘두르기 시작하면 모든것들은 분명 손톱처럼 보이기 시작할 것이다. 하지만 만약 너가 데드라인이 있는 일을 한다면 너는 아래의 사항들을 기초하여 결정하고 싶을 수도 있다.- 적은 응답 시간과 높은 동시성이 중요한가? 노드는 이것에 정말 좋다.- 프로젝트가 얼마나 큰가? 작은 프로젝트는 괜찮다. 큰 프로젝트는 아마 신중하게 평가해야 한다. (이용가능한 라이브러리, 버그를 고치기 위한 리소스들, 투 업스트림 등)윈도우에서 노드가 실행되니?안된다. 만약 너가 윈도우라면 너는 리눅스와 함께 버츄얼 머신을 실행해야 한다. (VirtualBox를 추천한다.) 윈도우는 노드를 지원하는 계획이 있지만 그 포트와 함께 도와주기를 원하지 않는다면 앞으로 몇 달 동안 뜸들이지 마라.노드에서 DOM에 접근할 수 있니?좋은 질문이다! 접근할 수 없다. DOM는 물질적인 브라우저고 노드의 자바스크립트 엔진(V8)은 감사하게도 그 복잡한 모든것들과 분리했다. 그러나 사람들은 노드 모듈로써 DOM를 실행하여 일한다. 이것은 클라이언트 사이드 코드 유닛 테스트와 같은 매우 놀라온 가능성을 열어줄 것 같다. 이벤트 드리븐 프로그래밍은 어렵지 않니?그것은 너에게 달렸다. 만약 너가 juggle AJAX를 호출하는 방법과 브라우저에서 유저 이벤트들에 대해 이미 배웠다면 노드 사용 방법을 배우는게 큰 문제 아닐 것이다.그렇지 않다면 너가 유지 보수 디자인을 마련하는데 도움을 줄 수 있는 드리븐 개발을 테스트해라.노드는 누가 사용하고 있니?node wiki에 작고 불안정한 리스트가 있다. 야후는 YUI를 위해 노드를 경험중이고 Plurk는 거대한 comet을 위해 사용중고 Paul Bakaus(jQuery UI fame)은 노드 백엔드를 가지는 mind-blowing game engine을 빌드 중이다. Joyent는 노드 창시자인 Ryan Dahi를 고용하여 개발에 막대한 지원을 해주고 있다.아 그리고 Heroku는 실험적으로 hosting support for node.js를 발표했다.어디서 더 배울수 있니?Tim Caswell는 훌륭한 How To Node 블로그를 운영중이다. 트위터에서 #nodejs를 팔로우해라. 메일링 리스트를 구독해라. 그리고 IRC 채널 #node.js에서 시간을 보내라. 우리는 곧 200 lurker-mark에 도달해 간다. 또한 나는 계속 http://debuggable.com/에 글을 쓰고 있다. #트레바리 #개발자 #안드로이드 #앱개발 #Node.js #백엔드 #인사이트 #경험공유
조회수 4087

서버 비용을 70%나 줄인 온디맨드 리사이징 이야기

비트윈의 서버에는 사용자들이 올리는 수많은 사진이 저장되어 있습니다. 2016년 3월 기준으로 커플들이 데이트에서 찍은 사진, 각자의 프로필 사진, 채팅을 나누며 올린 재미있는 짤방까지 약 11억 장의 사진이 저장되어 있습니다. 비트윈에서는 이러한 사용자들의 소중한 추억을 잘 보관하고, 사용자들의 요청을 빠르고 비용 효율적으로 처리하기 위해서 많은 노력을 기울이고 있습니다. 이번 포스팅에서는 비트윈 개발팀이 사용자들의 사진 처리를 보다 효율적으로 하기 위해서 어떠한 노력을 하였는지 공유하고자 합니다.기존의 아키텍쳐¶비트윈 사용자가 채팅창이나 모멘츠 탭에서 사진을 업로드 할 경우, 해당 사진은 업로더 서버라고 불리는 전 세계 각지에 퍼져 있는 사진 업로드 전용 서버 중 가장 가까운 서버를 자동으로 찾아서 업로드 됩니다. 업로더 서버는 사진을 해당 AWS Region의 S3 bucket에 적재하고, 미리 지정된 크기의 썸네일을 자동으로 생성하여 역시 S3에 저장합니다. 그리고 Tokyo Region에 있는 비트윈 메인 서버에 이 결과를 토큰 형태로 전송하여 DB에 그 정보를 저장하도록 합니다. 이러한 과정을 통해서 일반 HTTP request보다 훨씬 큰 용량을 가지고 있는 사용자의 사진이 최대한 적은 지연시간을 가지고 업로드되도록 합니다.사용자가 올린 사진은 원본이 S3에 저장됨과 동시에 미리 정해진 사이즈로 썸네일을 생성해서 저장된다.하나의 사진이 대략 5장에서 6장의 서로 다른 크기의 썸네일로 리사이징이 되는데, 이는 클라이언트의 디스플레이 크기에 따라서 최적화된 이미지를 내려주기 위함이었습니다. 예를 들어서 아주 작은 썸네일이면 충분한 채팅 프로필 표시 화면을 그리기 위해서 사용자가 올린 3백만 픽셀이나 되는 원본 사진을 받아서 클라이언트가 리사이징 하는 것은 지연 시간뿐 아니라 과도한 데이터 사용이라는 측면에서 효율적이지 않기 때문에 작게 리사이징 해놓은 사진을 내려주는 것이 더 바람직합니다.비트윈 사용자들의 넘치는 사랑(?)에 비트윈은 출시 후 5년 동안 약 11억 장, 썸네일을 모두 합치면 66억 장의 사진을 저장하게 되었습니다. 이 사진은 전부 AWS S3에 저장되어 있으며, 썸네일을 합친 총 용량은 2016년 3월 기준 무려 738TB였습니다. 이에 따라 사진을 저장하기 위한 S3 비용이 전체 인프라 운영 비용에서 상당 부분을 차지하게 되었습니다.기존 아키텍쳐의 비효율성¶비트윈 팀은 어느 날 위와 같은 기존의 사진 전송 아키텍쳐에 의문을 가지게 되었습니다. 비트윈 서비스가 다른 서비스와 가장 다른 특징 중의 하나는 커플 간의 데이터는 그 둘 사이에서만 공유된다는 점입니다. 일반적인 웹사이트 같은 경우, 하나의 게시물 혹은 이미지가 수천 수 만명의 유저에게 전달되지만 비트윈에서는 그렇지 않습니다. 즉, 개별 사진의 Fan-out이 작다는 점을 특징으로 가지고 있습니다.그리고 클라이언트에서 LRU를 기반으로 한 파일 캐쉬를 사용하고 있는데, 이를 통해서 위에서 말씀드린 채팅창 프로필 사진 같은 경우 클라이언트에서 캐쉬될 가능성이 매우 커지게 됩니다. 그리고 CDN으로 사용하고 있는 AWS의 CloudFront에서도 약 30~40%의 추가적인 Cache hit을 얻을 수 있었습니다. 즉, 이미 Fan-out이 낮은 리소스가 높은 Cache hit rate를 가지는 사용패턴을 가지고 있는 셈이 됩니다.더군다나 사용자의 디바이스 사이즈에 따라서 미리 리사이징 해놓은 썸네일 중 일부는 아예 사용하지 않는 사용패턴이 나타나기도 합니다. 아이패드와 같은 큰 디스플레이를 가진 클라이언트를 쓰는 사용자와 아이폰4를 사용하는 사용자가 필요로 하는 썸네일의 크기는 다를 수밖에 없기 때문입니다.아래의 그래프는 S3 접근 로그를 분석해서 파악한 특정 기간 내에 같은 해상도를 가지는 썸네일을 클라이언트가 한 번 이상 재요청 하는 비율을 나타내는 그래프입니다. 하루 내에 같은 해상도의 사진을 요청하는 경우는 10% 가 되지 않으며, 한 달 안에도 33% 정도에 불과한 것을 알 수 있습니다.특정 기간 내에 S3에 저장된 썸네일이 다시 요청되는 비율결국 비트윈 팀은 미리 여러 해상도의 썸네일을 준비해서 저장해 놓은 아키텍쳐보다는 사용자가 요청할 때 그 요청에 알맞게 리사이징된 썸네일을 새로 생성해서 내려주는 게 훨씬 비용 효율적이라는 결론에 도달하게 됩니다.새로운 아키텍쳐¶Skia¶하지만 이러한 온디맨드-리사이징 아키텍쳐로의 변환에 가장 큰 걸림돌이 있었습니다. 바로 사진의 리사이징에 오랜 시간이 걸린다는 점이었습니다. 비록 아키텍쳐 변화를 통해서 저희가 얻을 수 있는 비용 이득이 크더라도, 비트윈 사용자 경험에 느린 사진 리사이징이 방해가 되어서는 안 되었습니다.이때 저희가 찾은 것이 바로 Skia 라이브러리였습니다. Skia 라이브러리는 Google에 의해서 만들어진 2D 그래픽 라이브러리로써, 크롬이나 안드로이드, 모질라 파이어폭스 등에 사용되고 있었습니다. 그리고 이 라이브러리는 CPU 아키텍쳐에 따라서 인스트럭션 레벨로 매우 잘 최적화가 되어 있었습니다. 저희가 기존에 쓰고 있던 ImageMagicK에 비해서 거의 4배 속도로 이미지 리사이징을 처리할 수 있었으며, 총 CPU 사용량도 더 적었습니다. 저희는 이 라이브러리를 Python으로 wrapping한 PySkia라는 라이브러리를 내부적으로 만들어서 사진 리사이징에 사용하기로 하였습니다.WebP¶저희는 여기서 한발 더 나아가 보기로 했습니다. 단순히 리사이징만 Skia로 대체하는 것이 아니라, 원본 사진의 저장도 더 효율적으로 할 방법을 찾게 되었습니다. 그 결과 자연스럽게 떠오른 것이 비트윈 스티커 시스템에서 사용되었던 WebP 방식이었습니다. WebP 역시 구글이 만든 이미지 인코딩 방식으로써, 비슷한 화질을 가지는 JPEG에 비해서 약 26% 정도의 용량이 절약된다는 점에서 장점이 있습니다.온디멘드-리사이징¶위에서 언급한 대로 Skia 리사이징과 WebP 원본 저장을 합하여 아래와 같이 필요한 해상도의 사진을 그때그때 리사이징 하는 온디멘드-리사이징 아키텍쳐로 옮겨가게 되었습니다.사용자가 올린 사진은 원본이 WebP로 변환되어 S3에 저장된다. 클라이언트의 요청이 있을 때는 그때그때 요청한 사이즈로 리사이징한 썸네일을 생성해서 내려준다.리사이저 서버가 사용자의 요청을 받아서 원하는 해상도의 사진을 리사이징해서 내려주기까지 채 100ms가 걸리지 않는데, 이 정도면 사용자의 경험에 영향을 주지 않는다고 판단하였습니다. 리사이저 서버는 업로더 서버와 함께 세계 각지의 AWS Region에 배포되어 있으며, 이는 사용자가 요청한 사진을 최대한 빨리 받아가기 위함입니다.기존 사진 마이그레이션¶위와 같은 아키텍쳐 전환을 통해서 새롭게 업로드 되는 사진들은 원본만 WebP로 변환되어 저장한 후 요청이 들어올 때만 온디멘드 리사이징이 되지만, 그동안 비트윈 사용자들이 축적해 놓은 11억 장의 사진은 여전히 여러 사이즈의 썸네일로 미리 리사이징이 되어 있는 비효율적인 상태였습니다. 저희는 이 사진들도 마이그레이션하는 작업에 착수했습니다.11억 장이나 되는 원본 사진들을 전부 WebP로 변환하고, 나머지 50억 장의 미리 생성된 썸네일 사진을 지우는 작업은 결코 간단한 작업이 아니었습니다. 저희는 이 작업을 AWS의 Spot Instance와 SQS를 통해서 비용 효율적으로 진행할 수 있었습니다.Auto Scaling with Spot instance¶마이그레이션 작업은 크게 다섯 단계로 이루어져 있습니다.커플 단위로 작업을 쪼개서 SQS에 쌓아놓습니다.Worker가 SQS로부터 단위 작업을 받아와서, 해당 커플에 존재하는 모든 사진을 WebP로 변환하고 S3에 올립니다.S3로의 업로드가 확인되면, 그 변경 사항을 DB에 적습니다.기존 썸네일 사진들을 삭제합니다.기존 썸네일이 삭제되었다는 사실을 DB에 적습니다.작업을 하는 도중에 얼마든지 Worker가 중단되거나 같은 커플에 대한 작업이 두 번 중복되어서 이루어질 위험이 있습니다. 이를 위해서 마이그레이션 작업을 멱등적으로 구성하여서 사용자의 사진이 손실되는 등의 사고가 발생하지 않도록 하였습니다. 중간마다 DB에 접근해서 변경된 내용을 기록해야 하는 작업의 특성상, 작업의 병목 구간은 비트윈 DB였습니다. 그리고 사진 인코딩을 바꾸는 작업의 특징상 많은 CPU 자원이 소모될 것으로 생각하였습니다.DB에 부담이 가지 않는 범위내에서 많은 CPU 자원을 끌어와서 작업을 진행해야 할 필요성이 생긴 것입니다. 이 조건을 만족하게 하기 위해서 SQS를 바라보는 Worker들로 Auto-scaling group을 만들었습니다. 그리고 이 Auto-scaling group은 c3.2xlarge와 c3.4xlarge spot instance로 구성되어 있으며, DB의 CPU 사용량을 메트릭으로 하여 Scaling이 되도록 하였습니다. 작업은 주로 DB의 부하가 적은 새벽 시간에 집중적으로 이루어졌으며, 이 인코딩 작업은 대략 4일 정도가 소모되었습니다. 작업 과정에서 Tokyo Region에 있던 c4.2xlarge와 c3.4xlarge spot instance를 최대 140대를 사용했고, 총 사용 시간은 6,767시간이었습니다. 사용한 instance의 계산 능력을 ECU로 환산하면 총 303,933 ECU · hour를 작업에 사용하였습니다. 마이그레이션에 사용된 EC2 비용을 바탕으로 계산해 보면, 백만 장의 WebP 인코딩을 위해서 사용한 비용이 $1.8 밖에 되지 않았다는 것을 알 수 있습니다.작업 과정에서 AWS 서비스에 의외의 병목 구간이 있다는 것을 알게 되었는데, S3 단일 버킷에 1분당 1천만 개 이상의 object에 대한 삭제 요청이 들어오면 Throttling이 걸린다는 사실과 SQS의 in-flight message의 개수가 12만 개를 넘을 수 없다는 것입니다.결과¶위의 아키텍쳐 변화와 마이그레이션 작업 후 저희의 S3 비용은 70%가 넘게 감소했으며 전체 인프라 비용의 상당 부분이 감소하였습니다. 온디멘드 리사이징으로의 아키텍쳐 변화는 Storage 비용과 Computation 비용 사이의 교환이라고 볼 수 있는데, 아래 그래프에서 볼 수 있듯이 확연한 비용 절감을 달성할 수 있었습니다.총 마이그레이션 비용¶항목사용량비용 ($)EC2 spot instance6,767 hrs1,959.11SQS188,204,10489.59S3 Put/Get Requests2,492,466,8605,608.34총비용7,657.04마이그레이션 결과¶항목Before MigrationAfter Migration감소량 (%)S3 # of objects6.65 B1.17 B82.40S3 storage738 TB184 TB75.06비용 감소¶사진 저장과 리사이징에 관련된 비용이 68% 감소하였음못다 한 이야기¶이번 포스팅에서는 최근에 있었던 비트윈 사진 아키텍쳐의 변화에 대해서 알아보았습니다. 주로 사용자의 경험을 방해하지 않는 조건에서 비용을 아끼는 부분에 중점을 두고 저희 비트윈의 아키텍쳐 변화에 대해서 설명해 드렸습니다. 하지만 이 글에서 미처 언급하지 못한 변화나 개선 사항들에 대해서는 다루지 못했습니다. Tokyo Region에서 멀리 떨어져 있는 사용자를 위해서 전 세계 여러 Region에 사진 저장/전송 서버를 배포하는 일이나, 사진을 로딩할 때 낮은 해상도로부터 차례대로 로딩되도록 하는 Progressive JPEG의 적용, 사진을 아직 받아오지 못했을 때 Placeholder 역할을 할 수 있는 사진의 대표색을 찾아내는 방법 등이 그것입니다. 이에 관해서는 후에 자세히 다뤄보도록 하겠습니다.정리¶비트윈 개발팀에서는 많은 인프라 비용을 소모하는 기존 썸네일 저장 방식을 개선하여 70%에 가까운 비용 절감 효과를 보았습니다. 기존의 썸네일을 미리 생성해놓는 방식으로부터 클라이언트가 요청할 때 해당 크기의 썸네일을 리사이징해서 내려주는 방식으로 변경하였고, WebP와 Skia등의 새로운 기술을 적용하였습니다. 이를 통해서 사용자 경험에는 거의 영향을 주지 않은 상태로 비용 절감 효과를 볼 수 있었습니다.저희는 언제나 타다 및 비트윈 서비스를 함께 만들며 기술적인 문제를 함께 풀어나갈 능력있는 개발자를 모시고 있습니다. 언제든 부담없이 [email protected]로 이메일을 주시기 바랍니다!
조회수 2287

JPassKit 적용중 오류 발생

서비스에서 ios wallet을 제공하려고 하니, 예전과는 다르게 서버단 통신을 통해 인증받는 절차가 추가로 생겼단다. 다만, 애플에서 제공하는 서버쪽 데모를 보면 ruby로 만들어져있다. 왜 하필 루비인가? swift도 아니고… 여튼 그걸 java로 porting하려니 이미 만들어 놓은 것이 있을 것 같아서 구글링했더니, jpasskit이 그나마 제일 fork도 많이 되고, 사용도 하는 것 같아서 lib dependency를 추가했다.<!-- PassKit --> de.brendamour jpasskit 0.0.8 개발을 완료했는데, Test Case에서 오류가 나타나기 시작했다.com.fasterxml.jackson.databind.JsonMappingException: Can not resolve PropertyFilter with id 'validateFilter'; no FilterProvider configured난 jackson filter를 바꾼 적이 없는데 왜 에러가 나는 것인가? 처음에는 jpasskit issue를 보고 jackson lib의 version 호환성 문제가 있는 것 같아서 아래처럼 dependency처리를 했다.<!-- PassKit --> de.brendamour jpasskit 0.0.8 com.fasterxml.jackson.core jackson-core 위의 오류가 해결된 것처럼 보여서 SNAPSHOT version을 만들었는데, 됐다안됐다한다. 예를 들어서 local profile에서 하면 되고, develop profile에서 하면 오류나고… 혹은 전체 junit을 모두 돌리면 에러가 발생하는데, 에러나는 class만 테스트 돌리면 성공하고 ㅠ.ㅠ그래서 해당 소스를 파보다가 문제점을 발견하였다.우리의 프로젝트에서는 pojo type인 jackson object mapper를 bean으로 등록해서 사용하고 있다. bean으로 등록하면 몇 가지 장점이 있는데, 자세한 설명은 이 글의 범위를 벗어나기 때문에 생략한다.@Primary @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new CustomObjectMapper(); initializeObjectMapper(objectMapper); return objectMapper; }그래서 Object Mapper는 singleton으로 재사용하고 있는데, jpasskit은 Object Mapper를 변조시키고 있다.public final class PKFileBasedSigningUtil extends PKAbstractSIgningUtil { private static final String FILE_SEPARATOR_UNIX = "/"; private static final String MANIFEST_JSON_FILE_NAME = "manifest.json"; private static final String PASS_JSON_FILE_NAME = "pass.json"; private ObjectWriter objectWriter; @Inject public PKFileBasedSigningUtil(ObjectMapper objectMapper) { this.addBCProvider(); this.objectWriter = this.configureObjectMapper(objectMapper); } ...protected ObjectWriter configureObjectMapper(ObjectMapper jsonObjectMapper) { jsonObjectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); jsonObjectMapper.setDateFormat(new ISO8601DateFormat()); SimpleFilterProvider filters = new SimpleFilterProvider(); filters.addFilter("validateFilter", SimpleBeanPropertyFilter.serializeAllExcept(new String[]{"valid", "validationErrors"})); filters.addFilter("pkPassFilter", SimpleBeanPropertyFilter.serializeAllExcept(new String[]{"valid", "validationErrors", "foregroundColorAsObject", "backgroundColorAsObject", "labelColorAsObject", "passThatWasSet"})); filters.addFilter("barcodeFilter", SimpleBeanPropertyFilter.serializeAllExcept(new String[]{"valid", "validationErrors", "messageEncodingAsString"})); filters.addFilter("charsetFilter", SimpleBeanPropertyFilter.filterOutAllExcept(new String[]{"name"})); jsonObjectMapper.setSerializationInclusion(Include.NON_NULL); jsonObjectMapper.addMixIn(Object.class, PKAbstractSIgningUtil.ValidateFilterMixIn.class); jsonObjectMapper.addMixIn(PKPass.class, PKAbstractSIgningUtil.PkPassFilterMixIn.class); jsonObjectMapper.addMixIn(PKBarcode.class, PKAbstractSIgningUtil.BarcodeFilterMixIn.class); jsonObjectMapper.addMixIn(Charset.class, PKAbstractSIgningUtil.CharsetFilterMixIn.class); return jsonObjectMapper.writer(filters); }확실해졌다. 위에서 상황마다 오류가 간헐적으로 발생하는 이유는 이와 같은 것이었다. jpasskit이 실행되기 전까지는 정상적으로 동작한다. 그러다가 jpasskit을 한 번 거치면 이미 등록되어 있는 object mapper bean의 설정이 바뀌게 된다. 즉, 우리가 설정한 custom configuration들이 무시되어버려서, 전혀 엉뚱한 곳에서 에러를 일으킨다.jpasskit에서 사용하는 object mapper는 특별한 설정이 필요한 것은 아니라, bean을 사용하지 않고 기본 object mapper를 생성해서 넘기는 식으로 수정하였다.private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); ... private byte[] createPKPassBinaries(PKPass pass, PKSigningInformation pkSigningInformation, InputStream thumbnail, InputStream thumbnail2x) throws Exception { return new PKFileBasedSigningUtil(OBJECT_MAPPER).createSignedAndZippedPkPassArchive(pass, createPKPassTemplate(thumbnail, thumbnail2x), pkSigningInformation); }All Clear.해당 내용은 jpasskit에 issue reporting하여 신규 release(0.0.9)가 예정중이다.#데일리 #데일리호텔 #기술스택 #스택도입 #후기 #일지 #JPasskit

기업문화 엿볼 때, 더팀스

로그인

/