🧠
Hi, Daehuyn Lee
  • Fork-my-brain
  • Network
    • 7. "데이터가 전달되는 원리" OSI 7계층 모델과 TCP:IP 모델
    • [Netwhat] 연습문제 정리
    • 11. IP 라우팅(routing) 동작 과정
    • 3. IP address 란?
    • 2. 컴퓨터 구조를 통해 이해하는 파일(File)과 소켓(Socket)
    • 10 "더 편리한 인터넷을 위해" DHCP && DNS 프로토콜
    • 9. 데이터? 세그먼트? 패킷? 헷갈릴 땐 PDU를 알아보자
    • 8. TCP 와 UDP 차이를 자세히 알아보자
    • 5. 서브넷팅(subnetting)으로 네크워크를 효율적으로 관리하자
    • 4. 넷마스크(Netmask)와 서브넷마스크(Subnetmask)
    • 1. 비유로 이해하는 컴퓨터 구조
    • 6. 공인(Public) && 사설(Private) IP의 차이점
  • Django
    • [Django 1] 가상환경에 Django 설치하기
    • [Django 3] Hello World 웹사이트 만들기
    • [Django 9] static 으로 css 로드하기
    • [Django 10] 한 템플릿에서 복수의 css 파일 적용하기
    • [Django 11] URL app별로 관리하기
    • [Django 8] 템플릿 상속
    • [Django 4] MTV 패턴
    • [Django 6] 블로그 model 만들기
    • [Django 2] Django는 어떻게 작동할까
    • [Django 7] '새 글 작성' 기능 만들기
    • [Django 5] 템플릿 언어
  • Projects
    • 예발자닷컴
      • 4. 프론트엔드의 역할은 어디까지 - 더미데이터 만들기
      • 7. [React 리팩토링] CSS Inline Styling에 Props 사용하기
      • 6. [React 리팩토링] JSX에서 조건문 사용해 렌더링하기
      • 3. 예발자닷컴 프론트서버 업데이트 하기
      • 8. [React 리팩토링] 예발자 프로젝트에 Redux 적용하기
      • 5. [React 리팩토링] JSX로 HTML 렌더링하기
      • 1. 👨‍👨‍👦‍👦 Github로 협업 프로젝트 관리하기
      • 2. React Component를 활용한 웹페이지 디자인 연습
  • Git
    • [Git] Interactive Rebase 실습
    • 오픈소스 개발 참여에 필요한 Git 명령어 정리
    • 개발자가 오픈소스를 읽는 방법
    • 오픈소스 프로젝트 시작하기
    • SSH agent ; Passphrase 입력 없이 Push하기
    • SSH로 원격저장소 접속하기
    • [Github] 개인 저장소를 팀 저장소로 변경하기
    • GitHub Dependabot
    • Git add, commit, push 취소하기
    • 깃헙 잔디 관리 팁
    • 원격저장소 여러개 연결하기
    • Typora(마크다운 에디터) 사용법
  • C
    • C Piscine
      • 메모리 구조를 알아보자
      • Makefile 만들기
      • GCC로 정적 라이브러리 파일 만들기
      • 외부 라이브러리 GCC로 컴파일 하기
      • 정적(Static) 변수
      • 저수준 파일 입출력
      • Makefile 자주 사용하는 문법 정리
      • segmentation fault 해결하기
      • C의 구조체 개념
      • 연결 리스트(linked list)에서 이중 포인터 사용하기
      • 로컬에 Norminette 설치하기
    • GetNextLine
      • [GetNextLine] 과제소개-Reading a line on a fd is way too tedious
      • [GetNextLine] 삽질의 기록
      • [GetNextLine] 리팩토링-프로그램의 목적을 고려한 코드
    • ft_printf
      • 1. 과제소개
      • 2. 가변인자 (Variadic Arguments)
      • 3. 형식태그와 서식지정자 printf 함수의 옵션 알아보기
    • Libft
      • [Libft] Bonus
      • [Libft] Test Program
      • [Libft] 나만의 C 라이브러리 만들기
      • [Libft] Part 2
      • [Libft] Part 1
  • UNIX shell
    • [minishell] 4. 종료상태와 에러메세지 처리
    • [minishell] 1. 과제소개 및 선행지식
    • [minishell] 2. 프로그램 구조 및 개발 기록들
    • [minishell] 5. 파이프(Pipe) 처리
    • [minishell] 3. 시그널(Signal) 처리하기
    • [minishell] 6. 리다이렉션(Redirection) 처리
  • Web
    • Next.js
      • [Next.js] CSS모듈과 복수의 class 사용하기
    • Node.js
      • [Node.js] 웹페이지에 파일 띄우기
      • [Node.js] URL에서 쿼리스트링 추출하기
      • [Node.js] '새 글 작성' 페이지 만들기
    • React
      • [React] 2. 컴포넌트(Component) 생성 및 파일별로 분리하기
      • [React] 1. 파일 구조 이해하기
      • [React] 4. 컴포넌트의 State 란
      • [React] 3. 컴포넌트의 Props 란
    • Javascript
      • Click, Enter 두 개의 이벤트 동시에 등록하기
      • Click eventListener 등록하기
      • JavaScript & C 문법 비교
      • JavaScript 객체 지향의 특징
    • CSS
      • [CSS] box-model, display, position
  • Docker
    • ft_server
      • 2. 도커 설치부터 워드프레스 구축까지
      • 1. 선행지식-Docker? Debian Buster? Nginx? ...
      • 3. Dockerfile 만들기
  • Kubernetes
    • 🌌[쿠버네티스 아키텍처] 3. API 호출
    • 🌌[쿠버네티스 아키텍처] 1. 구성 및 설계
    • 🌌[쿠버네티스 아키텍처] 2. 오브젝트 (Objects)
  • Operating System
    • Philosophers
      • [Philosophers] 예시예제로 보는 뮤텍스와 세마포어의 차이
      • [Philosophers] 식사하는 철학자 문제 소개
  • CPP
    • [CPP-08] STL containers, iterators, algorithms
    • [CPP-06] CPP 형변환 연산자
    • [CPP-04 ex02] 인터페이스(Interface) 클래스
    • [CPP-04 ex00] 다형성(Polymorphism) 및 가상함수
    • [CPP-02] Canonical 클래스 복사 생성자와 대입 연산자 오버로딩
    • [CPP-07] Templates
    • [CPP-01] this 포인터와 문자열 스트림(stringstream)
    • [CPP-01] 클래스의 정적할당과 동적할당 new, delete
    • [CPP-01] 파일 입출력 및 문자열 치환하기
    • [CPP-01] 참조자(reference)와 포인터는 다르다
    • [CPP-02] 정수부동소수값 - 고정소수값 변환
    • [CPP-04 ex01] 추상 클래스의 필요성 순수 가상함수
    • [CPP-00] Megaphone! CPP 표준입출력
    • [CPP-03] (ClapTrap이 뭐지) 다중 상속과 가상 상속
    • [CPP-05] 예외 처리 (exception handling)
    • [CPP-00] 객체지향의 관점으로 클래스 이해하기
    • [CPP-01] 랜덤값 얻기
  • IBM Cloud
    • [IBM Cloud] 1. 클라우드 컴퓨팅 개요
    • [IBM Cloud] 5. 클라우드 컴퓨팅의 구성 요소
    • [IBM Cloud] 3. 클라우드 서비스 모델 및 배포 모델
    • [IBM Cloud] 2. 클라우드를 활용하는 새 기술들
    • [IBM Cloud] 4. 떠오르는 클라우드 트렌드
    • [IBM Cloud] 6. 클라우드 스토리지 유형 및 CDN
  • Assembly
    • [libasm] 어셈블리 프로그램 구조와 x64 레지스터 이해하기
    • [libasm] strlen 함수를 어셈블리어로 짠다면
    • [libasm] 어셈블리 명령어(opcode) 정리
