스토리 홈

인터뷰

피드

뉴스

조회수 1681

PyCon2017 첫번째날 후기

아침에 느지막이 일어났다. 어제 회사일로 피곤하기도 했지만 왠지 컨디션이 좋은 상태로 발표를 하러 가야지!라는 생각 때문에 깼던 잠을 다시 청했던것 같다. 일어나 아침식사를 하고 아이 둘과 와이프를 두고 집을 나섰다. 작년 파이콘에는 참가해서 티셔츠만 받고 아이들과 함께 그 옆에 있는 유아교육전을 갔었기에 이번에는 한참 전부터 와이프에게 양해를 구해둔 터였다.코엑스에 도착해서 파이콘 행사장으로 가까이 가면 갈수록 백팩을 메고, 면바지를 입고, 영어 글자가 쓰인 티셔츠를 입은 사람의 비율이 높아지는 것으로 보아 내가 제대로 찾아가고 있구나 라는 생각이 들었다.늦게 왔더니 한산하다.지난번에는 입구에서 에코백과 가방을 나눠줬던 것 같은데 이번에는 2층에서 나눠준다고 한다. 1층이 아무래도 복잡해지니 그런 것 같기도 하고, 2층에서 열리는 이벤트들에도 좀 더 관심을 가져줬으면 하는 것 같기도 하다. 우선 스피커 옷을 받고 싶어서 (솔직히 입고 다니고 싶어서) 2층에 있는 스피커방에 들어갔다.허락 받지 않고 사진찍기가 좀 그래서 옆방을 찍었다첫 번째 키노트는 놓쳤지만 두 번째 키노트는 꼭 듣고 싶었기에 간단히 인사만 하고 티셔츠를 들고 나왔다. (외국에서 오신 연사분과 영어로 대화를 나누고 있어서 자리를 피한것은 아니다.) 나가는 길에 보니 영코더(초등학교 5학년 부터 고등학생 까지 파이썬 교육을 하는 프로그램)을 진행하고 있었다. 의미있는 시도를 하고 있다는 생각이 들었다.이 친구들 2년 뒤에 나보다 잘할지도 모른다.키노트 발표장에 갔더니 아웃사이더님이 뒤에 서 게셨다. 지난 파이콘 때 뵙고 이번에 다시 뵈었으니 파이콘이 사람들을 이어주는 역할을 하는구나 싶었다.키노트에서는 현우 님의 노잼, 빅잼 발표 분석 이야기를 들을 수 있었다. 그리고 발표를 통해 괜히 이것저것 알려줘야만 할 것 같아 발표가 부담스러워지는 것 같다는 이야기를 들었다. 나 또한 뭔가 하나라도 지식을 전달해야 한다는 압박감을 느끼고 있었던 터라 현우 님의 키노트 발표를 듣고 나니 좀 더 오늘을 즐겨야겠다는 생각이 들었다.오늘은 재미있었습니다!현우님 키노트를 듣고 같은 시간(1시)에 발표를 하시는 경업님과 이한님 그리고 내일 발표이신 대명님, 파이콘 준비위원회를 하고 계신 연태님과 함께 식사를 하러 갔다. 가는 길에 두숟갈 스터디를 함께 하고 계신 현주님과 희진 님도 함께했다. 사실 이번에는 발표자도 티켓을 사야 한다고 해서 조금 삐져 있었는데 양일 점심 쿠폰을 주신다고 해서 삐진 마음이 눈 녹듯이 사라졌다.부담 부담식사를 하고 발표를 할 101방으로 들어가 봤다. 아직 아무도 없는 방이라 그런지 괜히 긴장감이 더 생기는 느낌이다. 발표 자료를 열어 처음부터 끝까지를 한번 넘겨 보고 다시 닫았다. 처음에는 가장 첫 발표라 불만이었는데 생각해보니 발표를 빨리 마치고 즐기는 게 훨씬 좋겠다는 생각이 들었다. 발표 자료를 다듬을까 하다가 집중이 되지 않아 밖으로 나갔다. “열린 공간” 현황판에 충동적으로 포스트잇을 하나 붙이고 왔다. 어차피 발표는 나중에 온라인으로도 볼 수 있으니까 사람들과 이야기를 나눠 봐야 겠다 싶었다. (내 발표에는 사람이 많이 왔으면 하면서도, 다른 사람의 발표는 온라인으로 보겠다는 이기적인 생각이라니..)진짜 궁금하긴 합니다다시 발표장으로 돌아왔다. 왠지 모르는 분들은 괜찮은데 아는 분들이 발표장에 와 계시니 괜히 더 불안하다. 다른 분들은 발표자료에 짤방도 많이 넣으셨던데.. 나는 짤방도 없는 노잼 발표인데.. 어찌해야 하나. 하지만 시간은 다가오고 발표를 시작했다.얼굴이 반짝 반짝리허설을 할 때 22분 정도 시간이 걸렸던 터라 조금 당겨서 진행을 했더니 발표를 거의 20분에 맞춰서 끝냈다. 그 뒤에 몇몇 분이 오셔서 질문을 해주셨다. 어리버리 대답을 한 것 같다. 여하튼 내 발표를 찾아오신 분들께 도움이 되었기를. 그리고 앞으로 좀 더 정확한 계산을 하시기를.대단히 발표 준비를 많이 하지도 못하면서 마음에 부담만 쌓아두고 있는 상황이었는데, 발표가 끝나니 아주 홀가분한 마음이 되었다. 발표장을 나가서 이제 부스를 돌아보기 시작했다. 매해 참여해 주고 계신 스마트스터디도 보이고 (정말 안 받고 싶은 ‘기술부채’도 받고 말았다.) 쿠팡, 레진 등 친숙한 회사들이 많이 보였다. 내년에는 우리 회사도 돈을 많이 벌어 여기에 부스를 내고 재미있는 이벤트를 하면 좋겠다는 생각이 들었다.부스를 돌아다니다가 이제 파이콘의 명물이 된 내 이름 찾기를 시작했다. 이름을 찾기가 쉽지가 않다. 매년 참여자가 늘어나서 올해는 거의 2000명에 다다른다고 하니 파이썬 커뮤니티의 성장이 놀랍다. 10년 전에 파이썬을 쓸 때에는 그리고 첫 번째 한국 파이콘이 열릴 때만 해도 꽤 마이너 한 느낌이었는데, 이제 주류가 된 것 같아 내 마음이 다 뿌듯하다. (그리고 내 밥줄이 이어질 수 있는 것 같아 역시 기쁘다)어디 한번 찾아보시라다음으로는 박영우님의 "Django admin site를 커스텀하여 적극적으로 활용하기” 발표를 들으러 갔다. (짧은 발표를 좋아한다.) 알고 있었던 것도 있었지만 커스텀이 가능한지 몰랐던 것들도 있어서 몇 개의 기능들을 킵해 두었다. 역시 컨퍼런스에 오면 내게 필요한 ‘새로운 것’에 대한 실마리를 주워가는 재미가 있다.익숙하다고 생각했지만 모르는것이 많다4시가 되어 OST(Open Space Talk)를 하기로 한 208B 방으로 조금 일찍 갔다. 주제가 뭐였는지는 잘 모르겠는데 주식 투자, Tensor Flow, 비트코인, 머신러닝 등등의 이야기들이 오가고 있었다. 4시가 되어 내가 정한 주제에 대해 관심 있는 사람들이 모였다. 괜히 모일 사람도 없는데 큰방을 잡은 것이 아닐까 하고 생각하고 있었는데, 생각보다 많은 분들이 오셨다.각 회사들이 어떤 도구를 사용하는지 설문조사도 해보고, 또 어떤 개발 방법론을 사용하는지, 코드 리뷰, QA는 어떻게 하고 있는지에 대한 이야기를 나눴다. 다양한 회사에서 다양한 일을 하는 사람들이 모여 있다 보니 생각보다 꽤 재미있게 논의가 진행되었다. 사실 내가 뭔가 말을 많이 해야 할 줄 알았는데, 이야기하고 싶은 분들이 많이 있어서 진행을 하는 역할만 하면 되었다. 마지막으로는 “우리 회사에서 잘 사용하고 있어서 다른 회사에도 추천해 주고 싶은 것”을 주제로 몇 가지 추천을 받은 것도 재미가 있었다.열심히 오간 대화를 적어두긴 했다5시에 OST를 마치고는 바로 집으로 돌아왔다. 오늘 저녁에 아이들을 잘 돌보고 집 청소도 열심히 해두어야 내일 파이콘에 참여할 수 있기 때문이다. 기대된다. 내일의 파이콘도.그리고 정말 감사드린다. 파이콘을 준비해주시고 운영해주고 계신 많은 분들께.#8퍼센트 #에잇퍼센트 #개발자 #개발 #파이썬 #Python #파이콘 #Pycon #이벤트참여 #참여후기 #후기
조회수 1737

