본문 바로가기

다양한 실습 해보기

1. 다양한 실습 해보기

이번 장에서는 앞서 살펴본 React의 장점을 충분히 활용해볼 수 있도록 다양한 예제를 통해 실습해보겠습니다. 모든 예제는 CDN 환경에서 진행됩니다. 여기서 충분히 많은 실습을 해본 후, 이후 장에서 React 개발 환경 설정 방법을 다루겠습니다.

1.1 기본 템플릿

아래 코드는 앞으로 실습에서 사용할 기본 템플릿입니다. 이 구조를 기반으로 다양한 컴포넌트를 만들어보겠습니다.

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>React 실습</title>
  </head>
  <body>
    <div id="root"></div>
    <!-- React 19 UMD (커뮤니티 빌드) -->
    <script src="https://unpkg.com/umd-react/dist/react.development.js"></script>
    <script src="https://unpkg.com/umd-react/dist/react-dom.development.js"></script>
    <!-- Babel CDN -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script type="text/babel">
      // 여기에 React 코드 작성
    </script>
  </body>
</html>

2. JSX 변수로 UI 구성하기

먼저 JSX를 변수에 저장하여 UI를 구성하는 방법을 알아보겠습니다.

2.1 순수 HTML 구조

아래는 일반적인 HTML로 작성된 간단한 웹페이지 구조입니다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>리액트 1분만에 추가해보기!</title>
  </head>
  <body>
    <header>
      <nav>
        <ul>
          <li>about</li>
          <li>product</li>
          <li>contact</li>
        </ul>
      </nav>
    </header>
    <main>우리회사 짱짱!</main>
    <footer>&copy; 2024 MyCompany</footer>
  </body>
</html>

2.2 JSX 변수로 변환하기

위 HTML을 React의 JSX 변수로 변환하면 다음과 같습니다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>리액트 1분만에 추가해보기!</title>
  </head>
  <body>
    <div id="root"></div>

    <!-- React 19 UMD (커뮤니티 빌드) -->
    <script src="https://unpkg.com/umd-react/dist/react.development.js"></script>
    <script src="https://unpkg.com/umd-react/dist/react-dom.development.js"></script>
    <!-- Babel CDN -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      // JSX 변수 정의
      const header = (
        <header>
          <nav>
            <ul>
              <li>about</li>
              <li>product</li>
              <li>contact</li>
            </ul>
          </nav>
        </header>
      );

      const main = <main>우리회사 짱짱!</main>;

      const footer = <footer>&copy; 2024 MyCompany</footer>;

      // JSX 내부에서 중괄호 {}를 사용하여 JavaScript 표현식 삽입
      const app = (
        <div>
          {header}
          {main}
          {footer}
        </div>
      );

      // DOM에 리액트 컴포넌트 렌더링하기
      const domContainer = document.querySelector('#root');
      const root = ReactDOM.createRoot(domContainer);
      root.render(app);
    </script>
  </body>
</html>

중괄호 {}의 역할

JSX 내부에서 중괄호 {}를 사용하면 JavaScript 표현식을 삽입할 수 있습니다. 변수, 함수 호출, 연산 등을 JSX 안에서 직접 사용할 수 있게 해주는 문법입니다. 이 문법은 앞으로 자주 사용하게 될 중요한 개념입니다.

3. 함수 컴포넌트로 UI 구성하기

JSX 변수 대신 함수 컴포넌트를 사용하면 더 체계적으로 UI를 구성할 수 있습니다.

3.1 함수 컴포넌트란?

함수 컴포넌트는 JSX를 반환하는 JavaScript 함수입니다. 컴포넌트 이름은 반드시 대문자로 시작해야 합니다.

3.2 함수 컴포넌트 만들기

앞서 만든 JSX 변수를 함수 컴포넌트로 변환해보겠습니다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>리액트 1분만에 추가해보기!</title>
  </head>
  <body>
    <div id="root"></div>

    <!-- React 19 UMD (커뮤니티 빌드) -->
    <script src="https://unpkg.com/umd-react/dist/react.development.js"></script>
    <script src="https://unpkg.com/umd-react/dist/react-dom.development.js"></script>
    <!-- Babel CDN -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      // 함수 컴포넌트 정의
      function Header() {
        return (
          <header>
            <nav>
              <ul>
                <li>about</li>
                <li>product</li>
                <li>contact</li>
              </ul>
            </nav>
          </header>
        );
      }

      function Main() {
        return <main>우리회사 짱짱!</main>;
      }

      function Footer() {
        return <footer>&copy; 2024 MyCompany</footer>;
      }

      // 컴포넌트를 태그처럼 사용
      const app = (
        <div>
          <Header />
          <Main />
          <Footer />
        </div>
      );

      // DOM에 리액트 컴포넌트 렌더링하기
      const domContainer = document.querySelector('#root');
      const root = ReactDOM.createRoot(domContainer);
      root.render(app);
    </script>
  </body>
