24.08.28_TIL (프론트엔드 예상 면접 질문)
5. useEffect vs useCallback
useEffect는 리액트에게 "어떤 일이 일어나면 이걸 해줘!"라고 말하는 방법, useCallback은 리액트에게 "이 일을 기억해 둬!"라고 말하는 방법이다. useEffect는 컴포넌트의 생명주기에 맞춰 특정작업을 수행하고자 할 때 쓰고, useCallback은 메모제이션하여 컴포넌트가 불필요하게 다시 렌더링되는 것을 방지하고 성능 최적화를 위해 사용된다.
useEffect(() => {
console.log("이제 물 줄 시간이에요!");
}, []); // 여기서는 "아침마다"라는 규칙이 설정된 거예요.
const 기억해둔일 = useCallback(() => {
console.log("이건 계속 같은 일이에요!");
}, []); // 여기서는 "이 일을 기억해둬!"라고 리액트에게 말하고 있어요.
6. var, const, let 키워드의 차이점
- var: 함수 범위, 변수 호이스팅, 재선언 가능, 재할당 가능.
- let: 블록 범위, 변수 호이스팅(일시적 사각지대), 재선언 불가, 재할당 가능.
- const: 블록 범위, 변수 호이스팅(일시적 사각지대), 재선언 불가, 재할당 불가 (객체 내부 변경은 가능).
1. var: 자유롭게 돌아다니는 친구
- var는 우리 친구들 중에서 어디든 자유롭게 돌아다닐 수 있는 친구예요. 그래서 var로 선언된 변수는 블록({ }) 안에 있더라도, 그 블록 밖에서도 여전히 쓸 수 있어요.
var myName = "Alice";
if (true) {
var myName = "Bob";
}
console.log(myName); // Bob (블록 밖에서도 바뀐 이름을 쓸 수 있어요!)
2. let: 정해진 장소에서만 노는 친구
- let은 어디든 돌아다니는 게 아니라, 정해진 장소에서만 노는 친구예요. 만약 let이 블록 안에서 선언되었다면, 그 블록 안에서만 놀 수 있어요. 블록 밖으로 나가면 그 친구를 찾을 수 없어요.
let myAge = 10;
if (true) {
let myAge = 12;
console.log(myAge); // 12 (블록 안에서만 쓸 수 있어요!)
}
console.log(myAge); // 10 (블록 밖에서는 원래 값만 보일 뿐이에요)
3. const: 절대 변하지 않는 친구
- const는 약속을 잘 지키는 친구예요. 이 친구는 한 번 이름을 정하면 절대 바꾸지 않아요. 만약 "너는 오늘부터 내 이름은 Charlie야!"라고 정하면, 영원히 Charlie예요. 하지만 만약 이 친구가 좋아하는 과자 목록을 가지고 있다면, 그 목록에 새로운 과자를 추가하거나 바꿀 수는 있어요.
const myFavoriteColor = "blue";
// myFavoriteColor = "red"; // 이렇게 바꾸려고 하면 에러가 나요!
const mySnacks = ["chips", "candy"];
mySnacks.push("cookies"); // 과자는 추가할 수 있어요!
console.log(mySnacks); // ["chips", "candy", "cookies"]
7. 호이스팅이란?
- 코드를 쓸 때 변수나 함수가 선언되기 전에 사용할 수 있도록 자바스크립트가 그 선언을 코드의 맨 위로 끌어올려 주는 것.
- 선언이 안되면 에러가 나야하지만 나중에 선언이 되더라도 이미 함수나 변수를 저장하고 있기 때문에 나중에 찾겠다고 undefined를 출력하고 나서 나중에 찾겠다고 함.
- https://www.youtube.com/watch?v=fETYLCU2YYc
- 호이스팅(Hoisting)은 자바스크립트에서 변수와 함수의 선언이 해당 스코프의 최상단으로 끌어올려지는 동작을 의미합니다. 이를 통해 변수를 선언하기 전에 참조할 수 있습니다.
- 변수 호이스팅: 변수 선언이 스코프의 최상단으로 이동하지만, var로 선언된 변수는 초기화가 함께 이동하지 않습니다. 따라서 선언 전에 접근하면 undefined를 반환합니다. let과 const로 선언된 변수는 호이스팅되지만, 초기화 전에는 접근할 수 없으며, 이를 "Temporal Dead Zone"이라고 합니다.
- 함수 호이스팅: 함수 선언문으로 정의된 함수는 스코프의 최상단으로 호이스팅되며, 선언 전에 호출이 가능합니다. 하지만 함수 표현식은 변수 호이스팅의 영향을 받습니다.
console.log(hoistedVar); // undefined var hoistedVar = 'I am hoisted!'; hoistedFunc(); // "I am a function!" function hoistedFunc() { console.log('I am a function!'); }
8. 클로저란?
클로저(Closure)는 자바스크립트에서 **함수가 자신이 선언된 환경(스코프)**을 기억하고, 그 환경에 있는 변수에 접근할 수 있는 기능을 말합니다.
특징:
- 외부 함수 변수 접근: 내부 함수가 외부 함수의 변수에 접근할 수 있습니다.
- 상태 유지: 외부 함수가 종료된 후에도, 내부 함수가 외부 변수의 상태를 유지합니다.
function outer() {
let count = 0;
return function() {
count++;
console.log(count);
};
}
const increment = outer();
increment(); // 1
increment(); // 2
https://enjoydev.life/blog/javascript/6-closure
간단한 비유:
생각해보세요. 우리가 상자를 가지고 있는데, 이 상자 안에는 작은 공이 들어있어요. 그리고 이 상자는 마법의 상자예요. 누군가 상자를 열어서 공을 꺼내기 전까지, 그 공은 상자 안에서 계속 자라날 수 있어요.
클로저 설명:
- 상자: 함수(어떤 일을 하는 작은 프로그램 조각)
- 공: 함수 안에 있는 변수(숫자, 글자 등)
- 마법의 상자: 클로저
이 마법의 상자(클로저)는, 그 안에 들어있는 공(변수)이 계속 기억되고, 자라날 수 있게 해줘요.
예시:
여기서 숫자세기는 그 마법의 상자(클로저)예요. 숫자세기()를 할 때마다, 숫자가 1씩 커지죠. 중요한 건, 숫자세기가 그 숫자를 계속 기억하고 있는 거예요!
이처럼 클로저는 어떤 함수가, 그 함수가 만들어졌을 때 주변에 있었던 것들을 기억할 수 있게 해주는 마법의 상자라고 생각하면 돼요!
9. Redux와 Zustand 비교
- Redux 사용 사례: Facebook, Netflix, Airbnb 등 대규모 애플리케이션에서 상태 관리를 수행합니다.
- Zustand 사용 사례: Khan Academy, New York Times, Figma 등에서 사용되며, 개발자들은 Zustand의 사용의 용이성과 빠른 성능을 강점으로 하지만, 기능 제한과 작은 커뮤니티 크기를 단점으로 꼽습니다.
Redux와 Zustand는 둘 다 자바스크립트 애플리케이션에서 상태 관리를 위한 라이브러리입니다.
- Redux는 대규모 애플리케이션에서 예측 가능성과 복잡한 상태 관리를 필요로 할 때 적합하며, 철저한 상태 추적과 디버깅을 중시하는 경우에 추천됩니다.
- Zustand는 간단하고 빠르게 상태 관리를 구현하고 싶을 때, 또는 중소규모 애플리케이션에서 유연한 상태 관리가 필요할 때 적합합니다.
1. 설계 철학
- Redux:
- 예측 가능성을 중시하며, 중앙 집중식 상태 관리를 통해 애플리케이션의 상태 변화를 추적하고 디버깅을 용이하게 합니다.
- Flux 아키텍처를 기반으로 하며, 상태 변경은 항상 **순수 함수(reducer)**를 통해 일어나야 합니다.
- 불변성을 중요하게 생각합니다. 상태를 직접 변경하는 대신, 상태의 사본을 만들어서 반환합니다.
- Zustand:
- 간결하고 직관적인 상태 관리를 목표로 합니다. 상태를 관리하는 데 필요한 설정이 최소화되어 있습니다.
- 상태를 액션과 분리하지 않고, 상태와 동작을 하나의 스토어에서 함께 관리합니다.
- React 훅을 기반으로 설계되어 있으며, 애플리케이션의 특정 부분에서만 상태를 관리하고 싶을 때 유용합니다.
2. API와 사용 편의성
- Redux:
- 설정이 상대적으로 복잡합니다. 스토어(store) 생성, 리듀서(reducer) 작성, 액션(action) 정의 등 여러 단계가 필요합니다.
- 미들웨어(예: redux-thunk, redux-saga)를 사용하여 비동기 작업을 처리해야 합니다.
- Redux Toolkit을 사용하면 설정이 단순해지지만, 여전히 비교적 복잡한 구조를 유지합니다.
- Zustand:
- 설정이 매우 간단합니다. 한 줄로 스토어를 생성할 수 있으며, 리듀서나 액션을 명시적으로 정의할 필요가 없습니다.
- 비동기 작업도 기본적인 자바스크립트나 React 훅을 통해 쉽게 처리할 수 있습니다.
- 코드가 직관적이고 적은 양으로 상태 관리를 구현할 수 있습니다.
3. 규모와 확장성
- Redux:
- 대규모 애플리케이션에 적합합니다. 상태 관리가 복잡해질수록 Redux의 예측 가능성과 디버깅 기능이 유리합니다.
- Redux DevTools와 같은 도구를 통해 상태 변화를 추적하고 디버깅할 수 있습니다.
- Zustand:
- 소규모에서 중간 규모의 애플리케이션에 적합합니다. 간단한 상태 관리가 필요할 때 효율적입니다.
- 대규모 애플리케이션에서도 사용할 수 있지만, 복잡한 상태 관리에는 상대적으로 덜 적합할 수 있습니다.
4. 커뮤니티와 에코시스템
- Redux:
- 매우 큰 커뮤니티와 다양한 미들웨어, 플러그인, DevTools 등을 제공합니다.
- 많은 개발자와 기업에서 사용하기 때문에 풍부한 학습 자료와 지원을 받을 수 있습니다.
- Zustand:
- Zustand도 빠르게 인기를 얻고 있지만, Redux에 비해 커뮤니티와 에코시스템은 상대적으로 작습니다.
- 그러나 React의 훅 기반 구조와 결합되어 있어 React 애플리케이션에서 직관적으로 사용할 수 있습니다.
5. 성능
- Redux:
- 불변성 유지와 관련된 작업 때문에, 특히 대규모 상태 트리를 가진 애플리케이션에서는 성능 최적화가 필요할 수 있습니다.
- 리덕스는 필요한 경우 특정 부분만 리렌더링되도록 최적화할 수 있지만, 설정이 복잡할 수 있습니다.
- Zustand:
- 내부적으로 분할된 상태와 구독 시스템을 사용하여 필요한 부분만 업데이트합니다. 성능 최적화가 기본적으로 내장되어 있어 성능이 매우 효율적입니다.
- 상태 변화에 따라 최소한의 리렌더링이 발생합니다.