유데미 강의를 듣고 복습차 정리해놓은 내용이다.

이번 기회에 리액트 강의 다 듣고 개념을 제대로 잡고 프로젝트로 들어가봐야겠다.

매번 절반까지만 듣고 말았지 뭐야 ... 

 

React => Component

가장 핵심 개념이다. 리액트는 재사용성을 고려하여 모든 요소를 각각의 component로 쪼갠 뒤 갖다 쓰는 방식으로 재사용성을 높였다. 불필요한 코드를 반복할 필요도 없으며, 각각의 기능을 쪼개 하나의 component가 각각 하나의 기능만을 수행하게 하여 관리하기 수월하게 만들었다.

 

component는 HTML + JS (+ CSS?)로 이루어진다. 

 

Create React App

쉽고 빠르게 리액트 프로젝트를 시작할 수 있는 툴이다. 그나저나 오랜만에 cra 썼더니 오래된 버전이라고 지우고 다시 설치하라고 떴다... 얌전히 npm uninstall -g create-react-app 해주고 npm install -g create-react-app 해줬다. 

 

React project 뜯어보기

리액트는 어쨌거나 JS 파일이다. 그러나 cra를 통해 생성된 index.js 파일을 뜯어보면 기존 js 문법에서는 허용되지 않는 부분들을 볼 수 있다. 가령 css 파일을 import 한다던지? <App /> 라던지

React는 브라우저로 전달해주기 전에 코드를 브라우저가 이해할 수 있게 잘~ 통역해서 보내준다. 

 

index.js 파일이 가장 먼저 실행되는 파일인데 한번 더 자세히 살펴보자. 

import ReactDOM from 'react-dom/client';

import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

react, react-dom 패키지를 통해 리액트 라이브러리가 실행된다. ReactDOM 패키지는 어떤 React dom object를 export를 해주고 그 요소를 index.js로 가져오고(import) 있다. 가져온 ReactDOM 객체의 createRoot 함수를 실행하는데 리액트로 개발하는 요소의 가장 root단에 존재하는 요소이다. 이 리액트 UI가 어디에 실행될지, index.html 파일 내에서 찾아볼 수 있다. 리액트는 single page application이므로, public 폴더 내의 index.html 파일 내에 <div id="root"> </div> 영역 내에 우리의 리액트 코드가 삽입될 것이다. 

해당 객체를 root라는 이름으로 저장한 뒤, 해당 div 내에 어떤 요소가 렌더링되어야할지 전달한다. 현재 코드 상으로는 < App /> 요소가 전달되고 있다. 이 App이라는 요소가 어디서 왔는지 살펴봤더니 App.js 파일에서 export된 요소로 보인다. 하지만 문법이 생소하다. 이 문법은 일반적인 JS 문법은 아니며, JSX라는 JS를 조금 더 확장한 문법이다.

 

App은 하나의 component이다. App.js 파일을 살펴보자.

function App() {
  return (
    <div>
      <h2>Let's get started!</h2>
    </div>
  );
}

export default App;

 

App.js는 하나의 함수이며 무언가를 리턴하고 있다. HTML 코드를 JS파일 내에서 리턴하는 방식은 일반적인 JS 에서 보지 못했던 JSX 문법이다. 

 

JSX란?

JSX란 JavaScript에 XML을 추가한 것으로, 브라우저로 전달되기 전에 브라우저가 이해하기 쉽게 한번 변환되어 전달된다. 실제로 우리의 react 프로젝트를 개발자도구에서 살펴보면 우리가 작성한 적 없는 코드들을 볼 수 있다. 

 

How React Works

기존 JS는 Id나 class이름이나 document에서 요소를 가져온 뒤 createElement로 요소를 추가하고, 추가된 요소를 append해주는 방식으로 html코드를 삽입했다. 이렇게 하나하나 어떻게 실행해야될지 명령하는 언어를 imperative(명령형) 언어라고 한다. 하지만 이 방식은 요소를 추가하거나 지울 때마다 꽤 수고롭다. 그에 비해 리액트는 일반 html코드를 적듯이 적어주기만 하면 된다. 리액트 컴포넌트는 custom html 요소나 마찬가지다.

 

'React > 개념' 카테고리의 다른 글

JS 복습하기  (0) 2022.07.20
React : create-react-app  (0) 2021.05.19
React의 메인 개념 : component  (0) 2021.05.19

모든 일련의 과정을 직접 적어줘야 하는 JS. React가 JS 기반 언어기 때문에 한번 전체적으로 JS를 훑고 들어가자.

 

var, const, let

