JavaScript/React

리액트 멸망전 1부

히키맨 2024. 2. 21. 17:26

하이하이 일주일만입니다. 글이 올라가는 시점은 8일째겠지만 쓰기 시작한 건 일주일 째가 맞습니다~ 일주일 사이에 별 특별한 근황은 없었구요 굳이 굳이 꺼내보자면 국민취업지원제도 상담이 마무리가 됐다는 것,,,?? 한 달  후 정도부턴 훈련지원금을 받을 수 있을 것 같습니다. 한 25만원 정도가 한 달에 한 번씩 지급될 것 같습니다. 이거랑 여기서 자체적으로 나오는 훈련장려금까지 생각하면 그래도 배 곯아 죽진 않을 것 같군요,,,

 

아 그리고 지금 교육과정 시작한 후로 아침도 안 먹고 운동이야 한참 전부터 안하다 보니 살이 벌써 2kg이나 빠졌답니다. 그래서 지난 주부터 아침을 먹기 시작했습니다. 전날 밤에 소보로빵 반 갈라서 땅콩버터 발라두고 다음 날 아침에 평소보다 10분 일찍 일어나서 커피랑 함께 마시듯이 먹고 있습니다. 미리 준비해놓기도 하고 목에 잘 넘어가서 10분도 채 안 걸려 먹을 수 있는 것 같은데 만족감이 대단합니다. 운동도 이제는 진짜 진짜 진짜 좀 열심히 좀 해볼랍니다 집에 사 놓은 풀업바 안 아깝게 살아야죠,,, 다만 집에서 하다보면 진짜 하다 못해 10kg 덤벨 한 쌍이라도 있었으면 좋겠다는 생각을 합니다. 내 팔은 아직 내 몸을 감당하기에 너무 모자랍니다,,,

 

정말 사소한 근황은 여기까지구요, 본론으로 들어가보죠!

 

리액트 강의가 끝났습니다. 후반부 분량이 워낙 많다보니 꽤 오래 걸리겠구나 싶어서 걱정을 했는데 다행인지 불행인지 요령이 늘어서 당장 필요한 부분은 좀 유심히 보고 필수적이진 않은 기능 개선과 관련된 부분은 후룩후룩 읽고 넘어갔습니다. 건실하게 다 들어야지 뭐하는 짓이냐! 라고 하기엔 당장 현장에서 리액트 강의가 진행 중이라서 여기에 합류하고 싶었달까요,,, 그리고 정말 주제 넘는 말이지만 이제는 어느 정도 필요한 것과 아껴놓을 것들이 구별할 수 있게 된 것 같습니다. 후반부에 심화된 내용을 다루는 만큼 당장 간단한 프로젝트도 감당하지 못하는 저에겐 조금은 미뤄도 되는 내용이었다고 봅니다. 변명이 참 기네요 그쵸? 

 

저번에 이어 배운 내용은 LifeCycle과 useEffect()입니다. 화면에 보이는 모든 컴포넌트들은 각자 LifeCycle을 갖고 있는데요, 화면에 박힐 때, 렌더링과 재렌더링 될 때, 그리고 화면에서 제거될 때로 대충 나눌 수 있고 각 단계를 mount, update, unmount라고 부른다고 합니다. 그리고 이런 단계를 거칠 때마다 특정 기능이 동작하도록 코드를 짤 수 있는데 그 때 useEffect()를 사용하게 됩니다. useEffect는 기본적으로 

 

 

이런 모양을 가지고 있습니다. 저 콜백함수 안에 있는 코드가 컴포넌트의 mount, update시에 실행된다는 것. 이걸 왜 쓰냐 라고 묻는다면

1. 저 useEffect()안의 함수는 html이 렌더링 된 이후에 동작하게 됩니다.

2. 만약 정말 쓸데 없이 실행하는데 한참 걸리는(반복문을 1억번 돌린다던가,,,)코드가 있다면

3. 그걸 useEffect()에 넣어두고 html이 렌더링 된 후에 동작하게 강제하는 겁니다.

컴포넌트의 핵심 기능은 html 렌더링인데 이상한 코드 돌리느라 렌더링이 느리면 안되지 않겠습니까 그래서 있는 기능이라고 합니다.

 

그럼 useEffect()는 쓰레기통 같은 존재일까나,,,?? 라고 생각하면 그건 또 아니라는 말입니다. 왜 보통의 useEffect()는 컴포넌트가 mount, update 될 때 동작한다고 했는데 

 

 

