렌더링의 종류

 

목차

  1. 서론
  2. SSR (Server-Side Rendering)
  3. CSR (Client-Side Rendering)
  4. SSG (Static Site Generation)
  5. ISR (Incremental Static Regeneration)
  6. 결론
  7. 참고사이트

 

서론

리액트가 클라이언트 사이드 렌더링인 것을 알고 있었다. 그래서 첫 접속 했을 때 모든 js파일을 다운로드하고 웹 사이트를 보여주는 방식이라고 알고 있었다. 하지만 더 자세히 알지 못했고 Nextjs가 나오면서 렌더링 방식들을 정리하는 것이 좋을 것이라 생각했다.. 각 페이지마다 전략적으로 렌더링 방식을 적용할 수 있기에 이번 기회로 SSR, CSR, SSG, ISR에 대해 알아보자

 

 

SSR (Server-Side Rendering)

SSR의 특징

서버 측 렌더링 (SSR)은 서버에서 HTML 콘텐츠를 생성하여 클라이언트로 전송하는 방식을 말합니다.

 

mdn 문서에 SSR에 대한 정의를 위의 말로 표현하고 있다.

사용자의 요청하는 것에 따라 서버에서 Html을 브라우저로 전송하는 방식이다.

 

장점

1) 첫 로드 시 CSR보다 비교적 빠른 로딩 속도를 가지고 있어 콘텐츠를 빠르게 볼 수 있다.

2) 서버에서 html을 보내 렌더하기에 온전한 구조를 가지고 있습니다. 이에 따라 SEO에 좋은 영향을 준다.

 

단점

1) 작은 부분을 업데이트 하더라도 전체페이지를 서버에 요청하므로 서버에 부하가 있을 수 있다.

2) 전체페이지를 받아오므로 화면 깜빡임으로 인해 사용자 경험이 좋지 않을 수 있다.

 

사용처 

SEO가 중요한 회사 소개 사이트나 블로그, 이커머스 등의 사이트에 적합하다.

 

 

CSR (Client-Side Rendering)

CSR 동작 방식

클라이언트 측 렌더링(CSR)은 브라우저에서 JavaScript를 사용하여 HTML 콘텐츠를 생성하는 방식을 말합니다.

 

mdn 문서에 CSR에 대한 정의를 위의 말로 표현하고 있다.

CSR은 초기 렌더 시에 html, javaScript파일을 받아 브라우저에서 실행하며 이후 컨텐츠를 업데이트하는 경우 부분적으로 서버에 요청하여 전체 페이지가 변경되는 것이 아닌 일부분만 업데이트가 된다.

 

장점

1) 첫 로드되면 모든 javaScript 번들 파일을 다운로드받아 페이지 전환 시 서버에서 받아오는 시간을 줄여 부드로운 사용자 경험을 줄 수 있다.

2) 서버에 요청 시 필요한 부분만 변경되기에 서버에 부하가 SSR에 비해 비교적 낮다.

 

단점

1) 첫 로드시에 모든 javaScript 번들링된 파일을 다운로드 받기에 초기 로딩 시간이 길어진다. javaScript 실행 전까지 DOM이 없기 때문에 빈화면 또는 로딩화면이 길어질 수 있다.

2) 검색 엔진 크롤러가 자바스크립트를 실행하지 못하는 경우 콘텐츠를 제대로 인식하지 못할 수 있다. (SEO에 불리함)

 

사용처

회사 내에서 사용하는 ERP나 검색 상위 노출이 되지 않아도 되는 어드민 페이지 등에 사용할 수 있다.

 

 

 

SSG (Static Site Generation)

SSG 프로세스

SSG는 빌드 시점에 HTML을 미리 생성해두는 방식이다.

사용자가 요청 시 서버에서 미리 생성된 HTML파일을 그대로 전송한다.

 

장점

1) 미리 생성된 HTML 파일을 전송하므로 로딩 속도가 매우 빠르다.

2) 서버 측 로직이 없어서 보안이 뛰어나다.

 

단점

1) 변경사항을 반영하기 위해서는 다시 빌드를 해야하는 번거로움이 있다.

2) 사용자별 맞춤 페이지나 실시간 데이터를 보여주기에 어렵다.

 

사용처

업데이트가 자주 이루어지지 않은 기업 웹사이트, 블로그 등이 있다.

 

 

 

ISR (Incremental Static Regeneration)

ISR의 장단점

Next.js를 사용하면 사이트를 빌드한 후 정적 페이지를 생성하거나 업데이트할 수 있습니다. Incremental Static Regeneration (ISR)을 사용하면 전체 사이트를 재빌드할 필요 없이 페이지별로 정적 생성을 사용할 수 있습니다.

 

ISR은 SSG의 단점을 보완한 방식으로 SSG의 빠른 속도를 유지하면서 데이터를 주기적으로 업데이트할 수 있게 해준다.

 

장점

1) SSG 장점을 가지고 있어 빠른 초기 로딩 속도와 높은 보안성을 가지고 있다.

2) 일정 시간 간격으로 HTML파일을 재 생성하므로 콘텐츠 업데이트를 비교적 쉽게 처리할 수 있다.

 

단점

1) HTML파일이 다시 생성되기 까지 데이터 업데이트 간 딜레이가 발생할 수 있다. (업데이트 이전의 컨텐츠가 표시될 수 있다)

2) SSG에 비해 revalidate 시간 설정 등 추가적인 설정이 필요하다

3) 특정 사용자가 업데이트 직전의 페이지를 보고 다른 사용자가 업데이트 이후 페이지를 보는 상황인 데이터 일관성 문제가 발생할 수 있다.

 

사용처

실시간 처리까지 진행되지 않는 블로그나 뉴스페이지 정도가 있을 것이다.

 

 

결론

어떤 렌더링 방식을 선택해야할까

 

렌더링 방식은 하나만 정답이 있는 것이 아니라 각 웹사이트의 성격에 맞게 전략적인 선택이 중요한 것 같다.

Next.js같은 프레임워크는 페이지 단위로 SSR, CSR, SSG, ISR을 섞어서 사용할 수 있기 때문에 상황에 따라 최적의 전략을 선택할 수 잇을 것이다.

 

 

참고사이트

https://www.educative.io/answers/ssr-vs-csr-vs-isr-vs-ssg

 

SSR vs. CSR vs. ISR vs. SSG

Contributor: Palwasha Zulfiqar

www.educative.io

https://sangminnn.tistory.com/entry/%EB%8D%94-%EC%A2%8B%EC%9D%80-%EC%9C%A0%EC%A0%80-%EA%B2%BD%ED%97%98%EC%9D%84-%EC%9C%84%ED%95%9C-Streaming-SSR

 

더 좋은 유저 경험을 위한 Streaming SSR

목차 서론Streaming SSR의 등장 배경, 기존의 CSR과 SSR 방식에 관하여웹 성능 지표 RemindStreaming SSR이란 ?Streaming SSR의 동작 방식Progressive HydrationStreaming SSR이 가능한 이유React 진영에서 Streaming SSR까지

sangminnn.tistory.com

https://medium.com/@khushbuchoksi/what-are-csr-ssr-ssg-and-isr-d59201e3b060

 

What are CSR, SSR, SSG, and ISR?

A Comprehensive Exploration of Web Rendering Techniques from traditional approach to CSR, SSR, SSG and ISR.

medium.com

https://developer.mozilla.org/en-US/docs/Glossary/SSR

 

Server-side rendering (SSR) - Glossary | MDN

Server-side rendering (SSR) refers to the practice of generating HTML content on the server and sending it to the client. SSR is opposed to client-side rendering, where the client generates the HTML content using JavaScript. Both techniques are not mutuall