데이터의 수정 여부에 관계 없이 모든 데이터 타입에 사용할 수 있었던 var는 구 버전 JS에서 많이 사용했다. 유저나 프로그래머가 값을 바꾸면 안되는 경우를 처리해주기 위해 수정 불가능한 const 자료형과 수정이 가능한 let 자료형이 등장했고 우리는 기본적으로 const로 데이터를 선언하되, 수정이 필요하다면 추후 let으로 바꾸도록 하자.

 

Exports & Imports 

const person = {
	name: 'Yeji'
}

export default person
export const someFn = () => { ... }
export const someData = 26;

위의 두 js 코드는 각각 default로 export 해주거나 개별 요소를 export 해주고 있다. 두 요소를 다른 js 코드에서 import 시킬 때 default로 내보낸 것은 어떤 이름으로 받아도 상관 없으나, 개별 요소가 export된 경우 정확한 이름을 명시하여 데이터를 가져와야 한다. 만약 데이터의 이름을 바꾸고 싶다면 'as'라는 키워드를 사용하여 alias를 설정한다.

 

만약 export한 데이터가 여러 개고 그 데이터를 모두 가져오고 싶다면 '*' 키워드를 사용하여 한꺼번에 모두 가져올 수 있다.

import person from './person.js'
import personData from './person.js'

import { someFn } from './util.js'
import { someData } from './util.js'
import { someData as age } from './util.js'

import * as bundle from './util.js'

 

Classes

class는 JS object의 blueprint라고 생각하자. 그 안에는 데이터, 함수, 생성자가 포함될 수 있으며 다른 클래스를 상속받을 수도 있다. 하단의 코드는 es6 방식이다.

class Female {
  constructor() {
    this.gender = 'Female';
  }
  printGender(){
    console.log(this.gender);
  }
}

class Student extends Female {
  constructor() {
    super();
    this.name = 'Yeji';
  }
  printName() {
    console.log(this.name);
  }
}

const student = new Student();
student.printName();
student.printGender();

 

다만 상속받은 데이터에 접근하려면 먼저 부모의 생성자를 호출( super() )한 뒤 사용해야 한다. 만약 Student  클래스 생성자 내에 super(); 가 빠지면 "ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor" 에러를 볼 수 있다. 

 

조금 더 모던한 방식으로 class를 선언해보자. 바로 변수값에 접근할 수 있고, this 키워드를 사용하지 않아도 된다는 장점이 있다. 만약 JS Bin으로 실습중이라면 상단에서 ES6 / Bable로 바꿔줘야 에러가 나지 않는다!

class Female {
  gender = 'Female';
  
  printGender = () => {
    console.log(this.gender);
  }
}

class Student extends Female {
  name = 'Yeji';
  
  printName = () => {
    console.log(this.name);
  }
}

const student = new Student();
student.printName();
student.printGender();

 

Spread & Rest Operators

'...' <- 이게 연산자다 놀랍게도.

 

Spread 연산자의 경우, array 요소나 object 속성을 쪼갤 때 사용한다. array나 object에 ...를 붙여주면 안에 들어있는 요소를 모두 꺼내서 처리해주는 편리한 기능이다.

const nums = [1,2,3];
const newNums = [...nums, 4];

const person = {
  name:"yeji"
}

const student = {
  ...person,
  age: 26
}

 

Rest 연산자의 경우, 함수의 arguments를 하나의 array로 합쳐줄 때 사용한다. 몇 개의 인자가 오든, 하나의 배열로 받아 처리할 수 있다.

const filter = (...args) => {
  return args.filter(data => data === 1);
}

console.log(filter(1,2,3,4));

 

Destructuring

Spread 연산자는 안의 모든 데이터를 꺼내서 새로운 요소를 만들 때 사용하지만, destructuring은 배열의 요소나 object의 속성을 추출해서 새로운 변수에 저장할 때 사용한다.

 

const nums = [1,2,3];
[num1, num2] = nums;
console.log(num1, num2); // 1 2

{name} = {name:'yeji', age:26}
console.log(name); // yeji
console.log(age); // undefined

 

Reference Type

자바에서 기본 데이터형(8가지, 논리형, 정수형, 실수형, 문자형)을 제외하고 다른 데이터 타입은 reference type이다. 즉 값을 메모리 상에 저장한 뒤 변수에는 그 메모리의 주소값만을 가지고 있는 타입이다. 따라서 JS에서 array나 object를 복제할 때 그 데이터 전체를 복제하게 되면 같은 주소를 다른 변수 2개가 가리키고 있는 상태가 될 수 있다.

