티스토리 뷰

Today I Learned

React 간단 개요

디아_ 2024. 11. 18. 04:17
728x90

 

 

리액트란?

사용자 인터페이스 구현을 위해 사용하는 자바스크립트 라이브러리

 

(바닐라 자바스크립트와 비교했을때) 리액트를 왜 쓰는가?

사용자에게 모바일앱과 같은 경험 제공

페이지 깜빡임 없이 부드러운 페이지 전환

페이지 re-loading 없이 페이지 내의 요소 업데이트

사용자가 어떤 요소와 상호작용할때 페이지 깜빡이거나 로딩하는 과정 없이 백그라운드에서 데이터를 fetching하고 관련 결과를 페이지에 자동으로 업데이트

 

좀더 간편한 멘탈모델* 제공

- 애플리케이션이 규모가 커질수록 바닐라 자바스크립트로만 개발하기에는 코드가 복잡해질 수 있다

- 복잡하게 짜여진 자바스크립트 코드는 에러 발생하기 쉽다(error-prone)

- 유지보수 하기 어렵다.

 

*멘탈 모델이란

프로그래밍의 멘탈 모델은 프로그래머가 프로그래밍 개념, 프로그램 및 프로그래밍 전반을 이해하는 데 도움이 되는 프레임워크입니다. 멘탈 모델은 더 나은 의사 결정, 결과 예측, 복잡한 문제 단순화, 복잡한 시스템과 프로세스 이해, 보다 효율적인 문제 해결에 도움을 줄 수 있습니다.

A mental model in programming is a framework that helps programmers understand programming concepts, programs, and programming in general. Mental models can help programmers: Make better decisions, Predict outcomes, Simplify complex problems, Understand complex systems and processes, and Make problem-solving more efficient.

 

Vite 같은 번들러를 쓰는 이유는?

index.html, index.js 각 파일 만들어서 쓰지 않고 번들러 쓰는 이유가 뭘까?

애플리케이션 규모가 커질 수록 일일이 파일을 만들고 script 태그로 html 파일에 스크립트 파일을 각각 연결하기는 쉽지 않을 것이다.

또한, JSX 같은 문법은 브라우저가 이해하지 못하므로 브라우저가 이해하도록 변환시키는 작업, 클라이언트 측에서 다운받아야하는 스크립트 파일의 크기를 최소한으로 만들기 위한 minification 작업 등을 번들러가 해준다.

 

모듈 import & export

리액트 프로젝트에서 import 할때 파일 확장자 까지 쓰지 않는다. 리액트가 알아서 빌드할때 변환하기 때문이다.

import ExpenseDate from './ExpenseDate';

// 바닐라 자바스크립트인 경우 확장자까지 써줘야함
// import ExpenseDate from './ExpenseDate.js'; 

 

빌드 시 리액트는 프로젝트 내의 import, export 되어있는 것들을 모두 모아서 몇개의 큰 파일 하나로 머지한 후 최종적으로 index.html 파일에 스크립트 태그로 주입한다. 리액트 프로젝트를 브라우저 인스펙트해서 봤을때 script 태그에 type=”module”이 없는 것은 이런 과정이 있기 때문이다.

 

default 키워드로 export 하는 경우, import 할때는 아무 이름으로 import 할 수 있다. 왜냐하면 export 할때 따로 const나 let으로 이름을 할당하지 않고, value만 export 했기 때문이다.

// util.js
 export default "abcd";
 
 // app.js
 import apiKey from './util.js'

 

 

명령형 프로그래밍 vs 선언형 프로그래밍

프로그래밍 패러다임으로 선언형 프로그래밍과 명령형 프로그래밍이 있다.

 

명령형 프로그래밍은 원하는 결과를 내기까지 프로그램에게 수행할 동작을 하나하나 지시하듯이 프로그래밍하는 것을 의미한다.

예를 들어, 페이지 내 버튼을 클릭하면 'Hello'라는 텍스트가 'Good-bye!'라는 텍스트로 바뀌어야하는 요구사항이 있다고 가정해보자. 이를 명령형으로 작성하면 다음과 같이 작성할 수 있다.

