Front_end

강의 자료 2

Ta_m 2026. 2. 25. 16:25

React 입문 — JSX · 컴포넌트 · CSS 스타일링

이 글은 프론트엔드 개발 커리큘럼 Week 1 강의 내용을 정리한 글입니다.


React란 무엇인가?

React는 Meta(구 Facebook)가 만든 UI 라이브러리다. 웹 페이지의 화면(UI)을 만드는 데 특화되어 있으며, 핵심 특징은 다음과 같다.

  • 컴포넌트 기반 — UI를 독립적인 조각으로 나눠 관리
  • Virtual DOM — 변경된 부분만 업데이트해서 성능이 뛰어남
  • 재사용성 — 한 번 만든 컴포넌트를 어디서든 재사용 가능

Node.js 설치하기

React 개발을 시작하려면 Node.js가 필요하다. nodejs.org에서 LTS 버전을 설치한 뒤 아래 명령어로 확인하자.

node -v
npm -v

버전 번호가 출력되면 설치 완료.


첫 리액트 프로젝트 만들기 (Vite)

Vite를 사용하면 빠르게 React 프로젝트를 시작할 수 있다.

npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev

브라우저에서 http://localhost:5173을 열면 React 앱이 실행된다.

컴포넌트 파일은 src/components/ 폴더를 만들어 관리하는 것이 일반적이다.


JSX 문법 이해하기

JSX는 JavaScript 안에 HTML을 작성할 수 있게 해주는 문법이다.

function App() {
  return (
    <div>
      <h1>안녕하세요!</h1>
      <p>React 시작!</p>
    </div>
  );
}

JSX 주의사항

  • 반드시 하나의 부모 요소로 감싸야 한다 (<div> 또는 <>...</>)
  • class 대신 className을 사용한다
  • 모든 태그는 반드시 닫아야 한다 (<img />)

컴포넌트 이해하기

컴포넌트는 UI를 구성하는 독립적인 조각이다. src/components/ 폴더 안에 파일을 만들어 관리한다.

컴포넌트 만들기

// Header.jsx
function Header() {
  return (
    <header>
      <h1>나의 쇼핑몰</h1>
    </header>
  );
}

export default Header;

다른 파일에서 불러오기

// App.jsx
import Header from './components/Header';

function App() {
  return <Header />;
}

Props — 컴포넌트에 데이터 전달하기

Props를 사용하면 컴포넌트에 데이터를 넘겨줄 수 있다. 구조분해할당을 쓰면 코드가 더 간결해진다.

// Product.jsx
function Product({ name, price }) {
  return (
    <div>
      <h3>{name}</h3>
      <div>{price}</div>
    </div>
  );
}

export default Product;
// 사용할 때
<Product name="언젠가 입을 수 있는 스웨터" price="13,000원" />

React에서 CSS 사용하기

React에서 스타일을 적용하는 방법은 크게 세 가지다.

① 일반 CSS 파일

가장 기본적인 방법. .css 파일을 만들고 import해서 사용한다.

/* Header.css */
.header {
  background: #1a1a2e;
  color: white;
  padding: 1rem;
}
// Header.jsx
import './Header.css';

function Header() {
  return <header className="header">나의 쇼핑몰</header>;
}

② CSS Module

.module.css 파일을 사용하면 스타일이 컴포넌트 단위로 격리되어 클래스명 충돌을 방지할 수 있다.

/* Header.module.css */
.header {
  background: #1a1a2e;
}
// Header.jsx
import styles from './Header.module.css';

function Header() {
  return <header className={styles.header}>나의 쇼핑몰</header>;
}

③ Inline Style

JSX에 직접 스타일 객체를 작성하는 방법. 간단한 스타일에 적합하다

React 입문: 개념부터 프로젝트 구조까지 한 번에 정리

1. React란 무엇인가?

React는 Facebook(현 Meta)이 만든 UI(User Interface) 라이브러리다. 웹 페이지의 화면을 구성하는 컴포넌트들을 효율적으로 렌더링하기 위해 만들어졌다.

React의 핵심 개념은 Virtual DOM이다. 브라우저의 실제 DOM을 직접 조작하면 성능이 느려지는데, React는 메모리 상에 가상의 DOM을 두고 변경된 부분만 비교해서 실제 DOM에 최소한으로 반영한다. 그 결과 화면이 빠르고 부드럽게 업데이트된다.

