최근 기술면접 스터디에서 비동기와 동기 처리에 대해 계속 이야기가 나오고 있기도 하고 프로젝트를 하기에 앞서 React를 프론트엔드에서 사용할 생각이라 이런 내용도 알고 있으면 구현하는 데도 도움이 될 것 같아 이번주 세미나는 이 세미나로 결정했다.
React를 사용하면서 비동기 처리를 고려해서 구현한 적이 많이 없었던 것 같고 왜 그렇게 구현해야하는지 주의 깊게 공부하지 못했던 것 같아 이번 세미나가 나에게는 비동기라는 개념에 대해서도 알 수 있고, 어떻게 비동기를 우아하게 처리할 수 있는지 방법까지 공부할 수 있는 세미나였다.
- 현재 토스의 상황
- 토스에서는 React, Next.js, Typescript를 현재 사용하고 있다.
- 웹 서비스에서 가장 다루기 어려운 부분은 비동기 프로그래밍
- 비동기 프로그래밍이 필요한 이유 : 순서가 보장되지 않는 경우 사용하며, 좋은 사용자 경험을 위해 필수
- Callback, Promise, RxJS 등으로 처리
- 좋은 코드란?
- 코드가 간결하다
- 예상할 수 있는 최적의 경우와 문법적 차이가 크지 않다
- 함수의 역할을 한눈에 파악할 수 있다
- '성공하는 경우'만 다루고, '실패하는 경우'는 catch 절에서 분리해 처리한다
- '실패하는 경우'에 대한 처리를 외부에 위임할 수 있다
- 성공, 실패의 경우를 분리해 처리할 수 있다
- 비즈니스 로직을 파악하기 쉽다
- 프론트엔드 웹 서비스에서 지금까지의 비동기 처리
- 비동기를 처리하는 부분을 정의한다
- 컴포넌트에서 로딩과 에러 처리를 동시에 수행한다
- 여러 개의 비동기 처리를 해야할 땐?
- 비동기 처리 지옥
- React의 비동기 처리는 어렵다
- 성공하는 경우에만 집중해 컴포넌트를 구성하기 어렵다
- 2개 이상의 비동기 로직이 개입할 때, 비즈니스 로직을 파악하기 점점 어려워진다
- React Suspense for Data Fetching (데이터를 가져오기 위한 Suspense)
- 컴포넌트는 성공한 상태만 다루고, 로딩 상태와 에러 상태는 외부에 위임함으로써 동기적인 코드와 큰 차이가 없는 코드를 만들겠다는 목표
- 에러 상태와 로딩 상태는 어떻게 분리되는가?
- 컴포넌트를 '쓰는 쪽'에서 로딩 처리와 에러 처리를 한다
- 로딩 상태는 가장 가까운 'Suspense'의 'Fallback'으로 그려진다
- 에러 상태는 가장 가까운 'ErrorBoundary'가 componentDidCatch()로 처리한다
- 일반적인 Suspense/ErrorBoundary의 용법
- Recoil - Async Selector
- SWR, React Query - {suspense: true}
- 'runPureTask'로 실행시키면, 비동기 함수도 동기적으로 작성할 수 있다
- 토스팀에서는 어디에 사용했는가?
- TUBA(Toss User Behavior Analyzer) : 토스 대부분의 데이터가 모이고 분석되는 내부 제품
- A/B Test 설정
- 전환율 분석
- 알림, 푸시 전송 - TUBA 메신저
- Recoil의 비동기 셀렉터를 이용해서 수많은 비동기 처리를 해결
- useRecoilValue를 이용해 Suspense 설정해줌
- ...
- 데이터가 준비되는 대로 하나씩 자연스럽게 보여주기
- TUBA(Toss User Behavior Analyzer) : 토스 대부분의 데이터가 모이고 분석되는 내부 제품
- 코드 복잡도를 낮춘 방법
- React hooks : 상태 관리, 부수 효과 관리, 메모이제이션 관리를 감싸는 컴포넌트가 수행하도록 하게 함
- Suspense : 실제 로딩 상태, 에러 상태 처리는 컴포넌트를 감싸는 부모 컴포넌트가 수행
- 에러 처리의 복잡도를 낮춘 방법
- try-catch : 실제 에러 처리는 컴포넌트를 감싸는 부모 함수가 수행 (실패할 수 있는 함수는 에러를 throw 문으로 발생시킴)
- 대수적 효과(Algebraic Effects)
- 함수는 필요한 코드 조각을 선언적으로 사용
- 실제 관련된 처리는 컴포넌트를 감싸는 부모 함수에 위임
- 더 공부하면 좋은 React 요소들
- React Concurrent Mode
- useTransition
- useDeferredValue
- -> React에서 컴포넌트의 렌더 트리를 부분적으로만 완성함으로써 사용자 경험을 크게 향상시킬 수 있다
//
<ErrorBoundary fallback={<MyErrorPage />}>
<Suspense fallback={<Loader />}>
<FooBar />
</Suspense>
</ErrorBoundary>
// React Team의 Sebastian Markbage의 Proof-of-concept
function getUserName(id) {
var user = JSON.parse(fetchTextSync('/user/' + id));
return user.name;
}
function getGreeting(name) {
if(name == "Seb") {
return 'Hey';
}
return fetchTextSync('/greeting');
}
function getMessage(){
let name = getUserName(123);
return getGreeting(name) + ', ' + name + '!';
}
runPureTask(getMessage).then(message => console.log(message));
- Recoil 공부하기
- React Concurrent Mode, useTransition, useDeferredValue 공부하기
'회고 > 세미나' 카테고리의 다른 글
토스 SLASH 21 - Micro-frontend React, 점진적으로 도입하기 후기 (0) | 2022.07.02 |
---|---|
[10분 테크톡] 결의 브라우저 렌더링 후기 (0) | 2022.06.11 |
[10분 테크톡] 렉스의 Git 브랜칭 전략 후기 (0) | 2022.05.31 |
토스 SLASH 21 - 실무에서 바로 쓰는 Frontend Clean Code 후기 (0) | 2022.05.30 |
4월 우아한테크세미나 <지속가능한 SW 개발을 위한 코드리뷰> 후기 (0) | 2022.05.09 |