const person = {
  name: "yeji"
}

const newPerson = person;

위와 같이 newPerson 객체를 만들게 되면, person 객체의 데이터를 변경했을 때 newPerson 객체의 데이터 역시 바뀌게 된다. 같은 주소지의 값을 가리키고 있기 때문에 당연한 결과다. 따라서 만약 안의 값들만 복제하고 싶다면 ... 연산자를 사용하여 새로운 배열이나 객체를 만들어 값을 넘겨주는 방식을 사용해야 한다. 

const person = {
  name: "yeji"
}

const newPerson = {
  ...person
};

 

참조 변수를 안의 데이터를 복사하여 새로운 요소를 만들어 복제하는 것이 아니라 단순 그 값 전체를 넘겨주게 된다면 예기치 못한 버그 폭탄을 맞을 수 있으니 주의하자.

 

Array Function 복습

array Function 방식은 코드를 간결하게 하는데 아주 유용하다. 많이 사용되는 패턴 하나를 통해 익혀보자.

const nums = [1,2,3];

const doubleNums = nums.map((num) => {
  return num*2;
})

 

array 내의 다양한 함수는 Mozilla 공식 문서(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)를 참고하자.

 

Array - JavaScript | MDN

The Array object, as with arrays in other programming languages, enables storing a collection of multiple items under a single variable name, and has members for performing common array operations.

developer.mozilla.org

 

map 함수는 해당 배열 내의 요소에 모두 접근하여 동작을 수행한 뒤 return되는 요소로 새로운 배열을 만들어주는 함수이다. 아주 유용하니까 기억해두자. 어차피 자주 사용해서 익숙해질 것이다 :) 

 

그 외에도 기억해두면 좋을 요소들은 한번 더 정리해두겠다. 기능이 기억나지 않는다면 읽어볼 것!

( 오,,, filter함수 shallow copy해준다.... 공식문서 영어버전을 보길 잘했다. 예기치 않은 버그를 만날 수도 있겠는걸)

'React > 개념' 카테고리의 다른 글

React Basics  (0) 2022.07.20
React : create-react-app  (0) 2021.05.19
React의 메인 개념 : component  (0) 2021.05.19

리액트 프로젝트를 시작하는 가장 쉬운 방법은 create-react-app을 사용한 방법이리라 생각된다.

 

계속하여 최선 버전으로 업데이트되도록, npx 명령어를 사용하여 생성한다.

// npx create-react-app *myapp
npx create-react-app test

*myapp 자리에 원하는 프로젝트 명을 적고 실행하면, 입력한 프로젝트 명으로 폴더가 하나 만들어져 있다.

해당 폴더를 실행하면, localhost:3000 으로 가장 기본적인 react 페이지가 뜬다.

 

여기서 이제 src폴더 내에서 App.js index.js index.css 를 제외한 파일은 다 지우고 프로젝트를 시작했다. 당장은 필요없기도 하고, 많은 리액트 강의에서도 다 지우더라!

 

index.js 파일을 열어보면 다음과 같다. (버전별로 차이는 있지만 신경X)

import ReactDOM from 'react-dom';

import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

 

리액트 자체는 js의 확장판이기 때문에, 기본적으로 js 문법을 따라간다. 다만 기본 js에서는 지원하지 않는 문법이 위 파일에서 2개 보인다.

 

import './index.css' <- 보통 js 파일에서는 위와 같이 import하지 않는다. 

<App /> <- js 코드 내의 HTML 코드이다. (JSX)

 

위와 같이 React가 도입한 문법은, npm run 명령어를 통해 실행되어, 개발자가 원하는 방향대로 화면에 뿌려진다. 원래대로라면 작동하지 않을 문법이 react로 인해, 브라우저로 전달되기 전 transform 되어 원하는 모습을 보여주는 것이다. 

 

그리고 또 하나 기억해야 할 것은, index.js 파일은 가장 먼저 실행되는 파일이라는 것이다. 

 

index.js가 최종적으로 실행하는 것은 다음이다.

ReactDOM.render(<App />, document.getElementById('root'));

App이라는 것은 위에서 App.js를 import했으므로, 이전에 소개했던 component이다. 

(third-party library나 js파일을 import할 때는 뒤의 확장자를 빼고 import한다)

 

document.getElementById('root')

리액트는 기본적으로 single-page-application이다. 즉, 하나의 페이지 안에서 전부 동작한다는 것이다. 유저에게 보여지는 파일은 여러개의 html로 이루어진 것 같지만, 실질적으로 리액트는 하나의 페이지만을 갖고 있다. 라우팅과 같은 부차적인 기능을 통해 다른 html로 이동하는 듯한 착각을 심어주는 것이다. 

