본문으로 건너뛰기

안동민 개발노트

본문 시작

첫 번째 React 앱 만들기

Vite 프로젝트의 파일 구조를 살펴보고 App 컴포넌트의 JSX와 CSS를 수정해 첫 React 화면을 완성합니다.

이 장에서는 그 기본 틀 위에서 여러분만의 첫 번째 리액트 앱을 만들어 봅니다.

리액트 코드가 실제로 어떻게 웹 페이지에 나타나는지 직접 경험해 볼 것입니다.

우리는 주로 src 폴더 안의 App.jsx 파일을 수정하며 리액트 컴포넌트를 작성하게 될 것입니다.

아직 모든 코드를 이해하지 못해도 괜찮습니다.

지금은 이것을 수정하면 웹 페이지가 이렇게 바뀌는구나! 하고 직관적으로 느껴보는 것이 중요합니다.

첫 React 앱 렌더링 흐름

파일을 수정했을 때 화면이 바뀌는 이유는 JSX가 컴포넌트로 실행되고 root DOM에 렌더링되기 때문이다.

  1. HTML 진입점
    브라우저가 빈 root 영역을 가진 기본 문서를 읽는다

    index.html

  2. 렌더 연결
    React가 root DOM을 찾고 App 컴포넌트를 렌더링한다

    src/main.jsx

  3. 화면 작성
    JSX로 제목, 문단, 버튼 같은 화면 구조를 표현한다

    src/App.jsx

  4. 스타일 적용
    컴포넌트에서 CSS를 import해 화면 표현을 바꾼다

    src/App.css


프로젝트 구조 살펴보기

VS Code로 my-first-react-app 프로젝트를 열고 왼쪽 탐색기(Explorer)를 보면 다음과 같은 폴더 및 파일 구조를 확인할 수 있습니다.

vite.svg # 기본 템플릿에서 쓰는 정적 이미지
...
react.svg # 기본 템플릿에서 쓰는 React 로고
App.css # App 컴포넌트의 스타일 시트
App.jsx # 메인 App 컴포넌트
index.css # 전역 스타일 시트
main.jsx # 리액트 앱의 시작점. App 컴포넌트를 root에 렌더링
.gitignore # Git이 추적하지 않을 파일 및 폴더 지정
index.html # root DOM을 제공하는 HTML 진입 파일
package.json # 프로젝트의 메타데이터, 의존성, 스크립트 정보
README.md # 프로젝트에 대한 설명 문서
vite.config.js # Vite 설정 파일
...

이 중에서 우리가 주로 관심을 가질 파일은 index.html, src/main.jsx, 그리고 src/App.jsx입니다.

  • index.html: 이 파일은 여러분의 리액트 애플리케이션이 로드될 기본 HTML 페이지입니다. <div id="root"></div>라는 빈 태그를 찾아보세요. 리액트 애플리케이션은 이 id="root"를 가진 div 안에 렌더링됩니다.
  • src/main.jsx: 이 파일은 리액트 애플리케이션의 시작점입니다. 여기서 App.jsx에서 가져온 <App /> 컴포넌트를 index.htmlroot 요소에 연결합니다.
  • src/App.jsx: 이 파일은 현재 웹 페이지에 보이는 내용을 담고 있는 메인 컴포넌트입니다. 우리는 주로 이 파일을 수정하면서 첫 번째 리액트 앱을 만들어 볼 것입니다.
#root에서 App 화면까지, 세 파일이 한 경로로 잇는다