응답시간 분포도

애플리케이션의 성능 개선은 웹 트랜잭션의 응답시간을 분석을 통해 이뤄집니다. 와탭의 응답시간 분포도는 대규모 트랜잭션 분석이 가능한 Heatmap 형태로 제공되고 있습니다. 와탭을 사용하는 사용자는 응답시간 분포도를 통해 웹 서비스의 응답시간이 느려지는 것을 알 수 있을 뿐만 아니라 패턴 분석을 통해 느려진 원인을 예측할 수도 있습니다. 와탭의 응답시간 분포도Y 축: 트랜잭션 응답시간을 의미합니다. 10s는 트랜잭션이 시작에서 종료까지의 시간이 10초가 걸렸다는 것을 의미합니다.X 축: 트랜잭션이 종료된 시간을 의미합니다.■: 트랜잭션이 발생한 위치에 색이 칠해집니다. 청색 계열은 정상적인 트랜잭션을 의미합니다. 노랑색과 붉은 색 계열은 에러가 발생한 트랜잭션을 의미합니다. 색상의 농도는 해당 영역에 발생한 트랜잭션의 밀도를 상대적으로 표시합니다.  와탭의 응답시간 분포도는 트랜잭션의 응답시간을 시각화하는 것입니다. 웹 서비스의 트랜잭션을 시각화 할 뿐만 아니라 추적하고자 하는 영역을 드래그하여 트랜잭션의 진행상황을 추적하는 것도 가능합니다.  추적하고 싶은 트랜잭션을 드래그 하는 모습와탭의 응답시간 분포도에서 트랜잭션을 선택하면 분석 화면으로 넘어갑니다. 해당 애플리케이션 서버 정보를 통해 선택된 트랜잭션이 어느 애플리케이션 서버에서 발생했는지 알 수 있습니다.애플리케이션과 선택된 트랜잭션 정보 화면분석하고 싶은 애플리케이션 서버를 클릭하면 해당 애플리케이션 서버에서 발생한 트랜잭션 목록을 확인 할 수 있습니다. 최종적으로 APM을 통해 확인하고 싶은 내용이 트랜잭션의 디테일한 정보일 것입니다. 와탭의 APM은 트랜잭션을 시각화하고 시각화된 트랜잭션을 선택하면 선택된 트랜잭션의 목록을 애플리케이션 서버 별로 분류하여 선택할 수 있는 구조를 가지고 있습니다. 이것은 능동적으로 웹 애플리케이션을 분석할 수 있는 최적화된 흐름이라고 생각할 수 있습니다. 사용자가 응답속도 분포도를 통해 선택한 트랜잭션 목록#와탭랩스 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 1881

Android Studio JCenter 이용하기

 안녕하세요. 크몽개발팀 입니다.오늘 포스트 주제는 Android Studio JCenter 이용하기입니다.JCenter????  JCenter에 대해 처음 들으시는분들도 있을거같은데요.JCenter는 라이브러리들이 모여있는 저장소라고 보시면 되겠습니다.그렇다면 JCenter를 이용하여 무엇을 할까요?바로 외부 라이브러리들을 가져와서 프로젝트안에 Import 할려고 합니다. JCenter 사이트 링크 : https://bintray.com/bintray/jcenterJCenter 페이지에 접속하시면 위와 같은 페이지를 볼 수 있는데요.여기서 사용하고 싶은 라이브러리를 검색해보겠습니다.제가 검색한 라이브러리는 ImageLoder 라이브러인 'Glide'를 검색했습니다.빨간색으로 표시되있는게 제가 찾던 라이브러리 입니다.검색한 라이브러리를 클릭하면 위와 같이 상세페이지를 볼 수 있는데요.라이브러리 Github 주소 와 버젼에 대한 정보를 확인할 수 있습니다.그럼 이제 검색한 라이브러리를  Android Studio Gradle에 Import 하겠습니다. Android Studio에서 프로젝트를 생성하게 되면 위와 같이 3개의 그래들 파일을 볼 수 있는데요.자주 사용할 그래들 파일은 app폴더에 있는 그래들 파일입니다.그래들 파일을 열어보면 낯익은 코드들이 보이는데요.ADT에서는 매니페스트에서 버젼관리를 햇었는데 Studio에서는 그래들로 빠진거같습니다.그리고 빨간표시를 해둔곳이 바로 JCenter에서 검색한 라이브러리를 Import 하시면 되겠습니다.  위에 JCenter에서 찾은 라이브러리명을 입력하고 뒤에 버젼번호도 같이 입력합니다.그리고 Sync 버튼을 눌러주면 라이브러리가 Import 됩니다. External Libraries를 확인해보시면 라이브러리가 추가된걸 확인할 수 있습니다.---------------------------------------------------------------------------------------이렇게 JCenter를 이용하여 간단하게 라이브러리들을 Import를 할 수 있습니다.그리고 그래들 과 JCenter를 이용하여 라이브러리를 적용할때 가장 좋은점은'com.github.bumptech.glide:glide:3.+' 이런식으로 버젼에대한 값을 주면라이브러리 상위버젼이 나올경우 자동으로 최상위 버젼으로 라이브러리를 Import 해준다는 점입니다.이로써 라이브러리 버젼관리도 많이 편해질거 같습니다.이것으로 Android Studio JCenter 이용하기 포스트를 마치겠습니다.#크몽 #개발팀 #인턴 #인턴생활 #인사이트
조회수 5543

AWS Instance Scheduler Bot 적용기

이 포스팅은 총 2부로 이어지며 현재는 2부입니다.1부 : AWS 비용 얼마까지 줄여봤니?2부 : AWS Instance Scheduler Bot 적용기1부에서 AWS 비용을 절감하기 위한 Instance Scheduler에 대한 소개를 하였습니다. 2부에서는 Instance Scheduler의 설정을 손쉽게 변경하기 위한 Bot을 적용한 사례에 대해서 소개합니다.Bot의 필요성Instance Scheduler의 설정을 변경하기 위해서는 정보를 담고 있는 Dynamo DB 의 데이터를 변경해야 합니다. AWS Console을 이용하여 직접 수정할 수도 있지만 여전히 불편하고 느립니다. 더군다나 이를 이용하는 사용자가 DB Table의 구조와 AWS Console 사용법을 알고 있어야 하고 비 개발자라면 더 쉽지 않은 문제입니다. 하지만 Bot을 이용하면 사용자는 어려운 DB Query나 구조를 알아야 할 필요도 없고 손쉽게 채팅 메시지를 통해 Bot에게 질의하고 처리 결과를 응답받을 수 있습니다.Outgoing WebhookJANDI에서는 Incoming Webhook과 반대되는 개념으로 Outgoing Webhook을 제공합니다. 특정 키워드로 시작하는 메시지가 있을 경우 내용을 설정된 URL Endpoint에 POST로 Webhook을 보내줍니다. Webhook을 수신한 곳에서는 일련의 처리 후 메시지 데이터 형식을 맞춰 응답하게 되면 채팅창에 메시지를 표시하게 됩니다. 이를 통해 다른 외부 시스템과 연동할 수 있습니다.POST Data예를 들어 날씨 키워드로 Outgoing Webhook을 생성했다면 /날씨 메시지가 시작될 때 다음과 같은 데이터가 Webhook으로 발송됩니다.{ "token": "YE1ronbbuoZkq7h3J5KMI4Tn", "teamName": "Toss Lab, Inc.", "roomName": "토스랩 코리아", "writerName": "Gloria", "text": "/날씨 서울", "keyword": "날씨", "createdAt": "2017-07-19T14:49:11.266Z" } token을 이용하여 요청의 유효성 체크를 할 수 있고 text를 적절히 파싱 하여 요청에 부합하는 처리를 할 수 있습니다.ResponsePOST Data를 적절히 처리 후 결과를 채팅창에 응답 메시지를 표시하고 싶다면 아래와 같은 JSON Data를 Response body에 넣어주면 됩니다.{ "body" : "서울의 현재 날씨", "connectColor" : "#FAC11B", "connectInfo" : [{ "title" : "온도", "description" : "최고:28.00, 최저:24.00, 현재: 24.30" }, { "title": "날씨", "description": "흐리고 비" }] } 이를 이용하여 Instance Scheduler에도 적용해봤습니다.Schedule BotSchedule Bot은 Instance Scheduler의 Lambda 함수에 함께 포함되어 작동하며 스케쥴 조회 / 예외 설정, 서버 강제 시작/중지, 서버 상태 조회 등의 기능을 수행합니다.API Gateway와 Lambda 함수를 연결하여 Endpoint URL을 생성하고 Outgoing Webhook URL로 설정하여 Webhook으로 Lambda 함수가 실행될 수 있도록 하였습니다. Lambda 함수는 Cloudwatch를 통해서 실행되면 Scheduler가 작동되고 API Gateway를 통해 실행되면 Schedule Bot이 작동됩니다.Schedule Bot 명령어Schedule Bot은 다음과 같은 명령어를 수행합니다./서버 help : 도움말 /서버 [스케쥴명] status : 현재 서버 상태 조회 /서버 [스케쥴명] info : 오늘의 스케쥴 조회 /서버 [스케쥴명] info [YYYY-MM-DD] : 특정일 스케쥴 조회 /서버 [스케쥴명] exception info : 오늘의 스케쥴 예외 조회 /서버 [스케쥴명] exception info [YYYY-MM-DD] : 특정일 스케쥴 예외 조회 /서버 [스케쥴명] exception set [YYYY-MM-DD] [start|stop] [h:m] : 예외 설정 /서버 [스케쥴명] exception del [YYYY-MM-DD] [start|stop] : 예외 삭제 /서버 [스케쥴명] force_start : 서버 강제 실행 /서버 [스케쥴명] force_stop : 서버 강제 중지 Schedule Bot 작동 화면Schedule Bot은 서버병이라는 컨셉으로 인격화(?)에 힘썼습니다.스케쥴 정보 조회서버 상태 조회서버 강제 시작/중지명령어 오류마무리AWS 기반의 서비스를 운영하는 스타트업이라면 더욱더 현실적으로 부딪히는 비용 문제에 대해서 저희가 고민한 내용과 솔루션에 대해서 공유하였습니다.아직 적용기간이 길지 않아 절감비용에 대해 수치적인 데이터를 언급하기는 힘들지만 많은 금액이 절감될 거라 예상하고 있습니다.저희와 같은 고민을 하고 있다면 Instance Scheduler를 적극 권장합니다.#토스랩 #잔디 #JANDI #개발 #개발자 #AWS #도입후기 #일지 #인사이트 #경험공유
조회수 969