또 한 가지 중요한 특징은 선언형(Declarative) 방식이다. “이 버튼을 클릭하면 이 요소를 찾아 텍스트를 바꿔라”처럼 어떻게 할지를 일일이 명령하는 게 아니라, “이 상태일 때 화면은 이렇게 생겼다”고 결과물을 선언한다. 상태가 바뀌면 React가 알아서 화면을 다시 그려준다.


2. Node.js가 필요한 이유

React 자체는 브라우저에서 동작하는 JavaScript 라이브러리다. 그런데 왜 Node.js가 필요할까?

React 프로젝트를 개발하다 보면 다음과 같은 작업들이 필요하다.

  • JSX 코드를 브라우저가 이해할 수 있는 JavaScript로 변환(트랜스파일)
  • 여러 파일을 하나로 번들링(bundling)
  • 로컬에서 개발 서버 실행
  • npm install외부 패키지 설치

이 모든 작업들이 Node.js 환경에서 실행된다. Node.js 자체가 웹 서버를 만들기 위한 것이라기보다는, React 개발을 위한 도구들의 실행 환경 역할을 한다고 보면 된다.


3. Vite를 사용하는 이유

예전에는 React 프로젝트를 시작할 때 Create React App(CRA) 을 주로 사용했다. 그런데 요즘은 Vite가 사실상 표준이 됐다. 이유는 단순하다: 빠르기 때문이다.

CRA는 프로젝트를 시작할 때 모든 파일을 한꺼번에 번들링한다. 프로젝트가 커질수록 개발 서버 시작 시간이 몇 십 초씩 걸리기도 한다.

Vite는 다르다. 개발할 때는 파일을 번들링하지 않고, 브라우저가 요청하는 파일만 그때그때 변환해서 내려준다. 덕분에 서버 시작이 거의 즉각적이고, 코드를 수정했을 때 화면에 반영되는 HMR(Hot Module Replacement) 속도도 월등히 빠르다.

구분 CRA Vite
개발 서버 시작 느림 (전체 번들링) 빠름 (필요한 파일만)
HMR 속도 느림 빠름
번들러 Webpack Rollup (esbuild)

4. Vite + React 프로젝트 구조 파악

npm create vite@latest로 프로젝트를 만들면 아래와 같은 구조가 생긴다.

my-app/
├── public/
├── src/
├── node_modules/
├── .gitignore
├── package.json
├── package-lock.json
├── README.md
└── vite.config.js

4-1. public/

정적 파일을 보관하는 폴더다. 이 안에 있는 파일들은 빌드 과정에서 가공 없이 그대로 복사된다. 파비콘(favicon.ico)이나 Open Graph 이미지처럼 코드에서 import하지 않고 URL로 직접 참조하는 파일들을 여기에 넣는다.

4-2. node_modules/

npm install로 설치한 외부 패키지들이 실제로 저장되는 폴더다. 용량이 매우 크기 때문에 Git에는 올리지 않는다. package.json만 있으면 언제든 npm install로 다시 생성할 수 있다.

4-3. .gitignore

Git이 추적하지 않을 파일 목록을 정의한다. node_modules/, 빌드 결과물인 dist/, 환경변수 파일인 .env 등을 여기에 등록해서 실수로 커밋되는 걸 막는다.

4-4. package-lock.json

프로젝트에 설치된 패키지들의 정확한 버전을 기록한 파일이다. 팀원들이 npm install을 실행했을 때 모두 같은 버전의 패키지를 설치하도록 보장해준다. 직접 편집하지 않는다.

4-5. package.json

프로젝트의 메타 정보와 의존성 목록을 담은 파일이다. 프로젝트 이름, 버전, 사용 중인 패키지 목록, 그리고 dev, build, preview 같은 스크립트 명령어들이 여기에 정의된다.

4-6. README.md

프로젝트 설명 문서다. GitHub에 올리면 저장소 메인 페이지에 렌더링되어 보여진다. 프로젝트 소개, 실행 방법, 사용 기술 스택 등을 적는다.

4-7. vite.config.js

Vite의 설정 파일이다. 개발 서버 포트 변경, 빌드 경로 설정, 플러그인 추가(예: @vitejs/plugin-react) 등을 여기서 관리한다.

4-8. src/