Vite는 index.html을 entry로 제공한다. main.jsx가 DOM node에 React root를 만들고 App.jsx의 JSX를 그 안에 표시한다.

  1. index.html

    DOM 자리 <div id="root"></div> 브라우저가 먼저 읽는 HTML entry.

  2. src/main.jsx

    React 연결 createRoot(#root) root.render(<App />)

  3. src/App.jsx

    UI 반환 function App() → JSX 문구·컴포넌트를 바꾸는 첫 수정 지점.

  4. Browser

    React 관리 영역 #root → App UI 저장하면 Vite HMR이 변경을 반영.


App.jsx 수정하여 내용 변경하기

이제 VS Code에서 src/App.jsx 파일을 열어보세요.

기본 템플릿에는 Vite와 React 로고, 카운터 예제, HMR 안내 문구가 들어 있습니다.

처음에는 이 예제 코드를 단순한 화면으로 바꾸며 컴포넌트 함수가 반환한 JSX가 브라우저 화면이 된다는 점을 확인하면 됩니다.

이제 이 내용을 우리가 원하는 간단한 문구로 변경해 보겠습니다.

기존 내용 삭제 및 새 내용 추가 기본 예제에서 로고와 카운터 관련 import를 지우고, 다음과 같이 간단한 <h1> 태그와 <p> 태그를 반환해 보세요.

src/App.jsx
import './App.css';

function App() {
  return (
    <div className="App">
      {/* 여기에 새로운 내용을 작성합니다 */}
      <h1>나 혼자 React!</h1>
      <p>첫 번째 React 앱을 만들고 있습니다.</p>
      <p>정말 재미있네요!</p>
    </div>
  );
}

export default App;

파일 저장: 코드를 수정한 후 Ctrl+S (macOS: Cmd+S)를 눌러 파일을 저장합니다.

결과 확인: 개발 서버(npm run dev로 실행했던)가 여전히 실행 중이라면, 웹 브라우저(http://localhost:5173)를 새로고침하지 않아도 자동으로 변경된 내용이 화면에 나타나는 것을 확인할 수 있을 것입니다!

화면에 나 혼자 React!, 첫 번째 React 앱을 만들고 있습니다., 정말 재미있네요!라는 문구가 보인다면 성공입니다!


JSX에 대하여 잠시 알아보기

App.jsx 파일에서 return 문 안에 작성했던 <div className="App"> ... </div>와 같은 코드들을 보셨을 것입니다.

이것은 HTML처럼 생겼지만 사실은 JSX(JavaScript XML)라고 부르는 리액트만의 특별한 문법입니다.

JSX는 자바스크립트 안에 HTML(XML)과 유사한 문법을 사용하여 UI를 기술할 수 있도록 해줍니다.

언뜻 보면 HTML과 매우 유사하지만, 다음과 같은 몇 가지 중요한 차이점이 있습니다.

  • HTML 속성 이름: HTML에서 class라고 쓰는 속성은 JSX에서는 className으로 작성해야 합니다. forhtmlFor로 작성해야 합니다. 이는 classfor가 자바스크립트의 예약어이기 때문입니다.

  • 단일 루트 요소: 컴포넌트는 항상 하나의 최상위(Root) 요소를 반환해야 합니다. 예를 들어, 여러 태그를 나란히 반환하고 싶다면 하나의 <div><> (프래그먼트)로 감싸야 합니다.

    // ⭕ 올바른 JSX (하나의 div로 감싸져 있음)
    function MyComponent() {
      return (
        <div>
          <h1>제목</h1>
          <p>내용</p>
        </div>
      );
    }
    // ❌ 잘못된 JSX (두 개의 최상위 요소)
    // function MyComponent() {
    //   return (
    //     <h1>제목</h1>
    //     <p>내용</p>
    //   );
    // }

    <div>로 감싸는 것이 번거롭거나 불필요한 DOM 노드를 생성하고 싶지 않을 때는 <></>와 같은 빈 태그를 사용할 수 있는데, 이를 프래그먼트(Fragment)라고 부릅니다.

    // ⭕ 올바른 JSX (프래그먼트 사용)
    function MyComponent() {
      return (
        <>
          <h1>제목</h1>
          <p>내용</p>
        </>
      );
    }
  • 자바스크립트 표현식 삽입: JSX 내부에서 중괄호 {}를 사용하면 자바스크립트 표현식을 삽입할 수 있습니다. 예를 들어, 변수의 값이나 함수의 결과 등을 UI에 바로 렌더링할 수 있습니다.

    function Welcome() {
      const name = '독자 여러분';
      return (
        <h1>안녕하세요, {name}!</h1>
      );
    }

    JSX는 자바스크립트 안에서 UI 구조를 선언할 수 있게 해 줍니다.

    이후 예제에서는 JSX로 리액트 컴포넌트를 작성합니다.

첫 앱 수정은 짧은 피드백 루프로 익힌다

코드를 바꾸고 결과를 확인하는 한 바퀴가 개발 환경 전체를 검증한다.

  1. 편집
    App.jsx 수정

    표시할 JSX와 값을 바꾼다

  2. 감지
    파일 저장

    Vite가 변경 모듈을 찾는다

  3. 교체
    Fast Refresh

    능하면 상태를 보존해 모듈만 갱신

  4. 확인
    화면·콘솔

    렌더 결과와 경고를 함께 읽는다


스타일 적용하기

현재 여러분의 웹 페이지는 글씨가 작고 정렬이 되어있지 않아 보기에 좋지 않을 수 있습니다.

리액트 컴포넌트에 스타일을 적용하는 방법은 여러 가지가 있지만, 여기서는 Vite 기본 프로젝트에서 바로 사용할 수 있는 일반 CSS 파일인 App.css를 수정해 보겠습니다.

App.css 파일 수정: VS Code에서 src/App.css 파일을 열어 기존의 모든 내용을 삭제하고 다음과 같이 간단한 스타일을 추가해 보세요.

src/App.css
.App {
  text-align: center; /* 텍스트를 가운데 정렬 */
  background-color: #f0f0f0; /* 배경색 변경 */
  min-height: 100vh; /* 최소 높이를 뷰포트 높이로 설정 */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin); /* 폰트 크기 조정 */
  color: #333; /* 텍스트 색상 변경 */
}

h1 {
  color: #007bff; /* 제목 색상 파란색 */
  margin-bottom: 20px;
}

p {
  color: #555; /* 단락 텍스트 색상 회색 */
  line-height: 1.5;
}

파일 저장: App.css 파일을 저장합니다.

결과 확인: 웹 브라우저를 확인하면 여러분이 추가한 스타일이 적용되어 텍스트가 가운데 정렬되고, 배경색과 폰트 색상이 변경된 것을 볼 수 있을 것입니다.

App.jsx 파일에서 import './App.css'; 라는 코드를 통해 CSS 파일을 불러왔기 때문에, 해당 스타일이 App 컴포넌트 화면에 적용됩니다.

리액트는 이처럼 자바스크립트 코드 내에서 CSS 파일을 불러와 화면 구조와 스타일의 연결을 한 곳에서 추적하기 쉽게 만듭니다.

첫 React 앱 수정 흐름

첫 React 앱에서는 파일 위치, JSX 수정, CSS 반영의 연결을 먼저 감각으로 익힙니다.

  1. 1
    App.jsx 찾기

    화면에 보이는 문구를 만드는 메인 컴포넌트를 엽니다.

  2. 2
    JSX 바꾸기

    h1과 p 태그를 수정해 원하는 내용을 렌더링합니다.

  3. 3
    CSS 적용

    App.css를 불러와 정렬, 색상, 간격을 화면에 반영합니다.

첫 React 앱에서는 프로젝트 구조를 통째로 외우기보다 진입 파일, App 컴포넌트, 스타일, 브라우저 화면이 이어지는 경로를 확인합니다.

이 연결이 보이면 다음 장부터는 JSX 안에서 데이터를 표현하고 이벤트로 상태를 바꾸는 흐름을 훨씬 자연스럽게 따라갈 수 있습니다.