<p>Hello</p>
<button>Click</button>

<script>
	const $button = document.querySelector('button');    
	$button.addEventListener('click', function() {
		const $para = document.querySelector('p');        
		$para.innerText = 'Good-bye!';
	});
</script>
1. 페이지 내에서 버튼 요소를 찾는다
2. 버튼 요소에 이벤트 리스너를 단다.
3. 이벤트 리스너에 다음의 콜백함수를 넘긴다.
  3-1. p 요소를 찾는다.
  3-2. 해당 요소의 innerText를 변경한다.

 

이렇게 단계별로 하나하나씩 지시하듯이 프로그래밍 하는것을 명령형 프로그래밍이라고 할 수 있다.

 

명령형 프로그래밍과 대조되는 개념으로 선언형 프로그래밍이 있다. 선언형 프로그래밍은 프로그램이 내야하는 결과가 무엇인지를 정의하는 방식의 프로그래밍이다.

 

리액트는 선언형 프로그래밍의 특징을 가지고 있다.

위와 동일한 요구사항을 리액트로 작성하면 다음과 같이 작성할 수 있다.

//...

const [text, setText] = useState('Hello');

const handleClick = () => setText('Good-bye!');

return (
	<>
	  <p>{text}</p>
	  <button onClick={handleClick}>Click</button>
	</>
)

 

어떻게 그 UI가 그려지고 업데이트 되는지는 리액트가 알아서 하고 코드작성자는 최종적으로 보이고 싶은 결과에 관한 코드만 작성하면 된다.

 

명령형과 선언형 프로그래밍의 각각 장단점이 있겠으나 선언형 프로그래밍 방식의 리액트를 사용하면 다음과 같은 장점을 가질 수 있다.

  • 개발자가 "어떻게(How)" 구현할지가 아닌 "무엇을(What)" 보여줄지에 집중할 수 있다.
  • UI가 어떤 상태여야 하는지 명확하게 선언하므로 코드의 의도를 파악하기 쉽다.

 

동적으로 값 렌더링하기

{} 안에 동적 값을 넣을 수 있다. 이때 if문, for문, 함수 정의 등의 블록 statement는 올 수 없다. 무조건 value를 생성하는 expression만 넣을 수 있다.

function ExampleComponent() {
  const user = {
    name: "Kim",
    age: 25
  };
  const isLoggedIn = true;
  const numbers = [1, 2, 3, 4, 5];
  
  return (
    <div>
      {/* 가능한 표현식들 */}
      <p>이름: {user.name}</p>                    {/* 객체 속성 접근 */}
      <p>나이: {user.age + 1}</p>                 {/* 산술 연산 */}
      <p>성인여부: {user.age >= 18 ? "성인" : "미성년자"}</p>  {/* 삼항 연산자 */}
      <p>로그인: {isLoggedIn && "환영합니다!"}</p>   {/* 논리 연산자 */}
      <p>배열: {numbers.map(n => n * 2).join(", ")}</p>  {/* 배열 메서드 */}
      <p>함수결과: {Math.random()}</p>            {/* 함수 호출 */}

      {/* 불가능한 표현식들 - 이것들은 에러가 발생합니다 */}
      {/* 
      {if (isLoggedIn) {                // if 문 사용 불가
        return "환영합니다"
      }}
      {for (let i = 0; i < 5; i++) {    // for 루프 사용 불가
        console.log(i)
      }}
      */}
    </div>
  );
}

 

 

이미지 표시하기

import 문법으로 image를 가져오지 않고 하드코딩으로 이미지 주소를 쓰게 되면 번들링 할때 해당 이미지들은 해당 프로세스에서 누락될 수 있고 결과적으로 배포 했을때 해당 이미지는 보여지지 않을 수 있다. 이를 방지하지 하기 위해서는 이미지를 import해서 사용하면 된다.

import Img from '@assets/image.png'


//...

return (
	<div>
	  <img src={Img} alt="image" />
	</div>
)

 

 

 

728x90