[React] # 11 Reactive 하게 사고하기

simoniful·2021년 7월 11일
0

React

목록 보기
11/13
post-thumbnail

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

모든 컴포넌트(와 하위 컴포넌트)의 주변에 박스를 그리고 그 각각에 이름을 붙이는 것을 시작으로 UI의 구성을 시작합니다. Photoshop 레이어처럼 기본적인 요소의 분화와 한 가지 일을 하는게 이상적이라는 대원칙을 토대로 컴포넌트를 분리하여 구성합니다.

UI와 데이터 모델이 같은 인포메이션 아키텍처(information architecture)를 가지는 경향이 있기 때문에, 각 컴포넌트가 데이터 모델의 한 조각을 나타내도록 분리해야합니다. 데이터 모델이 적절하게 만들어졌다면, 컴포넌트 구조는 잘 연결됩니다. 따라서, 사전에 상의를 통하여 데이터 테이블을 잘 구성하는 게 필요합니다.

기획 단계에서 이를 고려하여 컴포넌트를 잘 분리하여 활용하면, 재사용성에 있어서 보다 편리하게 접근이 가능하고 중복된 코드를 줄일 수 있습니다.

React로 정적인 버전 만들기

데이터 모델을 가지고 UI를 렌더링은 되지만 아무 동작도 없는 버전을 만들고 시작하면 작업에 있어서 단계를 파악하기 쉽습니다. 초기에 HTML과 CSS만으로 만들었던 사이트들은 생각하면서 레이아웃과 구조, 시멘틱에 관하여 뼈대를 만들어두고 작업하는 것이 좋습니다.

하향식(top-down)이나 상향식(bottom-up)으로 앱의 컴포넌트를 프로젝트에 따라 계층대로 구성하고, 가장 상위 컴포넌트에서 핵심 data를 아래로 흘려보내는 방식으로 props를 활용합니다. React의 단방향 데이터 흐름은 모든 것을 모듈화 하고 빠르게 만들어줍니다.

가장 작지만 완전한 역할의 State

UI를 상호작용하게 만들려면 기반 데이터 모델을 변경할 수 있는 방법이 있어야 합니다. React는 state를 통해 이를 변경합니다. 애플리케이션이 필요로 하는 가장 최소한의 state를 찾고, 필요에 따라 계산되도록 state의 초기상태를 구성합니다. 그리고, 한 가지 진리의 원천에서 가능하다면 해결하는 것을 우선적으로 상태 관리를 해야합니다.

예를 들어 TODO 리스트를 만든다고 하면, TODO 아이템을 저장하는 배열만 유지하고 TODO 아이템의 개수를 표현하는 state를 별도로 만드는 것은 비효율 적입니다. TODO 아이템 배열만으로 충분합니다.

**props와 state의 차이

  • props : (함수 매개변수처럼) 컴포넌트로 전달되어지는 값, 변경되지 않는 불변성
  • state : (함수 내에 선언된 변수처럼) 렌더링 간에 추적되어 변경되어지는 정보

State가 어디에 있어야 할 지 찾기

어떤 컴포넌트가 state를 변경하거나 소유할지 찾는 것 중에 기억해야 할 점은 데이터의 단방향성입니다. state를 기반으로 렌더링 되는 모든 컴포넌트 중에서 가장 상위에 있는 컴포넌트에 state를 소유하도록 하고, props로 해당 값을 아래 컴포넌트까지 넘겨주어 관리합니다.

역방향 데이터 흐름 추가하기

계층 구조의 하단에 있는 컴포넌트에서 상위에 state를 가지고 있는 컴포넌트에 핸들링 함수를 통하여 state의 변경을 요청하고 이를 업데이트 할 수 있습니다. 지식의 원천이라고 할 수 있는 한 곳에 있는 데이터를 관리하면서 이에 대한 순환을 이해하고 잘 활용한다면 트리구조가 잘 짜여진 컴포넌트 속에서 원활한 데이터 흐름을 구성할 수 있습니다.


목업

프론트엔드 개발을 하다보면 UI 구성에 필요한 데이터들이 생길 수 있습니다. 데이터가 정적일 경우 UI에 필요한 데이터를 서버에서 가져오지 않고 프론트 단에서 직접 구성합니다. 백엔드 측과 상의를 하여 조율하고 미리 UI를 구성하는데 있어서도 매우 유용하기에 서버에서 받을 값을 예상해서 UI 개발을 진행할 수 있습니다. JSON 타입과 JS 타입으로 활용이 가능합니다.

