[WEB-008][중급] 작은 화면 조각을 React 컴포넌트로 만들기
페이지 정보

본문
[이번 수업]
버튼, 카드, 입력창처럼 반복되는 화면을 한 덩어리로 복사하면 수정할 곳이 계속 늘어납니다. 이번에는 React 컴포넌트(component), 즉 화면의 독립적인 조각을 함수로 만들고, 입력값과 상태를 이용해 재사용하는 기초를 배웁니다.
[선수지식]
HTML 요소와 JavaScript 함수·객체·모듈을 알고 Node.js와 npm을 사용할 수 있어야 합니다. 터미널에서 npm create vite@latest ui-demo -- --template react를 실행한 뒤 cd ui-demo, npm install을 차례로 실행하세요. Windows PowerShell과 macOS·Linux에서 명령은 같습니다.
[학습목표]
1. JSX를 반환하는 함수 컴포넌트를 작성한다.
2. 부모가 props로 자식 컴포넌트에 값을 전달하는 흐름을 설명한다.
3. useState로 각 컴포넌트 인스턴스의 상태를 갱신한다.
[핵심개념]
React 컴포넌트는 JSX를 반환하는 JavaScript 함수입니다. JSX는 JavaScript 안에서 HTML과 비슷한 화면 구조를 쓰는 문법입니다. 직접 만든 컴포넌트 이름은 대문자로 시작해야 React가 HTML 태그와 구분합니다. 한 번 만든 Counter는 <Counter />처럼 여러 번 배치할 수 있습니다.
props는 부모가 자식에게 보내는 읽기 전용 입력값이며 함수의 인자와 비슷합니다. 자식은 props를 직접 바꾸지 않습니다. state는 화면이 다시 그려져도 컴포넌트가 기억해야 하는 값입니다. useState(0)는 현재 값과 값을 바꾸는 함수를 돌려주며, 변경 함수를 호출하면 React가 새 상태로 화면을 다시 그립니다. 같은 컴포넌트를 두 번 배치하면 각 인스턴스의 상태는 따로 저장됩니다. Hook은 컴포넌트 최상위에서 조건문 없이 호출합니다.
[따라하기]
생성된 프로젝트의 src/App.jsx 내용을 아래로 바꾸세요.
```jsx
import { useState } from "react";
function Counter({ label, step = 1 }) {
const [count, setCount] = useState(0);
return (
<section>
<h2>{label}</h2>
<p>현재 값: {count}</p>
<button onClick={() => setCount((current) => current + step)}>
{step}만큼 증가
</button>
</section>
);
}
export default function App() {
return (
<main>
<h1>독립된 카운터</h1>
<Counter label="첫 번째" />
<Counter label="두 번째" step={2} />
</main>
);
}
```
모든 운영체제에서 npm run dev를 실행하고 터미널에 표시된 로컬 주소를 브라우저로 여세요. 예상 화면은 제목 아래에 현재 값 0인 카운터 두 개가 보이는 모습입니다. 첫 번째 버튼을 한 번 누르면 첫 번째만 1이 되고, 두 번째 버튼을 두 번 누르면 두 번째만 4가 됩니다. 종료는 터미널에서 Ctrl+C를 누릅니다.
label과 step은 props입니다. count는 각 Counter가 기억하는 state이고 setCount가 값을 바꿉니다. 현재 값을 받는 갱신 함수 형태를 쓰면 연속된 클릭도 이전 상태를 기준으로 계산합니다.
[흔한 실수]
컴포넌트 이름을 소문자로 시작하거나 여러 줄 JSX를 괄호 없이 return 다음 줄에 쓰면 의도대로 렌더링되지 않습니다. props.label에 직접 대입하거나 count++로 state를 바꿔도 React에 갱신을 알릴 수 없습니다. 컴포넌트 안에서 다른 컴포넌트를 새로 정의하지 말고 파일의 최상위에 두세요. useState도 조건문·반복문 안에서 호출하지 않습니다.
[보안 주의]
브라우저에서 실행되는 props와 state에 비밀번호·토큰 같은 비밀정보를 넣지 않습니다. 서버에서 받은 값은 자료형과 허용 범위를 검증하고, 권한 판단은 서버에서도 반드시 수행해야 합니다. 사용자 입력을 dangerouslySetInnerHTML에 넣으면 스크립트 삽입 위험이 있으므로 신뢰할 수 없는 HTML에는 사용하지 말고 일반 JSX 텍스트로 표시하세요. 본인 소유의 로컬 개발 서버에서만 실습합니다.
[직접 해볼 과제]
Counter에 limit prop을 추가하고 값이 limit에 도달하면 버튼을 disabled로 만드세요. 첫 번째는 제한 3, 두 번째는 제한 6으로 배치하고, 각 상태가 독립적인지 확인하세요. 버튼 옆에는 0으로 되돌리는 초기화 버튼도 추가해 보세요.
[확인문제]
1. React 컴포넌트 이름을 대문자로 시작하는 이유는 무엇인가요?
2. props와 state는 역할이 어떻게 다른가요?
3. 같은 Counter 두 개가 서로 다른 값을 기억하는 이유는 무엇인가요?
[다음 학습]
BACK-008에서 자주 쓰는 값을 캐시에 저장하고 만료시키는 전략을 배웁니다.
[공식 참고 자료]
React 첫 컴포넌트
https://react.dev/learn/your-first-component
React props 전달
https://react.dev/learn/passing-props-to-a-component
React state
https://react.dev/learn/state-a-components-memory
Vite 시작 안내
https://vite.dev/guide/
React HTML 보안 주의
https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html
버튼, 카드, 입력창처럼 반복되는 화면을 한 덩어리로 복사하면 수정할 곳이 계속 늘어납니다. 이번에는 React 컴포넌트(component), 즉 화면의 독립적인 조각을 함수로 만들고, 입력값과 상태를 이용해 재사용하는 기초를 배웁니다.
[선수지식]
HTML 요소와 JavaScript 함수·객체·모듈을 알고 Node.js와 npm을 사용할 수 있어야 합니다. 터미널에서 npm create vite@latest ui-demo -- --template react를 실행한 뒤 cd ui-demo, npm install을 차례로 실행하세요. Windows PowerShell과 macOS·Linux에서 명령은 같습니다.
[학습목표]
1. JSX를 반환하는 함수 컴포넌트를 작성한다.
2. 부모가 props로 자식 컴포넌트에 값을 전달하는 흐름을 설명한다.
3. useState로 각 컴포넌트 인스턴스의 상태를 갱신한다.
[핵심개념]
React 컴포넌트는 JSX를 반환하는 JavaScript 함수입니다. JSX는 JavaScript 안에서 HTML과 비슷한 화면 구조를 쓰는 문법입니다. 직접 만든 컴포넌트 이름은 대문자로 시작해야 React가 HTML 태그와 구분합니다. 한 번 만든 Counter는 <Counter />처럼 여러 번 배치할 수 있습니다.
props는 부모가 자식에게 보내는 읽기 전용 입력값이며 함수의 인자와 비슷합니다. 자식은 props를 직접 바꾸지 않습니다. state는 화면이 다시 그려져도 컴포넌트가 기억해야 하는 값입니다. useState(0)는 현재 값과 값을 바꾸는 함수를 돌려주며, 변경 함수를 호출하면 React가 새 상태로 화면을 다시 그립니다. 같은 컴포넌트를 두 번 배치하면 각 인스턴스의 상태는 따로 저장됩니다. Hook은 컴포넌트 최상위에서 조건문 없이 호출합니다.
[따라하기]
생성된 프로젝트의 src/App.jsx 내용을 아래로 바꾸세요.
```jsx
import { useState } from "react";
function Counter({ label, step = 1 }) {
const [count, setCount] = useState(0);
return (
<section>
<h2>{label}</h2>
<p>현재 값: {count}</p>
<button onClick={() => setCount((current) => current + step)}>
{step}만큼 증가
</button>
</section>
);
}
export default function App() {
return (
<main>
<h1>독립된 카운터</h1>
<Counter label="첫 번째" />
<Counter label="두 번째" step={2} />
</main>
);
}
```
모든 운영체제에서 npm run dev를 실행하고 터미널에 표시된 로컬 주소를 브라우저로 여세요. 예상 화면은 제목 아래에 현재 값 0인 카운터 두 개가 보이는 모습입니다. 첫 번째 버튼을 한 번 누르면 첫 번째만 1이 되고, 두 번째 버튼을 두 번 누르면 두 번째만 4가 됩니다. 종료는 터미널에서 Ctrl+C를 누릅니다.
label과 step은 props입니다. count는 각 Counter가 기억하는 state이고 setCount가 값을 바꿉니다. 현재 값을 받는 갱신 함수 형태를 쓰면 연속된 클릭도 이전 상태를 기준으로 계산합니다.
[흔한 실수]
컴포넌트 이름을 소문자로 시작하거나 여러 줄 JSX를 괄호 없이 return 다음 줄에 쓰면 의도대로 렌더링되지 않습니다. props.label에 직접 대입하거나 count++로 state를 바꿔도 React에 갱신을 알릴 수 없습니다. 컴포넌트 안에서 다른 컴포넌트를 새로 정의하지 말고 파일의 최상위에 두세요. useState도 조건문·반복문 안에서 호출하지 않습니다.
[보안 주의]
브라우저에서 실행되는 props와 state에 비밀번호·토큰 같은 비밀정보를 넣지 않습니다. 서버에서 받은 값은 자료형과 허용 범위를 검증하고, 권한 판단은 서버에서도 반드시 수행해야 합니다. 사용자 입력을 dangerouslySetInnerHTML에 넣으면 스크립트 삽입 위험이 있으므로 신뢰할 수 없는 HTML에는 사용하지 말고 일반 JSX 텍스트로 표시하세요. 본인 소유의 로컬 개발 서버에서만 실습합니다.
[직접 해볼 과제]
Counter에 limit prop을 추가하고 값이 limit에 도달하면 버튼을 disabled로 만드세요. 첫 번째는 제한 3, 두 번째는 제한 6으로 배치하고, 각 상태가 독립적인지 확인하세요. 버튼 옆에는 0으로 되돌리는 초기화 버튼도 추가해 보세요.
[확인문제]
1. React 컴포넌트 이름을 대문자로 시작하는 이유는 무엇인가요?
2. props와 state는 역할이 어떻게 다른가요?
3. 같은 Counter 두 개가 서로 다른 값을 기억하는 이유는 무엇인가요?
[다음 학습]
BACK-008에서 자주 쓰는 값을 캐시에 저장하고 만료시키는 전략을 배웁니다.
[공식 참고 자료]
React 첫 컴포넌트
https://react.dev/learn/your-first-component
React props 전달
https://react.dev/learn/passing-props-to-a-component
React state
https://react.dev/learn/state-a-components-memory
Vite 시작 안내
https://vite.dev/guide/
React HTML 보안 주의
https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html
- 이전글[BACK-008][중급] 캐시에 저장하고 제때 새로 읽기 26.09.03
- 다음글[JSTS-008][중급] 여러 타입을 안전하게 구분하고 재사용하기 26.09.03
댓글목록
등록된 댓글이 없습니다.