</html>

3.3 JSX 변수 vs 함수 컴포넌트 비교

구분JSX 변수함수 컴포넌트
문법const header = <header>...</header>function Header() { return <header>...</header> }
사용법{header}<Header />
재사용성단순 값 복사독립적인 인스턴스 생성
상태 관리불가능가능 (Hooks 사용)
Props 전달불가능가능

함수 컴포넌트를 사용하면 나중에 배울 props(속성 전달)와 hooks(상태 관리)를 활용할 수 있어 더 강력한 기능을 구현할 수 있습니다.

4. 컴포넌트 중첩하기

컴포넌트 안에 다른 컴포넌트를 포함시켜 복잡한 UI를 구성할 수 있습니다.

4.1 컴포넌트 트리 구조

4.2 중첩된 컴포넌트 예제

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>리액트 1분만에 추가해보기!</title>
  </head>
  <body>
    <div id="root"></div>

    <!-- React 19 UMD (커뮤니티 빌드) -->
    <script src="https://unpkg.com/umd-react/dist/react.development.js"></script>
    <script src="https://unpkg.com/umd-react/dist/react-dom.development.js"></script>
    <!-- Babel CDN -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      // 가장 작은 단위의 컴포넌트
      function Button() {
        return <button>hello!!</button>;
      }

      // Button을 포함하는 Section 컴포넌트
      function Section() {
        return (
          <section>
            <h2>리액트 시작하기</h2>
            <p>리액트를 프로젝트에 추가하는 방법을 알아봅시다.</p>
            <Button />
          </section>
        );
      }

      function Header() {
        return (
          <header>
            <h1>리액트 1분만에 추가해보기!</h1>
            <nav>
              <ul>
                <li>about</li>
                <li>projects</li>
                <li>contact</li>
              </ul>
            </nav>
          </header>
        );
      }

      // Section을 여러 개 포함하는 Main 컴포넌트
      function Main() {
        return (
          <main>
            <Section />
            <Section />
            <Section />
          </main>
        );
      }

      function Footer() {
        return (
          <footer>
            <p>&copy; 2024 My React App</p>
          </footer>
        );
      }

      // 최상위 컴포넌트
      const app = (
        <div>
          <Header />
          <Main />
          <Footer />
        </div>
      );

      const domContainer = document.querySelector('#root');
      const root = ReactDOM.createRoot(domContainer);
      root.render(app);
    </script>
  </body>
</html>

4.3 컴포넌트 재사용의 장점

위 예제에서 Section 컴포넌트를 3번 사용했습니다. 만약 Section의 내용을 수정해야 한다면, 한 곳만 수정하면 모든 곳에 적용됩니다.

5. 실습 문제

5.1 실습 1: 기본 페이지 컴포넌트화

아래 HTML을 React 컴포넌트로 변환해보세요.

문제:

<header>
  <h1>리액트 1분만에 추가해보기!</h1>
  <nav>
    <ul>
      <li>about</li>
      <li>projects</li>
      <li>contact</li>
    </ul>
  </nav>
</header>
<main>
  <section>
    <h2>리액트 시작하기</h2>
    <p>리액트를 프로젝트에 추가하는 방법을 알아봅시다.</p>
    <button>hello</button>
  </section>
  <section>
    <h2>리액트 시작하기</h2>
    <p>리액트를 프로젝트에 추가하는 방법을 알아봅시다.</p>
    <button>hello</button>
  </section>
  <section>
    <h2>리액트 시작하기</h2>
    <p>리액트를 프로젝트에 추가하는 방법을 알아봅시다.</p>
    <button>hello</button>
  </section>
</main>
<footer>
  <p>&copy; 2024 My React App</p>
</footer>

요구사항:

  1. header, main, footer를 모두 함수 컴포넌트로 만들어주세요.
  2. main 컴포넌트 안의 section도 컴포넌트로 만들어주세요.
  3. 각 section 안에 있는 button은 별도의 컴포넌트로 만들어주세요.

힌트

컴포넌트를 작은 단위부터 만들어 나가세요. Button → Section → Main 순서로 만들면 됩니다.

