counter/06/ 와 counter/07 차이점| 항목 | counter/06/index.js | counter/07/index.js |
|---|---|---|
| console.log | 없음 | Header, Counter, App 함수 호출 시 로그 출력 |
| 상태 관리 방식 | 지역 변수 count 사용 후, 이벤트 핸들러 내에서 document.querySelector(...).textContent로 DOM 직접 업데이트 | Reaction.useState 훅으로 상태 저장, setCount 호출 시 내부적으로 자동 리렌더링 |
| 이벤트 핸들러 | handleDown/handleUp/handleReset에서 직접 count 조작 후 수동으로 텍스트 갱신 | 동일한 핸들러 이름 사용하나, 내부에서는 setCount만 호출해 리렌더링에 위임 |
| 렌더링 동작 | 최초 렌더링 이후 상태 변경 시 수동 업데이트 필요 | 상태 변경 시 컴포넌트 전체가 자동으로 재 렌더링 |
| 항목 | counter/06/reaction.js | counter/06/reaction.js |
|---|---|---|
| 전역 변수 선언 | 전역 상태 변수 없음 | _root, _stateValue 전역으로 선언 |
| createRoot 구현 | render(appFn) 호출 시 단순히 appendChild(appFn()) 실행 | 컴포넌트 함수 캐싱 (_appComponent = _appComponent **??** appFn)기존 자식 제거 ( firstChild?.remove()) 후 재렌더 |
| 상태 관리 (useState) | 없음 | useState(initialValue) 구현_stateValue 보관 및 setValue 호출 시 render() 트리거 |
| 상태 초기화 방식 | 해당 없음 | _stateValue = _stateValue ?? initialValue |
| 렌더링 동작 | 최초 렌더만 지원 | 상태 변경 감지 시 (Object.is 비교 후) render() 재호출 |
|| 논리 OR 연산자
false, 0, "", null, undefined, NaN) → 오른쪽으로 대체?? (Nullish Coalescing) 연산자 (null 병합 연산자)
null 또는 undefined일 때만 → 오른쪽으로 대체false, 0, "", NaN 등은 유효한 값으로 그대로 유지예시보기
function test(val) {
const initial = "기본값";
console.log(val || initial, " ← || 결과");
console.log(val ?? initial, " ← ?? 결과");
}
test(false); // 기본값 ← || , false ← ??
test(0); // 기본값 ← || , 0 ← ??
test(""); // 기본값 ← || , "" ← ??
test(null); // 기본값 ← || , 기본값 ← ??
test(undefined); // 기본값 ← || , 기본값 ← ??
| 구분 | todolist/06/index.js | todolist/07/index.js | todolist/08/index.js |
|---|---|---|---|
| 주요 목적 | 단일 App 함수로 Reaction.createElement() 활용한 UI 구성 | UI를 기능별 컴포넌트 함수로 분리 | useState 도입으로 상태 변경 시 화면 리렌더링 |
| 컴포넌트 구조 | App 하나만 정의 | Header, Todo, Footer, TodoItem, TodoInput, TodoList 분리 | 07과 동일한 분리 + 각 컴포넌트에 props/state 적용 |
| TodoItem 정의 | App 내 하드코딩 | 인자 없는 재사용 함수 | { item } 파라미터 받아 동적 데이터 렌더링 |
| TodoList 구현 방식 | App에서 static 요소 하드코딩 | Reaction.createElement("ul",…, TodoItem)로 함수 참조 전달 | itemList.map(item => TodoItem({ item }))로 리스트 매핑 |
| 상태 관리 | 없음 | 없음 | const [itemList, setItemList] = Reaction.useState(inititemList) |
| 이벤트 처리 및 props | 없음 | 없음 | TodoInput에 handleAddKeydown, handleAdd props로 전달, onkeydown/onclick 설정 |
| 동적 기능 | 없음 | 없음 | 아이템 추가(addItem), 삭제(deleteItem), 완료 토글(toggleDone) 기능 포함 |
| 파일 경로 표시 방식 | location.href.split("/ch")[1] 하드코딩 | 동일 | 동일 |
- 초기 값 및 Reaction 유틸 불러오기
- `inititemList`에 기본 할 일 배열을 정의
- `Reaction.useState` 훅을 통해 `itemList` 상태와 갱신 함수 `setItemList`를 선언
- Header 컴포넌트
- 앱 제목과 현재 파일 경로를 `<h1>`/`<span id="filepath">`로 표시
- `location.href.split("/ch")[1]` 로 URL에서 파일명만 추출
- TodoInput 컴포넌트
- 텍스트 입력창(`input`)과 추가 버튼(`button`)을 렌더링
- 두 가지 이벤트 핸들러를 props로 받음
- `handleAddKeydown` : 입력창에서 Enter 키 누르면 호출
- `handleAdd` : 추가 버튼 클릭 시 호출
- TodoItem 컴포넌트
- 개별 할 일 객체를 props로 받아서 `<li>`로 출력
- 클릭하면 완료 상태 전환(`toggleDone`), 옆의 삭제 버튼 클릭 시 해당 항목 삭제(`deleteItem`)
- TodoList 컴포넌트
- `itemList` 배열을 `map`으로 순회하며
- 각 요소를 `TodoItem({ item })` 형태로 렌더링
- Footer 컴포넌트
- 간단한 저작권 또는 추가 정보 표시
- App 컴포넌트 전체 구성
- 위의 컴포넌트들을 한데 모아 루트 `<div>` 안에 렌더링
- 상태 조작 함수 정의
- `addItem(title)` : 새 아이템 객체를 `itemList`에 추가
- `deleteItem(num)` : 필터링으로 해당 아이템 제거
- `toggleDone(num)` : 클릭된 아이템의 num을 조회한 후 `done` 속성 토글
- `handleAddKeydown(e)` : Enter 키일 때 `addItem` 호출
- `handleAdd()` : 버튼 클릭 시 `addItem` 호출
- 이들 함수를 `TodoInput`, `TodoItem` 등에 props로 전달
- DOM에 붙이기
- `document.querySelector("#root")` 로 루트 요소 선택
- `Reaction.render(App(), root)` 또는 `root.appendChild(App())` 호출해 화면에 표시
- 사용자 상호작용 흐름
- 페이지 로드 → `inititemList` 기반 렌더링
- 입력창에 텍스트 입력 후
- Enter 누르거나 추가 버튼 클릭 → `addItem` → `setItemList` → 자동 리렌더링
- 각 할 일 항목 클릭 시 `toggleDone` → 시각적 스타일 변경
- 삭제 버튼 클릭 시 `deleteItem` → 해당 항목 제거 → 리렌더링
┌───────── App ──────────┐ ← 최상위 컴포넌트
│ │ │
Header Todo Footer ← 주요 섹션 컴포넌트들
│
┌───┴────┐ ← Todo 내부 구조
TodoInput TodoList ← 입력부와 목록부
│
TodoItem ← 개별 할일 아이템
App() ← 최상위 함수 (파라미터 없음)
├─ addItem(title) ← 새 아이템 추가 함수 (text: string)
├─ deleteItem(num) ← 아이템 삭제 함수 (id: string)
├─ toggleDone(num) ← 완료 토글 함수 (id: string)
├─ handleAddKeydown(e) ← 엔터 키 이벤트 핸들러 (e: KeyboardEvent)
├─ handleAdd() ← 추가 버튼 클릭 핸들러 (파라미터 없음)
├─ Header() ← 헤더 컴포넌트 함수 (파라미터 없음)
├─ TodoInput( ← 입력부 컴포넌트
│ {
│ handleAddKeydown, ← props.handleAddKeydown: function
│ handleAdd ← props.handleAdd: function
│ })
├─ TodoList( ← 목록부 컴포넌트
│ { itemList } ← props.itemList: array of Todo 객체
│ )
│ └─ TodoItem( ← 개별 할일 아이템 컴포넌트
│ { item } ← props.item: Todo 객체
│ )
└─ Footer() ← 푸터 컴포넌트 함수 (파라미터 없음)
Counter
todoList
App 함수reaction REACT를 흉내낸 reaction.js