구름톤 유니브☁️ 4기 FE 스터디

서론

이번 포스팅에서는 리액트에서Composition과 Inheritance를 비교하여 알아보고자 합니다.


본론

1. Composition

📖 Composition란?

여러 개의 컴포넌트를 조합해 새로운 컴포넌트를 만드는 기법으로
리액트는 컴포넌트를 가볍고 독립적인 단위로 보고, 이들을 조합해 UI를 구성하도록 설계되어 있다.

 

✅ Composition 방법

📌 Containment

// children prop을 사용한 FancyBorder 컴포넌트
function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}
// WelcomeDialog 컴포넌트
function WelcomeDialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        어서오세요
      </h1>
      <p className="Dialog-message">
        우리 사이트에 방문하신 것을 환영합니다!
      </p>
    </FancyBorder>
  );
}

하위 컴포넌트를 children 프로퍼티로 포함하는 가장 기본적인 합성 방법이다.

FancyBorder안의 컴포넌트들이 children이라는 props로 전달되는 것이다.

// SplitPane 컴포넌트
function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}

// App 컴포넌트에서 SplitPane 사용 예시
function App(props) {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      }
    />
  );
}

만약 여러 개의 children 집합이 필요한 경우라면, 위 코드 처럼 left와 right라는 두 개의 props를 정의하여

각각 분리해서 렌더링하게 된다.

 

📌 Specialization

// Dialog 컴포넌트
function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

// Dialog를 특수화한 WelcomeDialog 컴포넌트
function WelcomeDialog(props) {
  return (
    <Dialog
      title="어서 오세요"
      message="우리 사이트에 방문하신 것을 환영합니다!"
    />
  );
}

범용 컴포넌트(개념)을 구별이 되도록 구체화하는 방법이다.

위 예시의 경우 WelcomeDialog(구체화된 개념)은 Dialog(범용적인 개념)의 특별한 케이스다.

기존 객체지향 개념에서는 상속을 사용하나 리액트에서는 Composition을 사용하여 Specialization을 한다.

 

✅ Containment와 Specialization 같이 사용하기

// 범용 Dialog 컴포넌트 (children을 사용하도록 확장)
function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
      {props.children}
    </FancyBorder>
  );
}
// Dialog를 사용한 SignUpDialog 컴포넌트
function SignUpDialog(props) {
  const [nickname, setNickname] = useState('');

  const handleChange = (event) => {
    setNickname(event.target.value);
  };

  const handleSignUp = () => {
    alert(`어서 오세요, ${nickname}님!`);
  };

  return (
    <Dialog
      title="환성 탐사 프로그램"
      message="닉네임을 입력해 주세요."
    >
      <input
        value={nickname}
        onChange={handleChange}
      />
      <button onClick={handleSignUp}>
        가입하기
      </button>
    </Dialog>
  );
}

✅ Inheritance

📖 Inheritance(상속)이란?
상속, 다른 컴포넌트로부터 상속을 받아서 새로운 컴포넌트를 만드는 것

 

복잡한 컴포넌트를 쪼개서 여러개의 컴포넌트로 만들고 만든 컴포넌트를 조합해서 새로운 컴포넌트를 만들자!

라는 개념을 이해하고만 가자

 

📌 Composition vs Inheritance

상속은 객체지향 프로그래밍에서 클래스 기반 상속을 통해 기능을 확장하는 방식인데,

이는 리액트에서는 권장되지 않는 방식이고 리액트에서는 합성 방식을 권장한다.

왜 그럴까?

 

리액트에서 상속을 잘 사용하지 않는 이유

  • 복잡도 증가: 컴포넌트 간 의존성이 높아져 유지보수 어려움
  • 재사용성 증가: 자식 클래스에 의존적인 API 설계 필요
  • 컨텍스트 공유 어려움: props·state 조합이 복잡
class BaseButton extends React.Component {
  render() {
    return <button {...this.props} className="base-button" />;
  }
}

class IconButton extends BaseButton {
  render() {
    return (
      <BaseButton onClick={this.props.onClick}>
        <Icon name={this.props.icon} />
        {this.props.children}
      </BaseButton>
    );
  }
}

위 코드처럼 상속을 사용하면, IconButton이 BaseButton 구현에 종속적이어서 변화에 약하다는 문제점이 존재한다.


마무리

이번 글에서는 리액트에서 컴포넌트를 조합하는 기법인 Composition과 Inheritance에 대해 다뤄보았는데

전체적인 내용을 요약하자면

  Composition Inheritance
유연성 매우 높음 (런타임에 조합 가능) 낮음 (컴파일/설계 시 결정)
재사용성 범용 컴포넌트 + 슬롯 구조 클래스 계층 설계 필요
유지보수성 낮은 결합도 → 용이 높은 결합도 → 어려움
결론 ✅ 권장 ❌ 비권장

 