[맛있는 인터뷰 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 #개발자 #앱개발자 #애플리케이션 #모바일 #팀원 #팀원소개 #팀원인터뷰 #인터뷰 #사내문화 #조직문화 #기업문화 #팀원자랑
조회수 1662

공용 계정용 OTP 관리방법

제대로 된 기업용 서비스라면 의례 다중 계정과 권한 제어 기능을 함께 제공하기 마련이다. 그래서 공용 계정을 굳이 만들 이유가 하나도 없다. 하지만 일부 서비스(그리고 대부분의 한국의 기업 서비스)는 단일 계정만 지원하는데다 AWS 같은 서비스도 root 계정이 따로 있어서 계정 관리 이슈가 불거지기 마련이다. 계정 아이디와 암호의 경우는 LastPass 같은 기업용 계정 관리 서비스를 사용하거나 팀 공용 계정 비밀번호 관리하기에서 소개된 방식과 같이 약간은 불편하지만 비용이 들지 않는 수단을 도입하여 관리하면 된다. 그런데 MFA 또는 2FA(2-Step Verification)라고도 부르는 OTP로 계정을 보호할 때는 OTP 정보를 공유하기가 쉽지 않다. 일반적으로 MFA 계정은 Google Authenticator 같은 앱을 설치해 관리한다. OTP 정보와 계정 암호를 한 계정에서 관리하지 않아야 한쪽이 노출되어도 보안을 유지할 수 있기 때문이다. 문제는 Google Authenticator와 Authy 같은 도구를 특정 휴대폰에 설치하면 여러 사람이 OTP 정보를 공유하기 힘들다는 것이다. 그래서 몇가지 솔루션을 찾아보았는데 “이거다!” 싶은 건 없어도 gauth라는 명령줄 기반 도구에 안착하게 되었다.gauth.csv라는 파일에 OTP 정보를 아래와 같이 입력하고AWS: ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 Airbnb:abcd efgh ijkl mnop Google:a2b3c4d5e6f7g8h9 Github:234567qrstuvwxyzgauth를 실행하면 아래와 같이 OTP 토큰을 확인할 수 있다.$ gauth prev curr next AWS 315306 135387 483601 Airbnb 563728 339206 904549 Google 453564 477615 356846 Github 911264 548790 784099 [======= ]이제 gauth.csv 파일만 라스트패스 등으로 제한된 사용자에게 안전하게 공유하면 된다.개선 사항DailyHotel/gauth는 pcarrier/gauth를 개선한 tuxmartin/gauth를 Docker 이미지로 감쌌다. 그래서 Golang 개발환경을 갖추고 소스코드를 빌드하지 않아도 바로 사용할 수 있다. 자세한 사용법은 README 문서에 적어두었다.#데일리 #데일리호텔 #개발 #개발자 #개발팀 #인사이트 #꿀팁
조회수 864

P2P금융에서 고도의 엔지니어링이 필수적인 이유

지난 8월30일, 매일경제신문이 주최하고 과학기술정보통신부와 금융위원회, 금융감독원이 후원한 매경핀테크어워드2018에서 렌딧이 최우수상을 수상했다. 렌딧이 굳이 이런 경연대회에 참여를 한 이유는 ‘P2P금융산업에서 기술력과 고도의 엔지니어링 파워가 얼마나 중요한 지’를 널리 알리고 싶기 때문이었다.매경핀테크어워드 수상 소식을 들은 후, 엔지니어링팀 렌딧맨들과최근 렌딧은 개발자 채용에 그 어느때보다도 열심이다. 많은 개발자들과 만나 P2P금융산업의 미래와 우리 회사가 하는 일에 대해 설명하고 좋은 개발자를 영입하기 위해 노력하고 있다. 그런데 생각보다 훨씬 더 개발자들에게 P2P금융기업이 어떤 일을 하고 있고, 왜 개발자가 도전할 만한 분야인지 알려져 있지 않다는 사실을 알게 되었다. 이번 글에서는 렌딧이 하는 일을 바탕으로 P2P금융회사에서 왜 고도의 소프트웨어 엔지니어링이 필수적으로 필요하고, 개발자 여러분이 어떤 일에 도전해 볼 수 있는지에 대해 설명해 보려고 한다. 우선 대출과 투자 등 모든 서비스가 기존 금융회사와 달리 온라인 상에서 이루어진다. 특히 렌딧이 집중하고 있는 개인신용 P2P금융의 경우, 대출 심사와 집행, 투자 모집과 운용 등 서비스 전 과정을 100% 온라인, 비대면 서비스로 구축하고 있는 디지털 금융 플랫폼이다.대출 서비스에서는 머신러닝 기반의 대출자 심사평가모델 개발이 핵심적이다. 렌딧이 자체 개발한 렌딧 개인신용평가시스템(Lendit Credit Scoring System)을 예로 들어 보겠다. 신용평가사에서 제공하는 250여가지의 금융 데이터를 순식간에 분석해 모든 대출 신청자마다 개인화 된 적정금리를 산출해 내는 시스템이다. P2P금융기업인 렌딧이 개발한 심사평가모델을 기존 금융권의 심사평가모델과 비교할 때 가장 큰 차이점은, 머신러닝 기법을 사용해 각종 금융 데이터의 최근 12개월 간 트렌드를 분석한다는 점. 이를 통해 보다 정교하게 개인의 신용을 평가해 낸다. 여기에 추가적으로 신용평가사에서 제공하는 사기정보공유(Fraud Bureau)데이터, 직장 신용정보, 상환 정보 등을 종합적으로 반영하고 있다. 최근에는 대출자가 제출하는 신분증 확인 과정에 머신러닝을 적용해 자동화해 나가기 시작했다. 투자 서비스에서는 실시간으로 분산투자 포트폴리오를 추천해 주는 알고리듬이 돌고 있다. 투자자가 투자할 금액을 입력하면 눈깜짝할 사이에 현재 투자 가능한 채권을 조합해 분산투자 포트폴리오를 추천해 주는 시스템이다. 포트폴리오에 조합된 모든 채권에 투자금을 일정한 비율로 고르게 나누어 분산투자할 수 있도록 추천해 주는 것이 특징이다. 렌딧이 개발한 분산투자 시스템은 투자자 1인이 수백~수천개의 채권에 분산하는 것과 동시에, 채권 1개도 평균 1,303명, 최대 3,814명(기준 2018년 6월30일 현재)이 나누어 리스크를 분산하도록 개발되어 있다. 이렇게 분산투자를 시스템적으로 활성화 시키고 있는 덕분에, 현재까지 렌딧의 모든 투자자가 하고 있는 분산투자의 총 누적 건수는 거의 800만 건에 육박하는 수준이다. 점점 더 많은 데이터가 축적되고 있기 때문에, 이러한 데이터를 바탕으로 고객에게 제공할 수 있는 서비스 아이디어도 하루 하루 쌓여 가고 있는 중이다.P2P금융산업이 가장 발전한 시장인 미국의 경우, 최대 규모인 렌딩클럽 한 회사가 미국 개인신용대출 시장 전체의 약 1.5%이상을 차지할만큼 금융 시장을 혁신해 나가고 있다. 렌딧 역시 지난 3년간 빅데이터 분석에 기반한 정교한 신용평가를 통해, 대출 고객의 이자를 총 100억원이 넘게 절약해 드리는 성과를 만들어 냈다. 그간 기존 금융회사들이 만들어 내지 못한 중금리 대출 시장을 스타트업인 렌딧이 활짝 열어낸 것이다.렌딧에서 우리 렌딧맨들과 함께 한국의 금융을 혁신하는 금융 플랫폼을 만들어 가실 엔지니어 여러분을 기다립니다. 관심있는 분은 주저없이 [email protected] 로 연락 주세요. 많은 엔지니어 여러분과 만나뵙고 싶습니다. 
조회수 4282

파이썬 코딩 컨벤션

스포카 개발팀 문성원입니다. 저희는 (익히 아시다시피) 서버를 개발하는데 파이썬(Python)을 사용하고 있는데, 오늘은 이러한 파이썬 코드를 작성할 때 기준이 되는 코딩 컨벤션(Coding Convention)에 대해서 알아보겠습니다.Coding Convention코딩 컨벤션이란 개념에 대해 생소하신 분들도 계실 테니 이를 먼저 알아보죠. 코딩 컨벤션은 프로그램 코드를 작성할 때 사용되는 일종의 기준입니다. 이를테면 들여쓰기(Indentation)는 공백으로 할거냐 탭으로 할거냐. 부터 var a = 3; 과 같은 코드에서 a와 =를 붙이느냐 마느냐라던지를 정해주는 것이죠. 알고 계시는 것처럼 이러한 차이는 특별히 실행 결과의 영향을 주지 않습니다. 다르게 이야기하자면 “실행 결과에 별 차이가 없는 선택지들”이기 때문에 일관성이 있는 기준을 두어 통일하자는 것이지요.그렇다면 왜 이런 선택지를 통일해야 할까요? 불행히도 우리가 작성한 코드는 많은 사람들이 보게 됩니다. 같이 일하는 동료, 이바지하고 있는 프로젝트의 리뷰어, 심지어 내일의 자기 자신까지도 말이죠. 그런데 이런 많은 사람들이 우리가 코드를 작성할 때 했던 선택지를 일일이 추론해서 이해하는 건 굉장히 피곤하고 짜증 나는 일입니다. 그래서 우리는 사소한 것부터 일종의 규칙을 정해서 이런 짜증과 불편함을 줄이려는 겁니다. 또한, 일반적으로 좋은 기준에는 훌륭한 프로그래머들의 좋은 습관이 배어있기 때문에 더 나은 품질의 코드를 작성하는 데에도 많은 도움이 됩니다.이런 코딩 컨벤션은 극단적으로 이야기하면 프로젝트마다 하나씩 존재한다고 볼 수도 있지만, 일반적으로 그 언어문화를 공유하는 공동체에서 인정하는 컨벤션은 대부분 통일되어 있습니다. 파이썬은 지금부터 살펴볼 PEP 8이 대표적입니다.PEP?PEP(Python Enhance Proposal)이란 이름대로 본디 파이썬을 개선하기 위한 개선 제안서를 뜻합니다. 이러한 제안서는 새로운 기능이나 구현을 제안하는 Standard Track, (구현을 포함하지 않는) 파이썬의 디자인 이슈나 일반적인 지침, 혹은 커뮤니티에의 정보를 제안하는 Informational, 그리고 파이썬 개발 과정의 개선을 제안하는 Process의 3가지로 구분할 수 있습니다. (좀 더 자세한 사항은 PEP에 대해 다루고 있는 PEP인 PEP 1을 참고하세요.) 파이썬은 언어의 컨벤션을 이러한 제안서(Process)로 나타내고 있는데 이것이 바로 PEP 8입니다.Laplace’s Box기본적으로 가이드라인이니만큼 규칙만 빽빽할 것 같지만, PEP 8는 서두부터 예외를 언급한 섹션이 있습니다.A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important.스타일 가이드는 일관성(consistency)에 관한 것입니다. 이 스타일 가이드의 일관성은 중요하죠. 하지만 프로젝트의 일관성은 더욱 중요하며, 하나의 모듈이나 함수의 일관성은 더더욱 중요합니다.But most importantly: know when to be inconsistent – sometimes the style guide just doesn’t apply. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don’t hesitate to ask!하지만 가장 중요한 건 언제 이것을 어길지 아는 것입니다. – 때때로 스타일 가이드는 적용되지 않습니다. 의심이 들 때는 여러분의 최선의 판단을 따르세요. 다른 예제를 보고 어느 게 제일 나은지 골라야 합니다. 질문을 주저하지 마세요!Two good reasons to break a particular rule:When applying the rule would make the code less readable, even for someone who is used to reading code that follows the rules.To be consistent with surrounding code that also breaks it (maybe for historic reasons) – although this is also an opportunity to clean up someone else’s mess (in true XP style).다음은 규칙들을 어기는 2가지 좋은 예외 사항입니다.규칙을 적용한 코드가 (규칙을 숙지한 사람 눈에도) 읽기 어려운 경우일관성을 지키려고 한 수정이 다른 규칙을 어기는 경우(아마도 역사적인 이유겠죠.)아직 아무것도 안나왔는데 좀 이르다구요?It’s all about common sense예외 규정을 보여주며 시작하는 PEP 8이지만 얼개는 그리 복잡하지도 않고 크게 난해하지도 않습니다. 여기서는 대표적인 몇 가지만 추려서 소개하겠습니다.Code lay-out들여쓰기는 공백 4칸을 권장합니다.한 줄은 최대 79자까지최상위(top-level) 함수와 클래스 정의는 2줄씩 띄어 씁니다.클래스 내의 메소드 정의는 1줄씩 띄어 씁니다.Whitespace in Expressions and Statements다음과 같은 곳의 불필요한 공백은 피합니다.대괄호([])와 소괄호(())안쉼표(,), 쌍점(:)과 쌍반점(;) 앞키워드 인자(keyword argument)와 인자의 기본값(default parameter value)의 = 는 붙여 씁니다.Comments코드와 모순되는 주석은 없느니만 못합니다. 항상 코드에 따라 갱신해야 합니다.불필요한 주석은 달지 마세요.한 줄 주석은 신중히 다세요.문서화 문자열(Docstring)에 대한 컨벤션은 PEP 257을 참고하세요.Naming Conventions변수명에서 _(밑줄)은 위치에 따라 다음과 같은 의미가 있습니다._single_leading_underscore: 내부적으로 사용되는 변수를 일컫습니다.single_trailing_underscore_: 파이썬 기본 키워드와 충돌을 피하려고 사용합니다.__double_leading_underscore: 클래스 속성으로 사용되면 그 이름을 변경합니다. (ex. FooBar에 정의된 __boo는 _FooBar__boo로 바뀝니다.)__double_leading_and_trailing_underscore__: 마술(magic)을 부리는 용도로 사용되거나 사용자가 조정할 수 있는 네임스페이스 안의 속성을 뜻합니다. 이런 이름을 새로 만들지 마시고 오직 문서대로만 사용하세요.소문자 L, 대문자 O, 대문자 I는 변수명으로 사용하지 마세요. 어떤 폰트에서는 가독성이 굉장히 안 좋습니다.모듈(Module) 명은 짧은 소문자로 구성되며 필요하다면 밑줄로 나눕니다.모듈은 파이썬 파일(.py)에 대응하기 때문에 파일 시스템의 영향을 받으니 주의하세요.C/C++ 확장 모듈은 밑줄로 시작합니다.클래스 명은 카멜케이스(CamelCase)로 작성합니다.내부적으로 쓰이면 밑줄을 앞에 붙입니다.예외(Exception)는 실제로 에러인 경우엔 “Error”를 뒤에 붙입니다.함수명은 소문자로 구성하되 필요하면 밑줄로 나눕니다.대소문자 혼용은 이미 흔하게 사용되는 부분에 대해서만 하위호환을 위해 허용합니다.인스턴스 메소드의 첫 번째 인자는 언제나 self입니다.클래스 메소드의 첫 번째 인자는 언제나 cls입니다.메소드명은 함수명과 같으나 비공개(non-public) 메소드, 혹은 변수면 밑줄을 앞에 붙입니다.서브 클래스(sub-class)의 이름충돌을 막기 위해서는 밑줄 2개를 앞에 붙입니다.상수(Constant)는 모듈 단위에서만 정의하며 모두 대문자에 필요하다면 밑줄로 나눕니다.Programming Recommendations코드는 될 수 있으면 어떤 구현(PyPy, Jython, IronPython등)에서도 불이익이 없게끔 작성되어야 합니다.None을 비교할때는 is나 is not만 사용합니다.클래스 기반의 예외를 사용하세요.모듈이나 패키지에 자기 도메인에 특화된(domain-specific)한 기반 예외 클래스(base exception class)를 빌트인(built-in)된 예외를 서브클래싱해 정의하는게 좋습니다. 이 때 클래스는 항상 문서화 문자열을 포함해야 합니다.class MessageError(Exception): """Base class for errors in the email package."""raise ValueError('message')가 (예전에 쓰이던) raise ValueError, 'message'보다 낫습니다.예외를 except:로 잡기보단 명확히 예외를 명시합니다.(ex. except ImportError:try: 블록의 코드는 필요한 것만 최소한으로 작성합니다.string 모듈보다는 string 메소드를 사용합니다. 메소드는 모듈보다 더 빠르고, 유니코드 문자열에 대해 같은 API를 공유합니다.접두사나 접미사를 검사할 때는 startswith()와 endwith()를 사용합니다.객체의 타입을 비교할 때는 isinstance()를 사용합니다.빈 시퀀스(문자열, 리스트(list), 튜플(tuple))는 조건문에서 거짓(false)입니다.불린형(boolean)의 값을 조건문에서 ==를 통해 비교하지 마세요.Give me a reason하지만 몇몇 규칙은 그 자체만으론 명확한 이유를 찾기 어려운 것도 있습니다. 가령 예를 들면 이런 규칙이 있습니다.More than one space around an assignment (or other) operator to align it with another.Yes:x = 1 y = 2 long_variable = 3No:x = 1 y = 2 long_variable = 3보통 저런 식으로 공백을 통해 =를 맞추는 건 보기에도 좋아 보입니다. 하지만 변수가 추가되는 경우에는 어떨까요. 변수가 추가 될때마다 공백을 유지하기 위해 불필요한 변경이 생깁니다. 이는 소스를 병합(merge)할 때 혼란을 일으키기 쉽습니다.언뜻 보면 잘 이해가 안 가는 규칙은 이런 것도 있습니다.Imports should usually be on separate lines, e.g.:Yes: import os import sys No: import sys, os굳이 한 줄씩 내려쓰면 길어지기만 하고 보기 안 좋지 않을까요? 하지만 이 역시 대부분의 변경 추적 도구가 행 기반임을 고려하면 그렇지 않습니다.#스포카 #개발 #파이썬 #개발자 #Python #컨벤션 #이벤트참여 #이벤트후기 #후기
조회수 2848

Retrofit2 로 전환

Android 와 NetworkAndroid 에서 Network 라이브러리들은 다양하지만 근 1년 사이에 주로 사용되는 라이브러리들이 점차적으로 적어지고 있습니다.오늘은 그 중에서 Retrofit 에 대해 이야기 하고자 합니다.토스랩의 Android Network Library1. Spring-Android, Retrofit 그리고 Retrofit2토스랩은 총 3개의 네트워크 라이브러리를 사용하였습니다. 초창기에는 AndroidAnnotations 에 연동되어 있는 Spring-Android 를 사용하였습니다. 하지만 다중 쓰레드 환경에서 동일한 Request 객체를 사용하면서 저사양 단말에서 문제로 두각되기 시작하였습니다.그래서 Retrofit 으로 2015년 중순쯤 전환을 하였습니다. 그러다 2016년 초 Retrofit2 가 정식 배포가 되면서 자연스럽게 Retrofit2 로의 전환이 대두되기 시작하였습니다. 전환의 이유는 내부의 네트워크 모듈에 대한 Refactoring 이었는데 그와 동시에 Retrofit2 로의 전환도 함께 진행되었습니다.2. 이슈들What the CALL기존의 Retrofit 은 200~399 에러에 대해서는 정상적인 Body 를 반환하고 400 이상의 경우에는 Typed Exception 형태로 로직을 진행하였습니다. 하지만 이정도로는 Response Status 나 Header 정보를 알기에는 추가적인 로직이 필요로 하였습니다. 물론 Success 케이스에도 마찬가지이긴 하였습니다.이는 Retrofit 의 기본적인 목적에 부합되지 않는다는 문제가 있었습니다. Retrofit 의 가장 기본적인 목적은 Okhttp 의 상위 구현체로써 쉽게 Request 와 Response 를 구현한다는 것입니다. 손쉬운 구현이 필요한 정보를 제외시킨다는 것은 별개의 문제이기 때문입니다.그래서 Retrofit2 에서는 Call 객체를 통해서 Request 와 Response 에 적용된 Header, StatusCode, Body 등을 직접 접근 할 수 있도록 인터페이스를 추가하였습니다.이 객체는 불변성을 가지고 있기 때문에 Getter 만이 존재하며 Request 에 필요한 정보는 다른 부분에서 적용되어야 함을 명시하셔야 합니다.Call 객체의 적용Call 객체를 적용하는 과정에서 2가지의 이슈가 있었습니다.Interface 의 모든 Return Value 를 Call 로 전환할 것Request Error 를 직접 핸들링 하도록 수정해야 함이 2가지 때문에 여러가지가 연쇄적으로 수정되어야 했습니다.먼저 수정과정을 설명하기 앞서 Jandi 앱의 Network 통신 전제조건에 대해서 설명해드리도록 하겠습니다.Jandi 앱은 모든 Network 통신은 Current Thread 에서 한다는 것을 전제로 합니다. 이는 MainThread 에서의 통신이 아니라 호출자의 Thread 를 따라간다는 것을 전제로 하고 있습니다. 또한 이를 위해 Reponse 반환, Error Handling, 세션 자동 갱신을 위해 Generic 으로 선언된 Facade 용도의 Wrapper Class 를 별도로 두고 있습니다.따라서 수정해야할 1,2 번을 위해 아래와 같은 수정을 하였습니다.Facade Class 내에서 성공여부를 직접 파악한다.성공시 Return Value 를 직접 반환할 수 있도록 한다.실패시 Status, Response 정보를 이용하여 throw Exception 을 한다. (세션 정보를 갱신 로직은 당연히 포함되어 있습니다.)그래서 아래와 같은 코드 형태가 되었습니다.Response response = apiExecutor.execute(); if (response.isSuccessful()) { RESULT object = response.body(); retryCnt = 0; return object; } else { // 400 이상 오류에 대해 처리 return handleException(apiExecutor, response, null); } Network 통신 과정에서의 Exception 이 나는 경우는 2가지 입니다.기기의 Network 자체가 끊겨 있거나 비정상인 경우Response 의 Parsing 과정에서 오류가 발생한 경우Annotation 의 변화Annotation 의 가장 큰 변화는 DELETE 였습니다. 기존의 Retrofit 에서는 DELETE 요청은 GET 방식으로 가능하였습니다. 즉 POST 처럼 Body 를 설정할 수 없게 되어 있었습니다. 따라서 DELETE 를 쓰기 위해서는 별도의 Custom HTTP Annotation 을 설정 할 적용하여야 했습니다.Retrofit2 에서는 이런 경우에 대비하기 위해 @HTTP 를 개방하였습니다. @HTTP(path = "{url}", method = "DELETE", hasBody = true) 와 같이 사용해야만 Custom HTTP Method 를 적용하실 수 있습니다.Jackson2-Converter 대응Jackson2-Converter 의 이슈는 최근에서야 알게 되었습니다. Jandi 앱은 그동안 Jackson 1.x 를 사용하였고 최근에서야 Jackson2 로 전환을 하였습니다.그 과정에서 Retrofit2 의 converter-jackson 라이브러리를 사용하려 하였으나 중대한 문제가 있었습니다.Retrofit2 에서 Reqeust Body 의 Serialize 는 메소드의 참조변수로 선언된 클래스만 지원하며 상속한 자녀클래스를 넣어도 부모 클래스의 결과만을 리턴 하는것이었습니다. (gson 과 여타 converter 에 대해는 해당 이슈에 대해 파악해보지 않았습니다).이를테면 아래와 같은 경우입니다.interface Api { @PUT("/profile") Call modifyProfile(@Body Profile profile); } public class Profile {} public class NameProfile extends Profile{ String name; } public class PhoneProfile extends Profile{ String phone; } // using case api.modifyProfile(new NameProfile("Steve")); 허나 아래와 같은 상황이 펼쳐집니다.// expect {"name":"Steve"} // actual {} 해당 문제는 Converter-Jackson 의 이슈이기 때문에 위와 같은 상황이 예상된다면 별도의 Converter.Factory 를 선언하여 사용하시기 바랍니다.OkHttpClient 생성 이슈Okhttp 에 여러가지 기능이 추가되었습니다. 그중 잔디가 사용 중인 목록입니다.okhttp-logging-interceptorauthenticatorCutome SSL이런 이유 때문에 OkHttpClient 를 직접 생성하여 사용 하고 있습니다.처음에는 OkHttpClient 를 모든 API 호출시 새로 생성하도록 하였습니다. 헌데 TestCode 가 200회가 넘어가면 File IO 를 너무 많이 사용했다는 오류가 계속적으로 발생하였습니다.이 오류가 단순히 File IO 가 많아서 라는 메세지 때문에 처음에는 Database 에 대한 오류인 줄 알고 Memory Cache 작업과 테스트코드 개선작업을 하였으나 정상 동작이 되지 않았습니다. (테스트 코드 1회에 평균 2번의 API 통신과 2회의 DB 처리를 합니다.)그 와중에 기존의 테스트 코드는 정상 동작하는 것을 보고 Retrofit2 작업을 진행한 branch 만의 문제임을 깨달았습니다.현재는 OkhttpClient.Builder 를 통해 생성한 1개의 OkhttpClient 만을 재사용하도록 변경하였습니다.Network Retry 시 동작 변경Retrofit2 는 Call 객체를 이용하여 동일한 정보로 재요청을 할 수 있도록 지원하고 있습니다. 하지만 이에 대한 제약이 하나 있습니다. 이미 Network IO 가 끝난 경우 Retrofit2 는 Call 객체를 복사하여 재사용할 것을 가이드 하고 있습니다. 그래서 재요청시 다음과 같이 코드를 작성하셔야 합니다.Call call = action0.call(); if (!call.isExecuted()) { return call.execute(); } else { return call.clone().execute(); } OkHttp3 의존성Okhttp 를 사용하는 타 라이브러리가 있다면 Okhttp3 의존성을 가지고 있기 때문에 이에 유념하셔야 합니다.3. 정리Retrofit1 -> Retrofit2 로 변경하는 과정에서 다양한 이슈를 발견하였습니다.Return Value 수정Exception 처리 강화Annotation 수정Request-Response Converter 수정OkhttpClient 재사용 정의재요청 처리에 대한 validation 추가OkHttp3 의존성Retrofit2 로 변경에 있어서 가장 큰 핵심은 Call 이라는 객체라고 할 수 있다는 것입니다.이 객체는 Request 에 대한 동작 제어(cancel, retry 등), Request-Response 의 독립성 보장, 그에 따라 각각의 정보에 대한 접근 등을 보장하게 됩니다.Retrofit2 는 그외에도 Okhttp3 와 다양한 플러그인 지원하고 있습니다. 요청-응답에 필요한 Body 의 변환툴 (Converter-xxx), EndPoint 에서 접근하는 Call 객체에 대한 다양한 툴 (CallAdapter-xxx)현재 Retrofit1 에서 잘 동작하고 있고 의도대로 흐름제어를 하고 있다면 Retrofit2 로 옮겨갈 이유는 없습니다. 하지만 변경을 하고자 한다면 이러한 영향도가 있을 것임을 공유해드렸습니다.참고하면 좋은 Slidehttps://speakerdeck.com/jakewharton/simple-http-with-retrofit-2-droidcon-nyc-2015Jake Wharton’ Retrofit2Presentation 영상#토스랩 #잔디 #JANDI #개발 #개발자 #인사이트 #경험공유
조회수 1240

스푼 라디오 오디오 랩 팀의 Jason을 만나보세요!

인상이 좋은 비결은.. 원래 이렇게 생겼어요 (찡긋)오디오 랩 팀의 막내, 알고 보니 세상 모든 매력을 덕지덕지 붙이고 다니는 Jason을 인터뷰해보았습니다.근데 대체 왜 이렇게 인상이 좋은 거예요? 출처: 알파카 월드 - 제이슨 닮은꼴"그냥 정말 원래 이렇게 생겼어요 하하. 웃는 상이예요. 사실 어릴 땐 눈이 좀 더 찢어지고(?) 올라가 있어서 좋은 인상이 아니었는데, 좋은 인상으로 변하더라고요..(나이 탓인가..) 웃는 게 습관이 되어버렸어요"인싸도 아싸도 아닌 '그럴싸'"인싸요? 아니에요 인싸. 그냥 저는 좀 알고 보면 반전도 많고 '모순덩어리' 일뿐이에요. 그래서 저를 표현하는 한 마디도 저는 '모순덩어리'라고 할래요. 예를 들면, 저는 해병대 출신인데 수영을 못하고요. 이성적인 것 같은데 또 되게 감성적이에요. 발라드를 되게 좋아하는데 제 노래방 18번은 '거꾸로 강을 거슬러 오르는 저 힘찬 연어들처럼'이에요. 사색하는 거 좋아하는데 또 가만히 있는 건 싫어요. 시간 아깝더라고요. (빵긋) 사내 제이슨 feat. 카이와 헤이든 듣고 싶은 당신의 스푼 라이프오디오 랩팀은 어떤 부서인가요?"오디오 랩팀은 스푼 라디오에서 오디오 방송 통신 기술을 연구하고 개발하는 부서입니다. 저희의 궁극적 목표는 세계 최고 오디오 기술 플랫폼이 되는 것이에요. 그리고 오디오 랩에서 제가 하고 있는 업무는 안드로이드 OS 클라이언트에 오디오 기술 개발하는 업무를 맡고 있어요. 오디오 랩팀에 막내이긴 한데.. 재간둥이 역할은 제가 맡고 있지 않아요 하하.. 저희 팀의 재간둥이 역할은 Ben님께서 하고 계십니다"스푼에 입사하기까지"제 입으로 말해도 되나요? 저는 수학을 좋아하진 않았는데, 잘했어요. 국어랑 사회 같은 문과계열 과목을 싫어했는데 이공계 쪽이 저와 적성에 맞더라고요. 수학 1등급 나왔는데 메가스터디 박 XX 선생님께 이 자리를 빌려 감사드립니다. 인강이 저를 만들어주셨어요.저의 원래 장래희망은 항공기 정비사였어요. 언제부터 비행기를 좋아했는지 모르겠지만 초등학교 때부터였던 것 같아요. 고3 때 진로를 정해야 하는데 항공정비과와 전자공학과와 고민을 했었어요. 그러다가 결국엔 전자 공학과 에 진학하게 되었고 자연스럽게 꿈 하고 멀어지게 되더라고요. 사실 항공 소프트웨어 쪽으로 일을 하게 될 줄 알았는데 다른 쪽으로 방향이 틀어지다 보니 어느덧 30대가 되어 있었어요. 사실 처음에 저는 스타트업에서 일하게 될 줄 몰랐어요. 이직을 준비하던 차에 제가 직접 스푼 라디오를 사용해보고, 기사도 읽게 되었고 Neil(대표)의 세바시 강연을 보고 이곳에서 일하고 싶다! 비전이 있다!라고 생각해서 오게 되었어요"내가 함께 일하고 싶은 사람서글서글한 사람을 좋아해요. 제가 그렇게 잘 못하는 편이라서요. 낯을 좀 많이 가리는데 저와는 다른 성향인 사람이라면 시너지 효과가 날 것 같아요파일럿 제이슨알고 싶은 Jason의 이야기해병대 출신부터 비행기 조종사까지"제가 안 그래 보이지만.. 사실 해병대 출신이에요. 해병대 왜 갔냐고 물어보신다면, 멋있어 보여서 가게 되었어요. 그게 전부예요. 복식 호흡하는 게 멋있어 보이더라고요. 원래 하고 싶은걸 다 하면서 살자라는 위주인지라, 꼭 무엇이든 하고 말거든요. 원래 꿈이 비행기 조종사였는데 꿈을 못 이루었으니 취미로도 해보자!라는 생각이 들어서 시작하게 되었어요. 한국에서도 할 수 있는데 제약이 너무 많아서 회사를 그만두고 미국에 갔어요. 여태 모아둔 돈 다 쓰고 왔어요. 4개월 정도 미국에서 하루 10시간씩 비행을 했었는데, 정말 행복했어요. 고등학교 때는 사실 실용음악도 준비했었어요. 아카펠라 중창단에 속해있었는데 2학년이 되고 이걸 진로로 결정하기엔 아니라고 판단이 들어서 그만두긴 했지만요. 그래서 대학교에 들어가고 밴드부에 들어가서 보컬을 맡았었어요. 저 점심시간에 혼자 코노가요. 같이 가기엔 부끄러워서.. 혼자 갑니다"유노윤호의 열정, 최강창민의 쿨함"제가 원래 자소서에 경청을 잘하는 사람이라고 적었는데 사실 가끔 듣는 것도 귀찮아요 하하.. 그리고 본인 이야기하는 것도 민폐라고 생각해서 잘하지 않는데 인터뷰하다 보니 엄청 많이 하게 되었네요. 근데 또 제가 남한테 지는 거 안 좋아해서 벤이랑 운동 누가 더 많이 하나 내기해서 요즘 매일 아침 출근 전에 수영 배우고 있고 화, 목은 영어학원을 다니면서 자기 계발을 하고 있어요. 목표가 없으면 안 되는 것 같아서 늘 목표를 일부러 세워요. 그래서 예전엔 사진도 배우러 다녔어요. 아 참! 수영을 배우다 보니 요즘 새로운 목표는 '라이프 가드'를 하고 싶어 졌어요. 이렇게 하고 싶은걸 하면서 열정적이게 살게 된 계기는 아마 아버지의 영향이 큰 것 같아요. 아버지가 매일 이렇게 말씀해주셨거든요"꿈을 꾸고 살아라, 돈은 따라온다! 반려견 '나무'의 아빠 Jason"저희 집 강아지 이름이 '나무'인데요. 식목일이 생일이라서 나무라고 지었어요. (나무 이야기할 때 눈빛이 초롱초롱해지면서 나무의 사진 보여주시던 제이슨) 나무는 귀엽고요. 비가 오나 눈이 오나 항상 저를 반겨줘요. 그래서 고마운 친구예요. 회사랑 집이 거리가 좀 멀어서 자취를 할까 생각했는데, 그러면 강아지가 혼자 집에 있어야 하니 안쓰러워서 하고 싶지 않았어요. 제가 없더라도 다른 가족들이 나무를 보살펴 줄 수 있어서 다행이라고 생각해요.팀원들이 Jason을 한마디로 표현한다면?Ian: JSON - "가볍고 빠르고 효과적이어서"*JSON [JavaScript Object Notation] :경량의 DATA교환 형식Ben: 알파카계의 알파치노 - "알파카처럼 온순한 외모의 소유자이지만 속엔 야망과 강한 카리스마를 가진 남자라서"
조회수 1906

CTE for postgresql and sqlalchemy

저희 서비스는 가게마다 웹에서 접속할 수 있는 어드민을 제공하는데, 프렌차이즈가 아닌 하나의 독립적인 가게들일 경우 정보를 가져와 나타내는 데는 굳이 CTE 를 쓸 필요가 없지만 프렌차이즈일 경우 본사와 지점들로 나누어져 있어서 본사와 지점들 정보를 다 가져오기 위해서 CTE 를 사용하게 되었습니다.그럼 postgresql 의 CTEReadme 에 나와 있는 예제와 sqlalchemy core 로 변환하는 것까지 살펴보겠습니다.CTE란?Common table expression 의 약자로 ‘공통 테이블 식’입니다.CTE 특징WITH절 같은 SELECT 문에서 효과적으로 테이블 식을 정의 할 수 있습니다.CTE는 VIEW의 사용방법과 비슷하지만, VIEW보다 편리합니다.VIEW와 달리 사전에 CTE를 정의할 필요가 없습니다.개체로 저장되지 않고, 쿼리 지속시간에만 존재합니다.CTE는 재귀 쿼리를 사용할 수 있습니다.재귀 CTE는 여러행을 반환 가능합니다.동일 문에서 결과 테이블을 여러번 참조 가능합니다.재귀 CTE 예제아래 예제는 ‘A’부서 하위에 있는 부서만 추출하는 예제입니다.일단 재귀 CTE를 이용한 쿼리를 사용하려면 ‘WITH RECURSIVE’ 키워드를 추가해야 합니다.Table ‘department’ 인접 리스트로 조직 구조를 나타냅니다.CREATE TABLE department ( id INTEGER PRIMARY KEY, -- department ID parent_department INTEGER REFERENCES department, -- upper department ID name TEXT -- department name ); INSERT INTO department (id, parent_department, "name") VALUES (0, NULL, 'ROOT'), (1, 0, 'A'), (2, 1, 'B'), (3, 2, 'C'), (4, 2, 'D'), (5, 0, 'E'), (6, 4, 'F'), (7, 5, 'G');부서 구조:ROOT-+->A-+->B-+->C | | | +->D-+->F +->E-+->G A의 하위 부서를 추출, 다음과 같은 재귀 쿼리를 사용할 수 있습니다.WITH RECURSIVE subdepartment AS ( -- non-recursive term SELECT * FROM department WHERE name = 'A' UNION ALL -- recursive term SELECT d.* FROM department AS d JOIN subdepartment AS sd ON (d.parent_department = sd.id) ) SELECT * FROM subdepartment ORDER BY name;위의 쿼리는 다음과 같이 설명할 수 있습니다.중간 테이블(Intermediate table), 작업 테이블(work table), 결과 테이블(result table)이 있습니다.초기화비재귀 구간을 실행 (SELECT * FROM department WHERE name = ‘A’)ResultTable = WorkTable = (‘A’) 결과 테이블과 작업 테이블에 결과를 배치합니다.IntermediateTable = () 중간 테이블을 비웁니다.재귀 쿼리 실행(SELECT d.* FROM WT AS d JOIN subdepartment AS sd ON d.parent_department = sd.id) 하위 부서와 작업 테이블을 바꾸고, 재귀 구간을 실행합니다.중간 테이블에 쿼리 결과를 할당합니다.결과 테이블 및 작업 테이블에 중간테이블 추가합니다.중간 테이블을 비웁니다.재귀가 끝났는지 확인2번 과정의 중간테이블이 비어 있으면 재귀의 실행이 종료되고, 결과 테이블은 반환됩니다.중간테이블이 비어 있지 않으면 다시 2번의 과정으로 돌아갑니다.“subdepartment”는 재귀 표현을 포함하고 있는 CTE입니다. 먼저 비재귀항이 평가되고, 다음 재귀항이 평가됩니다. 재귀항은 평가하고 처리하는 데이터가 없을 때까지 결과가 반복적으로 이전 결과에 추가됩니다. 끝으로 마지막 SELECT가 실행되고 데이터는 결과 집합에서 추출됩니다.CTE의 한계점SEARCH 및 CYCLE 절은 구현되지 않습니다.상호 재귀는 허용되지 않습니다.UNION ALL의 마지막 SELECT만 재귀 이름을 포함할 수 있습니다.재귀와 재귀스캔(RecursiveScan) 계획의 비용은 항상 0입니다sqlalchemy 로 변환sqlalchemy 에서 필요한 모듈들을 불러옵니다.from sqlalchemy import Table, Column, Text, Integer, MetaData, select metadata = MetaData() department 테이블을 정의합니다.department = Table('department', metadata, Column('id',Integer), Column('parent_department',Integer), Column('name',Text)) WITH 절부터 시작되는 CTE 부분의 비재귀항을 subdepartment로 만듭니다. 재귀 사용을 위해 .cte( recursive=True) 부분을 붙여줍니다.subdepartment = select([ department.c.id, department.c.parent_department, department.c.name]).where(department.c.name == 'A') \ .cte(recursive=True) department 와 subdepartment 에 각각 alias를 붙여줍니다.subd_alias = subdepartment.alias() department_alias = department.alias() CTE 부분의 재귀항과 비재귀 항을 union all 해주는 subdepartment를 만듭니다. (이 부분이 postgresql 예제 쿼리에서 봤던 WITH RECURSIVE subdepartment 전체를 나타내는 부분이라 할 수 있습니다.)subdepartment = subdepartment.union_all( select([ department_alias.c.id, department_alias.c.parent_department, department_alias.c.name]) \ .where(department_alias.c.parent_department == subd_alias.c.id)) 마지막으로 결과 쿼리를 출력하기 위한 statement를 만듭니다.statement = select([ subdepartment.c.id, subdepartment.c.parent_department, subdepartment.c.name]).order_by(subdepartment.c.name) 원문: CTEReadme참조: 공통 테이블 식 사용 ,공통 테이블 식을 사용하는 재귀 쿼리#스포카 #개발 #개발자 #서버개발 #개발팀 #꿀팁 #인사이트 #조언
조회수 2705

React + Decorator + HOC = Fantastic!!

React + Decorator + HOC = Fantastic!!지난 포스팅에서는 ES7의 Decorator 문법을 이용해 선언된 클래스와 그 프로퍼티들을 디자인 시간에 변경하는 법을 알아보았습니다. 그렇다면 리액트 컴포넌트와 Decorator가 만나면 어떤 시너지가 발생할까요?만약 ES7의 Decorator에 대해 모르신다면 지난 포스팅을 읽고 오시는 걸 권장합니다. 이 포스팅은 독자들이 Decorator에 대해 이미 알고 있다고 가정하고 작성됐습니다.Higher Order Component리액트 공식 문서를 보면 Higher Order Component(이하 HOC)를 다음과 같이 설명하고 있습니다.리액트 컴포넌트 로직을 재활용할 수 있는 고급 기법리액트에서 공식적으로 제공하는 API가 아니라 단순히 아키텍쳐이 설명으로는 HOC가 어떤 역할을 하는지 이해하기는 역부족이기 때문에 간단한 예제를 통해 HOC를 어떻게 작성하는지 알아보겠습니다.function withSay(WrappedComponent) {     return class extends React.Component {     say() {       return 'hello'     } render() {       return (                   {...this.props}           say={this.say} />       )     }   } } withSay 함수는 WrappedComponent를 인자로 받아 원하는 속성들을 결합해 새로운 컴포넌트를 반환합니다. 이렇게 만들어진 withSay 함수는 아래와 같이 사용 가능합니다.@withSay class withOutSay extends React.Component {     render() {     return (               {this.props.say()}           )   } } withOutSay 컴포넌트는 say 메소드를 가지고 있지 않습니다. 하지만 withSay 함수를 사용하니 say 메소드를 사용할 수 있게 됐습니다. 이처럼 컴포넌트를 인자로 받아 입맛에 맞게 바꾼 뒤 새로운 컴포넌트로 반환하는 기법을 HOC라고 부릅니다.그렇다면 HOC는 리액트에서 어떻게 사용을 해야 효율적일까요?Cross Cutting Concerns개발을 하다 보면 다음과 같은 상황에 직면하는 경우가 종종 있습니다.개발 전반에 걸쳐 반복해서 등장하는 로직그럼에도 불구하고 모듈화가 쉽지 않은 로직예를 들어 방명록 작성, 게시글 작성, 게시글 스크랩을 하는 컴포넌트들에서 유저 인증과 에러 처리의 과정이 필요하다고 했을 때 어떻게 코드를 디자인해야 할까요? 컴포넌트와 직접적으로 연관이 없는 기능들이 컴포넌트와의 결합이 너무 강해 쉽게 모듈화를 시키지 못합니다.그림 1. Cross Cutting Concerns의 예시이렇듯 코드 디자인적인 측면에서 공통적으로 발생하지만 쉽게 분리를 시키지 못하는 문제를 Cross Cutting Concerns라고 합니다. 이 문제를 끌어안고 가면 프로젝트의 코드는 쉽게 스파게티가 되고 나중에는 유지 보수를 하기 힘들어집니다.하지만 우리게에는 HOC와 Decorator가 있고 이를 이용해 이 문제를 쉽게 해결할 수 있습니다.유저 인증 문제를 HOC로 해결아래는 인증이 안된 유저에게 다른 페이지를 보여주는 코드입니다.class TeamChat extends React.Component {     constructor() {     super()     this.state = {       unAuthenticated: false     }   } componentWillMount() {     if (!this.props.user) {       this.setState({ unAuthenticated: true })     }   } render() {     if (this.state.unAuthenticated) {       return     }     return I'm TeamChat   } } 유저 인증을 전통적인 if-else 구문으로 구현했습니다. 당장 이 컴포넌트를 본다면 문제가 없어 보입니다. 어떻게 보면 정답처럼 보이기도 합니다. 하지만 유저 인증이 필요한 컴포넌트가 많아지면 상황이 달라집니다.100개의 컴포넌트에서 위와 같은 방식으로 유저 인증을 하고 있는데 유저 인증을 하는 로직이 변경된 상황을 생각해 봅시다. 100개의 컴포넌트 모두 유저 인증 코드를 바꿔야 하는 상황에 직면하게 됩니다. 전부 다 바꾸는 것도 일이지만 실수로 몇 개의 컴포넌트를 수정하지 않을 확률이 농후합니다. 당장에는 간단하지만 잠재적 위험을 안고 있는 위 코드는 아래와 같이 수정되어야 합니다.function mustToAuthenticated(WrappedComponent) {     return class extends React.Component {     constructor() {       super()       this.state = {         unAuthenticated: false       }      } componentWillMount() {       if (!this.props.user) {         this.setState({ unAuthenticated: true })       }     } render() {       if (this.state.unAuthenticated) {         return       }       return     }    } } HOC를 이용해 확장이 용이한 유저 인증 로직이 탄생했습니다!! 이렇게 만들어진 HOC는 아래와 같이 적용이 가능합니다.@mustToAuthenticated class TeamChat extends React.Component {     render() {     return I'm TeamChat   } } @mustToAuthenticated class UserChat extends React.Component {     render() {     return I'm UserChat   } } 기존의 코드와 비교했을 때 코드가 훨씬 간단해진 것을 확인할 수 있습니다. 비단 코드만 간단해진 것뿐만 아니라 아래와 같은 추가 효과를 기대할 수 있습니다.유저 인증 로직이 컴포넌트와 분리가 되어 자신이 맡은 역할에만 집중할 수 있습니다.유저 인증 로직이 바뀌어도 코드를 수정해야 할 곳은 하나의 컴포넌트뿐입니다.예시로 작성한 HOC는 최소한의 코드로만 작성된 예시입니다. 실제 제품에서 사용되기 위해서는 몇 가지 고려해야 할 사항이 있는데 이는 리액트 공식 문서를 참고해주세요.i18n 컴포넌트를 HOC로 작성채널 서비스는 한국어, 영어, 일본어를 지원하기 때문에 번역 기능이 필요했습니다. 초기에는 번역 서비스를 아래와 같이 구현했습니다.@connect(state => ({   locale: getLocale(state) }) class Channel extends React.Component {     render() {     const local = this.props.locale     const translate = TranslateService.get(locale)     return (               {translate.title}         {translate.description}           )   } } 처음에는 위와 같은 방식으로 번역 서비스를 구현하는 것이 괜찮았습니다. 하지만 번역을 제공해야 하는 컴포넌트가 많아지면 많아질수록 중복되는 코드가 많아지는 것을 보고 아래과 같이 HOC를 이용해 코드의 중복을 제거했습니다.function withTranslate(WrappedComponent) { @connect(state => ({     locale: getLocale(state)   }))   class DecoratedComponent extends React.Component {     render() {       const locale = this.props.locale       const translate = TranslateService.get(locale) return (                   {...this.props}           translate={translate} />       )    }   } } 이렇게 작성된 HOC는 아래와 같이 사용이 가능합니다.@withTranslate class Channel extends React.Component {     render() {     const translate = this.props.translate     return (               {translate.title}         {translate.description}           )   } } HOC의 작성 방법은 예시로 작성한 두 개의 HOC에서 크게 벗어나지 않습니다. 이를 응용해 자신의 프로젝트에 맞는 코드를 작성해보세요.중첩 가능한 HOCHOC는 여러 개를 중첩해서 사용할 수 있습니다.. 예를 들어 유저 인증과 i18n 서비스를 동시에 제공하고 싶을 때 두 HOC를 중첩해서 사용하면 됩니다.@mustToAuthenticated @withTranslate class Channel extends React.Component {     render() {     return (               {`Hello!! ${this.props.user.name}`         {translate.title}         {translate.description}           )   } } 마무리이상으로 리액트에서 HOC를 사용할 수 있는 상황과 작성 방법을 알아보았습니다. 본 포스팅에서 다루지는 않았지만 만능처럼 소개한 HOC에도 몇 가지 단점은 존재합니다.Component Unit Test를 할 때 문제가 있을 수 있습니다.HOC를 몇 개 중첩하면 디버깅이 힘들 수 있습니다.WrappedComponent에 직접적으로 ref를 달 수 없어 우회 방법을 사용해야 합니다.비동기 작업과 같이 사용하다 보면 예상치 못한 결과를 만날 수 있습니다.하지만 이러한 단점에도 불구하고 상속을 제공하지 않은 리액트에서 HOC는 많은 문제를 효율적으로 해결해주는 단비와 같은 존재입니다. 유명한 리액트 라이브러리들(react-redux, redux-form 등)은 이미 예전부터 HOC를 사용해 사용자들에게 편의를 제공해 왔습니다. 이러한 라이브러리들과 자신의 프로젝트가 직면하고 있는 문제에 맞는 HOC를 작성해 같이 사용한다면 우아하고 아름다운 설계에 한층 더 다가간 프로젝트를 발견할 수 있습니다.마지막으로 한 문장을 남기고 본 포스팅을 마치도록 하겠습니다.React + Decorator + HOC = Fantastic!!본 포스팅은 2017 리액트 서울에서 발표한 내용입니다. 발표 자료와 발표 영상을 확인해보세요.#조이코퍼레이션 #개발자 #개발팀 #인사이트 #경험공유 #일지

기업문화 엿볼 때, 더팀스

로그인

/