React_Docs : React로 사고하기

daymoon_·2022년 6월 10일
0

ReactDocs

목록 보기
11/11
post-thumbnail

React로 사고하기

🔎 React 공식문서 자료
React_React로 사고하기

React는 JavaScript로 규모가 크고 빠른 웹 애플리케이션을 만드는 가장 좋은 방법입니다. React는 Facebook과 Instagram을 통해 확장석을 입증했다.

React의 가장 멋진 점 중 하나는 앱을 설계하는 방식이다.


목업으로 시작하기

JSON API와 목업으로 디자이너로부터 받았다고 가정하자. 목업은 다음과 같다.

JSON API는 아래와 같은 데이터를 반환한다.

[
  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];

1단계 : UI를 컴포넌트 계층 구조로 나누기

우리가 할 첫 번째 일은 모든 컴포넌트(와 하위 컴포넌트)의 주변에 박스를 그리고 그 각각에 이름을 붙이는 것이다. 디자이너와 함께 일한다면, 이것들을 이미 정해두었을 수도 있다. 디자이너의 포토샵 레이어 이름이 React 컴포넌트의 이름이 될 수 있다.

하지만 어떤 것이 컴포넌트가 되어야 할지 어떻게 알 수 있을까? 우리가 새로운 함수나 객체를 만들 때 처럼 만들면 된다. 한 가지 테크님은 단일 책임 원칙이다. 이는 하나의 컴포넌트는 한 가지 일을 하는게 이상적이라는 원칙이다. 하나의 컴포넌트가 커지게 된다면 이는 보다 작은 하위 컴포넌트로 분리되어야 한다.

단일 책임 원칙(Single responsibility principle)이란?

주로 JSON 데이터를 유저에게 보여주기 때문에, 데이터 모델이 적절하게 만들어졌다면, UI(컴포넌트 구조)가 잘 연결될 것이다. 이는 UI와 데이터 모델이 같은 인포메이션 아키텍처(information architecture)를 가지는 경향이 있기 때문이다. 각 컴포넌트가 데이터 모델의 한 조각을 나타내도록 분리해야 한다.

다섯개의 컴포넌트로 이루어진 앱을 한 번 살펴보자!

각각의 컴포넌트에 들어간 데이터는 이탤릭체 로 표기했다. 이미지의 숫자는 아래 숫자에 해당된다.

  1. FilterableProductTable (노란색) : 예시 전체를 포괄한다.

  2. SearchBar (파란색) : 모든 유저의 입력(user input)을 받는다.

  3. ProductTable (연두색) : 유저의 입력(user input)을 기반으로 데이터 콜렉션(data collection)을 필터링해서 보여준다.

  4. ProductCategoryRow (하늘색) : 각 카테고리(category)의 헤더를 보여준다.

  5. ProductRow (빨강색) : 각각의 제품(Product)에 해당하는 행을 보여준다.


ProductTable을 보면 "Name"과 "Price" 레이블을 포함한 테이블 헤더만을 가진 컴포넌트는 없다. 이 같은 경우, 데이터를 위한 독립된 컴포넌트를 생성할지 생성하지 않을지는 선택이다. 이 예시에서는 ProductTable의 책임인 데이터 컬렉션(data collection)이 렌더링의 일부이기 때문에 ProductTable을 남겨두었다. 그러나 이 헤더가 복잡해지면 (즉, 정렬을 위한 기능을 추가하는 등) ProductTableHeader 컴포넌트를 만드는 것이 더 합리적이다.

이제 목업에서 컴포넌트를 확인했으니 이를 계층 구조로 나열해 보자!!
모형의 다른 컴포넌트 내부에 나타나는 컴포넌트 계층 구조의 자식으로 나타낸다.


2단계 : React 정적인 버전 만들기

이제 컴포넌트 계층구조가 만들어졌으니 앱을 실제로 구현해 보자!!

가장 쉬운 방법은 데이터 모델을 가지고 UI 렌더링은 되지만 아무 동작도 없는 버전을 만들어보는 것이다. 이처럼 과정을 나누는 것이 좋은데 정적 버전을 만드는 것은 생각이 적게 필요하지만 타이핑은 많이 필요로 하고, 상호작용을 만드는 것은 생각은 많이 해야 하지만 타이핑은 정게 필요로 하기 때문이다.

