1. 학습 배경
수업 중 강사님께서 Promise와 async/await를 설명해주시는 과정에서 "제이쿼리랑 리액트는 안 맞는다", "Hooks는 클로저를 사용해서 값을 가져오는 거다", "비동기이기 때문에 가능한 로직이다" 등의 말씀을 하셨다. 수업 당시에는 개념들이 파편화되어 헷갈렸는데, 따로 찾아보고 이해한 내용을 하나로 묶어 정리해보고자 한다.
2. jQuery와 React가 서로 맞지 않는 이유
💡 핵심 요약
"DOM(화면 요소)을 다루는 주인(Owner)이 서로 다르기 때문"
🔍 상세 내용
- jQuery (명령형): 개발자가 직접 **실제 DOM(Real DOM)**을 선택하고 변경한다.
- 예: $('#btn').text('클릭됨'); → "버튼을 직접 찾아서 글씨를 바꿔라!"
- React (선언형): **가상 돔(Virtual DOM)**을 사용한다. 변경 사항을 계산한 뒤, 리액트가 알아서 실제 DOM에 반영한다.
- 예: useState로 상태(State)만 바꾸면 리액트가 알아서 화면을 갱신한다.
🚫 왜 같이 쓰면 안 될까?
리액트가 "이 버튼은 내가 관리하는 요소야"라고 알고 있는데, jQuery가 몰래 와서 버튼을 삭제하거나 내용을 바꿔버린다면? 리액트는 해당 요소가 사라졌는지, 변경되었는지 모르기 때문에 에러가 발생하거나 화면이 꼬이게 된다. (마치 쉐프(React)가 요리 중인데 누군가(jQuery) 몰래 와서 재료를 바꿔치기하는 것과 같다.)
✅ 결론
리액트를 사용할 때는 document.getElementById나 jQuery 같은 직접적인 DOM 조작을 피하고, 철저하게 **State(상태)**를 통해 화면을 제어해야 한다.
3. 자바스크립트 클로저 (Closure)
💡 핵심 요약
"함수가 종료되어도 자신이 생성된 환경(변수)을 기억하고 있는 것"
🔍 상세 내용
자바스크립트 함수는 자신이 선언될 때의 **주변 환경(Lexical Scope)**을 기억한다. 외부 함수가 실행이 끝나서 사라져도(Return되어도), 내부 함수는 외부 함수의 변수에 계속 접근할 수 있다.
⚛️ 리액트 수업 때 왜 나왔을까?
리액트의 핵심인 useState, useEffect 같은 Hooks가 전부 클로저의 원리로 만들어졌기 때문이다. 함수형 컴포넌트가 다시 실행(렌더링)되어도 이전 상태값을 기억하는 비결이 바로 클로저다.
💻 코드 예시
function Counter() {
let count = 0; // 이 변수는 외부에서 직접 접근 불가 (은닉화)
return function() {
count++; // 내부 함수가 외부의 count 변수를 기억하고 있음 (클로저)
console.log(count);
}
}
const myCounter = Counter();
myCounter(); // 1
myCounter(); // 2
✅ 결론
useState에서 상태값을 유지하고 갱신할 수 있는 이유는 리액트가 클로저를 통해 그 값을 '기억'하고 있기 때문이다.
4. 동기(Synchronous) vs 비동기(Asynchronous)
💡 핵심 요약
- 동기: 앞의 일이 끝날 때까지 기다렸다가 다음 일을 하는 것 (순차적).
- 비동기: 앞의 일이 오래 걸리면 맡겨두고, 다음 일을 먼저 처리하는 것 (효율적).
🔍 상세 내용
자바스크립트는 기본적으로 한 번에 한 가지 일만 하는 싱글 스레드(Single Thread) 언어다. 하지만 서버 통신이나 파일 읽기 등 오래 걸리는 작업은 비동기로 처리하여 브라우저가 멈추지 않게 한다.
⚛️ 리액트 수업 때 왜 나왔을까?
- State 업데이트 (setState): 리액트의 상태 변경은 비동기적으로 일어난다. 성능을 위해 변경 요청을 모았다가(Batching) 한 번에 처리하므로, setState 직후에 console.log를 찍으면 변경 전의 옛날 값이 나올 수 있다.
- API 호출: 서버에서 데이터를 받아오는 fetch나 axios는 비동기 작업이므로, 이를 제어하기 위해 Promise, async/await 문법을 필수로 알아야 한다.
💻 코드 예시
// 비동기 예시 (리액트의 setState와 비슷)
console.log("1. 주문 받음");
setTimeout(() => {
console.log("2. 요리 완료 (오래 걸리는 작업)");
}, 1000);
console.log("3. 다음 손님 받음");
// 출력 순서: 1 -> 3 -> 2
✅ 결론
리액트에서 데이터 통신을 하거나 상태 관리를 할 때, 실행 순서가 꼬이지 않게 하려면 **비동기 처리 흐름(Event Loop)**을 이해해야 한다.
🚀 요약 및 다음 단계
오늘 정리한 내용은 단순히 이론이 아니라 **"리액트가 버그 없이 돌아가게 하기 위한 핵심 규칙"**들이다.
- jQuery 금지: DOM을 직접 건드리지 말고 State로 해결하자.
- 클로저: Hooks가 상태를 기억하는 원리다.
- 비동기: setState는 즉시 반영되지 않는다. API 호출은 기다려줘야(await) 한다.
이 개념들을 바탕으로 현재 진행 중인 프로젝트의 API 통신 로직을 다시 살펴봐야겠다.
'Archive > TIL' 카테고리의 다른 글
| [TIL] JPA 영속성 전이와 고아 객체: Cascade vs OrphanRemoval 정리 (0) | 2025.12.16 |
|---|---|
| [TIL] REST API 인증과 상태 관리: Session vs Token 정리 (0) | 2025.12.09 |
| [TIL] 리액트 라우팅과 전역 상태 관리: Router & Context API (1) | 2025.12.02 |
| [TIL] 리액트 필수 개념 정리: 콜백 함수, 캡슐화, AJAX (0) | 2025.11.26 |
| 2025.09.26 수업 내용 정리 (0) | 2025.09.26 |