본문 바로가기
Udemy - React완벽가이드

컴포넌트 구성 분할

by Hanachoi 2023. 2. 13.

#컴포넌트에 일반 JS 논리를 추가하고 컴포넌트 분할하기

  • 앞서 본 예시에서 처럼 <ExpenseItem>컴포넌트는 재사용이 가능하고 값도 동적으로 받아올수 있게 되었다. 하지만 하드코딩으로 고정하고 싶은 값은 언제든 고정이 가능하다.

하드코딩도 언제든 가능!

  • 날짜 부분을 달력에서 나오는 것처럼 표시해주려면 어떻게 해주면 될까?
  • 일단 날짜 부분은 이렇게 <div>안에서 Month / Year / Day로 나눠서 구성을 해줘야한다.

 

Date.prototype.toLocaleString() - JavaScript | MDN

The toLocaleString() method returns a string with a language-sensitive representation of this date. In implementations with Intl.DateTimeFormat API support, this method simply calls Intl.DateTimeFormat.

developer.mozilla.org

  • 이렇게 toLocaleString()을 이용해서 month를 설정해줄 수 있다. 하지만 이렇게 직접적으로 코드를 작성하는것보다 위쪽에 변수로 만들어 저장한뒤 넣어주는게 좀 더 깔끔하게 보인다.
  • year는 4자리 숫자가 나오도록 다른 메소드인 getFullYear()를 사용했다. 

 

 

#컴포넌트를 여러 컴포넌트로 분할하기

  • 프로젝트를 하다보면 어쩔 수없이 많은 컴포넌트가 생기고 JSX 코드는 점점 더 커지게 된다. 
  • 리액트의 컴포넌트 개념으로 더 작은 코드블럭으로 나눌 수 있게 해준다. 하나의 코드블럭과 컴포넌트들은 하나의 핵심작업에 집중한다. 그리고 이 컴포넌트들을 결합해 전체 사용자 인터페이스를 구축한다.
  • 이렇게 하면 작은 단위로 관리는 가능하지만 여전히 복잡한 사용자 인터페이스를 구축할 수 있다. 
  • 지금 <ExpenseItem>컴포넌트만 봐도 우리가 날짜를 만든것, title을 받아온것, amount를 설정한 것 등 모두 하나의 컴포넌트로 분리가 가능하다.
  • 여기서 날짜를 따로 관리하는 컴포넌트를 분리해보자.
  • ExpenseDate라는 컴포넌트를 따로 만들어주고 우리가 기존에 날짜를 만들기 위해 구성했던 코드들을 잘라와서 여기에 넣어준다. 

  • Export / import 해주는 작업도 잊지말자!
  • 이렇게 따로 컴포넌트를 만들어 준 뒤에는 원래 날짜 관련 코드가 있던 자리에 이 컴포넌트를 넣어주면 된다.
  • 이렇게 컨텐츠가 따로 없는 컴포넌트는 <ExpenseItem />로 그냥 닫기까지 가능하다.

  • 이렇게 컴포넌트를 각각 나눠서 더 깔끔하게 관리도 가능하다. 컴포넌트를 나눌 때는 특별한 룰은 없고 경험으로 분리를 하면 된다
  • 한 가지 잊지말아야 할 것은 ExpenseDate 컴포넌트에 props 속성을 넣어줘야 한다는 것.
  • ExpenseItem에서 얘를 사용해주려면 Date 속성을 설정해줘야 한다. 

  • 우리는 컴포넌트 트리를 다시 볼 필요가 생기는데, 우리는 <App />컴포넌트 뿐만 아니라 사용자 지정 컴포넌트들도 가지고 있다.  다수의 사용자 컴포넌트가 있고 그것들은 서로의 내부에 중첩되어 있다.

  • 우리가 지금까지 만든 애들을 보면 
    • <App />에서 <ExpenseItem /> 컴포넌트를 사용하고 있고,
    • <ExpenseItem />에서 다시 <ExpenseDate />컴포넌트를 사용하고 있다. 
    • 여기서 props를 사용해서 여러개의 컴포넌트르 통해 데이터를 보낸다.
  •  props.date를 통해 이미 데이터를 받아왔고 다음에 다시 props를 사용해서 더 안쪽에 있는 ExpenseDate 컴포넌트로 보내졌다. 
  • props는 A 컴포넌트에서 B 컴포넌트로 데이터를 전달하는 형식이기 때문이다. 컴포넌트에서 하위 컴포넌트로 데이터를 직접 보낸다.  이런 컴포넌트들은 생략이 불가능하다. 

 