developer.mozilla.org

https://developer.mozilla.org/en-US/docs/Glossary/SSG

 

Static site generator (SSG) - Glossary | MDN

A static site generator (SSG) is a software used to generate static websites. A static website is comprised of HTML, CSS, and JavaScript files. Most importantly static sites do not have server-side logic, so for any given URL, all users will receive the sa

developer.mozilla.org

https://developer.mozilla.org/en-US/docs/Glossary/CSR

 

Client-side rendering (CSR) - Glossary | MDN

Client-side rendering (CSR) refers to the practice of generating HTML content using JavaScript in the browser. CSR is opposed to server-side rendering, where the server generates the HTML content. Both techniques are not mutually exclusive and can be used

developer.mozilla.org

https://nextjs-ko.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration

 

Incremental Static Regeneration (ISR) – Nextjs 한글 문서

Learn how to create or update static pages at runtime with Incremental Static Regeneration.

nextjs-ko.org

https://www.napkin.ai/

 

Napkin AI - The visual AI for business storytelling

Just type, copy-paste or generate your text and Napkin will instantly transform it into insightful visuals. Make your communication more effective with Napkin.

www.napkin.ai

 

'학습 > web' 카테고리의 다른 글

[web] 브라우저는 어떻게 움직이나??  (0) 2025.07.07

react의 key prop / chatGTP 5버전 이미지 출력

 

 

 

 

리액트에서 배열을 렌더링하기 위해서는 map 메서드를 사용하여 아래와 같이 사용하게된다.

function MyComponent() {
  const items = ['사과', '바나나', '딸기'];

  return (
    <ul>
      {items.map((item, index) => (
        <li>{item}</li>
      ))}
    </ul>
  );
}

리스트 안에 자식들은 key 프롭을 가져야 합니다

단지 배열을 렌더링 했을 분인데 크롬 브라우저에서 에러가 발생한다. 

각 자식 리스트에는 유니크한 키 값을 가져야하는 내용인데 이에 대해 key를 설정하는 이유와 key 설정 시 주의할 점을 알아보고자 한다.

 

key가 필요한 이유

 

Key는 각 컴포넌트가 어떤 배열 항목에 해당하는지 React에 알려주어 나중에 일치시킬 수 있도록 합니다. 이는 배열 항목이 정렬 등으로 인해 이동하거나 삽입되거나 삭제될 수 있는 경우 중요해집니다. key를 잘 선택하면 React가 정확히 무슨 일이 일어났는지 추론하고 DOM 트리에 올바르게 업데이트 하는데 도움이 됩니다.

 

위 내용은 리액트 공식문서에서 key에 대한 내용을 알려주고 있다.

각 항목에 key가 있어야 배열을 추가하거나 삭제, 업데이트할 때 정확하게 처리할 수 있다는 내용이라고 요약할 수 있을 것이다.

 

리액트는 이전 렌더 트리와 다음 렌더 트리를 최소 변경으로 맞추기 위해 형제 노드 단위로 비교한다.

이때 각 형제요소를 식별하는 값이 key가 된다.

key가 없거나 적절치 아니하면 리액트는 요소를 잘못 매칭하거나 불필요하게 교체하게 되어 성능 저하나 입력값에 에러가 발생하는 일이 발생할 수 있다.

 

예를 들어 데이터베이스 sql문에서도 delete from table_name where id = value 와 같이 테이블의 튜플이 가지고 있는 고유한 값(id)을 지정해야 그 데이터를 지울 수 있는 내용과 일맥상통하지 않을까 생각이 된다.

 

 

key를 설정할 때 고려해야 되는 점

 

1. 배열의 인덱스를 key값으로 사용하면 안됩니다

(순서에 상관없는 정적리스트라면 인덱스를 사용하더라도 문제가 되진 않는다)

{todos.map((value, index) => (
  <TodoItem key={index} {...value} />
))}

React는 key를 기준으로 이번에 있던 요소와 새로 렌더링된 요소를 매칭한다.

하지만 index는 아이템의 순서를 나타내기 대문에 순서가 변하면 key가 변경되어버린다.

 

그래서 위와 같이 배열의 인덱스로 key값을 넣는 경우 변경, 삭제, 삽입 시 아이템의 식별이 꼬여 배열 조작에 문제가 발생할 수 있다.

예를 들어 0번 인덱스에 새로운 값을 추가할 경우 기존의 0번 인덱스 항목이 1번으로 변경되어 기존의 인덱스 값들이 변경되어 버린다.

이러한 과정에서 기존의 입력 값들이 다른 항목에게 옮겨져 버리거나 불필요한 DOM 변경이 발생할 수 있다.

 

2. 즉석으로 key를 만들면 안된다.

{items.map(item => (
  <li key={Math.random()}>{item.name}</li>
))}

 

예를 들어 key 값에 Math.random()과 같이 넣는 것인데 이는 매번 호출 때마다 새로운 숫자를 만들게 되어 렌더링할 때마다 key가 전부 변경되는 상황이 발생한다.

 

key가 변경되면 새로운 요소로 판단하여 실제 DOM을 업데이트하게 됩니다. 결국 성능에 영향을 끼치게 됩니다.

 

 

3. key는 prop으로 받지 않는다.

function Item({ id }) {
  return <div>{id}</div>;
}

<Item key={123} id={123} />

위에 코드처럼 Item에 key로 123을 작성하였지만 key의 123은 Item 내부에서 props.key로 접근할 수 없다.

react에서 키는 재조정 과정에서 사용하고 실제 props로는 내려주지 않는다. 컴포넌트 데이터가 아닌 내부 알고리즘을 위한 값이다.

 

<Item key={item.id} id={item.id} />

item.id가 필요한 경우 key로 설정하더라도 다른 Props로 내려주어야 한다.

 

 

4. 데이터베이스의 고유한 key, id를 사용하는 것이 안전하다.

{items.map((item) => (
  <li key={item.id}>{item.name}</li>
))}

key의 고유한 값을 가질 수 있으며 안정적이기 때문에 데이터베이스의 고유한 값을 사용하는 것이 안전하다.

이렇게 되면 각 자식에 고유한 키를 가지게 되어 요소를 변경, 생성, 삭제를 진행하더라도 불필요한 DOM 변경은 사라지게 되고 정확한 변경이 이루어지게 된다.

 

 

* 번외

1) 리스트를 렌더할 때 태그가 아닌 fragment로 사용할 수 있다.

import { Fragment } from 'react';

items.map(item => (
  <Fragment key={item.id}>
    <Title>{item.title}</Title>
    <Content>{item.body}</Content>
  </Fragment>
));

 

 

 

 

 

느낀 점

블로그를 작성하기 전 공식문서와 다른 블로그의 글들을 찾아보며 기존에 알고 있었던 key에 대한 이해가 있었다.

예를 들어 배열 렌더링할 때 키가 있어야 정확하게 리스트를 제거하고 추가, 업데이트 과정을 거칠 수 있다는 것이다.

이번에 다시 찾아보면서 각 배열의 자식 사이에서만 유일하면 되고 전역에서는 유일할 필요가 없다는 사실을 새롭게 인식하게 되었다.

사실 각 배열에 key를 넣으면서 당연시하게 사용했지만 개념적으로 다시 확인할 수 있었던 시간이었다.

그리고 재조정(Reconciliation) 과정인 앞, 뒤의 가상돔을 비교해 변경된 부분만 바뀌는 과정에서 키 값이 정확하지 않으면 비효율적 문제가 발생할 수 있다는 점도 새롭게 알게 되었다.

 

 

