Hello, React!
드디어 레벨 2, React와 만나게 되었습니다!
React와 처음 만나니 설레기도, 한편으로는 두렵기도 합니다.
슬슬 어려워지기 시작하는 개발과 유지보수
자바스크립트를 입문한 이후로, 학습할 때나, 프로젝트를 만들어 볼 때나 항상 바닐라 자바스크립트만을 사용했습니다. 라이브러리를 사용하지 않고도 충분히 구현할 수 있었던 것도 있었고, npm으로 정체불명의 무언가를 깔아보는 것은 사실 공포 그 자체였거든요. 뭘 하는지는 모르겠는데 엄청나게 파일이 생긴다라...음, 썩 유쾌한 상황은 아닌 것 같네요.
그런데 백준 확장 프로그램 토탐정을 개발하면서, 슬슬 불편한 상황이 다가오기 시작했습니다.
- 이거 일단 구현해놓긴 했는데, 나중에 다른 걸 수정해야 할 때면 어떻게 해야 하지? 특히나 그게 빈번하다면?
- 새로운 기능들을 추가해야 하는데, 기능들을 분리하기 어렵다. 대체 어디에 집어 넣어야 하지?
- 이슈에 올라온 요구사항을 반영하는 데 너무 시간이 오래 걸리는데...
슬슬 불만족스러워지기 시작했습니다.
불만 속에서 사람들은 새로운 기술을 만들어 내요
웹을 처음 입문할 때 생활코딩으로 입문했는데, 해당 강의에서 나왔던 인상 깊었던 멘트들을 여기 적어 볼게요.
처음에는 HTML만 있어도 사람들은 행복했습니다. 웹페이지는 혁명 그 자체였거든요.
하지만 사람들은 웹페이지를 아름답게 만드는 방법에 대한 깊은 고민에 빠지고, 불만을 토로했습니다. CSS가 탄생했습니다. HTML과 CSS의 환상의 콤비 속에서 사람들은 만족했습니다.
하지만 사람들은 정적인 페이지의 한계를 벗어날 수 없는 HTML에 대해 불만을 토로했고, 페이지를 동적으로 작동하게 해 사용자와 상호작용하고 싶은 웹페이지를 만들어 내도록 하고 싶었습니다. JavaScript가 탄생했습니다.
이와 같이, 새로운 기술들은 사람들의 불만과 그 불만을 해소하고자 하는 의지에서 비롯된 것이라 생각합니다. 오늘날 수많은 라이브러리들 역시, 사람들의 불만 속에서 탄생한 것이겠지요.
컴포넌트와 함께, 유지보수 하기 좋은 프로젝트를 꼭 만들고 싶어요. React와 함께 하고 싶어요
함수를 사용하고, 기능을 분리했을 때의 이점은 무엇일까요? 저한테 바로 떠오르는 장점은 바로 불필요한 반복을 줄여준다는 점, 그리고 그 기능(함수)에만 집중할 수 있다는 점이네요.
React에서는 컴포넌트 단위로 사용자의 인터페이스를 작성하기에 특화된 라이브러리라고 생각해요. 지금까지 불필요한 HTML 태그들을 반복해서 적고, 기능들을 분리하는 것에 어려움을 겪었어요.
React를 학습하면서 필요성을 느끼고, 사람들이 느꼈던 불만에 대해 어떻게 해결 방법을 찾아나가고 싶었는지를 느껴보고 싶어요. 그리고 컴포넌트 단위로 개발하면서, 그 컴포넌트에만 집중하면서 한땀한땀 정성껏 개발해 보고 싶어요.
다시, 점심 뭐먹지
설렘과 두려움 속에서 레벨2의 첫 번째 미션이 주어졌습니다. 이제부터는 React를 사용한다는 조건이 붙지만, 근본적으로는 레벨1의 점심 뭐먹지 미션과 해야 하는 고민은 같았습니다. 반복되는 것들을 보면서 불편함을 느끼고, 컴포넌트를 이용해 필요성을 깨닫기. 미션을 진행하면서 React를 이용해 기본적인 컴포넌트들을 어떻게 작성하는지, 그리고 React의 생명 주기를 통해 이러한 컴포넌트들이 어떻게 랜더링되는지에 대해 알아볼 수 있었습니다.
아래에 미션을 통해 배운 리액트의 기본 개념들을 적어보고자 합니다.
하위 컴포넌트에 속성을 전달 - props
React에서 컴포넌트를 사용하는 이유 중 하나는 바로 일일이 코드를 작성하지 않고 반복을 줄이기 위함이겠죠. props는 컴포넌트의 속성을 설정할 때 사용하는 요소입니다. 마치 매개 변수를 전달하듯이, 하위 컴포넌트에 필요한 속성들을 전달해 줍니다. 컴포넌트에 필요한 속성들만 전달해 주면, 나머지는 만들어 둔 컴포넌트가 알아서 작업을 수행하는 것이죠!
props를 전달할 때는 상위 컴포넌트에서 하위 컴포넌트로만 값을 전달할 수 있어요. 그 반대는 안 됩니다. 또한, 상위 컴포넌트로부터 받은 props는 절대 변경할 수 없습니다. 변경하려면, 상위 컴포넌트가 재랜더링 되면서 새로운 props를 전달해야만 하죠.
컴포넌트 내에서 관리하는 값 - state
외부에서 값들을 주는 props가 있다면, 컴포넌트 내에서도 값들을 관리할 수도 있습니다. 이를 state라고 합니다.
처음에는 일반 변수와 다를 바가 뭐가 있지를 생각했습니다만 눈에 띄는 state와 일반 변수의 차이점은 바로 state가 변경되면 해당 컴포넌트가 재랜더링이 일어난다는 것입니다. 재랜더링이 되면서 바뀐 state 값은 해당 컴포넌트와 하위 컴포넌트 등에게 영향을 줄 수 있겠죠. 뜻 그대로 컴포넌트의 상태를 관리합니다.
props와 다르게 state 값들은 언제든지 해당 컴포넌트에 의해 변경될 수 있습니다.
컴포넌트가 랜더링 되는 절차와 원리 - 생명주기(LifeCycle)
리액트에서는 컴포넌트가 생성될 때 / 업데이트 될 때 / 제거할 때 실행되는 절차가 있고, 그 때마다 호출되는 함수가 있습니다. 1단계에서 클래스 컴포넌트를 사용하여 미션을 구현했는데, 확실히 생명주기를 어느 정도 이해하고 사용하니 어떻게 랜더링이 일어날 지, 혹시 불필요한 랜더링이 여러 번 일어나지는 않을지에 대해 생각해 볼 수 있었습니다. 함수형 컴포넌트는 useEffect() 등을 사용하여 컴포넌트가 생성/재랜더링 될 때 실행할 동작들을 정의할 수 있습니다.
컴포넌트의 동작을 분리 - Custom Hooks
우리가 함수를 이용해 복잡한 기능들을 분리했다면 React에는 Custom Hooks가 있습니다. 일반 함수와의 차이점을 찾기가 정말 힘들었는데, Custom Hooks에서는 useState를 사용하여 컴포넌트의 기능들을 밖으로 빼내고, 복잡한 로직들을 편하게 사용할 수 있도록 도와줍니다. useState를 사용하므로 컴포넌트를 필요에 따라 랜더링시키는 것 역시 가능합니다.
사용하는 입장에서는 useState와 같은 Hook을 사용하듯이 손쉽게 사용할 수 있습니다.
위의 코드는 제가 첫 번째로 도입해 본, 모달이 열려 있는지의 여부를 관리하는 간단한 Custom Hooks입니다. 원래라면 App 내에 모달을 열고 닫는 로직을 두어야 하는데 App에서 굳이 그런 기능까지 알고 있어야 하는가에 대해 의문이 들었고, 고민 끝에 모달이 열려 있는지의 여부를 관리하는 로직들은 Custom Hooks로 빼냈습니다. 사용하는 입장에서는 별도의 함수를 또 정의할 필요 없이 openModal, closeModal만 실행하면서, 자동으로 isOpen 값이 변경되는 것만 지켜보면 되겠죠!
이 Custom Hooks 말고도, 아예 레스토랑에 대한 필터링/정렬 을 하는 Custom Hooks도 구현했는데, 만들다 보니까 덩치가 무지하게 커지고 수행하는 기능도 많아졌습니다. 함수와 마찬가지로 Custom Hooks 또한 담당하는 기능이 너무 많다면 여러 개로 적당히 쪼개는 작업이 필요합니다.
앞으로 계속해서 고민해 봐야 하는 것들
1. 메모이제이션
지금까지는 효율성을 고려하지 않고, 프로그램이 일단 돌아가도록 만드는 것을 중점으로 구현했습니다. 아무리 React가 최적화를 해 준다지만, 컴포넌트가 랜더링 된다는 것은 그 내용물이 모두 다시 랜더링 되고, 함수 등의 요소들도 다시 랜더링됩니다. 굳이 랜더링을 다시 해 주지 않아도 됨에도 불구하고 말이죠!
랜더링이 자주 일어나지 않아도 되는 부분, 불필요한 랜더링이 일어나는 부분들을 찾아 미리 결과들을 저장해 놓고, 이후 같은 props가 주어지는 경우 다시 재랜더링 할 필요없이 저장해 두었던 값들을 반영하는 등 여러 가지 최적화를 할 수 있을 것입니다.
메모이제이션... 알고리즘 문제에 적절히 활용해서 매우 큰 효율을 뽑아낸 적이 많죠. 이제 React에도 상황에 따라 활용할 때가 왔군요. 메모이제이션은 최적화에 좋지만, 그만큼 메모리를 할당해야 하는 trade-off가 있습니다. 기껏 값들을 메모이제이션 해 두었는데 정작 쓰이지도 않으면 안 쓴 것보다 못 하겠죠. 어떤 상황에서 메모이제이션을 하는 것이 좋을 지 생각해 보아야 겠네요.
2. 역할 분리하기
함수를 구현할 때 기능 단위로 분리하여 작성했듯이, custom hooks나 컴포넌트를 작성할 때도 마찬가지로 관심사를 분리하고 하나의 역할만 수행하도록 만들어 주는 것이 필요해 보입니다. 처음으로 custom hooks를 사용해 만든 useRestaurant hook은 기능이 엄청나게 많이 담긴 뚱보 그 자체였죠...!
custom hooks가 담당하고 있는 기능이 많다면 쪼개고, 컴포넌트는 UI와 이벤트만 알도록 만들어 봐야겠죠!
useMemo, useCallback, useEffect, ... 뭔가 use로 시작되는 생소한 개념들이 많습니다. 원리를 이해하지 못 한다면 예상치 못 한 상황이 발생할 수 있겠죠. 공식 문서와 책을 꼭 봐서 원리를 제대로 이해해야겠습니다!
'우아한테크코스' 카테고리의 다른 글
우아한테크코스 5기 - Lv. 2 "페이먼츠" 미션 (0) | 2023.05.15 |
---|---|
우아한테크코스 5기 - Lv. 1 자동차 경주 미션 (0) | 2023.03.24 |
온보딩 미션 - 연극 후기 (6) | 2023.02.27 |
우아한테크코스 5기 지원 후기 (2) | 2023.01.12 |
우아한테크코스 5기 - 최종 코딩테스트, 그리고 결과 (0) | 2023.01.12 |