학습 목표: React Todo 앱 실습을 통한 JSX 문법, 조건부 렌더링, 이벤트 핸들링 및 실무 패턴 습득
1. React JSX 괄호 구분 가이드
JSX에서 중괄호 {}와 소괄호 ()는 명확한 용도 차이가 있습니다.
- 중괄호 {} : JavaScript 표현식 삽입
- 내부 텍스트: 변수나 로직 삽입 시 사용 ({name})
- 배열 렌더링: {todos.map(todo => <li key={todo.id}>{todo.text}</li>)}
- 속성 값: value={content}
- 인라인 스타일 (객체 전달): style={{ color: 'red' }}
- 특수문자 출력: > 기호 등은 {'>'} 또는 {'}'} 처럼 문자열로 감싸서 처리
- 소괄호 () : 긴 JSX 반환 시 가독성 확보
- 여러 줄의 JSX를 반환할 때 하나의 묶음으로 처리하여 가독성을 높임
- 화살표 함수에서 직접 반환 시 유용: () => (<div>...</div>)
// ❌ 가독성이 떨어지는 방식
return <div><h1>제목</h1><p>내용</p></div>;
// ✅ 권장하는 방식 (소괄호 사용)
return (
<div>
<h1>제목</h1>
<p>내용</p>
</div>
);
2. 주요 로직 및 이벤트 핸들링
2.1 검색어 필터링 (대소문자 무시)
검색 기능 구현 시 toLowerCase()를 활용하면 영문 대소문자 구분 없이 필터링이 가능합니다.
const getSearchResult = () => {
return search === ""
? todo
: todo.filter((it) =>
it.content.toLowerCase().includes(search.toLowerCase())
);
};
2.2 엔터키(Enter) 입력 핸들러
버튼 클릭뿐만 아니라 엔터키를 눌렀을 때도 폼이 제출되도록 처리합니다.
const handleKeyDown = (e) => {
// e.keyCode === 13 과 동일한 역할
if (e.key === 'Enter') {
onSubmit();
}
};
2.3 삼항 연산자를 활용한 상태 업데이트 (리팩토링)
조건문(if-else)을 삼항 연산자로 변경하여 코드를 간결하게 작성할 수 있습니다.
// ❌ 수정 전 (if-else 사용)
const onUpdate = (targetId) => {
setTodo(
todo.map((it) => {
if (it.id === targetId) {
return { ...it, isDone: !it.isDone };
} else {
return it;
}
})
);
};
// ✅ 수정 후 (삼항 연산자 사용)
const onUpdate = (targetId) => {
setTodo(
todo.map((it) =>
it.id === targetId ? { ...it, isDone: !it.isDone } : it
)
);
};
3. ⚠️ 트러블슈팅 및 자주 발생하는 에러
🚨 에러 1: child in a list should have a unique "key" prop
React에서 map() 함수로 배열을 렌더링할 때 각 아이템에 고유한 key 속성을 부여하지 않아 발생하는 경고입니다.
React는 가상 DOM(Virtual DOM)을 비교할 때 이 key를 통해 어떤 항목이 추가/삭제/이동되었는지 추적합니다. key가 없으면 성능이 저하되고 예기치 않은 렌더링 오류가 발생할 수 있습니다.
// ❌ 잘못된 예 (key 누락)
{todos.map(todo => <li>{todo.text}</li>)}
// ✅ 올바른 예 (고유한 id 사용 권장)
{todos.map(todo => <li key={todo.id}>{todo.text}</li>)}
// 🔺 주의: 데이터에 고유 id가 전혀 없을 때만 최후의 수단으로 index 사용
{todos.map((todo, index) => <li key={index}>{todo.text}</li>)}
🚨 에러 2: setContent("") 실행 후 입력창이 초기화되지 않는 현상
폼 제출 후 setContent("")를 호출했음에도 input 창이 비워지지 않는다면, input 태그에 value={content} 속성이 누락되었기 때문입니다. 상태(State)와 UI를 동기화하려면 반드시 value 속성을 연결해야 합니다.
<input
ref={inputRef}
value={content} // 💥 이 부분이 누락되면 초기화가 반영되지 않음
onChange={onChangeContent}
onKeyDown={handleKeyDown}
placeholder="새로운 Todo..."
/>
🚨 에러 3: 체크박스 클릭 시 상태 업데이트 안 됨 (오타 이슈)
객체 스프레드 연산자를 사용할 때 속성명에 오타가 발생하면 기존 상태가 덮어씌워지지 않고 새로운 속성이 추가되어 버그가 발생합니다.
- ❌ 오타 발생: { ...it, idDone: !it.isDone }
- ✅ 정상 코드: { ...it, isDone: !it.isDone }
4. 🗓️ 개인 메모 및 향후 일정
- 현재 진행: 리액트 한입 Todo 앱 만들기 완료 (2025-11-28)
- 학습 예정:
- 7장: useReducer와 상태 관리 학습
- 12/1: 한입 리액트 감정일기장 만들기 (페이지 라우팅 핵심)
- 프로젝트 플랜:
- 과일농장 게시판 변형: Django를 이용한 CRUD 로직 구현 (커리큘럼상 형식적 진행)
- Spring Boot + React 연동 프로젝트: 2월부터 6주간 진행 예정인 핵심 프로젝트
- 참고 자료: React 공식 튜토리얼 (Tic-Tac-Toe)
- 개념 정리:
- export: 파일 외부에서 접근할 수 있도록 함수를 내보냄
- export default: 해당 파일의 주요 함수(메인 컴포넌트)임을 명시
'⏳ Time Log > 1. One Day (Daily · TIL)' 카테고리의 다른 글
| Day 32 (12/2) – Spring Legacy 프로젝트 환경 구축 (Day 1) (0) | 2026.02.20 |
|---|---|
| Day 31 (12/1) - Spring Boot 전환 및 React Router 동적 라우팅 실습 (0) | 2026.02.20 |
| Day 29 (11/27) - 파이썬 기초 문법 및 리액트 라이프사이클 (0) | 2026.02.20 |
| Day 28 (11/26) - React 기초 개념 및 주요 명령어 정리 (0) | 2026.02.20 |
| Day 26 (11/24) - 팀프로젝트 및 JSP Action 패턴 및 메서드 반환 (0) | 2026.02.20 |