참고문서

https://ko.react.dev/learn/rendering-lists#why-does-react-need-keys

 

리스트 렌더링 – React

The library for web and native user interfaces

ko.react.dev

https://ko.legacy.reactjs.org/docs/reconciliation.html#recursing-on-children

 

재조정 (Reconciliation) – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

https://ko.legacy.reactjs.org/docs/lists-and-keys.html

 

리스트와 Key – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

https://www.moonkorea.dev/React-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%9E%AC%EC%A1%B0%EC%A0%95%EA%B3%BC-key

 

React가 고유한 key를 권장하는 이유

리액트는 렌더링 간 효율적으로 DOM을 업데이트하고자 재조정 과정을 거치게 되는데요, 재조정에서 key의 역할과 key 값으로 인덱스의 사용을 지야하는 이유에 대해 알아봅니다.

www.moonkorea.dev

 

'학습 > react' 카테고리의 다른 글

[react] 함수형 컴포넌트와 클래스형 컴포넌트  (3) 2025.08.04
[react] Virtual DOM 가상 돔  (2) 2025.07.24
[react] 리액트의 렌더링 정리  (1) 2025.07.23
클론 프로젝트 회고2  (0) 2024.05.18
클론 프로젝트 회고  (1) 2024.02.12

 

chatGPT 함수형 vs 클래스형

 

hmlt, css, javaScript로만 페이지를 구성할 때 불편한 점을 많이 느꼈었다.

바로 페이지마다 반복되는 코드가 너무 많다는 것!

헤더, 푸터, 헤드 태그, 메타 태그 등 이걸 하나로 관리할 수 있으면 너무 좋을 텐데 하나로 수정되면 전체 페이지의 코드를 수정해야 하는게 너무나 불편했었다. 물론 옛날 프론트, 벡엔드 나누지 않았던 시절에는 서버로직으로 처리가 가능했다.

리액트 컴포넌트 개념을 알고나서부터 재활용 가능한 ui를 만들 수 있기에 너무나 편리한 도구임을 깨닫게 되었다.

하나의 압축된? 코드로 표현할 수 있다는 그 쾌감.. 컴포넌트에 대해서 알아보자

 

목차

  1. 컴포넌트란 무엇인가?
  2. 함수형 컴포넌트 (Function Component)
  3. 클래스형 컴포넌트 (Class Component)
  4. 함수형 vs 클래스형 비교
  5. 마무리 요약

 

1. 컴포넌트란 무엇인가?

리액트 공식문서를 보면 컴포넌트에 대한 내용을 아래와 같이 정의하고 있다.

React를 사용하면 마크업, CSS, JavaScript를 앱의 재사용 가능한 UI 요소인 사용자 정의 “컴포넌트”로 결합할 수 있습니다.
React 컴포넌트는 마크업으로 뿌릴 수 있는 JavaScript 함수입니다.

 

리액트를 사용하게 되면 javaScript에서 사용했던 createElement라던지 append 함수와 같은 것을 사용하지 않더라도 jsx문법으로 비교적 쉽게 컴포넌트화 하여 사용할 수 있다.

 

그래서 리액트 웹앱 내부에서 ui를 분할하고 재사용할 수 있는 단위라고 정리해볼 수 있을 것 같다.

 

2. 함수형 컴포넌트 (Function Component)

import React from "react";

function Greeting(props) {
  return <h1>Hello, {props.name}!</h1>;
}

// ES6 화살표 함수 형태
const Greeting = ({ name }) =>
  <h1>Hello, {name}!</h1>;

export default Greeting;

 

- 리액트에서 함수형태로 컴포넌트를 만들면 위와 같은 형태가 된다.

- 함수를 선언하고 내부에서 jsx문법을 리턴해주는 방식이다.

- 아래에서 정리해볼 class 문법보다 간결한 느낌이며 요즘엔 다 함수형 컴포넌트로 컴포넌트를 제작한다고 한다.

 

 

3. 클래스 컴포넌트 (Class Component)

import React, { Component } from "react";

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

export default Greeting;

 

- 클래스 컴포넌트는 React.Component로 부터 상속을 받아 컴포넌트를 선언한다.

- render() 메서드 내에서 jsx를 return 한다.

 

 

4. 함수형 vs 클래스형 비교

위에서 함수형 컴포넌트와 클래스 컴포넌트에 대해서 간략하게 정리해보았습니다.

형태만 보더라도 차이점이 존재하는데요 차이점에 대해 더 상세히 나열해보겠습니다.

 

1) 컴포넌트 선언 방식

- 함수형의 경우 function MyComponent(props) 또는 const MyComponent = (props) = {} 함수형태로 선언이 된다.

- 클래스의 경우 class MyComponent extends React.Component 형태로 작성되고 render() 메서드가 있어야한다.

 

 

2) props 와 state 처리방식

- 함수형 props의 경우 props.foo 또는 구조 분해 ({ foo }) 로 접근하고 state는 const [state, setState] = useState()로 생성한다.

- 클래스 props의 경우 this.props.foo로 접근하고 state는 constructor this.state ={} 로 생성한다.

 

 

3) this 키워드 사용 유무

- 함수형의 경우 props를 인자로 받아 사용하고, useState로 state를 관리하기 때문에 this를 사용하지 않아도 된다.

- 클래스의 경우 this를 통해 props, state, 메서드에 접근해야한다.

 

 

4) 생명주기 처리 방식

- 함수형의 경우 라이프사이클 메서드는 없고 useEffect 훅을 사용한다.

useEffect(() => {
  // Mount 혹은 의존성 변경 시 동작
  return () => {
    // Cleanup (Unmount 혹은 다음 useEffect 전)
  };
}, [ 의존성 배열 ]);

- useEffect 훅으로 생애주기를 처리할 수 있는데 의존성 배열과 cleanup 함수가 존재한다.

- 의존성 배열이 빈 배열일 경우 첫 마운트 되었을 때 한 번만 실행하게 된다. 다른 state값이 존재한다면 해당 state값이 변경될 때마다 실행된다.

- cleanup 함수는 언마운트 시 또는 다음 effect 실행전에 실행되고 마운트 시 실행된 setInterval 함수나 이벤트와 같이 메모리상에 계속 남아있는 작업들을 해제해주는 역할을 담당한다.

 

- 클래스형의 경우 생명 주기 메서드를 제공한다.

componentDidMount : mount 시 한 번만 실행

componentDidUpdate : props 변경 시 실행

componentWillUnmount : 타이머 해제, 이벤트 제거, 네트워크 요청 취소 등의 작업으로 사용

* 더 많은 메서드들이 있으나 주요 메서드만 정리했습니다.

 

 

5. 정리

- 함수형 컴포넌트는 비교적 문법이 간결하고 쉬우며 useEffect, useState를 이용하여 상태를 관리하고 생명주기를 설정한다.

- 클래스 컴포넌트는 this, 생명주기 메서드들이 존재하지만 현재 새 프로젝트에는 쓰이지 않으며 레거시 코드 유지보수 등에서 볼 수 있다.

 

여기까지 함수형 컴포넌트와 클래스 컴포넌트를 정리해보았다.

아직 클래스 컴포넌트를 접해보진 않았지만 실제로 직면하게 되더라도  정리한 내용이 있기에 완전 낯설지는 않을 것이다.

 

 

 


 

참고문서

https://ko.react.dev/learn/your-first-component

 

첫 번째 컴포넌트 – React

The library for web and native user interfaces

ko.react.dev

https://ko.legacy.reactjs.org/docs/components-and-props.html

 

Components와 Props – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

https://yong-nyong.tistory.com/78

 