데이터 모델을 렌더링하는 앱의 정적 버전을 만들기 위해 다른 컴포넌트를 재사용하는 컴포넌트를 만들고 props를 이용해 데이터를 전달한다. props는 부모가 자식에게 데이터를 넘겨줄 때 사용할 수 있는 방법이다. 정적 버전을 만들기 위해 state를 사용하지 말아야 한다. state는 오직 상호작용을 위해, 즉 시간이 지남에 따라 데이터가 바뀌는 것에 사용한다. 우리은 앱의 정적 버전을 만들고 있기 때문에 state는 필요 없다.

앱을 만들 때 하향식(top-down)이나 상향식(bottom-up)으로 만들 수 있다. 다시 말해 계층 구조의 상층부에 있는 컴포넌트 (즉, FillterableProductTable 부터 시작하는 것)q부터 만들거나 하층부에 있는 컴포넌트 (ProductRow)부터 만들 수도 있다. 간단한 예시에서는 보통 하향식으로 만드는 게 쉽지만 프로젝트가 커지면 상향식으로 만들고 테스트를 작성하면서 개발하기가 더 쉽다.

이 단계가 끝나면 데이터 렌더링을 위해 만들어진 재사용 가능한 컴포넌트들의 라이브러리를 가지게 된다. 현재는 앱의 정적 버전이기 때문에 컴포넌트는 render() 메서드만 가지고 있을 거이다. 계층구조의 최상단 컴포넌트 (FilterProductTable)는 prop으로 데이터 모델을 받는다. 데이터 모델이 변경되면 ReactDOM.render()를 다시 호출해서 UI가 업데이트 된다. UI가 어떻게 업데이트되고 어디에서 변경해야하는지 알 수 있다. React의 단방향 데이터 흐름 (one-way data flow) 또는 단방향 바인딩 (one-way binding)은 모든 것을 모듈화 하고 빠르게 만든어 준다.


3단계 : UI state에 대한 최소한의 (하지만 완전한) 표현 찾아내기

UI를 사용작용하게 만들려면 기반 데이터 모델을 변경할 수 있는 방법이 있어야 한다. 이를 React는 state를 통해 변경한다.

🔎 Props vs State : 차이점은??

  • React_state와 props
  • props(properties)와 state는 일반 JavaScript 객체이다.
  • 두 객제 모두 렌더링 결과물에 영향을 주는 정보를 작고 있는데, 방식에 차이가 있다.
  • props : 부모 컴포넌트가 자식 컴포넌트에게 전달한다. 단, 자식 컴포넌트는 부모 컴포넌트에게 전달할 수 없으며 오로지 읽기만 가능한 값이다.
  • state : 컴포넌트 안에서 관리한다. 즉, 함수 안에서 선언된 지역 변수처럼 사용되는 값이다.

애플리케이션을 올바르게 만들기 위해서는 애플리케이션에서 필요로 하는 변경 가능한 state의 최소 집합으로 생각해야 한다. 여기서 핵심은 중복 배제 원칙이다. 애플리케이션이 필요로 하는 가장 최소한의 state를 찾고 이를 통해 나머지 모든 것들이 필요에 따라 그때 그때 계산되도록 만들어야 한다. 예를 들어, TOTO 아이템의 개수를 표현하는 state를 변도로 만들지 말아야 한다. TODO 갯수를 렌더링해야 한다면 TODO 아이템 배열의 길이를 가져오면 된다.