이런 식으로 두 번째 인자에 state를 담고 있는 대괄호를 전달하면 저기에 있는 state가 update될 때만(다른 state가 변경될 땐 아무 일도 일어나지 않고) useEffect() 안의 기능을 동작시킬 수 있게 됩니다( mount될 때는 쩔 수임 그냥 받아들이셈 ). 그리고 이걸 dependency라고 부른다고 하네요. 컴포넌트에 들어있는 모든 state를 대상으로 변경사항이 생기면 재렌더링을 하는 입장에선 선녀같은 기능이지 않을 수 없습니다. 심지어 저기에 대괄호만 써두고 안을 비워두면 mount 시에만 동작하는 기능을 만들 수도 있다는 사실,,,!!

 

심지어 여기에 또 다른 기능이 있는데요

 

 

요런 식으로 useEffect()'의' 콜백함수'의' return()에 코드를 써놓으면 useEffect() 안의 콜백함수가 실행되기 전에 저 코드가 먼저 동작합니다 일명 clean-up function. 어떨 때 쓰려나,,,싶어서 생각을 해보면,,,,

 

만약 변경이 잦은 state를 dependency 인자로 전달해놓고 useEffect()의 콜백함수로 setTimeout() 같은 함수를 넣어놨을 때 clean-up function으로 clearTimeout을 해놓으면 Timeout이 밀려서 쌓이는 일을 방지할 수 있겠구요, useEffect()의 콜백함수로 html 태그의 className 속성을 변경하여 동적인 UI를 만드는 경우에도 요긴하게 쓸 수 있을 것 같습니다. 그래서 정리를 하자면

 

1. 이러면 재렌더링마다 코드를 실행가능합니다.
useEffect(()=>{ 실행할코드 })

2. 이러면 컴포넌트 mount시 (로드시) 1회만 실행가능합니다.
useEffect(()=>{ 실행할코드 }, [])

3. 이러면 useEffect 안의 코드 실행 전에 항상 실행됩니다. 
useEffect(()=>{ 
  return ()=>{
    실행할코드
  }
})

4. 이러면 컴포넌트 unmount시 1회 실행됩니다.
useEffect(()=>{ 
  return ()=>{
    실행할코드
  }
}, [])

5. 이러면 state1이 변경될 때만 실행됩니다.
useEffect(()=>{ 
  실행할코드
}, [state1])

 

이런 느낌이지요

 

이 다음으로 배운 내용은 axios를 통한 ajax 통신인데요, 앞서 많이 다뤘기 때문에 패스,,, 그냥 axios 라이브러리 설치하고 import 하고 

 

 

이런 식이잖아요 모,, 아 ajax 요청을 동시에 할 땐 Promise.all()을 활용하라고 하는데 당장 동시 요청을 할 일은 없을 것 같으니 패스,,!!

 

아 그리고 스쳐지나가듯 배운 건데 왜 그 동안 props 쓸 때 컴포넌트 함수의 매개변수로 props를 쓰고 함수 안에서 props.state1 이렇게 썼었잖아요? 그런데 그냥 매개변수로 { state1 } 이렇게 쓰면 함수 안에서 state1 그대로 쓸 수 있다고 합니다;; 진작 좀 알려주면 좋을 것을;;

 

이렇게 짧게 props를 환기시킨 후 배운 내용은 props를 멸망시킬 Redux입니다. Redux를 사용하면 props 없이 컴포넌트 간 state 공유가 가능하다고 하는데요, 그럼 도대체 props는 왜 있는 거임?이라고 하기엔 생각보다 사용법이 복잡해서 간단한 데이터는 props를 사용하는 게 낫겠더라구요. 지금 Redux 배운 내용 쓰려고 하니 막막합니다. 진짜 개 김 ㄷㄷ,,,

 

우선 세팅 먼저 해봅시다. 그 전에 사실 지금 쓰는 Redux는 Redux toolkit 이라는 점을 알아두고 갑시다. Redux 만든 아재가 본인이 만든 끔찍한 실험물(Redux)을 돌아보며 보다 쉽게 사용하라고 만든 게 Redux toolkit이라고 하네요.

 

세팅하기 전에 확인해야 할 게 있는데요, package.json에 가서 react와 react-dom이 모두 18버전 이상인지 확인해야 합니다. 18버전보다 아래면 안된다고 함ㅋㅋ 까다로운 게 노싸가지임ㅋㅋ 자 확인을 하셨다면 터미널 창에

 

npm install @reduxjs/toolkit@1.8.1 react-redux

 

를 입력해주시구요, src 폴더에 store.js를 만들어 줍니다. 거기에

 

 

이런 코드를 챡 써놓고서는 index.js 로 자리를 옮겨 봅니다. 거기 가선

 

 

store.js에서 export한 걸 store라는 이름으로 받아오고 <App/>을 <Provider>로 감싸줍니다. <Provider>의 속성으론 store = {store}가 들어갔군요. 세팅부터 짜증이 난다 그쵸?? 그럼 고생해서 세팅한 거, 사용해봅시다.

 

 