[React] 함수(Function) 컴포넌트 vs 클래스(Class) 컴포넌트 차이가 뭘까요?

📖 들어가며 함수 컴포넌트 도입 리액트에서 함수 컴포넌트는 리액트가 처음 생겼을 때부터 있었지만, 처음에는 상태관리나 생명주기 메소드를 사용할 수 없어서 주로 단순한 표현을 위한 용

yong-nyong.tistory.com

 

 

'학습 > react' 카테고리의 다른 글

[react] 배열 렌더링 했는데 key는 뭐야?  (1) 2025.08.10
[react] Virtual DOM 가상 돔  (2) 2025.07.24
[react] 리액트의 렌더링 정리  (1) 2025.07.23
클론 프로젝트 회고2  (0) 2024.05.18
클론 프로젝트 회고  (1) 2024.02.12

chatGPT 가상 돔 이미지 (정적인 느낌)

 

가상 돔에 대해 변경된 부분만 실제 돔에 적용하여 성능을 향상시킨다 정도의 내용만 알고 있었는데 이번 기회로 가상 돔에 대해서 정리해서 실제 리액트 개발을 할 때 이해도를 좀 높이고자 합니다.

 

브라우저 동작 방식

브라우저는 HTML과 CSS를 파싱하여 각각 DOM, CSSOM을 생성한다.
이후 두 트리를 결합해 렌더 트리(Render Tree) 를 만들고,
레이아웃(Layout)페인트(Paint)합성(Composite) 단계를 거쳐 최종 화면에 그려낸다.

이 과정 중에서 DOM을 자주 조작하거나 스타일 속성이 자주 변경되면 리플로우(Reflow) 또는 리페인트(Repaint) 가 발생한다.
이는 브라우저 렌더링 성능에 부담을 주는 작업으로, 과도하게 일어나면 사용자 경험을 해칠 수 있다.

 

이 문제를 좀 해결하고자 virtual dom을 사용해 볼 수 있을 것이다.

 

Virtual DOM 이란?

Virtual DOM은 실제 DOM의 구조를 흉내 낸 메모리상의 JavaScript 객체 트리이다.

React는 컴포넌트를 렌더링할 때, 이 Virtual DOM을 생성하여 UI의 현재 상태를 메모리상에 저장하고,
변경이 발생하면 이전 Virtual DOM과 비교하여 실제 DOM에 필요한 부분만 최소한으로 반영한다.

 

예를 들어 아래와 같은 jsx문법이 있습니다. 

function App() {
  return (
    <div id="app">
      <h1>Hello, React!</h1>
      <p>가상 DOM 예시입니다.</p>
    </div>
  );
}

 

위의 코드가 가상 dom 객체 구조로 나타내면 아래와 같은 모습이다

const virtualDOM = {
  type: 'div',
  props: {
    id: 'app',
    children: [
      {
        type: 'h1',
        props: {
          children: 'Hello, React!',
        },
      },
      {
        type: 'p',
        props: {
          children: '가상 DOM 예시입니다.',
        },
      },
    ],
  },
};

Virtual DOM의 동작 방식

  1. 상태(state)나 props가 변경되면 새로운 Virtual DOM이 생성된다.
  2. 이전 Virtual DOM과 비교(diffing 알고리즘)하여 변경된 부분을 찾는다
  3. 실제 DOM에는 변경된 부분만 최소한으로 업데이트한다.

이렇게 함으로써 불필요한 리플로우와 리페인트를 줄이고 성능을 향상시킬 수 있다.

 

 

 

리액트 렌더링 과정은 아래 페이지에서 정리하였습니다.

https://express.tistory.com/22

 

[react] 리액트의 렌더링 정리

리액트를 사용하면서도 리액트의 렌더링 과정을 자세하게 알아본 적은 없었다.리액트로 사용된 코드는 브라우저에서 직접 실행할 수 없어서 javaScript코드로 변환하는 과정을 거쳐서 사용가능하

express.tistory.com

 

 

왜 사용하지?

1. 성능이 향상된다.

- 직접 DOM을 조작하면 리페인트, 리플로우 현상으로 인해 많은 리소스를 소모한다.

- 하지만 virtual dom을 사용하면 변경된 부분만 배치처리하여 성능이 향상된다.

 

2. 개발이 편해진다.

- 개발자가 ui의 현재 상태를 선언적으로 정의할 수 있다.

- 리액트가 이 선언된 상태를 기반으로 ui를 자동으로 업데이트해준다.

- 복잡한 dom조작을 하지 않아도 간결하게 코드를 작성할 수 있다.

const ul = document.createElement('ul');
items.forEach(item => {
  const li = document.createElement('li');
  li.textContent = item;
  ul.appendChild(li);
});
document.body.appendChild(ul);

 

위와 같이 바닐라 자바스크립트로 작성하면 엘리먼트를 만들어주고 그 안에 텍스트와 태그를 이동하는 등의 복잡한 코드를 작성해야 한다.

<ul>
  {items.map(item => <li>{item}</li>)}
</ul>

 

위 리액트 환경에서는 선언적으로 코드를 작성 시 리액트에서 알아서 처리해 준다.

 

 

결론

가상 dom에 대해 알아보았습니다. virtual dom이 사실 객체 트리라는 것과 이전의 가상 dom과 새 가상 dom을 비교하여 변경된 부분을 한 번에 실제 dom에 반영한다는 디테일한 사실을 새롭게 알게 되었다.

 

실제로 React를 사용할 때 상태 업데이트가 비동기적으로 처리되는 것처럼 동작해서
내가 예상했던 값과 실제 값이 달라 혼란스러웠던 경험이 있었다.
하지만 이번에 virtual dom의 배치 처리 개념을 정리하면서 React의 동작 방식을 더 깊이 이해할 수 있었고,
그동안 헷갈렸던 부분들이 명확하게 정리되어 많은 도움이 되었다.

 

 

참고문서

https://velopert.com/3236

 

[번역] 리액트에 대해서 그 누구도 제대로 설명하기 어려운 것 – 왜 Virtual DOM 인가? | VELOPERT.LOG

리액트를 지난 2년간 사용하면서도 막상 말끔하게 설명하라고 하면 어려웠던 주제, 원래 번역글은 잘 안쓰지만 글 자체가 구성이 잘 되어있어서 글을 번역해보았습니다. 원본: https://hashnode.com/p

velopert.com

https://yong-nyong.tistory.com/80

 

[React] 가상 돔(Virtual DOM)이 무엇이고 왜 중요할까요?

📖 들어가며리액트가 뛰어난 성능을 보여줄 수 있는 비결 중 하나는 바로 가상 돔(Virtual DOM)입니다.이는 리액트의 핵심 개념 중 하나로 가상 돔에 대해 알아보겠습니다.DOM(Document Object Model)웹 

yong-nyong.tistory.com

https://d2.naver.com/helloworld/2690975

https://wikidocs.net/273873

 

3. Virtual DOM의 이해

### **Virtual DOM (가상 DOM)이란?** Virtual DOM(가상 DOM)은 UI 업데이트의 효율성을 극대화하기 위해 실제 DOM(Document Object…

wikidocs.net

 

 

 

chatGPT 생성 이미지

 

리액트를 사용하면서도 리액트의 렌더링 과정을 자세하게 알아본 적은 없었다.

리액트로 사용된 코드는 브라우저에서 직접 실행할 수 없어서 javaScript코드로 변환하는 과정을 거쳐서 사용가능하고 가상 돔을 사용하여 효율적으로 렌더링을 진행한다고만 알고 있는 나 자신을 돌아보게 되었다.

