December 3, 2021 • ☕️ 7 min read
새로운 시작 | 함수형 프로그래밍 | ES6의 블록 스코프
🍀 여기서 읽기
자바스크립트의 스코프는 ES6 이후 세 가지로 구분된다.
여기서 전역 스코프와 함수 스코프는 익숙하다. 코드가 처음 실행되거나, 함수가 호출되어 함수 구문에 진입했을 때 각각 전역/함수 실행 컨텍스트가 생성되고 스코프가 형성된다.
블록 스코프는 어떻게 동작할까?
전역/함수 실행 컨텍스트와 비교를 통해 알아보자. (전역/함수 실행 컨텍스트의 동작 원리는 비슷하므로, 하나로 취급할 것이다.)
var apple = "apple";
if (true) {
var apple = "banana";
console.log(apple); // banana
}
console.log(apple); // banana
전역 실행 컨텍스트에서는 하나의 변수 환경(Variable Environment)이 생성되므로, 두 번째로 선언한 apple
은 첫 번째 apple
을 덮어씌운다. 전역 실행 컨텍스트의 스코프에서 apple
은 banana
의 값을 갖게 된다.
블록 스코프는 어떨까?
var apple = "apple";
if (true) {
let apple = "banana";
console.log(apple); // banana
}
console.log(apple); // apple
첫 번째 선언한 apple
은 apple
의 값으로 남게 되고, if문(블록) 안에 let
으로 선언한 apple
만 banana
값을 갖는다.
전역 실행 컨텍스트가 생성될 때, 자바스크립트 엔진은 두 번째 apple
을 두 가지 이유로 건너뛰게 된다.
let
으로 선언된 변수기 때문에전역에 var
로 선언된 변수에는 apple
값이 할당되어 있다. 그러나 코드가 if문(블록)에 진입하면, 중첩 컴파일링이 시작된다. 이때 if문 안의 apple
은 변수 환경(Variable Environment)이 아닌 렉시컬 환경(Lexical Environment)에 추가된다.
렉시컬 환경은 스택과 같은 자료구조로 변수들을 관리하기 때문에, let
으로 여러번 선언한 변수들은 서로 다르게 관리될 수 있다.
var apple = "global apple";
let banana = "global banana";
{
let banana = "block banana";
var grape = "global grape";
let orange = "block orange";
console.log(apple); // global apple
console.log(banana); // block banana
}
console.log(banana); // global banana
console.log(grape); // global grape
console.log(orange); // 🚨 ReferenceError: orange is not defined
따라서 위 코드에서 전역에 생성된 banana
와, 블록에 생성된 banana
는 각각 독립적인 값을 유지할 수 있게 된다.
ES5까지는 오직 함수 스코프를 따르는 var
키워드로 변수를 선언하는 방법밖에 없었다. 그러나 ES6에 등장한 let
, const
키워드를 사용하여 블록 스코프에서 변수를 관리할 수 있게 되었다. 렉시컬 환경에서 관리되는 변수의 특성을 잊지 말자!
뻔하디 뻔한(?) 리액트 앱 성능 개선에 관한 글을 읽다가, Virtualized List라는 것에 대해 알게 됐다. 어디서 들어본 것 같기는 한데… 아무래도 어디서 들었는지 모르겠다. 알아보자.
List나 Grid와 같은 View가 있을 때, 엄청나게 많은 수의 아이템을 렌더링해야 한다면 스크롤을 내릴 때 렉이 걸릴 것이다. Virtual Rendering을 사용한다면 단지 아이템의 일부분만 렌더링할 수 있어, 성능상의 큰 개선을 이룰 수 있다.
react-virtualized 라이브러리를 사용할 수도 있지만, react-virtualized 공식 레포에서는 조금 더 가벼운 버전인 react-window로 시작해보는 것을 추천하고 있다.
react-virtualized 라이브러리의 기본적인 사용법은 아래와 같다.
import { List, AutoSizer } from "react-virtualized";
const InfiniteScroll = () => {
return (
<AutoSizer>
{({ height, width }) => (
<List
height={height}
rowCount={list.length}
rowHeight={20}
rowRenderer={rowRenderer}
width={width}
/>
)}
</AutoSizer>
);
};
이런 느낌?
AutoSizer
라는 HoC로 단일 자식 컴포넌트의 width와 height를 자동으로 조절한다. 제한된 범위 내에서 화면상에 보이는 아이템들만 실제로 렌더링하는 것 같다.
AutoSizer
의 자식인 List
는 window된 아이템의 리스트를 렌더링한다. 내부적으로 Grid
를 사용하여 행을 나열한다. 실제 아이템 각각은 List
의 어트리뷰트인 rowRenderer
를 사용하여 렌더링한다.
function rowRenderer({ index, isVisible, key, style }) {
const user = list[index];
const content = isScrolling ? "..." : <User user={user} />;
return (
<div key={key} style={style}>
{content}
</div>
);
}
windowing은 목록을 가상화한다는 의미다. virtualize와도 같은 의미다. 사용자에게 실제로 보이지 않은 컴포넌트는 렌더링하지 않고 영역만 차지하고 있다가, 스크롤을 내리면 비로소 해당 위치에 있는 컴포넌트를 렌더링해서 보여주는 방식이다.
다음에는 virtualized list를 사용해서 인피니티 스크롤을 구현해봐야겠다.
Ref https://javascript.plainenglish.io/react-app-performance-optimization-the-definitive-guide-9b658be3b6e4 https://github.com/bvaughn/react-virtualized https://github.com/bvaughn/react-window https://velog.io/@kimjh96/react-virtualized-렌더링-성능-최적화
수요일은 팰린드롬 데이였다. 앞뒤가 정확히 대칭인 이런 날이 작년 2월, 그니까 20200202에도 한번 있었는데, 그때만큼의 희열(!)은 아니지만 언제 또 이런 날짜가 다시 올까. 근데 이런 것에 그만 의미 부여하자. 유치해
피들리라는 좋은 사이트가 있다!
Ref https://www.youtube.com/watch?v=XEt09iK8IXs&feature=youtu.be
우아한테크코스를 수료한 이후, ‘우테코 n주차 기록’이 아닌 오롯이 나를 위한 12월 첫주차 기록이다. 한 해의 마지막인 12월, 그 달의 첫 주가 지나간다. 그래도 다시 정신 차리고 뭐라도 하고 있다. 알고리즘 스터디도 다시(그치만 혼자), 타입스크립트 이펙티브 스터디도 시작하고, 크루들과 함께하는 유캔두도 시작했다. 건강한 SNS 보는 기분. 재밌다.
우테코 4기에 지원한 분들은 프리코스를 진행하고 있다. 괜히 궁금해서 레포에 들어가봤는데, 이미 다들 엄청난 실력과 스펙을 보유하고 계신다. 이미 나보다 잘하는 분들도 많다. 우테코 3기로 활동할 수 있어서 참 다행이다(?)
그리고 아직도 많은 회사들에선 연락이 없다. 숨막힌다 정말 😞 빨리 다시 코딩하고 싶다. React Native로 뭘 만들지 기획까지 해놓고서, 진도를 나가고 있지 못하다. 아이패드 에어 사서 일러스트 강의 들어야지. 갑자기 폴라로이드도 꽂혀서 중고 뒤지고 있는 중. 물욕 장난 아니다. 그치만 뭐라도 욕심이 있어서 다행이다.