상수 데이터

이름 그대로 변하지 않는 데이터. 즉, 정적인 데이터 UI 구성에 필요하지만 동적으로 변하지 않아서 백엔드 API등을 통해서 가져올 필요가 없는 정적인 데이터들을 상수 데이터로 만들어 UI를 효율적으로 구성할 수 있습니다.

반복되는 UI를 하드코딩으로 만들어두게 되면, 가독성에 좋지 않고 수정이 필요할 시 해당하는 부분을 찾기 힘들어 추후 유지보수가 힘들어질 수 있습니다. UI를 상수 데이터 + Array.map() 함수의 조합을 이용해서 간결하게 표현이 가능합니다. 주로 메뉴 구성과 같은 반복적인 리스트 요소가 정렬되는 경우 사용합니다.

commentData.js

const COMMENT_LIST = [
  {
    id: 1,
    userName: 'wecode',
    content: 'Welcome to world best coding bootcamp!',
    isLiked: true
  },
  {
    id: 2,
    userName: 'joonsikyang',
    content: 'Hi there.',
    isLiked: false
  },
  {
    id: 3,
    userName: 'jayPark',
    content: 'Hey.',
    isLiked: false
  }
];

export default COMMENT_LIST;

CommentList.js

import React, { Component } from 'react';
import Comment from './Comment/Comment';
import COMMENT_LIST from './commentData';
import './CommentList.scss';

class CommentList extends Component {
  render() {
    return (
      <div className="CommentList">
        <h1>댓글</h1>
        <ul>
          {COMMENT_LIST.map(comment => {
            return (
              <Comment
                key={comment.id}
                name={comment.userName}
                comment={comment.content}
              />
            );
          })}
        </ul>
      </div>
    );
  }
}

export default CommentList;

Mock data

실제 API 에서 받아온 데이터가 아닌 프론트엔드 개발자가 필요에 의해 샘플로 만들어 본 데이터로 mock data를 만드는 과정에서 백엔드 API에서 보내주는 response가 어떤 형태인지, key-value값을 확인하고 미리 mock data와 백엔드 response의 형태를 맞춰보면서 개발을 진행한다면 추후 실제 API를 훨씬 수월하게 연결 할 수 있습니다. 백엔드 API를 모방하기에 실제 백엔드 API에서 응답값의 형태인 json 파일로 만들어줘야합니다.

commentData.json

[
  {
    "id": 1,
    "userName": "wecode",
    "content": "Welcome to world best coding bootcamp!",
    "isLiked": true
  },
  {
    "id": 2,
    "userName": "joonsikyang",
    "content": "Hi there.",
    "isLiked": false
  },
  {
    "id": 3,
    "userName": "jayPark",
    "content": "Hey.",
    "isLiked": false
  }
]

commentList.js

import React, { Component } from 'react';
import Comment from './Comment/Comment';
import './CommentList.scss';

class CommentList extends Component {
  constructor() {
    super();
    this.state = {
      commentList: [],
      commentValue: ''
    };
  }

  componentDidMount() {
    fetch('http://localhost:3000/data/commentData.json', {
      method: 'GET' // GET method는 기본값이라서 생략이 가능합니다. 
    })              // 예시코드에서는 이해를 돕기 위해 명시적으로 기입해뒀습니다.
      .then(res => res.json())
      .then(data => {
        this.setState({
          commentList: data,     
        });
      });
  }

 render() {
    const { commentList, commentValue } = this.state;

    return (
      <div className="comment">
        <h1>Main Page</h1>
        <ul>
          {commentList.map(comment => {
            return (
              <Comment
                key={comment.id}
                name={comment.userName}
                comment={comment.content}
              />
            );
          })}
        </ul>
        <div className="commentInput">
          <form onSubmit={this.addComment}>
            <input
              onChange={this.handleCommentValue}
              type="text"
              placeholder="enter comment"
              value={commentValue}
            />
            <button 
              className="addCommentBtn" 
              type="submit" 
              onClick={this.addComment}
            >
              Click
            </button>
          </form>
        </div>
      </div>
    );
  }
}

export default Comment;

Fetch
Fetch 사용법

Json Method

res Object

PostMan

profile
소신있게 정진합니다.

0개의 댓글