이번 기회로 블로그에 글을 정리해 보면서 리액트 렌더링에 대해서 알아보자!

 

자바스크립트로 dom을 직접 조작해서 ui 업데이트를 구현할 시,
동시에 발생한 업데이트를 모아서 레이아웃과 리페인팅을 최소화하기 위해 노력해야 한다. (사이트 최적화)

하지만 규모가 점점 커질수록 순수 자바스크립트로는 힘들므로 리액트의 렌더링 과정을 통해 업데이트를 자동화하게 된다.

따라서 개발자는 리액트로 컴포넌트를 개발하게 되면 뒤에 일어나는 렌더링 과정에 작업을 하지 않아도 된다.

이처럼 좋은 라이브러리인 리액트의 렌더링 과정에 대해 알아보자

 


1. 트리거 단계 (Trigger phase)

사용자가 접속하거나 버튼을 클릭하는 등의 트리거로 렌더링이 발생한다.

 

- 초기 렌더링은 아래 createRoot 호출과 render 메서드 호출로 웹앱을 최초로 접속했을 때 발생한다.

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

 

 

- 리 렌더링은 초기 렌더링이 진행한 후 set함수를 통해 상태를 업데이트하여 리 렌더링을 진행시킬 수 있다.

- useState, useReducer등으로 상태가 변경되거나 부모로부터 전달된 props가 변경될 때 렌더링 큐에 추가된다.

 

2. 렌더 단계 (Render phase)

컴포넌트 호출 및 가상 VDOM 생성

렌더 단계는 DOM에 그려질 요소들을 파악하는 과정이다.

 

React는 함수형 또는 클래스형 컴포넌트를 호출하여 React Element 객체 트리를 생성하고

이를 기반으로 VDOM(virtual DOM)을 구성한다.

 

- 초기 렌더에서는 루트 컴포넌트를 호출하여 createElement로 DOM 노드를 생성한다.

- 리 렌더에서는 이전 가상 DOM과 새 가상 DOM 트리를 비교하여 최소한의 변경점을 찾는다.

 

재조정

이 과정을 통해 어떤 부분을 DOM에 반영할지 결정한다. 이 과정을 재조정(Reconciliation)이라고 한다. 

(두 트리 간의 차이점을 효율적으로 찾기 위해 Diffing 알고리즘을 사용한다)

 

1) 리액트 컴포넌트 호출

2) React Element 객체 트리 반환

3) 객체 트리를 모아 VDOM 생성

 

 

3. 커밋 단계 (Commit phase)

커밋단계에서는 렌더 단계에서 비교한 가상 DOM 트리를 실제 DOM에 반영하는 단계이다.

 

- 초기 렌더링의 경우 렌더 단계에서 파악한 DOM 노드를 DOM에 반영한다.

- 리 렌더에서는 렌더링하는 동안 최소한의 변경사항을 DOM에 반영한다.

 

최종적으로 DOM 변경이 끝나면 브라우저가 화면을 새로 그린다.

 

 

4. 정리

1) 리액트 렌더링은 트리거 단계, 렌더 단계, 커밋 단계로 이루어진다.

2) 렌더 단계에서 가상 DOM을 생성 & 비교하여 동시에 발생하는 업데이트를 모아둔다.

3) 커밋 단계에서 가상 DOM에 반영된 모든 업데이트를 실제 DOM에 한 번에 반영한다.

4) 실제 DOM에 반영되면 브라우저의 페인트 & 레이아웃 과정 실행

 

 

추가 학습이 필요한 내용

- Fiber

- Concurrent Mode 스케줄링

 

 

 

 

참고문서

https://ko.react.dev/learn/render-and-commit

 

렌더링 그리고 커밋 – React

The library for web and native user interfaces

ko.react.dev

 

https://yceffort.kr/2022/04/deep-dive-in-react-rendering

 

리액트의 렌더링은 어떻게 일어나는가?

https://yceffort.kr

yceffort.kr

https://www.moonkorea.dev/React-%EB%A0%8C%EB%8D%94%EB%8B%A8%EA%B3%84-%EC%BB%A4%EB%B0%8B%EB%8B%A8%EA%B3%84

 

React의 렌더 단계와 커밋 단계

리액트 렌더링 단계라고 하면 렌더 단계(Render Phase)와 커밋 단계(Commit Phase)가 있는데요, 렌더 단계에서는 화면에 그릴 것들을 "파악"하고 커밋 단계에서는 직전에 파악한 것들을 화면에 "적용"해

www.moonkorea.dev

https://www.moonkorea.dev/React-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%9E%AC%EC%A1%B0%EC%A0%95

 

재조정

리액트는 렌더링 간 효율적으로 DOM을 업데이트하고자 재조정 과정을 거치게 되는데요, 재조정이 무엇이고 어떤 경우에 재조정이 이루어지는지 알아봅니다.

www.moonkorea.dev

https://www.youtube.com/watch?v=N7qlk_GQRJU

React.js의 렌더링 방식 살펴보기 - 이정환 | 2023 NE(O)RDINARY CONFERENCE

 

chatGPT로 뽑은 this 이미지

This?

자바스크립트에서 가장 많이 오해되는 키워드, this.
단어는 짧지만 동작은 상황에 따라 달라진다.
이번 글에서는 this의 개념을 간단한 예제와 함께 정리해보고자 합니다.

 

먼저 this는 함수가 호출되는 방식에 따라 this에 바인딩이 동적으로 결정된다.

*바인딩 : 식별자와 값을 연결하는 과정

 

1. 전역공간의 this

console.log(this) // window 객체

전역공간에서 this는 전역 객체를 가리킨다. node.js 환경에서는 global

 

 

2. 메서드 내부에서의 this

let obj = {
	fooA : function () { console.log(this); },
    inner : {
    	fooB : function () { console.log(this); }
    }
}

obj.fooA()
obj.inner.fooB()

메서드 내부 this 콘솔

this에는 호출한 주체 정보가 있는데 호출 주체는 바로 함수명 앞에 객체가 된다.

점 앞에 명시된 객체가 곧 this가 된다.

(ex. obj.fooA()는 obj가 this가 되고 obj.inner.fooB()는 obj.inner가 this가 된다)

 

 

3. 함수 내부에서의 this

function showThis() {
  console.log(this);
}

showThis(); // 브라우저 환경에서는 window, Node.js에서는 global

함수에서의 this는 전역 객체를 가리킨다.

 

3-1. 메서드 내부에서의 중첩 함수 호출

const person = {
  name: "Jane",
  greet() {
    function inner() {
      console.log(this.name);
      console.log(this);
    }
    inner(); // 여기서 inner 함수 호출
  },
};

person.greet(); // undefined (또는 브라우저에선 빈 문자열), window 객체

메서드 내부의 inner()함수는 함수로서 호출하였다.

그렇기에 this.name은 전역에서의 name값이기에 빈문자열이 되고 this는 전역 객체가 된다.

 

함수 호출에 따른 this를 객체로 가리키는 방법

const obj = {
  name: 'Alice',
  sayHi: function () {
  
    const self = this; // 여기서 self에 this를 할당
    function inner() {
      console.log('Hi, ' + self.name);
    }

    inner();
  }
};

obj.sayHi(); // Hi, Alice

함수 밖에서 self 변수에 this를 할당하여 inner 함수 내부에서 self를 사용하게 되면 결국 obj를 가리키게 된다.

따라서 inner() 라는 함수로 호출하게 되어도 함수 밖에서 this를 가져왔기 때문에 전역 객체를 가리키는 상황은 발생하지 않게 된다.

요 방법은 ES5 문법의 방법이다.

 

