-
Notifications
You must be signed in to change notification settings - Fork 0
/
component---src-app-templates-post-template-post-layout-ui-tsx-content-file-path-posts-2019-06-26-front-end-endgame-review-md-9172982d7e93d50f60c3.js
2 lines (2 loc) · 36.3 KB
/
component---src-app-templates-post-template-post-layout-ui-tsx-content-file-path-posts-2019-06-26-front-end-endgame-review-md-9172982d7e93d50f60c3.js
1
2
"use strict";(self.webpackChunkkyoungah_dev_blog=self.webpackChunkkyoungah_dev_blog||[]).push([[385],{9239:function(e,l,n){n.r(l),n.d(l,{default:function(){return g}});var t=n(6540),a=n(8453);function r(e){const l=Object.assign({p:"p",h2:"h2",h3:"h3",ul:"ul",li:"li",ol:"ol"},(0,a.R)(),e.components);return t.createElement(t.Fragment,null,t.createElement(l.p,null,"시험이 저번주 일요일에 끝나서 이제야 후기를 적는다."),"\n",t.createElement(l.p,null,"친구가 어디서 봤는지 이런 컨퍼런스가 있다고 같이 가자며 GDG FRONT-ENDGAME 컨퍼런스 festa 링크를 공유해줬다. 컨퍼런스를 안간지 좀 되서 부지런하게 살 겸 오랜만에 가볼까 하며 컨퍼런스 소개글을 읽고 있는데 발표자에 'Velopert'님이 있는걸 보고 아 이건 꼭 가야겠다고 마음을 먹었다. 하필 날짜가 방송대 기말 시험 전날 이었는데 밤 새서 공부하지 뭐, 라는 심정으로 티켓 판매 알람도 맞춰놓고 티켓 판매 당일날 1시 딱 되자마자 예매 시도 및 성공했다."),"\n",t.createElement(l.p,null,"컨퍼런스는 시험 공부를 포기한 보람이 있을 만큼 좋았다. 세션들도 내용이 알차면서 재밌었고 꽤 자극이 되었다. 그리고 기말고사 결과도 공부를 안한 셈치고 생각보다 점수가 잘나왔으니 안갔으면 진짜 후회했을 것 같다."),"\n",t.createElement(l.h2,null,"세션 후기"),"\n",t.createElement(l.h3,null,"여러분이 앵귤러를 안해봤다면 살아갈 이유가 하나 더 있는 겁니다."),"\n",t.createElement(l.p,null,"PUBG에서 일하시는 분의 세션이었는데 회사 옆건물에 PUBG가 있어서 그런지 괜히 반가웠다 ㅎ. 주로 앵귤러에 대해서 발표하셨는데 그 중에서 리액트와 앵귤러의 철학이 꽤 인상깊었다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"React의 철학은 철저한 방목형"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"상태관리는 redux, mobx, 서버 통신은 fetch, axios, 그 외 Babel, webpack 등등.. React는 우리는 개발자로 바라보고 있다."),"\n",t.createElement(l.li,null,"setState는 React의 모든 것의 시작."),"\n",t.createElement(l.li,null,"동기화 하는 시점을 개발자에게 맡긴다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Angular의 철학은 '철저한 사육형'"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"NgZone, Change Detection 등... 앱 상태 변화가 일어날 것 같으면 앵귤러가 알아서 동기화 해준다."),"\n",t.createElement(l.li,null,"React vs Angular (or Vue)"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"상황에 맞춰 아무거나 골라 쓰면 된다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"아니면 사다리 타기 해라."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Angular 단점."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"처음 시작하기엔 진입장벽이 높다."),"\n",t.createElement(l.li,null,"알아야 될 것이 많다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Ex) template 문법, TypeScript, RxJS"),"\n"),"\n"),"\n",t.createElement(l.li,null,"제약사항이 많다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Angular 장점."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"제약사항이 많다는 것은 잘못된 길로 빠지는것을 방지한다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Ex) React는 폴더구조, 로직 구분 등이 다 다른 반면 Angular는 폴더 구성, 로직 구분 등이 공식 도큐먼트에 잘 써져 있다."),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"TypeScript"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"여러명의 개발자가 js로 개발할 경우 변수 타입 때문에 큰 혼란이 온다. TypeScript로 타입을 미리 정해주면 이러한 혼란을 줄일 수 있다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"RxJS"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Angular를 하려면 RxJS는 무조건 해야한다."),"\n",t.createElement(l.li,null,"데이터의 흐름을 한 곳에서 조작할 수 있다."),"\n",t.createElement(l.li,null,"앞으로 웹 애플리케이션은 점점 더 복잡해질 것. 서버에서 하고 있던 일도 프론트엔드로 가지고 오는 추세."),"\n",t.createElement(l.li,null,"비동기 스트림의 lodash"),"\n",t.createElement(l.li,null,"비동기 스트림으로 데이터 조작을 하고 싶을 때 Rxjs로 언제든 구현할 수 있다."),"\n",t.createElement(l.li,null,"Dependency Injection"),"\n"),"\n"),"\n"),"\n",t.createElement(l.h2,null,"UX빼면 시체, 프론트엔드."),"\n",t.createElement(l.p,null,"가끔씩 궁금한게 생겨 리서치를 할 때 종종 들어가던 블로그나 깃허브에서 많이 봤던 분이 발표하셨는데 맨날 깃허브 프로필 사진으로만 보다가 실제로 뵈니 신기했다.\nUX에 대해 발표하셨는데 신기했고 조금 더 UX에 신경을 써야겠다는 느낌이 들었다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"웹 기술은 사용자가 웹을 이용할 때 풍부한 정보를 빠르고 우아하게 제공하기 위해서 발전함."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"성능 최적화"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"초기 로딩 최적화","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Code minification -> 웹팩, 로더 등..."),"\n",t.createElement(l.li,null,"Code splitting"),"\n",t.createElement(l.li,null,"Tree shaking"),"\n",t.createElement(l.li,null,"Css splite"),"\n",t.createElement(l.li,null,"Gzip code"),"\n",t.createElement(l.li,null,"Chck lighthouse"),"\n",t.createElement(l.li,null,"Critical path"),"\n"),"\n"),"\n",t.createElement(l.li,null,"빠르다는 느낌 전달"),"\n",t.createElement(l.li,null,"부드러운 애니메이션","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Intersection Observer"),"\n",t.createElement(l.li,null,"requestAnimation"),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"예상 가능한 동작"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"스크롤 복원 (봤던 거 보여주기)","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"with session storage","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"페이지 이동 시 현재 scroll 위치를 session storage에 저장한 후 다시 이전 페이지로 되돌아 왔을 때 storage에 값을 꺼내서 그 위치로 스크롤을 이동시켜주면 된다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"Restore state"),"\n"),"\n"),"\n",t.createElement(l.li,null,"딤드 영역 닫힘"),"\n",t.createElement(l.li,null,"손에 쉽게 들어오는 인터렉션 영역"),"\n",t.createElement(l.li,null,"예상 가능한 인터렉션"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"SEO/SMO"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"검색 엔진 최적화"),"\n",t.createElement(l.li,null,"소셜 미디어 공유 최적화"),"\n",t.createElement(l.li,null,"어디까지 공유가 가능해야 하는가?","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"url 쿼리 params에 태그 같은 상태를 저장할 수 있다."),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"측정과 개선"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"트래킹"),"\n",t.createElement(l.li,null,"상황 A/B 테스트","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"with Cookie"),"\n",t.createElement(l.li,null,"Random"),"\n"),"\n"),"\n",t.createElement(l.li,null,"이탈률은 어떻게 줄일 수 있을까?","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Google Analytics"),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"1px도 무시 하지말자. UX 디자이너와의 충분한 협업이 필요하다."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"성능 최적화 같은건 프레임워크가 알아서 해주니까 UX에 신경을 좀 더 쓰는게 좋을 거 같다고 요즘 생각이 들기도 한다."),"\n"),"\n"),"\n",t.createElement(l.h2,null,"프론트엔드 개발에 FRP(Functional Reactive Programming) 녹여보기"),"\n",t.createElement(l.p,null,"무려 중학생분이 발표하셨다. 생소한 용어가 많고 조금 이해가 안가서 필수 키워드만 기록해두고 집에와서 리서치 하는 식으로 메모를 정리했다. 나는 중학생때 메이플 하느라 바빴는데 이 분은 이렇게 어려운 내용으로 발표까지 하시니 자괴감도 조금 들었다 ㅎ..."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Imperative"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"명령형 프로그래밍."),"\n",t.createElement(l.li,null,"프로그램이 어떻게 동작하는지 정의한다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Declarative"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"선언형 프로그래밍."),"\n",t.createElement(l.li,null,"이게 무엇인지 선언한다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"함수형 프로그래밍"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"변화가 없다."),"\n",t.createElement(l.li,null,"사이드 이팩트가 없다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Ex) 사이드 이팩트: 함수를 실행했더니 외부 변수, 상태값이 변경되는 것."),"\n"),"\n"),"\n",t.createElement(l.li,null,"이 둘이 없으므로 코드 읽기가 편하다. 모든 수학적 지식을 코드에 갖다 쓸 수 있다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Reactive Programming"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"비동기적 데이터 흐름을 처리하는 프로그래밍.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"낮은 결합도 이득을 얻을 수 있다."),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"FRP = FP + RP"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"엄청난 코드 재사용성."),"\n",t.createElement(l.li,null,"코드들간의 결합도가 낮아져서 사이드 이팩트 일어날 확률 없음."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"순수 함수"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"사이드 이팩트가 없다."),"\n",t.createElement(l.li,null,"Referential transparency (참조 투명성)을 띈다."),"\n"),"\n"),"\n"),"\n",t.createElement(l.h2,null,"문과생의 커리어 프런트엔드로 refactoring하기"),"\n",t.createElement(l.p,null,"아는 동생이 비전공으로 웹디자이너를 하고 있는데 코딩에도 관심을 보여서 들었다가 얘기해주면 좋을 것 같다 싶어 메모하려고 노트북을 켰는데 어려운 얘기가 아니니 편하게 들어달라는 발표자분의 얘기에 노트북을 덮어서 딱히 메모해놓은 것은 없다."),"\n",t.createElement(l.p,null,"어떻게 개발자가 되어 어떤 회사에서 어떤 사수를 거치고 현재까지 오게 되었는지에 대한 발표자분의 개발 인생 이야기였는데 발표자분이 발표를 너무 재밌게 해주셔서 발표 시간 내내 웃으면서 들었다. 나도 이렇게 재미난 말솜씨를 가진 사람이 되고 싶다."),"\n",t.createElement(l.h2,null,"프론트엔드 개발 끝장내기(endgame) feat. Angular"),"\n",t.createElement(l.p,null,"발표자 분이 React로 프론트 개발을 하시면서 Angular를 사랑하시는 특이한(?) 분이셨다. Angular의 기술적인 내용을 발표해주셨는데 본인이 좋아하는 프레임워크가 어떻게 돌아가는지 잘 알고 있는게 멋있었고 그냥 대충 갖다쓰기만 하던 내모습이 부끄럽기도 했다. 예전에 Angular에 발만 담궜다가 뺀 적이 있었는데 그 떄 당시 모듈 컴포넌트니 모듈 서비스니 등등 구조가 너무 복잡해서 어렵다는 생각에 다시 쉽사리 손을 못대고 있었다. 기회가 되면 Angular도 다시 공부해보고 싶은데 당장 쓸 일이 없어서 먼 나중의 일이 될것 같다 ㅎ..."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Angular 바인딩은 어떻게 동작하나?"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Change Detection: 데이터의 변경을 감지하고 이를 뷰에 반영하는 메커니즘.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Angular는 이를 통해 데이터 변경을 감지하고 적절한 시점에 자동으로 뷰의 상태를 반영한다."),"\n",t.createElement(l.li,null,"Change Detection이 트리거되면 Angular는 위에서부터 아래로 모든 컴포넌트 트리를 순회한다."),"\n",t.createElement(l.li,null,"Output 바인딩 작업은 CD와 별개로 수행되어 CD동안 자식 컴포넌트가 부모 컴포넌트의 데이터를 변경하는 일이 없도록 강제한다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"개발 모드에서는 자식 컴포넌트가 부모 컴포넌트 값을 바꾸는지 확인하기 위해 두번 돈다"),"\n"),"\n"),"\n",t.createElement(l.li,null,"언제 Change Detection을 수행하는가?","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"zone.js: JS VM이 둘러쌓인 여려 환경에서 비동기 코드를 포함한 여러 테스크를 추적할 수 있는 실행 컨텍스트"),"\n",t.createElement(l.li,null,"앵귤러는 이 zone.js로 전체 애플리케이션을 감싸서 비동기 코드를 추적한다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"zone.js가 없어도 Angular는 작동하나 개발자가 수동으로 Change Detection을 트리거 해줘야 할것이다."),"\n",t.createElement(l.li,null,"모든 Web API를 몽키패치 하여 ZONE을 제공한다. 이것으로 각종 비동기 이벤트가 언제 끝나는 지 추적할 수 있다."),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"React와 Vue 에도 Change Detection이 있다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"리액트와 Vue는 개발자가 직접 알린다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"리액트는 setState를 통해서 변경을 알린다."),"\n",t.createElement(l.li,null,"Vue는 setter가 wrapping된 데이터를 변경해서 알린다. -> proxy API."),"\n"),"\n"),"\n",t.createElement(l.li,null,"앵귤러는 프레임워크가 자동으로 알아챈다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"적절힌 사점에 데이터의 이전값과 다음 값을 비교하여 업데이트 한다."),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Rx.js"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Observable을 이용하여 비동기, 이벤트 기반의 프로그램을 작성하는 라이브러리."),"\n",t.createElement(l.li,null,"RxJs의 연산자는 순수함수."),"\n",t.createElement(l.li,null,"여러 연산자를 합성하여 Observable의 흐름을 제어함."),"\n",t.createElement(l.li,null,"Angular는 내부 로직 전반에 RxJs를 활용한다."),"\n"),"\n"),"\n"),"\n",t.createElement(l.h2,null,"프로그래머로서의 성장을 도왔던 태도들"),"\n",t.createElement(l.p,null,"기술적인 이야기는 아니었지만 꽤 유익한 발표였다. 내가 평소에 생각하고 있던 것과 비슷해서 좀 자화자찬 하기도 했고 내가 잘못 행동하고 있구나 싶은 내용도 있어 반성도 했다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"프로그래머는, 그리고 오직 프로그래머만이 특별하지는 않다."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"혼자서 프로그래밍 만으로 만들 수 있는 임팩트의 크기는 생각보다 크지 않다."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"다른 직군들에게 일반적으로 필요한 자질 대부분이 프로그래머에게도 똑같이 요구된다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"팀워크."),"\n",t.createElement(l.li,null,"친절한 배려."),"\n",t.createElement(l.li,null,"글과 말을 이용해 생각을 정돈, 표현, 설득하는 능력"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"새로운 기술을 익힐 때, 이론을 파는것도, 이론을 아예 보지 않는것도 최선은 아니다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"이론적인 배경 공부와 그렇게 쌓은 지식을 활용하는 실습, 두 상태를 빠르게 오가기."),"\n",t.createElement(l.li,null,"배운 이론을 이용해 무언가를 구현했을 때, 결과물이 동작하는 상태여야 한다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"짧은 주기의 반복을 통한 빠른 피드백을 얻기 위해..."),"\n",t.createElement(l.li,null,"돌아올 수 있는 체크포인트를 만들기 위해..."),"\n",t.createElement(l.li,null,"동작한다?","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"MVP: 가치를 전달할 수 있는 가장 단순한 형태의 제품","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"MVP를 잘 설정하려면…","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"MVC를 예로 들어","\n",t.createElement(l.ol,null,"\n",t.createElement(l.li,null,"하드코딩 된 데이터를 읽기만 가능한 단계"),"\n",t.createElement(l.li,null,"데이터의 추가, 삭제, 수정을 구현하는 단계"),"\n",t.createElement(l.li,null,"인증 로직을 추가하는 단계"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"만들면서 배우자."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"어떤 프로그램을 짤지 생각하면서 문서를 읽고, 그 프로그램을 작성할 수 있겠다는 생각이 들 때 바로 코드를 짜기 시작하라."),"\n",t.createElement(l.li,null,"어떤 프로그램을 만들어야 될지 생각이 들지 않으면 이거를 진짜 배워야 될지 다시 생각해보자."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"사람들은 의도적으로, 때로는 의도치 않게 틀린 말을 많이 한다."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"배움의 과정에서 사람들의 틀린 말에 덜 휘둘리기 위해선 어떻게 해야 할까?"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"급할수록 돌아가기.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"쉽게 풀어서 설명해주는 블로그 글, 유튜브 영상 등…","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"저자의 재해석과 무엇을 말하고 무엇을 말하지 않을지에 대한 결정이 들어간다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"재해석의 단계가 깊어질수록 가장 사실에 가까운 정보로부터 멀어진다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"무언가 배울 때 가장 근원이 되는 정보를 직접 찾아보는 습관.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"소스코드, 언어, 라이브러리 공식 문서, 어떤 개념을 처음으로 주장한 이의 논문, 글 등…"),"\n"),"\n"),"\n",t.createElement(l.li,null,"사람을 믿어야 할 상황 없애기.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"자동화할 수 있는 검증의 책무는 사람이 아닌 기계에게 맡긴다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"자동화된 회귀 테스트가 검증하게 하기"),"\n"),"\n"),"\n",t.createElement(l.li,null,"문서에 적힌 이 함수를 이런 파라미터가 받습니다 라는 정보를 믿는 대신 정말 그런지 타입 체커가 자동으로 검사할 수 있게..."),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"더 견고한 프로그램을 위해서 스스로 검증하지 않은 정보를 함부로 믿지 말고 다른 프로그래머와 사용자를 올바르게 의심하며 최선을 바라되 최악을 대비하자."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"관심사를 공유하는 열정적인 동료가 되는 것이 중요하다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"내가 원하는 동료를 생각해보자."),"\n",t.createElement(l.li,null,"남들에게 바로 그런 동료가 되기 위해서 내가 할 수 있는 일을 생각해보자.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"블로깅."),"\n",t.createElement(l.li,null,"오픈소스 PR 작성 등."),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"새로 나오는 정보를 절대로 놓치지 않겠다고 개발에 관련된 모든 페이스북 그룹에 가입하고 뉴스레터를 받아보는 것은 불가능할 뿐만 아니라 비효율적인 전략이다."),"\n"),"\n"),"\n",t.createElement(l.h2,null,"리액트 꽃길만 걷기"),"\n",t.createElement(l.p,null,"기다리고 기다리던 Velopert님의 발표였다. 실무에 도움이 되는 알찬 내용들로 이루어진 발표였고 나 역시 React로 프론트 개발을 하고 있어서 그런지 공감가는 부분도 많았고 막히는 부분없이 재미있게 들을 수 있었다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"컴포넌트 스타일링."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"자주 쓰이는 방법은 컴포넌트 폴더에 js와 관련 css 파일을 같이 생성 하는 것."),"\n",t.createElement(l.li,null,"기존 프로젝트에 React를 도입할 땐 css.module 괜찮음."),"\n",t.createElement(l.li,null,"styled-Component.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"충분히 안정적이고 편함."),"\n",t.createElement(l.li,null,"기존에 하고 있던 프로젝트가 있으면 기존 컴포넌트 까지 styled-component로 리팩토링 하는 것은 비추천."),"\n"),"\n"),"\n",t.createElement(l.li,null,"Boostrap, 시멘틱 ui 같은 ui 프레임워크들은 필수 요소가 아님.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"내부 직원들이 쓰는 페이지나 인력이 적고 빨리 서비스를 구축해야할 때를 제외하고는 비추천."),"\n",t.createElement(l.li,null,"매번 UI 프레임워크 문서를 보면서 작업해야함."),"\n",t.createElement(l.li,null,"스타일 커스터마이징 까다로움."),"\n",t.createElement(l.li,null,"사용되지 않는 기능들이 수두룩함."),"\n",t.createElement(l.li,null,"직접 개발한 ui와 ui 프레임워크 디자인과 어울리지 않으면 상당히 못생김."),"\n",t.createElement(l.li,null,"걷어내야 할 때 힘듬."),"\n",t.createElement(l.li,null,"직접 작성하는 것 어렵지 않음."),"\n",t.createElement(l.li,null,"꼭 사용해야 한다면 Tree Shaking 지원 여부 확인하자."),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"함수형 컴포넌트로 작성하자."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"16.8 이전에는 class 컴포넌트를 사용함.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"setState, lifeCycle Api 등…"),"\n"),"\n"),"\n",t.createElement(l.li,null,"16.8 이후에는 hooks 등장으로 state 관리, lifecycle api 비슷한 기능들을 사용할 수 있다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"반복되는 로직들은 Custom Hooks로 만들어서 쓸 수 있음 -> HOC 사용 필요 없음."),"\n"),"\n"),"\n",t.createElement(l.li,null,"이제 클래스형 컴포넌트를 쓸 일이 없다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Context API랑 Hooks가 있는데 Redux/MobX를 써야하나?"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"단순한 글로벌 상태관리를 원하거나 프로젝트의 규모가 작다면 Redux, Mobx를 사용할 필요가 없다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"대신 미들웨어, 리덕스 개발자 도구, 유틸 함수들을 포기해야 한다."),"\n",t.createElement(l.li,null,"그렇다고 이미 리덕스를 도입한 프로젝트에서 리덕스를 걷어낼 필요는 없다."),"\n"),"\n"),"\n",t.createElement(l.li,null,"MobX는 생각보다 재미있는 프로젝트니 한번 써보자.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"불변성 신경 안씀."),"\n",t.createElement(l.li,null,"이것 저것 변하는게 많으니 쓸려면 1 ~ 2달 뒤에 써보자."),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"어떤 상태를 리덕스로 관리해야 할까?"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"상태를 다른 컴포넌트와 공유 할 때."),"\n",t.createElement(l.li,null,"다른 컴포넌트에서 해당 값 바꿀 때."),"\n",t.createElement(l.li,null,"컴포넌트 엄청 깊숙한 곳에서 상태 필요."),"\n",t.createElement(l.li,null,"서버사이드 렌더링시 데이터 재사용 필요."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"컨테이너 안에 꼭 여러개의 컴포넌트를 사용할 필요가 없다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Presentational / Contianer.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Container.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"상태 관리 컴포넌트."),"\n"),"\n"),"\n",t.createElement(l.li,null,"Presentational 컴포넌트.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"UI만 출력해주는 컴포넌트."),"\n"),"\n"),"\n",t.createElement(l.li,null,"이 패턴을 꼭 따를 필요가 없다.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"여러 컴포넌트들을 하나로 묶으면 코드가 길어져서 유지보수가 길어진다."),"\n"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"reudcer 작정시 switch 말고 handler로 이루어진 key-value 객체를 사용하자."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"호불호 갈릴 수 있음."),"\n",t.createElement(l.li,null,"직접 만들어서 쓰거나, redux-actions, redux-act, typesafe-actions 라이브러리 사용."),"\n",t.createElement(l.li,null,"기존에 불편하다고 느끼는게 있으면 해결방안이 있는지 찾아보고 더 편해질수 있는 방법을 항상 고민하자."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"상태는 너무 깊숙하지 않게."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"상태가 한눈에 들어오지 않음."),"\n",t.createElement(l.li,null,"상태가 깊어진다면 Immer.js를 사용하자."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"imuttable.js?"),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"Typescript 지원 구림."),"\n",t.createElement(l.li,null,"걷어내는데 힘듬."),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Ducks 패턴."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"하나의 파일에 관련 action, reducer 등 관리 하는 것.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"편함."),"\n",t.createElement(l.li,null,"action이 많아질 것 같으면 분리하자."),"\n"),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.p,null,"-배열 업데이트 시 Keys-by-id 패턴 사용 추천."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Loadsh, rambda 라이브러리."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"데이터 요청 상태 어떻게 관리할까?"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"서버사이드렌더링이 아니라면 redux, mobx가 아닌 hooks로 관리하자."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"서버사이드 렌더링은 꼭 필요하다."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"Next.js 사용하면 시간을 많이 아낄 수 있으나 제약이 있다."),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"React-Router 컴포넌트를 사용해도 되나 SSR을 직접 해야 한다."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"직접 구현하면 Hell Gate 생성.","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"올바른 가이드가 있으면 해볼만도 함."),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.li,null,"\n",t.createElement(l.p,null,"타입스크립트 도입과 테스트 도입은 일찍하자."),"\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"지금 도입하기엔 프로젝트가 너무 크면 점진적으로 적용해보자","\n",t.createElement(l.ul,null,"\n",t.createElement(l.li,null,"새로 만드는 컴포넌트부터 적용, 나머지 기능을 어쩌다 리팩토링 하게 될 때 적용"),"\n"),"\n"),"\n"),"\n"),"\n"),"\n",t.createElement(l.h2,null,"마무리"),"\n",t.createElement(l.p,null,"나보다 날고 기는 분들이 많다는 사실을 또 한번 느꼈다. 열심히 공부하고 일해야겠다."),"\n",t.createElement(l.p,null,"마지막 QNA 시간에 Velopert님이 답변해주신 질문 사실 내가 쓴거다 ㅎ... 그냥 씹히겠지 싶어서 진담 반, 농담 반을 담아 익명으로 적었는데 Velopert님 이 답변해주셔서 기뻤다. 다른 분들도 답변해 주셨는데 엄청 도움이 되었다. 뭔가 계속 마음속에 프론트엔드 개발로는 오랫동안 개발자를 못해먹을거 같아서 보험으로 백앤드를 배워놓거나 대학원을 가서 딥러닝을 전공해야하나 라는 고민이 작년부터 계속 들었는데 덕분에 이 쓸데없는 고민을 좀 덜어낼 수 있었다. 질문에는 보험이라고 적었지만 다행히 백앤드는 예전부터 계속 관심 있어서 틈틈히 공부 및 토이 프로젝트를 진행할 예정이고 딥러닝쪽은 당분간은 쿨하게 포기하기로 했다. 내가 배우고 싶어서 배우는 것도 아니고 솔직히 아직까지는 크게 관심이 가지는 않는다. 다음 학기에 인공지능 수업이 있는데 그때 들어보고 재밌다 싶으면 관심을 갖기로 하고 당분간은 머릿속에서 지우자."),"\n",t.createElement(l.p,null,"그리고 겁이 좀 나긴 하지만 언젠가 나도 멀지 않은 미래에 사람들 앞에 서서 내가 배우고 느꼈던 것을 발표해보고 싶다."))}var u=function(e){void 0===e&&(e={});const{wrapper:l}=Object.assign({},(0,a.R)(),e.components);return l?t.createElement(l,e,t.createElement(r,e)):r(e)},c=n(2877),m=n(7736),i=n(407),E=n(7735),o=n(685),s=n(2248),p=n(8066),d=n(4848);function h(e){var l,n;let{data:t,children:r}=e;const{date:u,tags:h,title:g}=null!==(l=null==t||null===(n=t.mdx)||void 0===n?void 0:n.frontmatter)&&void 0!==l?l:{};return(0,d.jsx)(m.i,{children:(0,d.jsxs)(c.m,{className:p.q,children:[(0,d.jsx)(s.l,{className:p.V,title:g}),(0,d.jsx)(E.l,{date:u}),(0,d.jsx)(o.I,{tags:h}),(0,d.jsx)(i.E,{children:(0,d.jsx)(a.x,{children:r})})]})})}function g(e){return t.createElement(h,e,t.createElement(u,e))}},407:function(e,l,n){n.d(l,{E:function(){return u}});var t=n(4164),a="post-layout-content-module--post-layout-content-root--01754",r=n(4848);function u(e){let{children:l,className:n,...u}=e;return(0,r.jsx)("div",{className:(0,t.$)(a,n),...u,children:l})}},7735:function(e,l,n){n.d(l,{l:function(){return u}});var t=n(4164),a="post-layout-date-module--post-layout-date-root--f34d1",r=n(4848);function u(e){let{className:l,date:n,...u}=e;return(0,r.jsx)("span",{className:(0,t.$)(a,l),...u,children:n})}},685:function(e,l,n){n.d(l,{I:function(){return c}});var t=n(9143),a=n(4194),r="post-layout-module--post-layout-tags--837df",u=n(4848);function c(e){let{tags:l}=e;return(0,u.jsx)(t.Y,{className:r,children:l.map((e=>(0,u.jsx)(a.Link,{to:"/tags/"+e,children:(0,u.jsx)(t.Y.Tag,{tag:e})},e)))})}},2248:function(e,l,n){n.d(l,{l:function(){return u}});var t=n(4164),a="post-layout-title-module--post-layout-title-root--88374",r=n(4848);function u(e){let{className:l,title:n,...u}=e;return(0,r.jsx)("h1",{className:(0,t.$)(a,l),...u,children:n})}},9143:function(e,l,n){n.d(l,{Y:function(){return r}});var t=n(4164),a=n(4848);const r=Object.assign((function(e){let{children:l,className:n,...r}=e;return(0,a.jsx)("div",{className:(0,t.$)("tags-module--tags-root--e3461",n),...r,children:l})}),{Tag:function(e){let{className:l,tag:n,...r}=e;return(0,a.jsx)("span",{className:(0,t.$)("tag-module--tag-root--aae01",l),...r,children:n})}})},2877:function(e,l,n){n.d(l,{m:function(){return u}});var t=n(4164),a="container-module--container-root--3b208",r=n(4848);function u(e){let{children:l,className:n,...u}=e;return(0,r.jsx)("div",{className:(0,t.$)(a,n),...u,children:l})}},2629:function(e,l,n){n.d(l,{$:function(){return u}});var t=n(4164),a="basic-layout-module--basic-layout-root--a11e0",r=n(4848);function u(e){let{children:l,className:n,...u}=e;return(0,r.jsx)("div",{className:(0,t.$)(a,n),...u,children:l})}},7736:function(e,l,n){n.d(l,{i:function(){return x}});var t=n(4194),a=n(4164),r="header-module--about--32ac9",u="header-module--header-logo--5bbdc",c="header-module--header-navigation--24bcb",m="header-module--header-navigation-item--ba248",i="header-module--header-navigation-item-link--d6da9",E="header-module--header-navigation-list--3815c",o="header-module--header-root--01ceb",s="header-module--tags--eb332",p=n(4848);function d(){return(0,p.jsxs)("header",{className:o,children:[(0,p.jsx)(t.Link,{to:"/",children:(0,p.jsx)("img",{src:"/images/logo.png",srcSet:"/images/logo-small.png 200w, /images/logo.png 300w",sizes:"(max-width: 360px) 200px, 300px",alt:"dev.kyoungah.me",className:u})}),(0,p.jsx)("nav",{className:c,children:(0,p.jsxs)("ul",{className:E,children:[(0,p.jsx)("li",{className:m,children:(0,p.jsx)(t.Link,{to:"/tags",children:(0,p.jsx)("span",{"aria-label":"tags",className:(0,a.$)(i,s)})})}),(0,p.jsx)("li",{className:m,children:(0,p.jsx)("a",{href:"/about",rel:"noopener",target:"_blank",children:(0,p.jsx)("span",{"aria-label":"about",className:(0,a.$)(i,r)})})})]})})]})}var h="footer-module--footer-root--795ff";function g(){return(0,p.jsxs)("footer",{className:h,children:[(0,p.jsx)("span",{children:"Powered by Gatsby, Hosted by GitHub Pages."}),(0,p.jsxs)("span",{children:["©",(0,p.jsx)("a",{href:"https://github.com/partykyoung",rel:"noreferrer",target:"_blank",children:"KyoungAh"}),", All rights reserved."]})]})}var f=n(2629);function x(e){let{children:l}=e;return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(d,{}),(0,p.jsx)(f.$,{children:l}),(0,p.jsx)(g,{})]})}},8066:function(e,l,n){n.d(l,{V:function(){return a},q:function(){return t}});var t="post-layout-module--post-layout-container--f40b5",a="post-layout-module--post-layout-title--1c575"},8453:function(e,l,n){n.d(l,{R:function(){return u},x:function(){return c}});var t=n(6540);const a={},r=t.createContext(a);function u(e){const l=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(l):{...l,...e}}),[l,e])}function c(e){let l;return l=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:u(e.components),t.createElement(r.Provider,{value:l},e.children)}},4164:function(e,l,n){function t(e){var l,n,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e)){var r=e.length;for(l=0;l<r;l++)e[l]&&(n=t(e[l]))&&(a&&(a+=" "),a+=n)}else for(n in e)e[n]&&(a&&(a+=" "),a+=n);return a}function a(){for(var e,l,n=0,a="",r=arguments.length;n<r;n++)(e=arguments[n])&&(l=t(e))&&(a&&(a+=" "),a+=l);return a}n.d(l,{$:function(){return a}})}}]);
//# sourceMappingURL=component---src-app-templates-post-template-post-layout-ui-tsx-content-file-path-posts-2019-06-26-front-end-endgame-review-md-9172982d7e93d50f60c3.js.map