오늘 GDSC에서 주최한 'kprintf'라는 행사를 다녀왔다. 디스코드에서 kprintf라는 행사가 열린다는 것을 확인하고 무슨 주제에 대한 강의가 열리는지 살펴봤다. 다양한 주제들이 있었는데 그 중에 React에 대한, 정확히는 React 버전이 19로 업데이트되면서 어떻게 바뀌는지 알려주는 강의가 있길래 바로 신청했다. React를 사용해본 적은 꽤 있지만 버전이 몇인지, 또 최신 기능은 무엇인지에 대한 관심은 갖지 않았었다. 이번 세션을 통해 React에 대하여 더 깊은 이해도를 가질 수 있기를 기대했다.
이번 학기에(사실 저번학기도) 신공학관에서 수업을 듣지 않기에 정말 오랜만에 신공학관을 방문한 것 같다. 입장권 QR코드를 체크하고 학번과 이름을 작성했다. 그리고 위 사진과 같이 경품을 받았다. 사실 간식들보단, 저 스티커가 많이 갖고 싶었다. 아무래도 구글은 간지가 난다. 조만간 저 스티커들 중 하나는 노트북에 붙일 예정이다.
3시 50분에 강의실에 입장했다. 얼마만에 듣는 웹 프론트엔드에 대한 대면 강의더라. React를 알려주는 학교 수업이 있었으면 좋았을 것 같은데. 그래서 더욱 적극적이여야 한다. 곧 듣게 될 이 강의는 1시간 50분 정도 진행된다. 과연 무엇을 새롭게 배우게 될까. 4시에서 5분 정도 지났을 때, 강의가 시작되었다.
React 19 업데이트 강의 정리
1. The Evolution of Core Concepts of react
v16.8 함수형 컴포넌트, 리액트 훅 도입
v.18.x Concurrent Mode(React Layer)
리액트는 세가지 레이어가 있다.
Code Layer: 우리가 작성하는 코드가 담겨있는 레이어
React Layer: 하나의 중간자, Virtual DOM 같이 브라우저에게 던져주기 전에 소통하는 레이어
Browser Layer: Browser DOM을 갖고 있는 레이어
1-1. React 16.8 - Functional Component
16.8의 큰 변화 → 함수형 컴포넌트
그 전까지는 클래스형 컴포넌트를 사용했다.
클래스형과 함수형의 코드를 비교하면 구조가 상당히 비슷해보인다. 그렇다면 왜 옮겼을까?
예시)
함수형 컴포넌트 → 영희의 페이지에서 팔로우를 누르고 철수의 페이지로 옮겨도 영희를 팔로우했다고 뜸(정상)
클래스형 컴포넌트 → 영희의 페이지에서 팔로우를 누르고 철수의 페이지로 옮기면 철수를 팔로우했다고 뜸(오류)
클래스형 컴포넌트 해결법 : JS의 Closure를 활용
- props를 render 시점에 가져옴
- render 함수 내에서 함수를 선언 → 이들은 class의 메서드가 아니다.
근데 이러면, 모든 것을 render 안에 넣으면 되지 않을까?
render() {
const props = this.props
...
}
function (props) {
...
}
functional 컴포넌트는 항상 렌더링된 값을 UI에 보여주는구나!
→ 사용자는 더 이상 UI와 데이터 간 동기화를 생각하지 않아도 됨
데이터 업데이트를 언제, 어떻게, 무엇을 UI에 알리지?
State = User Interaction으로 발생한 데이터 변화
모든 데이터는 자신만의 생명주기를 가진다(모든 프로그래밍에 통용되는 법칙)
State도 생명주기를 가지고, 독립적인 생명 주기를 보장해야 한다.
컴포넌트를 호출한다 → 함수를 호출한다.
리렌더링이 된다 → 함수를 다시 호출한다 → 이전의 State 값은 사라진다.
하지만 우리가 useState를 쓰면, 렌더링과 관계없이 작동한다. → 자신만의 값을 독립적으로 가진다.
React Hooks = 독립적인 state 데이터 조작 API
useState = 독립적으로 데이터를 관리할거야
useEffect = 독립적으로 side-effect를 관리할거야
useMemo = 독립적으로 데이터 캐싱을 관리할거야
useCallback = 독립적으로 함수 캐싱을 관리할거야
useRef = 독립적으로 데이터를 가리키는 레퍼런스를 관리할거야
useReducer = 독립적으로 이벤트 handling을 관리할거야
React Hooks가 되지 못한 것들..
useSuspense → 다른 컴포넌트의 영향을 받기 때문(독립적인 데이터로 관리가 안됨)
useCatch(useThrow)
useProvider → Provider와 Consumer는 서로 소통하기 때문
useShouldComponentUpdate → 함수와 데이터가 서로 영향을 주고 받기 때문
1-2. React 18 - Concurrent React
모든 데이터 update가 즉시 이루어져야 하는가?
→ 언제 알릴지 React가 선택권을 쥐고 있으면, 필요한 UI 먼저 업데이트할 수 있다!
Concurrency(동시성)에 대한 추가 설명
철수와 통화(덜 중요한)하다가 영희와 통화를 하려면?
→ 철수와 하던 통화를 전부 끝내고 영희와 통화하는게 나을까?
→ 아니면 철수와 하던 통화를 잠시 멈추고 영희와 통화하는게 낫지 않을까?
통화 = setState 업데이트 요청
React 18의 의의 = React Layer는 독립된 스케쥴링을 한다.
→ 신기술이었던 Suspense도 같은 맥락
Suspense
렌더링 중 Stop이 걸려 가까운 Suspense가 처리(마치 try-catch-throw의 관계)
Suspense 자식이 resolve되면, 다시 렌더링을 시도한다.
실제 React 내부에서는 Ping을 통해 렌더링을 시도해달라 요청한다.
→ 굳이 컴포넌트를 async하게 처리하지 않아도 되는 이유
→ 필요하면 Suspense로 감싸도 되므로
Automatic Batching
// 리액트 18 이전
function handle Click() {
setIsFetching(false); // <- 렌더링
setError(null); // <- 렌더링
setFormStatus('success') // <- 렌더링
}
// 리액트 18 이후
function handle Click() {
setIsFetching(false); // 대기
setError(null); // 대기
setFormStatus('success') // 대기 후 렌더링
}
Two React 패러다임의 부상
UI = f(state, data)
→ 즉 UI는 state의 결과이다.
UI = f(data)
→ 즉 UI는 data의 종합이다.
각 컴포넌트가 실행되어야하는 곳은 다른 곳이다.
→ <Counter />는 클라이언트에서, <Posts />는 서버에서
<Counter />
UI = f(state)로 동작
->State는 client에 존재하고, 결국 사용자와 상호작용해야 그 의미를 가진다.
<Posts/ >
UI = f(data)로 동작
->데이터는 Server에 존재하고, 그 데이터는 Server에서만 처리가 가능하다.
UI = f(state, data)
→ state가 없는 컴포넌트는 client에서 다룰 필요가 없다. (중요: React Server Component의 시작)
→ data가 없는 컴포넌트는 server에서 다룰 필요가 없다.
2. React 19는 어떤 점이 달라질까?
Code Layer → Client Code Layer / Server Code Layer로 나뉘어짐
2-1. Server Component
Server Component → state가 없는 컴포넌트는 client에서 다룰 필요X
- Server Component는 서버에서만 실행되는 컴포넌트로, 실제 client에 코드가 전달X
- Server Components는 DB, 파일 ,다른 서버 등 Server-side resource에 접근 가능
- Server Components는 Server-side resource에 따라 어떤 컴포넌트를 렌더링할지 결정 가능
- Server Component는 server 상태가 바뀌어도 client의 상태를 보존할 수 있어야 함
Server Component와 Suspense가 합쳐지면 최적화 + 최적의 UI를 보여줄 수 있음
(알아둬야 될 것: JavaScript는 인터프리터 언어이므로 위에서부터 한 줄 씩 내려온다.)
Suspense로 감싸면 서로의 동작이 서로에게 영향을 주지 못한다.
→ Suspense로 각각의 fetching을 가두고 병렬적으로 실행이 가능하다.
2-2. Server Action
Client → Server로 소통하는 Server Action (Form)도 준비 중
- Form 전송(Client)
- addToCart 실행(Server)
- DB 수정(DB)
React 19 이전과 큰 차이: Client에서는 addToCart 코드가 필요없다!
→ 사용자 경험에 도움
이에 따른 새로운 React Hooks도 도입됨
useFormState → Form을 전송할 때
useFormStatus → Form이 어떻게 전송되고 있는지(에러가 났는지)
useOptimistic → 실제로 addToCart를 서버에서 DB로 보낼 때 성공했다고 가정하고 사용(낙관적인)
2-3. Asset Loading
유저의 관점에서, css와 폰트, 이미지도 UI의 일부
지금까지는 실제 렌더링 시 React 렌더링과 Asset을 가져오는 차이로 UI 불균형이 생김
React-Helmet으로 처리가 가능했지만, 이제 React 자체로 처리 가능
실제 static하게 빌드 시 index.html의 head에 들어간다.
→ <link/>, <meta/>, <script/>, <style/> , <title/>
2-4. Resource Hints
Resource Hints도 이제 React 내부에서 사용가능
→ preconnect, dns-prefetch, preload, preinit 사용가능
Resource Hints는 우리가 어떤 리소스를 다운 받을지 브라우저에게 알려주는 것
DNS
우리가 아는 www.naver.com은 실제가 주소가 아니다.
실제 주소는 12.34.56.78과 같은 ip 형식
→ DNS 서버가 따로 존재
어떤 버튼을 눌렀을 때 이동하는 주소가 어떤 ip주소를 가지고 있는지 미리 알 수 있게 -> dns-prefetch 사용
preconnect
preconnect는 미리 서버와 연결까지(TCP, TLS Handshake) 구성
→ 더 바르게 resource를 들고 올 수 있다.
preload
preconnect + 리소스까지 포함
→ 특정 resource가 쓰일 것이 확실하면 preload는 좋은 선택지!
→ style.css 안에 font를 사용하고 있다면 같이 다운로드 받아야 빠르므다.
2-5. Web Components
Web Components에 대한 지원은 공지되어 있지만 사실 큰 소식은 없다.
React나 다른 프레임워크 없이도 Component를 만들 수 있다.
→ React가 아닌 vanilla JS, Vue, Svelte에서도 컴포넌트를 사용할 수 있다.
어떤 라이브러리를 만드는 입장이라면, 리액트가 아니라 다른 환경에서도 사용하는 것을 고려해야 한다.
→ 실제로 Github와 같은 서비스에선 Web Components를 적극 활용한다.
2-6. The ‘use’ hook
Server Component는 hooks를 사용하지 못하고, 사용할 일이 없다.
→ hooks는 state를 조작하는 API이므로
Client Component에서는 async한 컴포넌트를 사용하지 않는다.
기존에는 react-query나 useEffect를 통하여 fetching을 해왔다.
‘Use’ hook을 사용하면 비동기 함수도 동기적으로 활용할 수 있다.
예시: const note = use(fetchNote(id));
1. use(…) 문법은 await와 비슷해보인다.
2. use(…) 문법은 Promise, Context면 모두 활용가능
3. Suspense와 같이 사용 가능
-> use(…) 문법은 ReactQuery의 useSuspenseQuery와 매우 비슷해보인다!
2-7. ForwardRef 삭제
React는 렌더링과 상관없는 값을 가리키기 위한 ref(reference)란 개념이 있다.
React 18까지 ForwardRef라는 특수한 형태로 ref로 접근해야했다.
→ 만약 일반 prop으로 접근하면 warning을 띄운다.
→ 왜냐하면 Class Component 내 ref의 값은 prop 내 고유한 값이 있기 때문
→ 정확히는 Class의 instance인지 여부를 담고 있음
그런데 이제, Functional Component를 쓰고, function에는 instance라는 개념이 없다.
→ React 19에서는 forwardRef를 없애고 ref를 일반 prop처럼 다룰 수 있게 된다.
번외 - React Compiler (React Forget)
원래 React 19에서는 Auto-Memoization을 지원할 계획이었다.
→ React.memo를 안써도 자동으로 할 수 있게..
→ 현재 Instagram 웹페이지에서는 시험 적용되어 있다.
→ React 19 마이너 업데이트 때 적용이 되지 않을까하는 기대
3. 우리는 다가오는 업데이트를 어떻게 준비할까?
(오늘 한 이야기는 pre-release이므로 내일 바뀔 수도 있다!)
- 가장 좋은 방법은 직접 체험해 보는 것
- 그 다음으로 정보를 수집하기 좋은 곳은 공식 채널(React Working group과 같은)
- 적어도 Blog Driven Knowledge는 안했으면 좋겠음 → 서로가 서로의 것을 복제하기 때문
프레임워크를 대할 때는, 왜 이렇게 설계되었을까 생각해 본 사람과 아닌 사람은 차이가 크다.
React 19의 API나 사용법이 바뀌어도, 그 철학은 변하지 않는다.
→ 본질에 집중하자!
React의 발전에 대하여 알 수 있었던, 정말 알찬 강의였다. 마지막에 강의자분께서 프레임워크의 기능을 사용할 때 왜 이렇게 설계되었을까 생각해보는 것을 강조하셨다. 어떤 기능을 사용할 때, 옛날부터 써왔으니까 그냥 사용하는 식으로 사용하지 말고, 왜 이 기능이 지금 필요하고 사용하려고 하는지 생각을 해보는 것이 중요한 것 같다.
아직 React 19로 업데이트가 된 것은 아니다. 언제쯤 React 19의 기능들을 실질적으로 사용하게 될 지는 미지수지만, 오늘 강의 덕분에 React 19의 기능을 사용해야되거나 관련 코드를 본다 하더라도 당황하지 않을 수 있게 되었다.
강의가 다 끝나고 지하 1층에서 경품을 추첨하는 행사가 열렸다. 구글 로고가 그려져있는 경품들, 갖고 싶었는데 아쉽게도 가위바위보를 전부 졌다. 그래도 스티커 얻었으니까. 배운 것도 많고. 보람찬 시간이었다.
'Event' 카테고리의 다른 글
[2024 FEConf] 'React Native와 Web이 공존하는 또 하나의 방법' 내용 정리(feat. AI) (0) | 2024.08.30 |
---|---|
[2024 FEConf] '바퀴 대신 로켓 만들기' 내용 정리(feat. AI) (0) | 2024.08.30 |
큐시즘 전시회 - ENGAGE ENERGY 갔다온 후기 (4) | 2024.06.08 |
동아리에서 주최한 해커톤 참여 후기 (1) | 2023.12.21 |
SCPC 2023 1차 예선 참가 후기 - 아직 갈 길이 멀다. (0) | 2023.07.31 |