Powered by GitBook
On this page
  • 1. 목표
  • 2. 현재 컴포넌트 구조
  • 3. map() 메서드를 사용하는 이유
  • 4. map() 메서드 사용법
  • 4.1. 프로토타입
  • 5. Refactoring
  • 5.1. TimelineList 수정
  • 5.2. TimelineListItem 수정
  • 5.3. HorizontalTimeline 에서의 호출
  • 6. 결론
  • 6.1. 프론트엔드의 역할이 어디까지인지 이해하게 됐다.
  • 6.2. 리액트 앱를 리액트답게 개발할 수 있게 됐다.

Was this helpful?

  1. Projects
  2. 예발자닷컴

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

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

Previous예발자닷컴Next7. [React 리팩토링] CSS Inline Styling에 Props 사용하기

Last updated 3 years ago

Was this helpful?

1. 목표

  • 코드 리팩토링하기

    • 더미데이터 배열 만든 뒤 TimelineListItem 컴포넌트에 각각 다른 데이터 넣기.

2. 현재 컴포넌트 구조

스크린샷 2020-07-25 오후 5 22 41
  • TimelineList

    • TimelineListItem

      • Title : "2차"

      • Status : "모집중"

      • Content : "온라인 코딩테스트"

      • Date : "7. 4."

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

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

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

4. map() 메서드 사용법

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

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

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

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

console.log(dataSet[0].name);
> "taelee"

4.1. 프로토타입

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 구조를 짜봐야한다.

  • 그래야

    • 서버측에 어떤 데이터를 요구할지도 명확하게 정리되고(사실 요청할 필요도 없이 백쪽에서 우리 더미데이터를 보고 DB를 짜면 된다),

    • 변수명도 통일되고,

    • 데이터를 전달하기 위해 자바스크립트 문법을 사용하게 된다.

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

  • 사실 데이터를 받아올 때 굳이 리덕스 같은 상태관리라이브러리를 사용해야되나? 고민 중이었었다. 예발자 프로젝트는 계층적으로 컴포넌트를 렌더링하는 경우가 거의 없었기 때문이었다.

  • 간단하고 단순한 구조의 프로젝트라고 생각해왔었는데, 사실은 충분히 컴포넌트화 시킬 수 있는 부분을 컴포넌트로 만들지 않았기 때문이었다.

  • 테이블, 리스트, 타임라인 등 중복되는 내용을 정리/비교하는 요소가 많은 예발자닷컴 같은 웹 페이지는 오히려 컴포넌트가 계층적으로 만들어질 여지가 큰 프로젝트다.

  • 아무리 단순한 코드라도 재사용성이 보이는 코드는 무조건 컴포넌트화 시키자!

    • 특히 ol, li 같은 리스트 태그들. 무조건 컴포넌트가 될 녀석들이다.

더 다양한 예제는 참고.

여기
예발자닷컴