실제로 코드를 작성하는 폴더다. 컴포넌트 파일(.jsx), 스타일, 이미지, 유틸 함수 등 개발자가 만드는 모든 소스 파일이 여기에 들어간다. 이 안의 파일들은 Vite가 번들링 과정에서 처리한다.


5. JSX란 무엇인가?

React 코드를 처음 보면 JavaScript 안에 HTML이 섞여 있는 것처럼 보인다.

function Greeting() {
  const name = "준태";
  return (
    <div className="greeting">
      <h1>안녕하세요, {name}!</h1>
      <p>React 공부 중입니다.</p>
    </div>
  );
}

이게 바로 JSX(JavaScript XML) 다. JavaScript 코드 안에서 HTML과 유사한 문법으로 UI 구조를 표현할 수 있게 해주는 문법적 확장(syntactic sugar) 이다.

브라우저는 JSX를 직접 이해하지 못한다. Vite와 Babel이 JSX를 아래처럼 순수한 JavaScript 함수 호출로 변환해준다.

React.createElement("div", { className: "greeting" },
  React.createElement("h1", null, "안녕하세요, ", name, "!"),
  React.createElement("p", null, "React 공부 중입니다.")
)

JSX를 사용할 때 주의할 점이 몇 가지 있다.

  • HTML의 class 대신 className을 사용한다 (class는 JavaScript 예약어)
  • 모든 태그는 반드시 닫혀야 한다 (<img />, <br />)
  • 반환값은 반드시 하나의 루트 요소로 감싸야 한다
  • JavaScript 표현식은 {}로 감싸서 삽입한다

6. React Component란?

React의 모든 UI는 컴포넌트(Component) 로 이루어져 있다. 컴포넌트는 UI를 독립적이고 재사용 가능한 단위로 쪼갠 것이다.

레고 블록을 생각하면 쉽다. 헤더, 버튼, 카드, 모달 같은 UI 요소들을 각각 독립된 블록으로 만들고, 이걸 조합해서 전체 페이지를 완성한다.

현대 React에서는 함수형 컴포넌트를 사용한다.

// Button 컴포넌트
function Button({ label, onClick }) {
  return (
    <button onClick={onClick}>
      {label}
    </button>
  );
}

// App 컴포넌트에서 Button을 재사용
function App() {
  return (
    <div>
      <Button label="확인" onClick={() => alert("확인!")} />
      <Button label="취소" onClick={() => alert("취소!")} />
    </div>
  );
}

컴포넌트는 다음 규칙을 따른다.

  • 이름은 반드시 대문자로 시작한다 (소문자면 HTML 태그로 인식)
  • JSX를 반환하는 JavaScript 함수다
  • 자신만의 상태(state)와 로직을 가질 수 있다

7. Props란?

Props(Properties) 는 부모 컴포넌트가 자식 컴포넌트에게 데이터를 전달하는 방법이다. HTML에서 <img src="..."> 처럼 속성을 넘기는 것과 비슷하다.

// 부모 컴포넌트
function App() {
  return (
    <UserCard
      name="김준태"
      role="Frontend Developer"
      isActive={true}
    />
  );
}

// 자식 컴포넌트 - props를 받아서 사용
function UserCard({ name, role, isActive }) {
  return (
    <div>
      <h2>{name}</h2>
      <p>{role}</p>
      <span>{isActive ? "활동 중" : "비활동"}</span>
    </div>
  );
}

Props의 핵심 특성은 다음과 같다.

단방향 데이터 흐름: 데이터는 항상 부모 → 자식 방향으로만 흐른다. 자식이 부모의 데이터를 직접 바꿀 수 없다. 자식에서 부모로 무언가 전달하고 싶다면, 부모가 함수를 props로 넘겨주고 자식이 그 함수를 호출하는 방식을 사용한다.

읽기 전용: 자식 컴포넌트는 받은 props를 직접 수정할 수 없다. 데이터의 흐름을 예측 가능하게 유지하기 위한 규칙이다.

어떤 값이든 전달 가능: 문자열, 숫자, 배열, 객체, 함수, 심지어 다른 컴포넌트도 props로 전달할 수 있다.


이 내용들이 React의 첫 번째 허들이라고 할 수 있다. 컴포넌트 → JSX → Props 이 세 가지 개념이 서로 맞물려서 React 앱 전체를 구성하는 기반이 된다. 다음 글에서는 상태 관리의 핵심인 useStateuseEffect를 다뤄볼 예정이다.