---
description: 더미데이터를 만들어 컴포넌트에 데이터를 전달해보고, map()을 이용해 더 계층적인 컴포넌트로 리팩토링 해보면서 느낀점들.
---

# 4. 프론트엔드의 역할은 어디까지 - 더미데이터 만들기

## 1. 목표

* [예발자닷컴](https://www.yebalja.com) 코드 리팩토링하기
  * 더미데이터 배열 만든 뒤 `TimelineListItem` 컴포넌트에 각각 다른 데이터 넣기.

## 2. 현재 컴포넌트 구조

![스크린샷 2020-07-25 오후 5 22 41](https://user-images.githubusercontent.com/37580034/88452736-22a9e100-ce9c-11ea-8428-d0751984ff19.png)

* `TimelineList`
  * `TimelineListItem`
    * Title : "2차"
    * Status : "모집중"
    * Content : "온라인 코딩테스트"
    * Date : "7. 4."

## 3. map() 메서드를 사용하는 이유

리액트에서는 state 내부의 값을 직접적으로 수정하면 안 된다. 이를 **불변성 유지**라고 한다.

push, splice, pop 같은 내장함수는 배열 자체를 직접 수정하게 되므로 **불변성 유지** 원칙에 적합하지 않다. 그 대신에, 기존의 배열에 기반하여 새 배열을 만들어내는 함수인 concat, slice, `map`, filter 같은 함수를 사용해야한다고 한다.

## 4. map() 메서드 사용법

`map()` 메서드는 `callback` 함수를 **각각의 요소에 대해 한번씩** 순서대로 불러 그 함수의 반환값으로 새로운 배열을 만든다.

> 주의 : `callback` 함수는 배열 값이 들어있는 인덱스에 대해서만 호출된다. 즉, 값이 삭제되거나 아직 값이 할당/정의되지 않은 인덱스에 대해서는 호출되지 않기 때문에 값을 꼭 초기화해두자.

```javascript
const dataSet = [{
    name : 'daelee',
    age : '24'},
    {
    name : 'secho',
    age : '27'}];

dataSet.map(obj => obj.name = 'taelee');

console.log(dataSet[0].name);
```

```
> "taelee"
```

더 다양한 예제는 [여기](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map) 참고.

### 4.1. 프로토타입

```javascript
arr.map(callback(currentValue[, index[, array]])[, thisArg])
```

#### 매개변수

* `currentValue` :   처리할 현재 요소.
* `index` : 처리할 현재 요소의 인덱스.
* `array` : `map()`을 호출한 배열. <- 어떤 용도인지 잘 이해안됨. 그냥 써두는건가?

#### 반환 값

배열의 각 요소에 대해 실행한 `callback`의 결과를 모은 새로운 배열.

## 5. Refactoring

### 5.1. TimelineList 수정

```
export function TimelineList() {

    const dataList = [
            {
                title: "-",
                status: "-",
                content: "-",
                date: "-"
            },
            {
                title: "-",
                status: "-",
                content: "-",
                date: "-"
            },
            {
                title: "-",
                status: "-",
                content: "-",
                date: "-"
            },
            {
                title: "-",
                status: "-",
                content: "-",
                date: "-"
            },
            {
                title: "-",
                status: "-",
                content: "-",
                date: "-"
            },
            {
                title: "-",
                status: "-",
                content: "-",
                date: "-"
            },
        ]

    return (
        <>
            {dataList.map((v, idx) => <TimelineListItem data={v} key={idx}/>)}
        </>
    )
}
```

* `dataList` 라는 더미데이터 배열을 만든다. 프론트에서 여기까지 해놔야 서버에서 어떤 데이터를 가져올지 감을 잡을 수 있다.
* `{dataList.map((v, idx) => <TimelineListItem data={v} key={idx}/>)}`
  * 모든 `dataList` 에 `map()`을 적용한 `TimelineListItem` 을 반환한다.
  *   `v` 에는 아래 배열 하나하나, 총 6개의 배열이 리스트로 담긴다.

      ```
      {
       title: "2차",
       status: "모집중",
       content: "온라인 코딩테스트",
       date: "7. 4."
      },
      ```
  * `TimelineListItem`에 `v`를 `data`로, `idx`를 `key`로 담아 보낸다.

### 5.2. TimelineListItem 수정

```
export function TimelineListItem ({data}) {
    return (
            <li className={styles.list}>
                <div className={classNames({[styles.card]: true, [styles.card_edu]: true})}>
                    {data.title}
                    <span className={styles[data.status]}></span>
                    <div className={styles.content}>{data.content}</div>
                    <div>{data.date}</div>
                </div>
            </li>
    )
}
```

* 원래 하드코딩 되어있던 title, status, content, date의 내용을 `data` state의 값들로 바꿔주었다.
* 아직 idx는 사용하지 않았는데, 추후 css를 인덱스 별로 다르게 적용할 때 사용하려고 한다.

### 5.3. HorizontalTimeline 에서의 호출

```
export default function HorizontalTimeline() {

    return (
        <div className={styles.body}>
            <Header className={styles.header}>
                <h1>네이버 부스트캠프</h1>
                <p>개발자의 지속 가능한 성장을 추구하는 학습 커뮤니티</p>
            </Header>
            <div className={styles.line}></div>
            <div className={styles.timeline}>
                <TimeLineList />
            </div>
        </div>
    );
}
```

* `<TimeLineList />`를 단 한번 호출하는 것만으로 총 6개의 타임라인 리스트 아이템이 렌더링된다.
*   아래 원래 `HorizontalTimeline`코드와 비교해보면 얼마나 코드가

    구조화되고, 깔끔해졌고, **리액트스러워졌는지** 알 수 있다...!

```
export default function HorizontalTimeline() {

    return (
        <div className={styles.body}>
            <Header className={styles.header}>
                <h1>네이버 부스트캠프</h1>
                <p>개발자의 지속 가능한 성장을 추구하는 학습 커뮤니티</p>
            </Header>
            <div className={styles.line}></div>
            <div className={styles.timeline}>
                <ol className={styles.order}>
                    <li className={styles.list}>
                        <div className={classNames({[styles.card]: true, [styles.card_end]: true})}>
                            접수기간<span className={styles.status_end}>마감</span><div className={styles.content}>6.1 11:00 ~ 6.30 23:59</div>
                        </div>
                    </li>
                    <li className={styles.list}>
                        <div className={classNames({[styles.card]: true, [styles.card_end]: true})}>
                            1차<span className={styles.status_end}>마감</span><div className={styles.content}>온라인 코딩테스트<br/>7.4</div>
                        </div>
                    </li>
                    <li className={styles.list}>
                        <div className={classNames({[styles.card]: true, [styles.card_now]: true})}>
                            2차<span className={styles.status}>모집중</span><div className={styles.content}>온라인 코딩테스트<br/>7.4</div>
                        </div>
                    </li>
                    <li className={styles.list}>
                        <div className={classNames({[styles.card]: true, [styles.card_now]: true})}>
                            최종 합격자 발표<span className={styles.status}>모집중</span><div className={styles.content}>수료자 선발<br/>7.20</div>
                        </div>
                    </li>
                    <li className={styles.list}>
                        <div className={classNames({[styles.card]: true, [styles.card_edu]: true})}>
                            부스트캠프 챌린지<span className={styles.status_edu}>D-43</span><div className={styles.content}>수료자 선발<br/>7.27 ~ 8.21</div>
                        </div>
                    </li>
                    <li className={styles.list}>
                        <div className={classNames({[styles.card]: true, [styles.card_edu]: true})}>
                            부스트캠프 멤버쉽<span className={styles.status_edu}>D-55</span><div className={styles.content}>챌린지 과정 수료자만<br/>8.31 ~ 12.21</div>
                        </div>
                    </li>
                    <li>
                    </li>
                </ol>
            </div>
        </div>
    );
}
```

## 6. 결론

### 6.1. 프론트엔드의 역할이 어디까지인지 이해하게 됐다.

* 지금까지 너무 css 스타일링 위주로 시간을 투자했었다. 그게 프론트엔드가 할 일의 전부인 줄로만 알고!
* 서버에서 데이터를 슬슬 받아와야 할 때쯤 _**그래서 그걸 누가 어떻게하지?**_ 라는 고민이 들면서 리팩토링이 시작됐다.
* 하드코딩 스타일로 값을 넣어둘 게 아니라, 마치 서버에서 데이터를 받아온 것 처럼 더미데이터 배열을 만들고 그녀석을 활용해 html 구조를 짜봐야한다.
* 그래야&#x20;
  * 서버측에 어떤 데이터를 요구할지도 명확하게 정리되고(사실 요청할 필요도 없이 백쪽에서 우리 더미데이터를 보고 DB를 짜면 된다),&#x20;
  * 변수명도 통일되고,&#x20;
  * 데이터를 전달하기 위해 자바스크립트 문법을 사용하게 된다.

### 6.2. 리액트 앱를 리액트답게 개발할 수 있게 됐다.

* 사실 데이터를 받아올 때 _**굳이 리덕스 같은 상태관리라이브러리를 사용해야되나?**_ 고민 중이었었다. 예발자 프로젝트는 계층적으로 컴포넌트를 렌더링하는 경우가 거의 없었기 때문이었다.&#x20;
* 간단하고 단순한 구조의 프로젝트라고 생각해왔었는데, 사실은 **충분히 컴포넌트화 시킬 수 있는 부분을 컴포넌트로 만들지 않았기 때문**이었다.
* 테이블, 리스트, 타임라인 등 중복되는 내용을 정리/비교하는 요소가 많은 예발자닷컴 같은 웹 페이지는 오히려 컴포넌트가 계층적으로 만들어질 여지가 큰 프로젝트다.
* 아무리 단순한 코드라도 **재사용성이 보이는 코드는 무조건 컴포넌트화** 시키자!
  * 특히 `ol`, `li` 같은 리스트 태그들. 무조건 컴포넌트가 될 녀석들이다.
