리액트는 컴포넌트로 구성되어있음
선언적 접근 방식(declarative approach)
를 사용한다.명령적 접근 방식
으로 일련의 액션들을 단계 별로 코딩해야하며, 절차적인 세부 사항을 신경써야 한다리액트 프로젝트를 생성하는데 사용하며, 간단한 파일, 폴더와 미리 설정된 환경 설정 파일들이 존재한다.
npx create-react-app 프로젝트_이름
cd 폴더명
npm install
npm start
Node.js가 필요하다. 프록시나 VPN, 백신을 확인해야한다.
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
index.js는 처음으로 실행되는 파일이다. 하지만 index.js의 코드 그대로가 아닌 변환된 버전의 코드가 실행된다. cra 프로젝트 설정에서 코드를 변환하고 최적화하는 스크립트가 포함되었다면 이 과정은 백그라운드에서 처리된다.
위 코드는 브라우저에서 그대로 실행되지 않는다. npm start 프로세스는 코드를 확인해서 변환한 후 브라우저에 전달한다. 브라우저 안에서 특정 작업이 추가로 처리된다.
import './index.css';
과 같은 코드는 css 파일을 js 파일로 변환하는 것과 같은데, 일반적인 JS에서는 작동하지 않는 코드이다. 유효하지 않는 구문이다.
root.render( <React.StrictMode> <App /> </React.StrictMode> );
코드도 JS 파일 안에 HTML 코드처럼 보인다. 유효하지 않은 코드지만, 브라우저로 전달되기 전에 코드가 변환되어 개발자가 더 편한 코드로 개발할 수 있게 해준다.
react의 서드파티 라이브러리이다. import ReactDOM from 'react-dom/client';
코드를 통해 라이브러리가 제공하는 기능을 index.js에서 사용할 수 있다. const root = ReactDOM.createRoot(document.getElementById('root'));
는 React로 구축할 UI를 React 앱의 엔트리 페이지(public/index.html)에 어디에 배치해야하는지 React에 알려주는 기능을 한다.
index.html에 <div id="root"></div>
에 React가 주도하는 UI(렌더링되어야할 것들)를 추가한다.
import App from './App';
을 가져와 root에 render시킨다. App파일은 JSX 구문으로 만들어진 컴포넌트이다. root에 렌더링할 첫 번째 컴포넌트이다.
App.js 파일 안에는 대문자로 시작하는 App() 함수가 존재하고 이를 export하고 있다.
JS 파일 안에 HTML 코드를 반환하고 있는 App() 함수는 익숙한 형태가 아니고 유효한 JS 코드도 아니다. 이 형태가 JSX이다.
JS안에 있는 HTML 코드이다. JSX는 JavaScriptXML을 의미한다. 결국 HTML은 XML이라고 할 수 있기 때문이다. 실제로 JSX로 작성하더라도 브라우저에 로드된 js파일의 코드를 열어보면 변환된 코드들이다. 브라우저 devtool에 보이는 코드들은 리액트 패키지 코드 + 작성한 코드가 번들링되어 보여진다.
JSX 코드는 개발자로서 개발 친화적으로 작성하기 쉬운 코드이며, 일반적으로 브라우저에서 지원되지 않는다. 브라우저에서는 브라우저 친화적으로 변환된다.
하나의 컴포넌트는 하나의 js 파일로 만든다.
App.js는 앱 내 루트 컴포넌트이다. 리액트는 컴포넌트 트리를 만들어서 App 컴포넌트 또는 다른 부모 컴포넌트 하위로 추가해서 사용한다. 이 컴포넌트 트리의 구조를 렌더링한다.
컴포넌트 규칙이 존재한다.
리액트의 컴포넌트는 js 함수이며, JSX 코드(html 코드)를 반환한다. 관습적으로 컴포넌트의 함수명은 파일명과 같게 사용한다. 그리고 이 함수를 밖으로 export한다.
이 커스텀 컴포넌트를 다른 js파일에서 import해서 사용하며, html 요소처럼 사용할 수 있다. 일반적인 html처럼 사용하되, 대문자로 시작하는 import명으로서 사용한다.
리턴하는 JSX코드를 인라인으로 작성하면 가독성에도 문제가 있고, 작성된 코드가 유효하지 않다.
위와 같은 문제점의 가장 쉬운 해결법은 또 하나의 <div>
로 감싸주는 방법이 있다. 그리고 중괄호를 사용하여 요소를 감싸준다. 그리고 auto format을 사용한다.
리턴된 JSX코드의 스타일을 위해서 class명을 추가해준다. JSX코드는 HTML의 속성이 유사하지만 동일하지는 않다. JS에서 class
는 예약어이기 때문에, JSX 코드에서는 className
속성을 사용한다.
관심사의 분리와 재사용성을 위해 JSX 코드 내 값들을 동적으로 바꿔야 한다.
우선은 정적 값을 넣어보자. 함수 안에 JS 코드로 값을 정의하고 JSX 코드 내 기본 JS 코드를 넣을 수 있는 중괄호 안에 값을 넣어준다.
이전의 내용은 컴포넌트를 기계적으로 복붙했을 뿐, 재사용한 것이 아니다. props
를 통해 데이터를 넘겨줘야 한다.
Props는 properties를 나타내는 것으로 커스텀 컴포넌트의 속성을 설정할 수 있다.
커스텀 컴포넌트에 파라미터를 추가(일반적인 JS와 같음)한다. 하지만 파라미터들을 일일이 나열하는 것이 아닌 단 1개의 파라미터 프로퍼티(모든 속성을 받는 객체인) props
를 사용한다. props의 키는 부모 컴포넌트에서 바인딩된 속성명이다. 이런 식으로 리액트 컴포넌트 사이에 데이터를 공유할 수 있다.
리액트의 컴포넌트를 더 작은 조각으로 나눌 수 있다. 작은 블록들을 모아 UI를 만드는 것을 컴포지션이라고 한다.
중복되는 코드들을 모아 하나의 작은 컴포넌트 (e.g. Card 형태)를 만들어 이를 감싸서 재사용한다.
function Card(props) {
const classes = `card ${props.className}`;
return (<div className={classes}>{props.children}</div>);
}
export default Card;
children
은 예약어이다. 상위 컴포넌트 안에 있는 하위 요소들이 모두 props.children이다. modal이나 alert 등에서 사용할 수 있으며, 코드 추출을 통한 래퍼 컴포넌트로 코드 중복을 피하고 컴포넌트들을 깔끔하게 유지할 수 있다. 컴포넌트를 결합할 때 composition을 이요한다.
JSX는 가독성이 높고 간편한 문법이다. 브라우저에서는 변환된 코드를 볼 수 있다.
package.json 파일에서 리액트와 관련있는 react, react-dom 패키지가 존재한다.
과거 오래된 버전의 리액트 프로젝트에서는 모든 JSX파일에서 react를 import했다. 최신 플젝 셋업에서 이를 처리해줘서 지금은 사용하지 않는다.
3가지 타입의 전달인자가 존재한다. (3개 이상이 될 수 있음)
JSX 코드를 React.createElement()로 구성할 수 있는데, 개발이 복잡하고 번거롭다. JSX 코드를 작성하면 자동적으로 내부에서 React.createElement()로 생성되는 코드가 된다.
React.createElement()로 생성하는 경우 1개 이상의 자식 요소를 가질 수 없기 때문에 JSX 문법으로 반환하는 코드는 1개의 래퍼 루트 요소를 가져야한다.
Vue 3의 h() 함수와 동일한 구조를 갖고있다. 전달인자의 타입도 동일하다.
components 폴더에 모두 다 넣기에는 컴포넌트 규모와 개수가 많아지는 우려가 있다.
앱의 특정 기능과 관련없는 일반적인 UI 컴포넌트와 기능이 존재하여 렌더링하는 컴포넌트로 나눌 수 있으며, 이에 따라 하위 폴더로 구성한다.
파일을 잘 정리하고 컴포넌트들을 체계적으로 유지할 수 있게 만들어주며, 하나의 폴더에 많은 컴포넌트들을 한 번에 넣지 않게 해주기 위함이다.
동료 개발자들과의 규칙에 따라 폴더 구조는 달라질 수 있다.
선호에 따라 arrow function 사용하기