또 다른 방법으로 화살표함수 사용법. (ES6 문법)

const obj = {
  name: 'Alice',
  sayHi: function () {
    const inner = () => {
      console.log('Hi, ' + this.name);
    };

    inner();
  }
};

obj.sayHi(); // Hi, Alice

화살표함수의 경우 정의된 시점의 외부 실행 컨텍스트 this를 그대로 사용한다.

화살표 함수는 실행 컨테스트를 만들 때 this 바인딩을 하지 않는다.

대신 정의된 시점의 스코프 체인에서 가장 가까운 함수의 this를 그대로 사용한다.

 

 

4. 콜백 함수 호출 시 그 함수 내부의 this

     const obj = {
        name: "Kim",
        hobbies: ["reading", "tennis"],

        showThisInSetTimeout: function () {
          setTimeout(function () {
            console.log("setTimeout (일반 함수):", this.name); // window 객체 (전역 객체)
          }, 500);

          setTimeout(() => {
            console.log("setTimeout (화살표 함수):", this.name); // obj 객체 this.name은 Kim
          }, 1000);
        },

        showThisInForEach: function () {
          this.hobbies.forEach(function (hobby) {
            console.log("forEach (일반 함수):", this.name + " likes " + hobby); // this.name은 빈 값을 가짐 (브라우저)
          });

          this.hobbies.forEach((hobby) => {
            console.log("forEach (화살표 함수):", this.name + " likes " + hobby); // 화살표함수는 this.name이 Kim값을 가짐
          });
        },

        showThisInEventListener: function () {
          const btn = document.getElementById("myBtn");

          // 일반 함수
          btn.addEventListener("click", function () {
            console.log("addEventListener (일반 함수):", this); // this → 버튼 요소
          });

          // 화살표 함수
          btn.addEventListener("click", (event) => {
            console.log("addEventListener (화살표 함수):", this); // this → obj
          });
        }
      };

      obj.showThisInSetTimeout();
      obj.showThisInForEach();
      obj.showThisInEventListener();

 

 

 

5. 생성자 함수 내부의 this

생성자 함수는 어떤 공통된 성질을 지니는 객체를 생성하는데 사용하는 함수이다.

객체지향 언어에서는 생성자를 클래스, 클래스를 통해 만들어진 객체를 인스턴스라고 한다.

new 명령어와 함께 함수를 호출하면 해당 함수가 생성자로서 동작하게 된다.

 

생성자 함수 내부에서의 this는 만들어진 인스턴스 자신이 된다.

function Person(name, age) {
  this.name = name;
  this.age = age;

  this.sayHello = function () {
    console.log(`Hi, my name is ${this.name} and I'm ${this.age} years old.`);
  };
}

const person1 = new Person('Alice', 30);
const person2 = new Person('Bob', 25);

person1.sayHello(); // Hi, my name is Alice and I'm 30 years old.
person2.sayHello(); // Hi, my name is Bob and I'm 25 years old.

console.log(person1)
console.log(person2)

 

1) Person이라는 함수를 선언한다.

2) 함수 내부에서는 this에 접근하여 name, age 속성에 값을 대입한다.

3) new라는 키워드로 person1, person2 변수에 할당 (생성자 함수로 동작)

4) person1, person2를 콘솔로 출력하면 각각의 인스턴스 객체가 출력되고 this는 각각의 인스턴스 임을 알 수 있음.

 

 

그외 명시적 this 바인딩

call, apply, bind 메서드를 통해 별도의 대상을 바인딩하는 방법도 있다.

추후에 다시 알아보자

 

 

 

참고문서

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this

 

this - JavaScript | MDN

JavaScript에서 함수의 this 키워드는 다른 언어와 조금 다르게 동작합니다. 또한 엄격 모드와 비엄격 모드에서도 일부 차이가 있습니다.

developer.mozilla.org

https://ko.javascript.info/object-methods

 

메서드와 this

 

ko.javascript.info

https://product.kyobobook.co.kr/detail/S000001766397

 

코어 자바스크립트 | 정재남 - 교보문고

코어 자바스크립트 | 자바스크립트의 근간을 이루는 핵심 이론들을 정확하게 이해하는 것을 목표로 합니다!최근 웹 개발 진영은 빠르게 발전하고 있으며, 그 중심에는 자바스크립트가 있다고

product.kyobobook.co.kr

 

 

 

 

 

 

 

 

 

 

 

 

출처 : chatGPT 이미지 출력

변수?

변수란 "하나의 값을 저장할 있는 메모리 공간이자 값을 나타내는 문자나 문자들의 집합이며 실행 중인 컴퓨터 프로그램에서임의의 값을 저장한 메모리 주소 대응한다." 라고 위키피디아에서 정의하고 있다.

 

좀 풀어서 말해보면 컴퓨터에서 데이터는 메모리 공간에 존재하는데 2진수로 처리되어 있으며 메모리와 대응되는 메모리 주소가 존재한다.

결국 변수 이름(식별자)는 메모리에 저장된 값의 주소를 가리키는 이름과 같다. 결국 식별자는 값이 아니라 메모리주소를 기억하고 있다.

 

변수를 사용하려면 선언이 필요한데 이때 js에서는 var, let, const 키워드를 사용한다.

각 키워드들에 대해서 알아보자

 

* Scope (스코프) : 변수와 식별자가 선언된 위치에 의해 다른 코드가 자신을 참조할 수 있는 유효범위 (참조 유효범위)

* 호이스팅 (hoisting) : 변수 선언이 스코프의 맨 위로 끌어올려진 것처럼 동작하는 자바스크립트의 특징  (스코프 단위로 적용)

 

 

 


 

 

javaScript의 변수 키워드

var 키워드

1) 변수의 중복 선언이 허용된다.

var a = 1;
var b = 1;

var a = 2;
var b;

console.log(a);
console.log(b);

콘솔탭 출력결과

1) 위 코드를 실행해보면 a값은 2가 출력되고 b값은 1이 출력된다.

2) var 키워드로 선언한 변수는 동일한 식별자로 중복 선언하여 사용이 가능하다.

3) 위 예시 코드를 보면 변수 a는 1로 할당 했다가 중복 선언으로 값이 2가 된 결과를 볼 수 있다.

4) 변수 b는 다르게 동작하는데 선언만하고 초기화문이 없는 변수는 무시되어 처음 값인 1이 출력된다.

 

2) 함수 레벨 스코프에서 지역변수로 적용된다.

var a = 1;

if(true) {
	var a = 2;
}

console.log(a); // 2가 출력된다.

콘솔탭 출력결과

1) 위 if문의 블록 레벨 스코프에서 var 키워드는 전역 변수로 적용되어 변수 a의 값은 2가 출력된다.

 

var a = 1;

function foo(){
	var a = 2;
    console.log(a); // 2
}
foo()
console.log(a) // 1

함수 레벨 스코프 콘솔탭 출력결과

1) 위 코드의 경우 함수 블록에서 지역 스코프로 인정되므로 foo함수 안에서는 2가 출력된다.

2) 함수 밖 콘솔에서는 글로벌 변수 a값인 1이 출력되는 모습을 볼 수 있다.

 

3) 호이스팅 (선언 + 초기화 한번에 진행)

console.log('첫 번째 ' + a); // undefined

var a = 1;

console.log('두 번째 ' + a); // 1

호이스팅 관련 콘솔 결과

1) 위 var 변수 선언은 자바스크립트 런타임 이전에 실행되어 마치 맨위에서 실행된 것처럼 보이는 호이스팅 현상이 발생한다.

2) var 키워드는 런타임 이전에 선언과 동시에 undefined로 초기화하기 때문에 위 콘솔에서 undefined가 출력된다.