오늘도 읽어주셔서 감사합니다 🫡

'TIL > React' 카테고리의 다른 글

[React] Handling Events & Conditional Rendering & List and Keys  (1) 2025.05.06
[React] useMemo(), useCallback(), useRef()  (0) 2025.04.14
[React] JSX & Rendering Elements  (0) 2025.04.08
[React] React.js란?  (0) 2025.04.08

구름톤 유니브☁️ 4기 FE 스터디

서론

이번 포스팅에서는 JSX란 무엇이고 리액트에서 화면에 요소를 표시하는 렌더링에 대해 간단히 알아보고자 합니다.


본론

1. JSX란?

JSX는 JavaScript + XML/HTML의 줄임말로,
JS 코드 안에서 마치 HTML처럼 태그를 쓸 수 있게 해주는 JS 문법 확장이다.

const element = <h1>Hello, world!</h1>;

위 JSX 코드는 내부적으로 다음과 같은 JS 코드로 변환된다.

const element = React.createElement(
  'h1',
  { className: null },
  'Hello, world!'
);

 

JSX의 장점

 

  • 📦 간결한 코드: 보기 쉽고 쓰기 편함
  • 👁️ 가독성 향상: HTML 구조처럼 보여서 코드 흐름 파악이 쉬움
  • 🐞 버그 찾기 쉬움: 구조가 명확해 디버깅에 유리
  • 🛡️ 보안성 강화: Injection 공격 방지 등 내부적으로 보안에도 강점

리액트에서 JSX를 사용하는 것이 필수는 아니나, 가독성과 코드 복잡성 면에서 매우 편리하여 많은 개발자가 JSX를 사용하고 있다.

 


2. Rendering Elements (렌더링 요소)

Elements는 어떤 물체를 구성하는 성분이라고 정의할 수 있다.

이는 리액트에서는 리액트 앱을 구성하는 요소라고 볼 수 있다.

즉, Element는 리액트 앱을 구성하는 가장 작은 블록을 의미한다.

const element = <h1>Hello</h1>;

 

이건 React Element라고도 불리며, HTML 요소와 비슷하지만 JS 객체 형태이다.

이 Element는 실제로는 이런 JS 객체라고 보면 된다.

{
  type: 'h1',
  props: {
    children: 'Hello'
  }
}

 

 

React Elements = Virtual DOM

 

React Element(왼쪽)는 Virtual DOM을 구성하고, render를 통해 실제 브라우저 DOM(오른쪽) 바뀐다.

리액트에서 <h1>Hello</h1> 같은 JSX는 결국 React Element라는 자바스크립트 객체로 변환된다.
그리고 이 React Element 들이 모여 만들어진 것이 바로 Virtual DOM이다.

 

Elements의 특징

  • Immutable (불변성)

Component = 붕어빵 틀 / Element = 붕어빵

 

React Element는 불변성을 지니므로 한 번 만든 Element는 바꿀 수 없고, 변경되면 새로 만들어서 갈아끼운다.

즉, 변경해야할 사항이 있다면 새로운 Element를 만들어서 이를 re-rendering하게 된다고 보면된다.

 

Element Rendering

const element = <h1>안녕, 리액트!</h1>
ReactDOM.render(element, document.getElementById('root'));

리액트 렌더링은 Virtual DOM에서 실제 DOM으로 이동하는 과정

function tick(){
  const element = (
    <div>
    	<h1> 안녕, 리액트!</h1>
    	<h2> 현재 시간 : {new Date().toLocalTimeString()}</h2>
	</div>
  );
  ReactDOM.render(element, document.getElementById('root'));
}
setInterval(tick, 1000);

setInterval() 함수에 의해 1초마다 tick 함수가 실행될 때 마다 새로운 Element가 갱신되게 된다.

이는 기존 Element를 변경한다기보다는 매 초마다 새로운 Element를 생성하고 이를 re-rendering하는 개념으로 봐야한다.


마무리

이번 글에서는 JSX와 Rendering Element의 개념을 다뤄보았는데 전체적인 내용을 요약하자면

  • JSX는 XML/HTML이 더해진 JS 문법 확장이고
  • Element는 리액트 앱을 구성하는 가장 작은 단위
  • React에서는 Virtual DOM과 비교 후, 필요한 부분만 실제 DOM에 반영하는 방식으로 빠르게 렌더링

 

읽어주셔서 감사합니다 🫡

구름톤 유니브☁️ 4기 FE 스터디

서론

프론트엔드 개발을 시작하게 된다면 꼭 들어보고 사용하게 될텐데

정작 리액트가 뭐냐고 물어봤을 때 대답하기가 어렵곤 했습니다 (ㄱㅡ)...

따라서 이번 포스팅에서는 React에 대한 간단한 소개를 하고자 합니다!


본론

React.js

1. React란?

