[Day45] React - 기초
[Day45] React - 기초
JS와 프레임워크의 필요성
🔹 JavaScript
- 초기: 단순한 연산과 시각적 효과를 위한 스크립트 언어
- 현재: 웹 애플리케이션의 핵심 기술
⚠️ 문제점
- 순수하게 JS만으로 규모가 큰 애플리케이션을 관리하기 어려움 → 이를 해결하기 위해 프레임워크 등장
🔹 프레임워크의 역할
- MVC(Model-View-Controller) / MVVM 아키텍처 기반
- 모델(Model): 애플리케이션이 사용하는 데이터를 관리
- 뷰(View): 사용자에게 보이는 부분
- 컨트롤러(Controller): 모델 데이터를 조회하거나 수정하고, 변경된 사항을 뷰에 반영 👉 여러 구조가 지닌 공통점은 모델(Model)과 뷰(View)가 있다는 것
- 사용자의 Request(요청)를 Controller가 받는다.
- Controller는 Service에서 비즈니스 로직을 처리한 후 결과를 Model에 담는다.
- Model에 저장된 결과를 바탕으로 시각적 요소 출력을 담당하는 View를 제어하여 사용자에게 전달한다.
⚠️ 문제점
- 애플리케이션 규모가 크면 복잡해지고 관리를 제대로 하지않으면 성능이 저하됨
✅ 최대한 성능을 아끼고 더 나은 사용자 경험을 위해 ‘React’의 등장
- Facebook 개발팀이 만든 UI 라이브러리
- 기존 뷰를 날려버리고 새롭게 렌더링하는 방식
- 단점: CPU 점유율 증가 및 성능 문제 발생 → Virtual DOM 도입
React와 Virtual DOM
🔹 React란?
- JavaScript 라이브러리
- 어떤 데이터가 변할 때마다 어떤 변화를 줄지 고민하지 않고 기존의 뷰를 날려버리고 새롭게 렌더하는 것
- “오직 View에 집중” → 다른 기능(라우팅, 상태 관리 등)은 별도 라이브러리를 사용해야 함
React 초기 렌더링
- render() 함수 호출 -> 컴포넌트가 어떻게 생겼는지 정의
- 뷰가 어떻게 생겼고 작동하는지에 대한 정보를 지닌 객체를 반환
- 렌더링 작업이 끝나면 지니고 있는 정보들을 HTML 마크업 생성 & DOM에 주입
- 사용자 화면에 표시됨
React의 업데이트 과정 (Reconciliation, 조화 과정)
뷰를 업데이트 할 때에는 ‘업데이트 과정을 거친다’라고 하기보다는 ‘조화 과정을 거친다’라고 표현하는것이 정확한 표현
why? 컴포넌트에서 데이터를 업데이트했을 때 단순히 업데이트한 값을 수정하는 것이 아니라, 사실 새로운 데이터로 변환하는 것이기 때문
- 단순히 업데이트한 값을 수정하는 것이 아니라, 새로운 데이터를 가지고 render 함수 재호출.
- render 함수가 반환하는 결과를 곧바로 DOM에 반영하지 않고, 이전에 render 함수가 만들었던 컴포넌트 정보와 현재 render 함수가 만든 컴포넌트 정보를 비교
- 두가지 뷰를 최소한의 연산으로 비교 후, 최소한의 연산으로 DOM 트리를 업데이트
⭐️ 전체 UI를 다시 렌더링하는 것처럼 보이지만, 실제로는 변경된 부분만 효율적으로 업데이트
🔹 Virtual DOM
- 실제 DOM을 직접 조작하지 않고, 메모리에 가상의 DOM을 만들어 비교 후 변경 사항만 업데이트
- 리액트의 주요 특징 중 하나는 Virtual DOM을 사용하는 것임
- 성능 저하 문제를 해결하기 위해 도입 된 것
- DOM을 최소한으로 조작
DOM (Document Object Model) 이란?
객체로 문서 구조를 표현하는 방법으로 XML이나 HTML로 작성한다.
- 트리 구조를 가지며, 규모가 커질수록 성능 저하 발생
- 동적 UI에 최적화되어 있지 않음
Virtual DOM 단계
- 데이터를 업데이트하면 전체 UI를 Virtual DOM에 리렌더링
- 이전 Virtual DOM에 있던 내용과 현재 내용을 비교
- 변경 부분만 실제 DOM에 적용
⚠️ 오해:
- Virtual DOM을 사용한다고 언제나 항상 빠르지 않음
- 단순한 작업(예: 정적인 페이지)에는 오히려 React가 비효율적일 수 있음
라이브러리
- React는 프레임워크가 아니라 ‘라이브러리’
- 정말 뷰만 신경쓰기 때문에 다른 기능들은 직접 구현해야 한다.
- 다만, 다른 사람들이 만들어 둔 라이브러리를 가져와 사용할 수 있다
- react-router, axios, fetch, redux, Mobx
- 여러 라이브러리를 사용해야하는 단점이 있다.
라이브러리 vs 프레임워크
프레임워크
- 컴퓨터 프로그래밍에서 복잡한 문제를 해결하거나 효율적으로 작업하기 위해 사용되는 기본 개념 구조.
- 간단한 뼈대(골조) 역할을 하며, 개발자가 정해진 규칙 안에서 코드를 작성해야 함.
- 프로그램의 흐름을 프레임워크가 제어 → 주도권이 프레임워크에 있음.
라이브러리
- 소프트웨어 개발 시 사용되는 비휘발성 자원의 모음(데이터, 문서, 미리 작성된 코드 등 포함).
- 특정 기능을 수행하는 도구로서, 개발자가 원하는 부분에서 직접 호출하여 사용 가능.
- 프로그램의 흐름을 개발자가 제어 → 주도권이 개발자에게 있음.
항목 | 프레임워크 | 라이브러리 |
---|---|---|
유연성 | 낮음 - 정해진 방식대로 개발 | 높음 - 필요한 기능만 선택 가능 |
학습 곡선 | 높음 - 구조와 규칙을 익혀야 함 | 낮음 - 특정 기능만 익히면 사용 가능 |
개발 속도 | 빠름 - 기본 구조 제공 | 상대적으로 느림 - 직접 구조 설계 필요 |
일관성 | 높음 - 코드 스타일링과 개발 방식이 동일 | 낮음 - 여러 라이브러리 조합 시 코드 스타일이 다를 수 있음 |
확장성 | 높음 - 표준화된 방식으로 유지보수 용이 | 상황에 따라 다름 - 구성에 따라 유지보수 난이도 달라짐 |
보안 | 상대적으로 강함 - 내장된 보안 기능 포함 | 직접 관리해야 함 - 외부 라이브러리 보안 검토 필요 |
- 프레임워크 : 레시피와 재료가 포함된 밀키트 → 정해진 방식대로 요리해야 함.
- 라이브러리 : 각종 재료가 있는 슈퍼마켓 → 원하는 재료만 골라서 직접 요리.
🔹 라이브러리와 프레임워크의 조합
- 라이브러리: 다른 라이브러리와 프레임워크와 조합하여 사용 가능.
- 프레임워크: 다른 프레임워크와 함께 사용할 수 있지만, 제약이 심함.
- 다른 계층(예: 백엔드 + 프론트엔드) 조합 가능.
- 마이크로서비스처럼 독립적으로 사용 가능 (예: 결제 서비스, 인증 서비스, 추천 시스템).
⚠️ 프레임워크는 자체적으로 강한 제어력을 가지므로, 같은 역할을 수행하는 프레임워크끼리는 함께 사용하기 어려움.
🔹 React Life Cycle
- React를 사용하면 컴포넌트 단위로 UI를 화면에 보이게 하거나 다른 UI로 변경하거나, 현재 보이는 UI를 화면에서 제거할 수 있다.
- 따라서 각 컴포넌트들을 생성(Mounting)하고, 업데이트(Updating)하고, 제거(unMounting)하는 단계를 차례로 겪는 생명주기를 가지고 있다는 것이다.
✅ 컴포넌트 라이프사이클 3단계
- Mounting (컴포넌트 생성 & 화면에 나타남)
- Updating (컴포넌트 업데이트: props/state 변경 시 재렌더링)
- Unmounting (컴포넌트 제거)
Class 컴포넌트 라이프사이클
1
2
3
componentDidMount(); // 컴포넌트가 마운트된 직후 실행
componentDidUpdate(); // 업데이트 후 실행
componentWillUnmount(); // 언마운트되기 직전 실행
Function 컴포넌트 라이프사이클
- 함수 방식 자체는 이전에는 쓰이지 않았지만 업데이트되면서 라이프 사이클을 다룰 수 있게 됨
1
2
3
4
useEffect(() => {
console.log("컴포넌트 마운트");
return () => console.log("컴포넌트 언마운트"); // cleanup 함수
}, [/* dependency array */]);
🔹 JSX (JavaScript XML)
JSX란?
- JavaScript를 확장한 문법
- React에서 UI를 정의할 때 사용
- JSX는 JavaScript 객체로 변환됨 → JavaScript 코드와 혼용 가능
- React에서
.js
확장자를 사용해도 JSX를 활용할 수 있음.- js랑 jsx쓰는게 다른 이유 : 코드 스타일을 통일하기 위함
JSX의 주요 특징
- 반드시 하나의 부모 요소 안에 포함되어야 함
- JavaScript 표현식(변수, 함수 호출 등)을
{}
안에서 사용 가능1
<TAG_NAME> 내용 {JavaScript 표현식} </TAG_NAME>
- inline
class
대신className
사용- 닫는 태그 필수 (
<input />
같은 셀프 클로징 태그 포함)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function App() {
const name = "자바리액트";
const named = undefined;
return (
<div>
{/* JSX에서는 요소 여러 개를 반환할 경우 부모 요소가 필요함 */}
{/* JSX에서 주석은 중괄호 안에 넣어야 함 */}
{/* Ctrl + / -> 주석 단축키 */}
{/* 자바스크립트 표현식 사용 가능 */}
<h1>{name} 안녕</h1>
{/* 조건부 렌더링: 삼항 연산자 */}
{name === "자바리액트" ? <h1>자바리액트 맞습니다.</h1> : <h1>자바리액트가 아닙니다.</h1>}
{/* 조건부 렌더링: && 연산자 */}
{name === "자바리액터" && <h1>자바리액터가 맞습니다.</h1>}
{/* Undefined를 렌더링하지 않도록 처리 */}
{named || "리액트 언디파인"}
{/* 인라인 스타일 적용 방법 */}
<div style=>{name}</div>
{/* className을 활용한 스타일링 */}
<div className="react">{name}</div>
{/* 셀프 클로징 태그 */}
<input />
</div>
);
}
export default App;
var, let const 차이점
var
- 변수 선언 가능
- 단점 :
- 동일한 변수명을 중복해서 선언 가능 (=> 프로그램에 버그가 발생할 수 있다)
- 상수 선언 안됨
let
- ES6에 추가된 변수 선언 방식
- 동일한 이름으로 중복해서 선언 불가능
- 동적인 값을 상수나 변수로 선언할 때 쓰임
const
- ES6에 추가된 상수 선언 방식 -> 값 변경 불가능 (immutable)
- 동일한 이름으로 중복 선언 불가능
JS 기존 함수의 동작
- 인자(argument)가 전달되지 않으면 에러가 발생하지 않음
하지만, 해당 인자의 값은 undefined가 됨.
Default Parameter (기본 매개변수)
- 함수의 인자값이 전달되지 않았을 때 기본값을 설정할 수 있음.
1
2
3
4
5
6
function sayHello(name = "Guest") {
console.log(`Hello, ${name}!`);
}
sayHello(); // "Hello, Guest!"
sayHello("John"); // "Hello, John!"
React 객체 생성 함수
- Root DOM에 렌더링할 ReactDOM 객체를 생성하는 함수
1
2
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<StrictMode>
(엄격 모드)
- 개발 중 잠재적인 버그를 빠르게 발견할 수 있도록 도와주는 기능.
- 개발 환경에서만 활성화되며, 실제 프로덕션 빌드에서는 영향 없음.
1
2
3
<React.StrictMode>
<App />
</React.StrictMode>
END
This post is licensed under CC BY 4.0 by the author.