중복 배제 원칙(Don't repeat yourself; DRY)

  • wikipedia_중복 배제
  • 소프트웨어 개발 원리의 하나로, 모든 형태의 정보 중복을 지양하는 원리이다.
  • 특히, 다층 구조 시스템에서 유용하다.
  • "모든 지식은 시스템 내에서 유일하고 중복이 없으며 권위있는 표상만을 가진다."

예시 애플리케이션 내 데이터들을 생각해 보자!! 애플리케이션은 다음과 같은 데이터를 가지고 있다.

  • 제품의 원본 목록
  • 유저가 입력한 검색어
  • 체크박스의 값
  • 필터링 된 제품들의 목록

각각 살펴보고 어떤 게 state가 되어야 하는지 살펴보자!! 이는 각 데이터에 대해 아래의 세 가지 질문을 통해 결정할 수 있다.

  1. 부모로부터 props를 통해 전달이 가능한가?

  2. 시간이 지나도 변하지 않는가?

  3. 컴포넌트 안의 다른 state나 props를 가지고 계산 가능한가?


제품의 원본 목록은 props를 통해 전달되므로 state가 아니다. 검색어와 체크박스는 state로 볼 수 있는데 시간이 지남에 따라 변하기도 하면서 다른 것들로 부터 계산될 수 없기 때문이다. 그리고 마지막으로 필터링된 목록은 state가 아니다. 제품의 원본 목록과 검색어, 체크박스의 값을 조합해서 도출할 수 있기 때문이다.

결과적으로 애플리케이션은 유저가 입력한 검색어체크박스의 값이 state를 가진다.


4단계 : state가 어디에 있어야 할 지 찾기

다음으로 어떤 컴포넌트가 state를 변경하거나 소유할지 찾아야 한다.

🛑 주의

  • React는 항상 컴포넌트 계층구조를 따라 아래로 내려가는 단방향 데이터 흐름을 따른다. 그래서 어떤 컴포넌트가 어떤 state를 가져야 하는지 바로 결정하기 어려울 수 있다.
  • 초보자들이 가장 어려워 하는 부분!! 집중! 🙀

애플리케이션이 가지는 각각의 state에 대해서

  1. state를 기반으로 렌더링하는 모든 컴포넌트를 찾는다.

  2. 공통 소유 컴포넌트(common owner component)를 찾는다. → 계층 구조 내에서 특정 state가 있어야 하는 모든 컴포넌트들의 상위에 있는 하나의 컴포넌트

  3. 공통 혹은 더 상위에 있는 컴포넌트가 state를 가져야한다.

  4. state를 소유할 적절한 컴포넌트를 찾지 못했다면, state를 소유하는 컴포넌트를 하나 만들어서 공통 오너 컴포넌트의 상위 계층에 추가한다.


이 전략을 애플리케이션에 적용하면 다음과 같다.

  • ProductTable은 state에 의존한 상품 리스트의 필터링해야 하고 SearchBar는 검색어와 체크박스의 상태를 표시해야 한다.

  • 공통 소유 컴포넌트는 FilterableProductTable이다.

  • 의미상으로도 FilterableProductTable이 검색어와 체크박스의 체크 여부를 가지는 것이 타당하다.


먼저 인스턴스 속성인 this.state = {filterText: '', inStockOnly: false} 를 FilterableProductTable의 constructor에 추가하여 애플리케이션의 초기 상태를 반영합니다. 그리고 나서 filterText와 inStockOnly를 ProductTable와 SearchBar에 prop으로 전달합니다. 마지막으로 이 props를 사용하여 ProductTable의 행을 정렬하고 SearchBar의 폼 필드 값을 설정하세요.


5단계 : 역방향 데이터 흐름 추가하기

지금까지 우리는 계층 구조 아래로 흐르는 props와 state의 함수로써 앱을 만들었다. 이제 다른 방향의 데이터 흐름을 만들어 보자!!

계층 구조의 하단에 있는 폼 컴포넌트에서 FilterableProductTable의 state를 업데이트할 수 있어야 한다.

React는 전통적인 양방향 데이터 바인딩(two-way data binding)과 비교하면 더 많은 타이핑을 필요로 하지만 데이터 흐름을 명시적으로 보이게 만들어서 프로그램이 어떻게 동작하는지 파악할 수 있게 도와준다.

4단계의 예시에서 체크하거나 키보드를 타이핑할 경우 React가 입력을 무시하는 것을 확인할 수 있다. 이는 input 태그의 value 속성이 항상 FilterableProductTable에서 전달된 state와 동일하도록 설정했기 때문입니다.

우리가 원하는 것이 무엇인지를 한번 생각해 보자..!

우리는 사용자가 폼을 변경할 때마다 사용자의 입력을 반영할 수 있도록 state를 업데이트하기를 원한다. 컴포넌트는 그 자신의 state만 변경할 수 있기 때문에 FilterableProductTable는 SearchBar에 콜백을 넘겨서 state가 업데이트되어야 할 때마다 호출되도록 할 것이다. 우리는 input에 onChange 이벤트를 사용해서 알림을 받을 수 있다. FilterableProductTable에서 전달된 콜백은 setState()를 호출하고 앱이 업데이트될 것이다.


👋 Comment

React를 너무 후다닥 배운 감이 있어서 공식 문서를 보면서 기초를 다시 공부했다..
그리고.. 너무 무지성으로 짠것 같아서 스스로에게 너무 화가 났기도..ㅠㅠ🙀🙀

아직 갈 길이 멀다..!! 기본적인 실습을 하고 고급 안내서로..!!!

profile
미지의 공간🌙

0개의 댓글