createSlice()라는 함수의 인자로 객체를 전달합니다. name과 initialState라는 키가 보이는데요, name의 값엔 state의 이름, initialState의 값엔 실제 데이터를 넣어줍니다. 앗 createSlice()를 쓰는 순간 위에 createSlice가 import 되었군요! 자동으로 편리한 시대라지만 긴장을 늦추지 맙시다. 리액트 배우면서 가장 성가신 게 import 였던 것 같습니다. 여튼, 그 후엔 configureStore()의 인자에 담긴 reducer에 사용할 이름을 키로, 사용할이름.reducer를 값으로 적어줍니다. 이렇게 만든 slice 하나가 state 하나와 같습니다. 진짜 개귀찮죠? 이왕 만든 거 써볼까요 그래도

 

 

간단한 컴포넌트를 만들어왔습니다. useSelector()라는 함수를 통해 store.js에 있는 state들을 가져와 주고 그걸 사용한 모습입니다. useSelector도 import 해야하구요(물론 useSelector()를 치면 알아서 됨). 왜 저 useSelector의 콜백함수의 반환값에 state가 아니라 state.myAge 를 쓰면 저 아래서 state.myAge가 아니라 그냥 myAge로 변수를 쓸 수 있다고 하는데 아무래도 state는 한 개만 있는 게 아니니까 저는 그냥 state 쓰겠습니다. 자 state를 사용해봤으면 변경해보기도 해야겠죵?

 

 

createSlice() 안에 있는 객체에 reducers라는 객체를 만들어줍니다. reducer 아닙니다. reducers 입니다. 그리고 그 안에 변경함수를 만들어 주면 되는데요, 콤마로 구분해서 여러개 만들 수 있구요, 각 변경함수에 있는 첫번째 인자(나중에 두번째 인자도 나온다는 떡밥임ㅋㅁㅋ)는 기존 state 값이구요, return으로 변경된 state 값을 넣어주고요,,,

 

export도 해줘야 합니다. myAge.actions 라고 하면 그 자리에 변경함수들이 남는데요 그걸 변수에 잘 담아 떠나보내는 모습입니다. 그래서 이렇게 한 덩어리가 state 하나가 됩니다. 그래서 store.js에 모든 state를 담게 되면 여기도 여간 더러워질 것이기 때문에 여러 파일로 나눠서 state(slice)를 만들고 import 해오는 법도 있었는데 그건 사실 필기도 안하고 까먹어버림 ㅎㅎ,,ㅋㅋ!

 

 

자 변경함수를 만들었으면 써봐야겠죠! 사용할 컴포넌트로 가서! 변경함수 import 하고! useDispatch()써서 그것도 import 하고! dispatch 변수 만들고! 쓸 때는 dispatch()의 인자로 사용할 함수를 적고! 하면 사용할 수 있게 됩니다. 근데 저기 addMyAge() 함수를 보면 왠지 저 인자를 채워주고 싶지 않으실까요,,,?? 그쵸,,,?? 그럼 마음대로 나이를 더할 수 있다구요,,,?? 여튼 저기에 인자를 전달해주면 그 값은,,,

 

 

아까 떡밥을 던졌던 변경함수의 두번째 매개변수에 전달된답니다. 보통 변경함수의 첫번째 매개변수는 state, 두번째 매개변수는 action이라고 한다해서 그냥 그대로 썼구요, action을 함수 내에서 사용하려면 action.payload라고 써야한다고 합니다. 먼길 화물차 타고 오셨으니까,,, 추가로 state가 만약 object / array인 경우에는 변경함수에 return이 없어도 된다고 합니다. 그리고 이것도 앞서 배운 변경함수처럼 원본을 건들지 않고 deep copy를 사용해서 변경하는 걸 리덕스랑 리액트 만든 양반이 추천한다고 함!

 

와 씨 오늘 안에 Redux 다 못할 줄 알았는데 결국 해냈다 다들 박수,,,
사실 남은 내용이 좀 있긴 합니다. js문법인 findIndex(), 일전에 쓴 localStorage, 실시간 데이터를 다룰 때 쓰는 react-query 등이 있는데 이건 다음 게시물에서 쓰기로 합시다. 원래 한 포스팅에서 끝내려고 했는데 오늘은 뭔가 임시저장 안하고 깔끔하게 발행하고 싶은 마음이랄까,,,ㅎㅎ,,,,

 

다 읽은 분이 계실까요? 계신다면 제가 이 링크를 뿌린 곳에 "문영빈 결혼 축하해"라고 써주시길 바랍니다. 이번 주에 친구가 결혼하는데 여러분의 응원을 모아모아 친구에게 잘 전달하도록 하겠습니다. 그럼 20000