9/26 ~ 9/30
useEvent
- RFC: useEvent ❌
- useEffect나 useCallback에서 디펜던시로 추가하고 싶지는 않지만 사용해야하는 경우 ref로 조건 처리하고는 했는데
- 이런 상태를 대체할 수 있을 것이라 보고 있었으나
- 뒤돌아서 생각해보면 디펜던시 대혼란에 빠지게 될 것 같았다
- 린트 룰을 꺼버리는게 차라리 나을지도 모르는? (이게 더 명시적이니깐)
- 근데 useEvent가 대혼란을 극복하지 못하고 사라지는중
default export
- [번역] 자바스크립트 모듈에서 default export는 끔찍합니다
default export는 어떤 이름으로든 export 할 수 있으므로 여러 개발자는 default import를 위해 각각 다른 이름과 명명 스키마를 생각할 것입니다- 만약 다른 모듈에서 명명된 두 named export의 이름이 같은 경우 어떻게 해야하나요?"라고 생각할 수 있습니다. 다행히 이 문제는 import aliasing으로 쉽게 해결할 수 있습니다.
- 그러나 import 할 때마다 이름을 고민하는 것 보다 하나의 파일 안의 스코프에서 일회성으로 이름을 고민하는 것이 훨씬 편합니다.
- default export로 매번 import 할때마다 고민하기보다 동일한 이름의 named export가 발생한 시점에 일회성으로 고민하는 것이 더 낫다
- 그럼에도 default export 를 써야겠다면?
- index 파일을 만들어서 여기에 전부 default import 하고 이 index 에 접근하도록
{}
- (번역) 소프트웨어 변경에 대해 이야기하는 방법
우리는 {새로운 가설} 때문에 {변경}이 {미흡한 점}을 개선할 것으로 기대합니다- 무섭게 다가오는 문장
- 리팩터링을 통해 더 나아졌기를
9/19 ~ 9/25
flex 레이아웃
- 항상 잘 사용하지 못하는 flex
- 이 글 여러번 읽었더니 드디어 이해가...
- 감성으로 이해하는데, 이제 이성으로도 살짝!
- 두번 정도 더 겪으면 될 것 같다
- 하지마 알고 있고 이해하는 것과 다르게 제대로 사용하는 것
- 제대로 사용하는 것까지 이어져야 완전히 내것이 되는데
- 가장 조심해야하는 것이 무의식적인 사용
- 지금도 잘 사용하고 있다고 생각하는 것이 있다면....
- 나혼자만의 착각
데드라인 드리블 글쓰기
- 데드라인 드리블 글쓰기
- 한달에 하나 정도 더 쓰자는 마음이였는데 실행하지 못한지 반년 훌쩍
- 나 또한 마찬가지로
한달동안을 마지노선으로 가져간다... - 글감을 바로 메모해두며 그것이 글이 되어야하는데, 내 글감은 그대로 한마디가 되고 끝나버린다
- 짧은 생명주기
스터디를 진행하고 나면
- 책을 한권 읽는다던지 그리고 후기를 적는다면
- 이런느낌으로 정리해두는 것도 좋겠는데
- 스터디를 참여하는 것 자체가 부담이라면
- 이런 온라인에 올라와있는 후기와 함께 개인적으로 느낀 것을 정리하면서 읽어보는 것도 재밋겠다
- 단위테스트 책을 읽어보고 싶었는데, 후기에 올라온 내용처럼 보통 백엔드 위주의 내용이라 어떻게 접목할 수 있을까 하는 고민이였다
타입스크립트 프로젝트 클린 아키텍처 (의존성 분리)
- (번역)타입스크립트 프로젝트를 위한 궁극적인 클린 아키텍처 템플릿
- 예제는 core, data, di, presenter 구성인데, RN 플젝을 이렇게 구성한다면?
- presenter에 일반적인 components, container
- core에서는 presenter에서 사용할 유즈케이스
- data에 core의 유즈케이스에서 사용할 데이터 구조
- di에서 data를 core의 유즈케이스에 따라 변환하여 실제 presenter에서 사용
- 패키지 간의 종속성 설정에서 이런 의존성을 확인할 수 있다
- data는 core에 의존
- di는 data, core에 의존
- presenter는 di, core에 의존
- 이런 의존 관계로 인해 core가 변경되면 data, di, presetner 모두 다시 빌드 되어야한다
- data가 달라지면 core에서 처리하는 과정이 변경되어야하고 이에 따라 di도 달라질 수 있다
- di가 변경되면 core에서 data를 변환하는 과정이 달라져야하고
- core가 변경되면 data를 변환한 di가 달라지고 presenter에서 보여지는 것이 달라질 수 있기 때문
- 확실하게 의존성 분리가 되겠는데, 갑자기 리덕스가 생각난다 🤔
9/12 ~ 9/18
프론트엔드 아키텍쳐
- 프론트엔드 아키텍쳐 트랜드?
- redux + saga가 원탑이라고 생각하던 지난 시간
- 지금은 서버 API 캐싱을 잘 관리하는 것이 더 중요해졌다
- 이렇게 계속 변화되는 아키텍쳐 속에서 하고자 하는 의미만 알아두면 좋겠다
- 비즈니스 로직을 완전히 분리하여 View를 구성할 수 있다면 좋겠지만
- 분리하지 못한다면 비즈니스 로직을 포함한 거대한 컴포넌트가 되어버리는데
- 로직도 있고 View도 있고
- 여기서 View만 이라도 한번 더 분리해서 UI 독립적일 수 있게 되면 좋겠지만
- 그럼 props drilling하게 되고 오히려 컴포넌트가 어디서든 재사용하는 것이 어려운
- UI 독립이기는 하지만 정말 독립적이지는 않은 이 로직에 대하여 의존적인 컴포넌트가 되었다
- 어차피 재사용 되지 못한다면 비즈니스 로직에 의존적이더라도 언제든 다른 것으로 교체가능하도록
- 재사용은 되지 않지만 교체는 수월한 최소한의 컴포넌트
선언형, 명령형 관계
-
-
명령형 => 어떻게(How)
const 등록완료된_리스트 = (list) => { const result = []; for (let i = 0; i < list.length; i++) { if (list[i].isCompleted) { result.push(list[i]); } } return result; }; -
선언형 => 무엇을(What) => 명령형에서 어떻게(How)를 감추고 무엇을(What)만 노출 => 명령형을 추상화하였다
const 등록완료된_리스트 = (list) => { return list.filter((item) => item.isCompleted); }; -
선언형 내부에 명령형이 추상화되어 숨겨져있다
-
-
그렇다면 명령형 선언형 구분할 필요 없이 명령형을 구조적으로 정리하여 내부에 숨겨두는 것이 무조건 선언형인가?
선언형은 사이드 이펙 없이 순수해야한다라는 내용에 따르면언제 어디서 + 어떤 상황에서 호출되어도 동일한 기댓값을 주어야한다- 명령형 => 시간 순서를 지켜야하는 절차적으로 호출
- 선언형 => 순수하기 때문에 시간 순서 상관없이 어디서든 호출
-
모든것을 선언형으로만 작성할 수 없을 것 같다
- 선언형 내부를 따라가다보면 결국 시간 순서에 따라 작성되어있는 명령형이 감춰져있을 것
- 이것들을 추상화하여 잘 전달하고 사용하도록
-
그럼 이런 명령형 코드를 찾아보게 되는 시점이 언제 있을까?
- 추상화되어있는 RN 컴포넌트나 브릿지 사용하다가 무언가 오잉? 하는 시점에 따라가다보면
- 어디엔가 나열되어있는 명령형 코드를 찾아볼 수 있다
-
이 글을 읽고 하나 더 와닿은
회사 프론트 동료들과 추상화와 선언적인 코드의 관계에 대해서 이런저런 이야기를 나눴습니다. 머릿속에 추상적으로 있던 개념이 좀 각이 잡혀서 ㅎㅎ 한 번 글로 적어보려 합니다.- 이야기 한 것 만으로 머릿속에서 정리하고 흘러갈 수 있는 것을 기록하면서 다시 한번 다듬어서 남겨두기
9/5 ~ 9/11
리액트 베타 문서
- 기대되는 것: Offscreen
- 마음은 알겠지만...: When Strict Mode is on, React mounts components twice (in development only!) to stress-test your Effects.
- 초기 렌더에는 결국 모두 계산해야하니깐: useMemo won’t make the first render faster. It only helps you skip unnecessary work on updates.
리액트 컴포넌트 리렌더링
- 부모, props, state가 변경되었을때 리렌더가 일어날 것이라 생각한다
React에서 렌더링에 대해 이야기할 때, 우리는 대부분 render 함수의 실행에 대해서만 이야기합니다. 하지만 렌더링이 항상 UI 업데이트를 의미하지는 않습니다.리렌더가 일어날 것이라 생각되는 부분은render 함수의 실행이였다- 실제로 diffing 연산에 의해 UI 업데이트는 발생하지 않았다
- 확인해보면 컴포넌트 자체는 리렌더 되는 것처럼 보이지만 DOM은 업데이트 되지 않았다
- 그러나 render 함수가 실행되었다는 사실은 변함없기 때문에
- 리액트는 diffing 연산을 계속 사용해야만했다
- DOM은 업데이트 되지 않더라도 함수형 컴포넌트 자체는 계속 재실행 되었다
- 참고:
클래스 컴포넌트와 다르게 함수형 컴포넌트는 아무 것도 변경되지 않는 경우에도 다시 함수를 호출하기 때문에렌 리렌더링된다
- 여기서 리액트의 연산은 최적화 되어있다는 신뢰 기반으로 🤔
DOM은 업데이트 되지 않더라도 함수형 컴포넌트 자체는 계속 재실행 되었다는 부분을 최적화해야만한다컴포넌트의 render 함수가 호출된다는 것 > 모든 하위 컴포넌트들이 리렌더링 (render 실행)- 의도치 않은 낭비
- 메모이제이션 하는 것 외에 코드 재구성(상태를 처리하는 코드를 별도의 리렌더가 되어야하는 컴포넌트로 이동)을 통한 리렌더링 방지해야한다
- 참고: memo를 사용하지 말아야하는 이유
- 메모리에 저장 + 얕은 비교
- 그나마 얕은 비교의 위험? 연산 낭비?을 해결 하기 위해
- 원시타입으로 사용하는 것을 추구하거나 정말 필요한 프로퍼티만 포함하도록 하였는데
- 이미 리액트가 diffing 으로 최적화를 해두었는데, 그 최적화를 오히려 방해하는 연산이 들어가게 되는 것
- 참고:
컴포넌트에 많은 props가 있고 자손이 많지 않은 경우 컴포넌트를 다시 렌더링하는 것과 비교하여 props가 변경되었는지 확인하는 것이 실제로 더 느릴 수 있습니다. - 그럼 불필요한 메모리 저장을 제거하고 최소한의 연산을 위해 복잡한 컴포넌트에서의 memo를 제거해볼까
- 결론
- render 함수의 실행 자체를 방지하려면 상태가 변경되는 지점을 해당 컴포넌트 내부에 위치해야한다
- 순수 컴포넌트로 만들어서 자식 컴포넌트가 불필요하게 리렌더 되는 것을 방지한다
- 컨텍스트는 보이지 않는 props 또는 내부 props로 위험 인자다...
RN fabric
- 아직도 안드로이드 fabric 버전에서 ReactNavigation 라이브러리가 동작하지 않는다
- 이것저것 확인해보니 디펜던시 라이브러리가 문제가 되고 있는 듯 (react-native-screens, react-native-safe-area-context 무언가)
- ndk 오류 관련 깃헙 이슈 코멘트
- 최근에 RN 0.70.0 에서도 cmake로 변경되었던데....?
- 혹시나 해보면 RN 버전부터 다시 올려본다 => 그러나 safe-area-context가 아직 대응이 되지 않았기에 여전했다...
- 같은 이슈가 올라와있는데 아직....
- 근데 전부터 FabricExample 살펴보면 항상 의문인 것은
newArchEnabled=false?- fabric 버전으로 올린 이유가 이거 때문 아닌가..?
- ☠️ 대체 왜...
리액트 상태 관리
-
리액트에서는 전역으로 상태를 관리하는 방법에 대한 가이드라인이 없다
- 단순히 전역으로 전달하는 것은 Context로 할 수 있지만
- 여기서 말하는 상태 관리와는 목적이 다르다
- 참고: 전역상태 관리에 대한 단상 - Context API 성능
- 전역 상태 관리에 대한 최적화 처리가 되어있는 Redux와 달리 Context는 전달하는 목적만 있었기에 최적화 작업이 포함되어있지 않다
- 그렇다면 Context를 활용해 전역에서 접근한다면 어떻게 될까?
- 사용하는 곳에서 단순한 Context 변경사항에도 리렌더를 유발하게 된다
-
Provider 하위에서 context를 구독하는 모든 컴포넌트는 Provider의 value prop가 바뀔 때마다 다시 렌더링 됩니다 . 상위 컴포넌트에서 React.memo 또는 shouldComponentUpdate를 사용하더라도 useContext를 사용하고 있는 컴포넌트 자체에서부터 다시 렌더링됩니다. . useContext를 호출한 컴포넌트는 context 값이 변경되면 항상 리렌더링 될 것입니다. - 문서: useContext
- 컨텍스트 잘 사용하기: 메모이제이션 최적화
- 컨텍스트 분리 또는 하위 컴포넌트 memo 또는 useMemo로 jsx 반환
-
- 하위 컴포넌트에서 최적화를 진행하더라도 결국 불필요한 리소스가 소요된다
-
각각의 라이브러리들은 서로 다른 문제에 대해 서로 다른 해결방법을 제시했는데
- 요구사항에 맞는 적절한 라이브러리를 선택할 수 있어야한다
-
전역 상태 관리 라이브러리가 해결하고자 하는 문제
- 저장된 상태를 컴포넌트 트리 어디에서든지 읽어 올 수 있는 기능
- props drilling을 피하고 어디서든 이 상태를 가져와서 사용하고자
- 이때 상태 변경에 따른 리렌더링 최적화 필요
- 저장된 상태를 수정하는 기능
- 불편성을 유지하면서 상태 업데이트 할 수 있도록
- 렌더링을 최적화하는 메커니즘을 제공
- 실제 상태 변경에 따라 리렌더 되어야하는 컴포넌트에서 셀렉터를 구독하도록
- 사용하지 않는 곳에서는 이 상태를 구독할 필요가 없다 (불필요한 리렌더를 유발할뿐)
- 메모리 사용을 최적화하는 메커니즘을 제공
- 저장된 상태를 컴포넌트 트리 어디에서든지 읽어 올 수 있는 기능
-
이러한 문제를 해결하고자 Redux가 초기 도입되었다
-
그러나 전역상태 + 로컬 UI 상태 + 원격 API 상태 ....
-
예를 들어 로컬 UI 상태의 경우 데이터와 해당 데이터를 업데이트하는 메서드 모두 드릴링하는 것은 상황이 커질수록 상대적으로 빠르게 문제가 되는 경우가 많습니다. 이 문제는 상태 끌어 올리기와 함께 컴포넌트 컴포지션 패턴을 사용하면 꽤 깔끔하게 해결할 수 있습니다. - 현재 마주하고 있는 문제이다
- 이를 끌어올리거나 컴포지션으로 정리해야하는데...
-
-
수 많은 상태들이 분리되기 시작하였다
- 여기서 또 다른 문제는 모든 상태가 전역에 들어가버릴 수 있다 (정말 불필요했다...)
-
실제로 많은 웹 애플리케이션은 주로 프런트엔드를 원격 상태 데이터와 동기화해야 하는 CRUD(생성, 읽기, 업데이트 및 삭제) 스타일의 애플리케이션입니다. 즉, 시간을 할애할 가치가 있는 주요 문제는 원격 서버 캐시 문제들입니다. 이러한 문제에는 서버 상태를 가져오고 캐시하고 동기화하는 방법이 포함됩니다. -
이러한 이유 (=원격 API 상태를 관리하기 위해서)로 리액트 쿼리를 사용하게 되었는데
-
-
아직 리덕스, 컨텍스트에서 완전히 빠져나오지 못했으며
-
잘못된 구독으로 불필요한 리렌더를 유발하는 것을 정리하지 못했다
-
여기서 다시 보니 반가운 Context는 상태 관리가 아니다
9/1 ~ 9/4
리액트 성능 최적화를 위해
- (번역) 리액트 성능 최적화, 500ms 에서 1.7ms 까지 : 그 여정과 체크리스트
- 리액트 메모를 사용해야하는 시점 === 퍼포먼스가 잘 나오지 않다고 느껴지는 경우
- 습관적으로 메모를 사용하고 있으나 실제로 최적화가 필요한 포인트를 찾아야함
- 단순히 성능을 개선했다는 것이 아니라 원인이 되는 것을 제거하도록
과도한 메모이제이션🙈
- 큰 컴포넌트를 잘 정의된 작은 컴포넌트로 분해하고 컴포넌트가 원시 타입의 프로퍼티만을 사용하도록 한다면 리렌더링 최적화를 이끌 수 있다
- memo로 개선할 수 있지만
원시 타입의 프로퍼티만을 위해서 현재 컴포넌트에 드릴링 되는 무거운 프로퍼티들을 제거하거나- diffing 조건을 잘 이렇게 저렇게 하는 작업이...
- 최근 신경 쓰는 부분: jsx를 const로 변환
renderCallback (useCallback<JSX.Element>)이 아닌RenderComponent (useMemo<JSX.Element>)또는RenderComponent (memo)함수 호출은 항상 발생하고 jsx를 다시 빌드하기 때문에, jsx의 const 변수를 컴포넌트로 변환하는 것이 더 성능이 좋은 것으로 간주할 수 있습니다.
- 컴포넌트가 리렌더링 되는 이유를 파악하여 그 원인을 해결해야하는데
- 간단하게 memo가 효과가 있을 수 있으나
- 결국 원시 타입이 아닌 객체가 재생성되어 리렌더를 유발 시키기 때문에
- 이런 컴포넌트 트리를 찾아내야한다 🤡
계속 추가되는 비즈니스에 대응하기
- [더 나은 쿠폰 서비스에 대한 아이디어 기록)(https://johngrib.github.io/wiki/article/coupon-service-and-code-data/)
- 쿠폰 서비스를 위한 ifelse 지옥...
- 쿠폰 뿐만 아닌 그 어떤 곳에서도 마주할 수 있는 상황에서
- 이를 조합으로 해결할 수 있을까하여 참고하고자