3) 아래 콘솔 a에서는 1이 출력된다.

 

 

let 키워드

1) 재선언 불가능

 

재선언 불가능

1) let 키워드로 선언된 변수는 같은 스코프내에서 재선언이 불가능하다.

2) 위 이미지에서 재선언 시 이미 선언되었다는 에러가 발생한다.

3) 재할당은 가능하다.

 

2) 블록 레벨 스코프 적용

let a = 1;

if(true){
    let a = 2;
    let b = 3;
    console.log(a); // 2
}

console.log(a); // 1
console.log(b); // b is not defined

출력 결과

1) 첫 번째 콘솔에서는 if문 블록의 a값인 2가 출력된다. (let은 블록 스코프)

2) 두 번째 콘솔에서는 글로벌 변수 a값인 1이 출력된다.

3) 세 번째 콘솔에서는 if문 안에 변수 b가 있으므로 레퍼런스 에러 b is not defined 에러가 발생한다.

 

 

3) 호이스팅 발생 (TDZ 발생)

console.log(a); // Uncaught ReferenceError: a is not defined
// TDZ (temporal dead zone) 일시적 사각지대 : 스코프 시작 지점에서 변수를 참조할 수 없는 구간

let a; // 초기화 단계 진행 (undefined로 초기화)

console.log(a); // undefined

a = 1; // 할당 단계

console.log(a); // 1

1) var 키워드는 런타임 이전에 선언과 초기화(undefined)가 동시에 이루어진다

2) let 키워드는 런타임 이전에 선언만 이루어지고 변수 선언문에서 초기화가 이루어진다.

3) 같은 스코프내에서 변수를 참조할 수 없는 구간인 TDZ 일시적 사각지대 구간이 발생한다.

4) 할당문에서 할당이 진행된다.

 

 

const 키워드

1) 재선언 불가능

재선언 불가능

var, let 키워드와 다르게 const 키워드는 재선언이 불가능하다.

 

 

2) 재할당 불가능

재할당 불가능

let 키워드는 재할당이 가능하나 const는 재할당이 불가능하다.

 

 

3) 선언과 초기화

const c; // Uncaught SyntaxError: Missing initializer in const declaration

const d = 1; // 선언과 동시에 초기화해야 한다

1) const 의 경우 선언과 동시에 초기화를 진행해야 한다.

2) let 키워드와 마찬가지로 블록 레벨 스코프를 가지며 변수 호이스팅도 발생한다. (TDZ 발생)

 

 

4) 상수

const car = { 
  brand: 'BMW',
}

car.brand = 'Benz'; // 객체의 값 생성, 삭제, 변경은 가능하다

console.log(car); // Benz

const 키워드 변수의 객체 값은 변경 가능

1) const 키워드 변수는 재할당이 되지 않는다.

2) 재할당이 불가능하지만 객체를 할당한 경우 값은 변경할 수 있다.

3) 객체 값은 변경되더라도 변수에 할당된 참조 값은 그대로이기에 가능하다.

 

 

 

정리

 

구분 항목 var let const
스코프(Scope) 함수 스코프 (Function Scope) 블록 스코프 (Block Scope) 블록 스코프 (Block Scope)
재선언 가능 여부 가능 불가능 불가능
재할당 가능 여부 가능 가능 불가능 (단, 객체는 내부 변경 가능)
호이스팅(hoisting) 선언이 위로 끌어올려짐 (초기값은 undefined) 선언만 호이스팅됨 (TDZ 존재) 선언만 호이스팅됨 (TDZ 존재)
초기화 여부 선언과 동시에 초기화 안 해도 됨 선언과 동시에 초기화 안 해도 됨 반드시 선언과 동시에 초기화 필요
대표 사용 예 예전 JS 코드 / 함수 내부 임시 변수 일반적인 변수 상수, 변경되지 않아야 하는 참조값

 


 

 

참고자료

https://ko.wikipedia.org/wiki/%EB%B3%80%EC%88%98_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)

 

변수 (컴퓨터 과학) - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 컴퓨터 프로그래밍에서 변수(變數, variable) 또는 스칼라(scalar)는 아직 알려지지 않거나 어느 정도까지만 알려져 있는 양이나 정보에 대한 상징적인 이름이다.

ko.wikipedia.org

https://www.yes24.com/Product/Goods/92742567

 

모던 자바스크립트 Deep Dive - 예스24

『모던 자바스크립트 Deep Dive』에서는 자바스크립트를 둘러싼 기본 개념을 정확하고 구체적으로 설명하고, 자바스크립트 코드의 동작 원리를 집요하게 파헤친다. 따라서 여러분이 작성한 코드

www.yes24.com

https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-var-let-const-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B3%80%EC%88%98-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85

 

📚 var / let / const 차이점 정리 (변수 호이스팅)