#컴포지션의 개념 (Children props)

  • React is all about components. Components are html elements you combined hmtl code and jsx code and styling. Also if you want to, you can add js concepts
  • 이렇게 작은 빌딩 블록으로부터 사용자 인터페이스를 구축하는 접근방식을 composition이라고 부른다.
  • 리액트에서는 수많은 컴포넌트들을 가지게 될 것이고 그 안에서 props를 통해 데이터를 받게 될 것이다 .
  • 이런 props가 가끔은 컴포넌트를 구성하기보다는 그냥 태그 사이에서 컨텐츠를 전달하고 싶을 수도 있다.

  • 현재까지 만든 브라우저 파일을 보면, 특정 디자인의 컴포넌트들이 반복되고 있는 형태인 것을 알 수 있다. 각각의 데이터들이 light grey 색의 컴포넌트에 들어가 있고 그 컴포넌트들을 dark grey 색의 <div>가 다시 감싸고 있는 것을 볼 수 있다.  
  • 우리는 컴포넌트들 사이에 공통적으로 가지고 있는 스타일들을 추출해서 또 다른 하나의 컴포넌트로 만들 수도 있다.
  • 이렇게 둥근 모서리와 옅은 그림자를 가지고 있는 박스들을 보통 웹개발사에는 Card라는 이름을 통해 부른다. 그래서 우리도 Card.js 파일을 컴포넌트 폴더에 만들어 준다. 
  • 그리고 기존에 Expenses.css에서 border-radius 와 box-shadow를 가져와서 Card.css에 넣어준다. 그리고 다시 ExpenseItem.js에서 가장 root가 되는 <div calssName= 'expense-item'>에서 border-radius 와 box-shadow를 삭제해준다.
  • 이렇게 해주면 card는 attribute로 고려되지 않는다. 대신 우리는 그냥 ExpenseItem.js에서 가장 상위에 있는<div>를 <Card>로 변경해준다.
  • 이렇게 하면 Card.js는 자동적으로 이미 설정된 Card.css의 스타일을 가지게 된다. 

  • 여기까지 하게 되면 우리의 데이터가 모두 손실된 것을볼 수 있는데 이건 박스 바깥에 있기 때문이다.
  • 이유는 우리가 만든 <Card>처럼 커스텀 컴포넌트로는 전체를 감싸줄 수 없기 때문이다.
  • 그 안에 있는 <h2>나 <div>는 작동하겠지만 커스텀 컴포넌트가 래퍼(wrapper) 로 전체를 감싸줄 수는 없다. 
  • 물론 리액트는 해결책을 가지고 있고 우리는 래퍼 컴포넌트를 만들 수 있다. Card.js에서 props를 취해주면 됨!
  • 그리고 리액트에서 이미 예약된 언어이고 내장된 특별 props를 사용하면 된다.  props.children
  • props.children은 리액트에서 예약된 단어라 우리가 딱히 설정한 것이 없는데도 사용이 가능하다 

  • props.children은 사용자컴포넌트에 있는 열고 닫는 태그 사이에 있는 컨텐츠를 불러준다. 
  • 이렇게 해주면 아까 <Card>로 감싼 ExpenseItem.js의 html 태그들이 다시 나타나게 된다. 하지만 스타일이 전체적을 로 깨져서 나오게 된다

  • 이유는 <Card>는 사용자 컴포넌트이기 때문에 우리가 설정한 스타일을 우선적으로 따르게 되고 그 안에 있는 태그들은 className이 지정되어 있는 스타일을 지원한다. 
  • 그래서 디폴트인 스타일을 사용자 지정컴포넌트에서도 가지게 하려면 <Card>컴포넌트를 수정해줘야 한다. 

  • 우리는 <Card>컴포넌트의 className에  무엇이든 우리가 추가하도록 조정하고 싶기 때문에 상수로 classes라는 변수를 하나 만들어 준다. 
  • 'card ' 는 디폴트 클라스이고 꼭 card뒤에 스페이스(띄기)가 있어야한다!!
  • 이제 우리가 바깥에서 classNAme으로 받는 것들은 문자열로 추가된다. 
  • 다음에는 동적으로 {classes}를 받아준다. 
  • 그럼 원래의 파일처럼 다시 잘 작동하게 된다.
  • 우리는 이제 다른 파일에서도 Card를 래퍼컴포넌트로 사용할 수 있게 된다. 
  • 똑같이 Expenses에서도 import로 Card를 받아와서 <Card>로 전체를 감싸줄 수 있게 된다.  그럼 똑같은 스타일을 다시 가지게 된다!

  • 이렇게 하는 이유는 무엇일까? 지금은 간단한 케이스지만 계속 더 복잡한 코드가 발생하게 될 것이다. 이때마다 중중복되는 수많은 코드를 피할 수 있게 해준다. 또 컴포넌트를 깔끔하게 관리할 수 있게 된다.
  • 이래서 composition은 리액트에서 중요하다!! 

 

