프론트엔드 스터디 11주차: React 기초 2 —.
useEffect로 사이드 이펙트를 다루고, 이벤트 처리와 폼 상태 관리까지 — React로 실제 동작하는 앱을 만들기 위한 핵심 기술을 배웁니다.
학습 챕터: poiemaweb — this / 실행 컨텍스트 / 이터러블
자료 바로가기: 1. this
딥다이브 요약본 (보충용):
이 자료는 1학기 커리큘럼에서 빠진 JS 심화 내용으로, React를 배우다가 this가
헷갈리거나 면접 준비가 필요한 시점에 참고하는 자료입니다.
지금 당장 읽지 않아도 됩니다. 이런 내용이 있다는 것만 알고
넘어가도 좋습니다.
이 자료를 지금 읽을 필요가 없다고 판단되면, 나중에 필요할 때 참고하세요. 아래 문제를 막힘없이 풀 수 있다면 넘어가도 좋습니다.
Post Q&A
프론트엔드 스터디 심화: this, 실행 컨텍스트, 이터러블 전체를 기준으로 질문과 피드백을 받아요.답을 본 뒤에는 이 내용을 댓글로 달아서 서징에게도 물어볼 수 있어요. 작성자가 직접 볼 수 있어요!
JS의 this는 함수가 호출될 때 동적으로 결정됩니다. 선언
위치가 아니라
호출 방식에 따라 다릅니다. (화살표 함수만 예외)
// 1. 일반 함수 호출 — 전역 객체 (strict mode에서는 undefined)
function foo() {
console.log(this); // window (브라우저)
}
foo();
// 2. 메서드 호출 — 호출한 객체
const obj = {
name: "철수",
greet() {
console.log(this.name); // "철수"
},
};
obj.greet();
// 3. 생성자 호출 — 새로 생성되는 인스턴스
function Person(name) {
this.name = name; // 새 인스턴스를 가리킴
}
const p = new Person("영희");
// 4. 명시적 바인딩 — call / apply / bind
function greet() {
console.log(this.name);
}
greet.call({ name: "민수" }); // "민수"
greet.apply({ name: "지수" }); // "지수"
const boundGreet = greet.bind({ name: "하준" });
boundGreet(); // "하준"const timer = {
name: "타이머",
start() {
// 일반 함수 — this가 전역으로 바뀜
setTimeout(function () {
console.log(this.name); // undefined
}, 1000);
// 화살표 함수 — 상위 스코프(start 메서드)의 this 유지
setTimeout(() => {
console.log(this.name); // "타이머"
}, 1000);
},
};
timer.start();React에서 이벤트 핸들러를 화살표 함수로 쓰는 이유도 이 때문입니다. 클래스
컴포넌트에서 this.handleClick = this.handleClick.bind(this)처럼 bind를 쓰는
것도 같은 문제를 해결하는 방법입니다.
실행 컨텍스트는 코드가 실행될 때 JS 엔진이 생성하는 환경 정보 묶음입니다. 스코프, 호이스팅, 클로저, this가 모두 실행 컨텍스트 안에서 관리됩니다.
const x = "전역";
function outer() {
const y = "outer";
function inner() {
const z = "inner";
console.log(x, y, z); // 스코프 체인으로 탐색
}
inner();
}
outer();
// 콜 스택의 변화:
// 1. 전역 실행 컨텍스트 생성 (x 등록)
// 2. outer() 호출 → outer 실행 컨텍스트 생성 (y 등록)
// 3. inner() 호출 → inner 실행 컨텍스트 생성 (z 등록)
// 4. inner 종료 → inner 컨텍스트 제거
// 5. outer 종료 → outer 컨텍스트 제거각 실행 컨텍스트는 외부 렉시컬 환경에 대한 참조를 가지며, 이것이 스코프 체인과 클로저의 실제 구현 방식입니다.
Symbol.iterator 메서드를 가진 객체는 이터러블입니다. for...of,
스프레드(...), 구조 분해 할당이 내부적으로 이터러블 프로토콜을 사용합니다.
// 배열, 문자열, Map, Set — 모두 이터러블
for (const char of "hello") {
console.log(char); // h, e, l, l, o
}
const [a, b, ...rest] = new Set([1, 2, 3, 4]);
// a=1, b=2, rest=[3, 4]// 중복 제거
const arr = [1, 2, 2, 3, 3, 4];
const unique = [...new Set(arr)]; // [1, 2, 3, 4]
// 기본 사용
const set = new Set([1, 2, 3]);
set.add(4);
set.has(2); // true
set.delete(1);
set.size; // 3
// 집합 연산
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
const union = new Set([...a, ...b]); // {1, 2, 3, 4}
const intersection = new Set([...a].filter((x) => b.has(x))); // {2, 3}// 일반 객체와 달리 어떤 타입이든 키로 사용 가능
const map = new Map();
map.set("name", "철수");
map.set(1, "숫자 키");
map.set({ id: 1 }, "객체 키");
map.get("name"); // "철수"
map.has("name"); // true
map.size; // 3
// 이터러블이라 for...of 가능
for (const [key, value] of map) {
console.log(key, value);
}
// 객체 → Map 변환
const obj = { a: 1, b: 2 };
const mapFromObj = new Map(Object.entries(obj));아래 코드를 브라우저 콘솔에서 직접 실행해보고 결과를 입력해보세요.
const obj = {
value: 10,
double: function () {
return this.value * 2;
},
doubleArrow: () => {
return this.value * 2;
},
};
console.log(obj.double());
console.log(obj.doubleArrow());다음 상황에서 이 자료로 돌아오세요.
this 관련: React 클래스 컴포넌트를 읽거나, 이벤트 핸들러에서 this가 예상과 다르게 동작할 때
실행 컨텍스트: 면접에서 "호이스팅과 클로저의 원리를 설명하라"는 질문을 받았을 때
Set/Map: 중복 제거, 빠른 조회가 필요한 데이터 구조가 필요할 때 (지금 바로 써도 됩니다!)
이터러블: 커스텀 이터레이터를 만들거나, for...of 동작 원리가 궁금할 때
지금 당장 읽지 않아도 됩니다. React를 배우면서 에러 처리가 필요해지거나 면접 대비가 필요할 때 참고하세요.