정답 보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>리액트 1분만에 추가해보기!</title>
  </head>
  <body>
    <div id="root"></div>

    <!-- React 19 UMD (커뮤니티 빌드) -->
    <script src="https://unpkg.com/umd-react/dist/react.development.js"></script>
    <script src="https://unpkg.com/umd-react/dist/react-dom.development.js"></script>
    <!-- Babel CDN -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      function Button() {
        return <button>hello!!</button>;
      }

      function Section() {
        return (
          <section>
            <h2>리액트 시작하기</h2>
            <p>리액트를 프로젝트에 추가하는 방법을 알아봅시다.</p>
            <Button />
          </section>
        );
      }

      function Header() {
        return (
          <header>
            <h1>리액트 1분만에 추가해보기!</h1>
            <nav>
              <ul>
                <li>about</li>
                <li>projects</li>
                <li>contact</li>
              </ul>
            </nav>
          </header>
        );
      }

      function Main() {
        return (
          <main>
            <Section />
            <Section />
            <Section />
          </main>
        );
      }

      function Footer() {
        return (
          <footer>
            <p>&copy; 2024 My React App</p>
          </footer>
        );
      }

      const app = (
        <div>
          <Header />
          <Main />
          <Footer />
        </div>
      );

      const domContainer = document.querySelector('#root');
      const root = ReactDOM.createRoot(domContainer);
      root.render(app);
    </script>
  </body>
</html>

5.2 실습 2: 위니북스 페이지 컴포넌트화

아래 HTML을 React 컴포넌트로 변환해보세요.

문제:

<!-- 위니북스 페이지 -->
<div>메뉴</div>
<div>이미지 슬라이드</div>
<div>
  <button>버튼</button>
  <button>버튼</button>
  <button>버튼</button>
  <button>버튼</button>
  <button>버튼</button>
</div>
<div>
  <div>
    <img src="" alt="" />
    <div>책 제목</div>
    <div>가격</div>
    <div>설명</div>
    <a href="">바로가기</a>
  </div>
  <div>
    <img src="" alt="" />
    <div>책 제목</div>
    <div>가격</div>
    <div>설명</div>
    <a href="">바로가기</a>
  </div>
  <div>
    <img src="" alt="" />
    <div>책 제목</div>
    <div>가격</div>
    <div>설명</div>
    <a href="">바로가기</a>
  </div>
  <div>
    <img src="" alt="" />
    <div>책 제목</div>
    <div>가격</div>
    <div>설명</div>
    <a href="">바로가기</a>
  </div>
</div>
<div>푸터영역</div>

요구사항:

  1. 모든 영역을 함수 컴포넌트로 만들어주세요.
  2. 버튼과 책 정보는 여러 개가 있으니 재사용 가능한 컴포넌트로 만들어주세요.

컴포넌트 구조 힌트:

정답 보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>위니북스</title>
  </head>
  <body>
    <div id="root"></div>

    <!-- React 19 UMD (커뮤니티 빌드) -->
    <script src="https://unpkg.com/umd-react/dist/react.development.js"></script>
    <script src="https://unpkg.com/umd-react/dist/react-dom.development.js"></script>
    <!-- Babel CDN -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      function Menu() {
        return <div>메뉴</div>;
      }

      function ImgSlide() {
        return <div>이미지 슬라이드</div>;
      }

      function Button() {
        return <button>버튼</button>;
      }

      function Buttons() {
        return (
          <div>
            <Button />
            <Button />
            <Button />
            <Button />
            <Button />
          </div>
        );
      }

      function BookCard() {
        return (
          <div>
            <img src="" alt="" />
            <div>책 제목</div>
            <div>가격</div>
            <div>설명</div>
            <a href="">바로가기</a>
          </div>
        );
      }

      function Main() {
        return (
          <div>
            <BookCard />
            <BookCard />
            <BookCard />
            <BookCard />
          </div>
        );
      }

      function Footer() {
        return <div>푸터영역</div>;
      }

      const app = (
        <div>
          <Menu />
          <ImgSlide />
          <Buttons />
          <Main />
          <Footer />
        </div>
      );

      const domContainer = document.querySelector('#root');
      const root = ReactDOM.createRoot(domContainer);
      root.render(app);
    </script>
  </body>
</html>

6. 정리

이번 장에서 배운 내용을 정리해보겠습니다.

개념설명
JSXJavaScript 안에서 HTML과 비슷한 문법을 사용할 수 있게 해주는 문법
중괄호 {}JSX 내부에서 JavaScript 표현식을 사용할 때 사용
함수 컴포넌트JSX를 반환하는 함수, 재사용 가능한 UI 조각
컴포넌트 중첩컴포넌트 안에 다른 컴포넌트를 포함시키는 것

다음 장에서는...

지금까지는 모든 컴포넌트가 동일한 내용을 보여주었습니다. 다음 장에서는 Props를 사용하여 각 컴포넌트에 다른 데이터를 전달하는 방법을 배워보겠습니다.