
프론트엔드
MobX
React의 상태 관리를 전역적으로 쉽게 관리할 수 있게 해주는 라이브러리
StackOverflow 질문 수: 1898
Github Stars : ★ 27805
사용 기업

왓챠

메쉬코리아

야놀자

우아한형제들

네이버

직방

번개장터

아이오크롭스

윙잇

아이디어스

메타몰프

카카오페이

SK플래닛

엔터플

프리윌린

카카오

지바이크

매드업
더 보기
인프런
React Form 컴포넌트 개발기
인트로안녕하세요 인프랩 프론트엔드 개발자 라비입니다:)온라인 강의 플랫폼 인프런을 서비스하고 있는 저희는 올해 초 채용 서비스인 랠릿을 런칭했는데요.Vanilla JS로 개발한 인프런과 달리 React를 사용하여 웹 페이지를 개발하면서, 특히 이력서라는 특성상 복잡한 폼을 다루면서 렌더링 성능 이슈 등 다양한 문제에 직면했고, 이를 해결하기 위한 다양한 고민 과정을 정리하여 글로 공유하려고 합니다.랠릿에는 한 페이지에 최대 700여개의 인풋창이 렌더링되는 개인 프로필 페이지와 지원서 작성하기 페이지가 존재합니다. 구직자가 이력서를 작성할 때 필요로 하는 최대한 다양한 유형의 정보를 한 페이지에서 입력하고 관리할 수 있도록 하기 위함입니다.구직자 입장에서는 여러 페이지를 오고가면서 정보를 관리할 필요 없이 단일 페이지에서 자신의 모든 이력을 관리할 수 있기 때문에 편리하지만, Input, Select 등 다양한 Form Control의 값과 유효성 등의 상태를 관리하는 입장에서는 렌더링 성능이슈가 발생할 여지가 다분한 페이지입니다.요구사항랠릿에는 개인의 이력을 관리할 수 있는 프로필 페이지와 프로필 정보를 기반으로 실제 기업에 지원하는 지원서 작성 페이지가 존재합니다. 해당 페이지에서 이번 글과 관련있는 핵심적인 기능들은 다음과 같습니다.유효성 검사: 유저가 Form Control에 대하여 change나 blur 액션을 취할 경우, 현재 입력된 값이 유효하지 않다면 에러 메세지를 보여준다.동적인 폼 요소: 경력, 교육 등 일부 영역은 동적으로 요소를 추가 또는 삭제하거나, 순서를 변경할 수 있다.앞으로 예제에서는 핵심적인 요구사항을 기반으로 설명하기 위해 동적으로 변경되는 경력사항, 그 중에서도 회사 이름만을 구현해보려고 합니다.Form 컴포넌트 개발하기1. useState로 ProfileForm 컴포넌트 만들기먼저 가장 쉽고 일반적인 방식으로 이름과 휴대폰 번호를 입력 받는 폼을 구현하면 다음과 같이 구현할 수 있습니다.import { useState } from "react" ; import _ from "lodash" ; const ProfileForm ( { initialProfile } ) => { const [ profile , setProfile ] = useState ( initialProfile ) ; const handlerChange = ( { target : { name , value } } ) => { const newProfile = _ . cloneDeep ( profile ) ; _ . set ( newProfile , name , value ) ; setProfile ( newProfile ) ; } ; return ( < form > { profile . companies . map ( ( company , index ) => { const error = company . name > 0 ; return ( < div key = { company . id } > < label > 회사 이름 < / label
mobx
reactjs
우아한형제들
Store에서 비동기 통신 분리하기 (feat. React Query)
안녕하세요, 저는 배민주문서비스팀의 Frontend Engineer 배민근입니다. 배민앱에서는 다양한 Web Frontend(이하 FE) 프로덕트들을 사용하고 있으며 요청사항이나 결제수단 등을 선택하는 주문하기 화면, 여러분이 지금까지 주문하신 것들을 볼 수 있는 주문내역 등 웹뷰로 된 화면을 심심치 않게 보실 수 있습니다. 주문 같은 경우에는 배민앱 내에서도 굉장히 오래전부터 있던 도메인이고, FE 특성상 기술이 빠르게 변화하므로 소위 Legacy 코드라 부르는 부분들이 많았습니다. 프로덕트의 개선과 생산성 향상을 위해 올해 저희가 가지고 있는 주문 FE 프로덕트의 개편을 준비했고 순차적으로 진행하고 있습니다. 오늘은 주문에서 사용하는 FE 프로덕트의 구조 개편을 준비하며 FE에서 사용하는 Store에 대해 개인적으로 고민했던 내용 및 팀원들과 검토하고 논의했던 내용을 펼쳐보려고 합니다. 이 과정에서 생긴 여러 가지 의문과 도달한 생각, 그리고 React Query를 도입하기로 했던 배경에 대해 소개하고자 합니다. 본격적인 글에 앞서 먼저, FE를 개발하시는 분들에게 질문을 하나 드리면서 글을 시작하겠습니다. "최근에 개발하면서 Store가 너무 비대해졌다고 느끼신 순간이 없으신가요?" STORE와 비동기 통신 > 먼저, 이 글에서 언급하는 Store는 별도 언급이 없다면 모두 Client Store라고 생각해 주시면 됩니다..! Store를 한마디로 정의하면 전역 상태가 저장되고 관리되는 공간입니다. FE 개발할 때 보통 Redux, Mobx와 같은 상태 관리 라이브러리를 이용해 다루는 여러 상태와 이를 관리하는 코드들이라고 말할 수 있습니다. 제가 위에서 질문의 출발점은 FE 개발에서 전역 상태 관리를 위해서 Store를 사용하고 있는 것은 맞지만 상당 부분이 비동기 통신을 위해 쓰이고 있는 것 같다는 생각이었습니다. 개발하고 운영하는 프로덕트들에 빗대어 살펴보니 비동기 통신 자체와 이에 얽혀있는 다양한 정책들과 함께 Store의 역할이 너무 비대하고 이게 과연 Store의 본질이 맞는지 의문을 가지게 되었습니다. 저희가 예전에 많이 썼었던 Redux를 가지고 Store 예시와 함께 한 번 비동기 통신과 얽혀있는 코드를 살펴봅시다. Redux에서는 redux-saga, redux-thunk 등의 미들웨어를 통해, Mobx에서는 Flow를 통해 비동기 통신의 해법을 제공하고 있으며 아래 예시는 redux-saga를 사용한다는 가정으로 작성했습니다. // Redux로 구현하는 Store 예시 export const FETCH_ORDER_REQUEST = 'FETCH_ORDER_REQUEST'; export const FETCH_ORDER_SUCCESS = 'FETCH_ORDER_SUCCESS'; export const fetchOrderRequest = createAction<number, string>(types.FETCH_ORDER_REQUEST, (page: string): number => { const parsed = Numb
mobx
reactjs
redux
딜리셔스
딜리의 서재 개발기
안녕하세요. 광고개발파트의 김한비입니다. 이 글에서는 인턴 과정으로 사내 도서 관리 서비스를 개발한 경험을 공유하고자 합니다. 프로그래머스 2020 Summer Coding 여름방학 스타트업 인턴 프로그램으로 딜리셔스에 입사한 저는 2달 동안 토이 프로젝트를 수행하는 임무를 부여받았습니다. 어떤 프로젝트를 진행해볼까 멘토와 논의하던 도중, 기존의 사내 도서 관리 시스템이 눈에 띄었습니다. 딜리셔스는 직원들의 복지를 위해 업무나 자기 계발에 필요한 도서를 무제한으로 지원하고 있습니다. 그런데 도서 구매 신청과 보유 도서 관리가 Google Docs를 이용해 이뤄지고 있었습니다. 직원들은 책 정보를 양식에 맞춰 일일이 입력해야 했고, 피플팀은 일련번호와 보유 현황을 직접 타이핑해야만 했습니다. 기존 도서 신청 기존 도서 관리 이런 불편함을 개선하고자 저는 딜리의서재라는 이름으로 새로운 도서 관리 서비스를 만들어보기로 했습니다. 기획 먼저 기존 프로세스를 파악하려고 했습니다. 도서를 신청해본 적 없는 인턴으로서, 새로운 도서 관리 시스템이 왜 필요한지 생각해 보기 위함이었습니다. 서비스의 깊은 이해가 선행되어야 목적에 맞는 개발을 수행할 수 있다 믿기 때문에 간단한 프로세스라도 직접 경험하며 불편함을 느껴보려 했습니다. 그러고 나서 피플팀 담당자님, 멘토와 세 명이 여러 번의 회의를 진행했습니다. 서비스 운영자로서 필요한 필수 기능이 무엇인지, 어떤 점이 개선되었으면 좋겠는지, 장기적으로 무슨 기능이 더 추가되길 원하는지 생생한 이야기를 들을 수 있었습니다. 저 또한 기존 프로세스에서 궁금했던 점을 질문할 수 있었습니다. 그렇게 기능 목록을 도출할 수 있었고, Kakao Oven을 이용하여 프로토타이핑을 진행했습니다. 학생 때 팀 프로젝트를 진행하면서 팀원들의 작업을 지켜봤던 경험은 있었지만 제가 직접 만들어본 것은 처음이었습니다. 옆에서 지켜볼 때와 달리 직접 프로토타이핑하는 일은 생각보다 신경 써야 할 것이 많았고 페이지 간의 연결 고리도 자세하게 작성해야 했습니다. 게다가 간단한 디자인이 포함되는 작업이라, 미적 감각이 부족한 저에겐 크나큰 난관이었습니다. 디자인, 너무 어려워 그렇지만 멘토의 도움으로 페이지를 하나하나 완성해나갈 수 있었습니다. 기능 목록만 도출했을 땐 어떻게 화면을 구성해야 하고 어떤 기능들이 위치할까 정말 모호했었는데, 구체적인 화면으로 그려내니 개발의 방향성이 좀 더 뚜렷해졌습니다. 또한 프로토타이핑 결과물을 피플팀과 공유하여 부족한 부분을 보완할 수도 있었습니다. 프로토타이핑 with Kakao Oven 개발 구체적인 기획을 완성했으니 이제 본격적으로 서비스를 만들 단계입니다. 멘토와 저는 제일 먼저 어떤 기술 스택을 사용할 것인지 결정했습니다. API 서버는 주로 저희 파트에서 사용되는 기술들을 사용하여 개발하기로 했습니다. 이에 더해 기능을 개발하면서 필요한 jsoup이나 spring security 등을 추가로 도입했습니다. Spring Boot (2.3.2) Spring Data JPA Querydsl
mobx
reactjs
spring
직방
Mobx 최적화로 직방앱 성능 개선하기
현재 직방에서는 상태관리 도구로 Mobx를 사용하고 있습니다. 종종 오래된 코드에서 Mobx 의 개념을 오해한 코드 때문에 성능이 저해되는 문제가 있었습니다.그로 인해 불필요하게 render가 발생하는 부분을 찾고 테스트하여 성능을 개선한 과정을 공유하고자 합니다.맵 리스트 화면직방 PC 웹 지도 화면직방에서 가장 많이 사용 되는 서비스 중에 하나인 맵 리스트 화면 입니다.위 처럼 맵을 드래그해서 위치 정보가 변경 되면 해당 정보에 맞는 매물 리스트을 갱신 합니다.우측 리스트 UI 변경되는 과정위치 정보 변경“매물 확인중” 텍스트 변경 ? Re-render로딩 UI 노출? Re-render데이터 갱신 후 리스트 렌더링? Re-render컴포넌트 구조상 리스트 갱신 시 최대 3회의 re-render가 일어날것으로 예상했지만 실제로는 달랐습니다.크롬 React Dev Tool 을 사용해서 rendering과정을 살펴보았습니다.수정 전 프로파일링렌더링 과정우측 사이드바 영역에서 해당 컴포넌트의 렌더링 횟수와 실행 시간을 확인할 수 있습니다.해당 리스트 컴포넌트 기준 렌더링이 6회 발생하고 있었습니다.( 지저스 크라이스트? )예상보다 2배나 렌더링이 되고있었습니다. 원인을 찾아서 최소화 하도록 변경해 봅니다.원인해당 리스트 컴포넌트에서 위와 같이 각각 observable 변수가 변경 될때마다 forceUpdate(re render)를 실행하는 reaction이 사용되고 있던게 원인이었습니다.https://mobx.js.org/getting-started.htmlMobx는 observable값을 변경하면 자동적으로 그에 해당하는 Derivations와 Reactions를 발생 시킵니다.reactionobservable 값 변경시 reation 발생observable와 1 : 1 대응 하여 발생위와 같은 함수를 실행한다고 가정 해봅니다.screenModel 객체의 state,sections,needMoreZoomIn 프로퍼티는 모두 observable 값이므로 reaction이 3회 발생합니다.이때 위의 사례처럼 reaction의 콜백으로 forceUpdate를 사용하게 되면 컴포넌트 render가 발생합니다.reaction이 3회 발생했으므로 rendering도 3회가 발생하게 됩니다.결과적으로 불필요한 re rendering이 발생해서 예상보다 많은 render가 동작했습니다.솔루션골목식당 솔루션 렌더링 3회로 줄여야쥬Mobx는 observable를 observer 컴포넌트 내부에서 사용해야 됩니다. 그렇게 해야 observable이 업데이트 되면 Mobx가 자동으로 observer 컴포넌트를 렌더링 할수 있습니다.해당 코드를 제거 하고 컴포넌트를 observer decorator를 사용해서 observer 컴포넌트로 변경해주면 정상적인 rendering 과정이 됩니다.reaction 을 줄이자.앞서 말한거처럼 observable이 update되면 reaction이 발생하게 됩니다.위 코드 처럼 observable 상태를 변경하면 3번의
mobx
연관 기술 스택

Immer

React Context

Recoil

Redux