따라서 root id를 가진 document는 어디 있느냐하면, public폴더 내의 index.html을 보면 찾을 수 있다.

(public 폴더는 잘 접근할 일은 없지만, index.html이 이곳에 있다)

 

따라서 우리는 App이라는 이름의 component를 root div 내에서 실행하는 것이다. 

(App.js는 다른 component와 달리, index.js에서 실행되는 root component이다. 추후 여러개의 component가 등장하더라도, App.js 내에서 nested 될 것이다)

 

우선 가장 기본적인 문장을 띄우도록 App.js를 작성해보았다.

function App() {
	return (
    	<div>
        	<h2>Hello, world!<h2>
        </div>
    );
}

export default App;

js 내에서 html 코드를 return하는 형식은 처음 보면 굉장히 낯선 광경이다. 이 문법은 react에 도입된 문법으로, JSX라 불린다. 이는 react가 npm start로 실행되면서 브라우저에 전달될 때는 transform하여 전될되는데, 구체적으로 어떻게 변하는지 보고싶다면 해당 리액트 프로젝트를 시작한 후 개발자 도구의 source 파일을 보면 된다. 위에서 적은 js와는 사뭇 다른 코드가 보일 것인데, 이는 리액트가 JSX를 transform하여 브라우저에 전달한 결과이다. 

 

기본적인 js와 달라 혼란스러울 수 있지만, 개발자에게 더 편한 환경을 제공해주는 것이므로 금방 익숙해지는 것이 좋다!

 


기본적인 js 문법과의 차이를 한번은 짚고 넘어가는 것이 좋을 것 같아 추가한다.

function App() {
	return(
		<div>
    		<h2>Hello world!</h2>
        	<p>my cat is rockstar</p>
    	</div>
    );
}

위의 App.js 파일에서 p 태그 하나를 추가하고 싶으면 기본 리액트 문법은 위와 같이 작성하면 된다. 하지만 기본 js 문법에 따르면 다음과 같이 작성해야한다. (imperative approach로, js에게 명료하게 하나하나 어떻게 해야할지 전달)

function App() {
	const paragraph = document.createElement('p');
    paragraph.textContent = 'my cat is rockstar';
    document.getElementById('root').append(paragraph);
	return(
		<div>
    		<h2>Hello world!</h2>
    	</div>
    );
}

 

단순히 코드만 봐도, 리액트가 좀 더 짧고 간결하다. 

'React > 개념' 카테고리의 다른 글

React Basics  (0) 2022.07.20
JS 복습하기  (0) 2022.07.20
React의 메인 개념 : component  (0) 2021.05.19

서론

React 자체를 너무 어렵게 접근할 필요는 없다. 리액트는 UI를 보다 쉽게 개발할 수 있도록 도와주는 자바스크립트 라이브러리다. 물론 Html, css, js로도 UI를 만들 수 있으나, 리액트를 사용하면 component라는 개념 덕분에 코드가 훨씬 깔끔하고 구현 난이도가 내려간다. 

 

Component란 무엇인가?

쉽게 말하자면, UI 상에서 다시 사용할 수 있는 building block이다. 단순히 표시해줘야하는 데이터만 바뀌고 UI는 그대로라면, 굳이 여러번 동일한 코드를 반복해서 작성할 필요 없이, 하나의 block을 만들고, 그 안의 데이터만 넘겨주는 방식이다.

Component 자체는 쉽게 말하자면, Html+js (+ css) 덩어리다. (css를 괄호처리한 이유는 리액트 상에서는 크게 중요한 개념이 아니라서다.) 각각의 UI 상에서 모든 걸 쪼개서 component로 구성할 수도 있다. 따라서 개발자는 UI를 구성하는 모든 요소를 쪼개서 component로 만든 뒤, 최종적으로 어떻게 UI를 그릴지 React에게 구성도를 던져주기만 하면 된다. (재사용성에 너무 집착할 필요는 없다.) 

 

Component 단위의 구성은 개발자에게 Reusability & Separation of Concerns를 제공한다.

불필요한 코드의 반복도 없고, 한 곳에서 지나치게 많은 요소를 관리할 필요도 없다. 각각의 component는 자신이 수행해야 하는 하나의 목표만 집중하면 되는 것이다. 

'React > 개념' 카테고리의 다른 글

React Basics  (0) 2022.07.20
JS 복습하기  (0) 2022.07.20
React : create-react-app  (0) 2021.05.19

+ Recent posts