#JSX 자세히 보기

  • 우리가 리액트에서 JSX 문법을 쓰고 있지만 실제 브라우저의 개발자도구에서 살펴보면 JSX 문법을 볼 수 없다. 이는 리액트에서 컴파일 과정에서 문법을 변환시켜주기 때문이다. 
  • 수많은 파일중 package.json 파일이 있는데 수많은 dependency들이 있다. 대부분의 것들은 화면 뒤에서 움직이는 애들이다. 
  • 많은 dependency 중에서 react / react-dom 부분을 볼 수 있는데, 사실 원래 JSX 문법을 쓰기위해서는 꼭 React를 import 해와야 했었다. JSX는 그냥 Syntax sugar에 불과하기 떄문이다. 하지만 최신 문법에서는 생략이 가능하다. 

  • JSX를 사용하지 않는다면 문법은 읽기 힘들어진다. 아래의 return 부분은 JSX를 사용하지 않고 작성한 문법.

  • 이제 저 JSX가 아닌 문법을 보면 왜 우리가 하나의 <div>로 나머지 코드들을 감싸줘야 하는지 알게 된다.  
  • 리액트에서 createElement를 두개만 만들어서 반환하려고 하면 에러가 뜬다. 하나 이상을반환할 수 없기 때문이다. 

 

#컴포넌트 파일 구성하기

  • 컴포넌트가 많아지면서 파일도 점점 많아지게 될 것이다.
  • 하나의 componenet 파일에 다 담아두기보다 또 세분화를 하면서 정리해두는게 좋다. 
  • 방식은 내 맘대로지만 팀작업일 경우 룰을 정해서 하면 된다.
  • 지금 여기 예시에서는 Expenses / UI 파일 두개로 나눠서 UI 에는 래퍼 컴포넌트와 css파일을 넣어줬다, 

'Udemy - React완벽가이드' 카테고리의 다른 글

useState 훅 자세히 살펴보기  (0) 2023.02.18
리액트 state 및 이벤트 다루기  (0) 2023.02.18
JSX  (0) 2023.02.03
Basic of React  (1) 2023.01.30
Javascript 리마인드  (0) 2023.01.29

댓글