리액트는 JavaScript UI 라이브러리. 쉽게 말해, 사용자 인터페이스(UI)를 효율적이고 빠르게 만들 수 있게 도와주는 도구라고 볼 수 있다.

 

리액트 외에도 Angular JS, Vue JS와 같은 Java Script UI 프레임워크가 존재한다.

프레임워크? 라이브러리?

사실 리액트를 사용하면서도 은근 자주 헷갈려했던 부분인데, 리액트는 프레임워크가 아닌 라이브러리라는 점이었다.

그럼 프레임워크와 라이브러리는 어떻게 다른걸까? 이는 App의 흐름의 제어권한이 누구에게 있냐의 차이로 볼 수 있다.

  • 프레임워크: 흐름의 제어권한을 프레임워크가 가지고 있다.
  • 라이브러리: 흐름의 제어권한이 개발자에게 있다. 즉, 개발자가 라이브러리의 코드를 호출하여 사용한다고 볼 수 있음.

2. React의 장점

- Virtual Dom을 통한 빠른 렌더링

DOM? Virtual DOM?

DOM(Document Object Model)은 HTML 문서를 계층 형태로 표현한 인터페이스이다.

즉, DOM은 웹사이트의 정보를 모두 담고있는 객체이고, 화면이 업데이트되는 것은 곧 DOM이 수정됨을 의미한다.

 

그런데 문제점은 이러한 브라우저 DOM을 수정하는 작업은 비용이 많이 드는 무거운 작업이라는 것이다.

 

따라서 리액트에서는 Virtual DOM을 사용함으로써 State가 변경되었을 때 이 변경된 부분에 대해서만 업데이트를 수행하기 때문에 빠른 렌더링이 가능해지는 것이다.

 

- Components-Based (컴포넌트 기반)

리액트의 또 다른 장점은 컴포넌트 기반으로 개발이 진행된다는 점이다.

마치 레고 블럭을 조립하듯 리액트에서는 각 컴포넌트들을 조합하여 웹 사이트를 개발하는 것이다.

 

예를 들어, 하나의 웹페이지를 '헤더', '네비게이션 바', '게시글 목록', '댓글창'처럼 각각의 독립된 컴포넌트로 나눌 수 있고, 이걸 조립하듯이 붙여서 하나의 화면을 만든다.

이러한 컴포넌트 기반 방식이 가지는 장점은 다음과 같다.

  • 재사용성: 각각의 독립된 컴포넌트들을 여러 곳에서 재사용할 수 있다.
  • 유지보수 용이: 변경 사항이 생기더라도 해당 컴포넌트만 수정하면 되므로, 유지보수가 용이하다.

- 활발한 커뮤니티와 생태

리액트는 Meta에서 진행 중인 오픈소스 프로젝트인만큼, 지속적인 업데이트와 풍부한 생태계를 갖고 있다.

  • 문서화가 잘 되어있으며
  • StackOverFlow나 Github에서 활발한 지식 공유가 이루어지고 있으며
  • React Native를 통해 Java Script만으로 웹과 모바일 서비스를 모두 개발할 수도 있다.

- 단점 역시 존재하는데...

  • 배워야 할 개념이 많음 (JSX, Props, State, Hook, Routing, 상태관리 등등...)
  • 상태 관리를 하려면 Recoil, Redux 같은 추가 도구가 필요함
  • 업데이트가 잦은 만큼 학습량이 늘어나는 경향이 있다

하지만 이건 프론트엔드 개발 분야가 워낙 트렌드에 민감한 분야라 어쩔 수 없는 운명이기도 하다...🥲


3. 리액트 시작하기

- 직접 리액트를 연동하는 방법

1. 기존 HTML 코드에 DOM Container (root DOM node)를 추가한다. 이는 Virtual DOM의 시작점이라고 이해

<div id="root"></div>

2. 리액트 JS 파일들을 가져온다.

    <!-- 리액트 가져오기 -->
    <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>

    <!-- 리액트 컴포넌트 가져오기 -->
    <script src="MyButton.js"></script>

 

- create-react-app

1. Node.js와 npm 환경 설정

  • Node.js v14.0.0 이상
  • npm v6.14.0 이상
  • VS Code 설치

2. npx 명령어를 이용해 실행

npx create-react-app <프로젝트 이름>

패키지를 정해진 위치에 설치하고 찾아서 사용하는 같은 번거로운 작업을 편리하게 수행해준다.


마무리

리액트를 처음 접하면 생소하고 어려운 개념들이 많을 수 있지만, 그만큼 매력도 많은 라이브러리입니다.

이번 글에서는 React의 개요에 대해 다뤘고, 다음 포스팅에서는 JSX나 Props, State 같은 더 구체적인 리액트 개념을 하나씩 알아볼 예정입니다!

 

읽어주셔서 감사합니다 🫡

+ Recent posts