자바스크립트 var / let / const 차이점 5가지 중복 선언 가능 여부 재할당 가능 여부 변수 스코프 유효범위 변수 호이스팅 방식 전역객체 프로퍼티 여부 1. 중복 선언 가능 여부 var : 중복해서 선언(+

inpa.tistory.com

 

 

chatGPT 브라우저 렌더링 과정

 

왜 브라우저를 학습해야 해?

출처 : mdn 문서 서론 글

웹 개발자, 특히 웹 프론트엔드 개발자라면 브라우저와 함께 살아야 한다.

그런데 브라우저에 대해서 잘 모른다면? 어떻게 동작하는지 모른다면 앞으로의 여정에 힘들어지지 않을까 생각하게 된다.

 

위 mdn문서에서 가져온 글과 같이 사용자는 빠르고 상호작용이 원활한 콘텐츠를 원한다..

출처 : thinkwithgoogle / Google/SOASTA Reasearch, 2017

 

위 가져온 조사결과를 보면 페이지 표시속도가 1초에서 3초까지 되면 이탈률 32% 증가된다.

결국 느리면 느릴수록 유저가 나가버리고 이러한 결과는 회사의 비즈니스에 큰 영향을 끼칠 것이다.

 

제품을 만드는 개발자는 이러한 점을 최소화하기 위해 브라우저를 알고 최적화해야 되지 않을까 생각이 된다.

 

웹 프론트의 근간인 html, css, javaScript를 해석하는 브라우저에 대해서 알아보자

 


 

브라우저의 렌더링 과정

*렌더링 : HTML, CSS, JAVASCRIPT로 작성된 문서를 파싱하여 브라우저에 시각적으로 출력하는 것을 말한다.

*파싱 : 프로그래밍 언어의 문법에 맞게 작성된 텍스트 문서를 읽어서 실행하기 위해 텍스트 문서의 문자열을 토큰으로 분해하고 토큰에 문법적 의미와 구조를 반영하여 트리 구조의 자료구조인 파스트리를 생성하는 일련의 과정이다.

*토큰 : 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 의미한다.

const foo = 1 + 3;

위 const, foo, =, 1, +, 3, ; 과 같은 문법적으로 더 이상 나눌 수 없는 기본 요소이므로 모두 토큰이다.

 

1.  요청과 응답

브라우저는 필요한 데이터를 서버에 요청하고 응답을 받아서 화면에 표시한다.

브라우저는 서버에 요청하기 위해 주소창에 URL을 입력하고 전송할 수 있다.

전송된 URL은 DNS에 의해 ip주소로 변환되고 이 주소를 가진 서버에 요청을 전송하게 된다.

 

예를 들어 naver.com으로 요청을 하면 네이버의 Ip주소로 변환되어 서버에 요청하게 된다.

요청받은 서버는 요청받은 것에 따라 리소스를 응답한다.

naver.com으로 응답받은 리소스는 네트워크탭에서 확인할 수 있다.

수많은 이미지, js, css 파일 등을 확인할 수 있다.

출처: 네이버 네트워크탭

 

2. HTML 파싱과 DOM생성

브라우저가 응답받은 html은 문자열 텍스트이다. 

이를 브라우저가 읽을 수 있도록 렌더링 엔진이 해석하는데

바이트 -> 문자열 변환 -> 이를 토큰으로 분해 -> 토큰을 객체화하여 노드 생성 -> 중첩관계에 의해 부자관계 형성, 이를 트리 자료구조로 구성한다. 이것이 DOM(document object model)이다.

출처 : 위시켓 html 파싱 이미지

Html 파싱 순서는 위 이미지로 정리할 수 있다.

따라서 DOM은 Html 문서를 파싱 한 결과물이다.

이 dom을 js로 접근하여 html을 조작할 수 있게 된다.

 

3. CSS 파싱과 CSSOM 생성

html 문서를 파싱 하다가 link태그나 스타일 코드를 만나면 파싱을 일시중단하고 css파싱이 진행된다.

css파싱이 끝나면 그때 다시 html 파싱이 재 진행된다.

 

css 파싱은 html파싱과 동일한 과정으로 진행하여 cssom (css object model)을 생성한다.

 

출처 : 위시켓 CSS 파싱

cssom은 상속을 반영하여 생성되는데 위 이미지에서 body에 font-size: 16px이 아래 자식 트리에게도 상속된 것을 볼 수 있다.

 

 

4. 렌더트리 생성

렌더링 엔진은 응답된 html, css를 파싱하여 DOM, CSSOM을 생성한다.

DOM, CSSOM 렌더링을 위해 렌더트리로 합쳐진다.

렌더트리는 display : none이나 meta, script태그 등 화면에 보이지 않는 노드는 렌더트리에 포함하지 않는다.

 

출처 : 위시켓 렌더트리

결국 렌더트리는 화면에 나타나는 요소들을 결정하는 트리이다.

이후 완성된 렌더트리는 html요소의 레이아웃을 계산하는 데 사용되고 브라우저 화면에 픽셀을 렌더링 하는 페인팅 처리에 입력된다.

이러한 과정은 브라우저 창의 뷰포트 크기가 변경되거나 js에 의한 노드 추가 및 수정, html 요소 레이아웃 변경이 되면 레이아웃 계산과 페인팅이 반복된다.

 


 

5. 자바스크립트 파싱과 실행

자바스크립트는 브라우저 렌더링 엔진이 아닌 자바스크립트 엔진이 처리한다.

해당 엔진은 js를 해석하여 추상적 구문 트리를 생성하고 이를 기반으로 바이트코드를 생성하여 실행한다.

(추상적 구문 트리 위키백과)

 

 

6. 리플로우와 리페인트

리플로우는 레이아웃 계산을 다시 하는 것을 말한다.

js로 노드를 추가하거나 삭제, 요소의 크기를 변경하는 등의 레이아웃에 영향을 주는 것이 발생하면 실행된다.

 

리페인트는 리플로우에 의해 다시 레이아웃 계산이 된 것을 기반으로 요소들에게 색을 입히는 작업이다.

 

리플로우와 리페인트는 브라우저 성능에 큰 비용이 적용되는데 이에 대한 비용을 가상 DOM을 이용해 연산 횟수를 최소화할 수 있게 된다. 가상 DOM은 실제 렌더링 되지 않지만 실제 DOM구조를 반영한 상태로 메모리에 있는 가상의 DOM이다. 변경사항을 한 번에 적용할 수 있도록 하기 때문에 비용을 줄일 수 있다. 이러한 가상 DOM을 사용하는 게 react, vue 이다.

 


 

웹사이트 진단 방법

그래서 브라우저 동작 방법에 대해 알아보았는데 결국 이걸 어떻게 체크하는지 알아야 될 것이다.

내가 만든 웹사이트가 건강한지 체크하는 방법을 소개하고자 한다.

1. lighthouse

출처 : 네이버 lighthouse 측정

개발자도구 네트워크 탭에 있는 lighthouse를 이용하면 성능 등을 측정할 수 있고 여러 이슈에 대해 진단도 해주기 때문에 유용하게 쓸 수 있다.

 

 

2. PageSpeed Insights

 

페이지 스피드 인사이트라는 사이트를 이용해 성능을 측정할 수도 있다.

(pagespeed insights)

 

3. 개발자도구 - 네트워크 탭

개발자도구의 네트워크 탭 하단에 보면 로드된 시간과 파일들의 크기들을 확인할 수 있다.

그래서 용량이 큰 파일이 무엇인지 확인하여 조치할 수도 있을 것이다.

 

 


 

참고문서

https://yozm.wishket.com/magazine/detail/1338/

 

프론트엔드 개발자라면 알고 있어야 할 브라우저의 동작 과정 | 요즘IT

프론트엔드 개발자에게 있어 브라우저는 거의 모든 것과도 같습니다. 하지만 그렇다고 해서 프론트엔드 개발자가 브라우저의 모든 원리에 대해 잘 알고 있는 것은 아니지만, 복잡한 웹 어플리

yozm.wishket.com

https://developer.mozilla.org/ko/docs/Web/Performance/Guides/How_browsers_work

 

웹페이지를 표시한다는 것: 브라우저는 어떻게 동작하는가 - 웹 성능 | MDN

사용자는 로드가 빠르고 상호작용이 원활한 컨텐츠로 이루어진 웹 경험을 원합니다. 따라서 개발자는 이 두 가지 목표를 달성하기 위해서 부단히 노력해야합니다.

developer.mozilla.org

https://yozm.wishket.com/magazine/detail/2036/

 

구글의 프론트엔드 성공 지표 ‘Core Web Vitals’ | 요즘IT

프론트엔드 성능은 사용자 경험과 웹사이트의 성공에 매우 중요한 역할을 합니다. 이는 사용자가 웹사이트를 방문했을 때 페이지가 로드되는 속도나 반응성, 사용자의 인터랙션(interaction) 등을

yozm.wishket.com

https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/mobile-page-speed-new-industry-benchmarks/

 

Find Out How You Stack Up to New Industry Benchmarks for Mobile Page Speed

It's critical that marketers design fast mobile web experiences. New research shows how various sectors are performing when it comes to mobile page speed.

www.thinkwithgoogle.com

https://ko.wikipedia.org/wiki/%EC%B6%94%EC%83%81_%EA%B5%AC%EB%AC%B8_%ED%8A%B8%EB%A6%AC

 

추상 구문 트리 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 유클리드 호제법을 사용하여 다음의 코드를 나타낸 추상 구문 트리: while b ≠ 0 if a > b a := a − b else b := b − a return a 컴퓨터 과학에서 추상 구문 트리(abstract sy

ko.wikipedia.org

https://pagespeed.web.dev/

 

PageSpeed Insights

올바른 URL을 입력하세요.

pagespeed.web.dev

https://www.yes24.com/Product/Goods/92742567

 

모던 자바스크립트 Deep Dive - 예스24

『모던 자바스크립트 Deep Dive』에서는 자바스크립트를 둘러싼 기본 개념을 정확하고 구체적으로 설명하고, 자바스크립트 코드의 동작 원리를 집요하게 파헤친다. 따라서 여러분이 작성한 코드

www.yes24.com

 

 

 

 

 

'학습 > web' 카테고리의 다른 글

[Web] 웹 페이지 렌더링 방식 (CSR, SSR, SSG, ISR)  (2) 2025.08.16

+ Recent posts