March 25, 2022 • ☕️☕️☕️ 13 min read
첫 판교 드라이브
React 18 미만에서 사용자 이벤트에 대한 상태 변경은 일괄처리(Batching)되었다. 즉 일반적인 핸들러 내에서는 setState
를 여러번 호출하더라도 일괄적으로 처리되어 리렌더링이 한번만 발생했다.
그러나 Promise
나 setTimeout
으로 발생하는 상태 변경은 일괄처리되지 않았다. setTimeout
에서 setState
를 두 번 호출하면 두 번 렌더링되었던 것이다.
React 18에서는 상태 변경이 발생한 원인에 상관없이 모든 상태 변경은 일괄처리된다.이때, 의도적으로 일괄처리하지 않으려면 flushSync
를 사용하면 된다.
Ref https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#automatic-batching
useImperativeHandle
useImperativeHandle
은 ref
를 사용할 때 부모 컴포넌트에 노출되는 인스턴스 값을 사용자화(customizes)합니다. forwardRef
와 함께 쓸 수 있는 hook이다.
부모 컴포넌트가 자식 컴포넌트 내의 DOM에 접근하고 싶을 때, 자식 컴포넌트에서 forwardRef
를 통해 넘겨받은 ref
를 특정 DOM에 지정할 수 있다. 이때, 자식 컴포넌트에서 부모 컴포넌트에 노출하고 싶은 ref
에 대한 인스턴스를 커스터마이징하고 싶다면 useImperativeHandle
hook을 통해 정의할 수 있다. 즉 부모 컴포넌트로부터 forwarding된 ref
를 재정의하는 것이다.
// 자식 컴포넌트
function FancyInput(props, ref) {
// 자식 컴포넌트의 ref를 새롭게 생성한 뒤,
// useImperativeHandle의 두 번째 인자로 들어가는 함수 바디에서 사용한다.
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
부모 컴포넌트는 자식의 DOM에 직접 접근하는 것이 아니라, useImperativeHandle
로 전달된 메서드에만 접근이 가능해진다. 이로써 더욱 컴포넌트 간의 독립성을 보장할 수 있게 된다.
‘imperative’는 ‘반드시 해야 하는’, ‘긴요한’이라는 뜻이라고 한다. 뭐가 그렇게 긴요했을까. 이름만 봐서는 예측하기가 어렵다. 토스의 김 모 개발자에 의하면, ‘명령적이다’라는 뜻도 있다고 한다. 😑
Ref https://ko.reactjs.org/docs/hooks-reference.html#useimperativehandle https://kelly-kh-woo.medium.com/react-hook-useimperativehandle-89fee716d80
TypeScript의 enum
은 서로 연관된 상수들을 하나로 관리하기 위해 사용한다.
enum COLOR {
RED,
BLUE,
GREEN,
}
let red = COLOR.RED;
위 코드를 babel로 컴파일하면 결과는 아래와 같다.
var COLOR;
(function (COLOR) {
COLOR[(COLOR["RED"] = 0)] = "RED";
COLOR[(COLOR["BLUE"] = 1)] = "BLUE";
COLOR[(COLOR["GREEN"] = 2)] = "GREEN";
})(COLOR || (COLOR = {}));
var red = COLOR.RED;
enum
은 즉시 실행 함수 ((function())()
의 형태)로 컴파일된다. 따라서 트리셰이킹(tree-shaking)이 불가능하다.
enum
에 const
를 붙인 const enum
은 그냥 enum
과 조금 다르게 동작한다.
const enum COLOR {
RED,
BLUE,
GREEN,
}
let red = COLOR.RED;
const enum
을 babel로 컴파일하면 결과는 아래와 같다.
let red = 0;
const enum
은 일반적인 enum
과 달리 컴파일 과정에서 완전히 제거되고, 값에 해당하는 상수만 남는다. 트리셰이킹이 되기 때문에 용량 측면에서 그냥 enum
보다 낫다고 할 수 있지만, TypeScript 사용 시 패키지 등에서 const enum
을 사용한다면 값이 상수로 치환되어버리기 때문에 타이핑이 불가능해진다는 단점이 있다.
이때는 일반 객체에 as const
를 사용하는 방식으로 enum
을 대체할 수 있다.
const COLOR = {
RED: 0,
BLUE: 1,
GREEN: 2,
} as const;
as const
는 타입 단언(type assertion)의 한 종류로써 리터럴 타입의 추론 범위를 줄이고 값의 재할당을 막아준다. enum
을 흉내낼 수 있으며, 컴파일 후에 용량도 enum
보다 작은 편이다.
Ref https://velog.io/@logqwerty/Enum-vs-as-const https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/ https://darrengwon.tistory.com/1310
docker는 linux 기반의 가상환경으로, VM(virtual machine)과는 뚜렷한 차이점이 있다.
VM은 일종의 x86 하드웨어를 가상화한 형태다. VM 위에 다양한 종류의 OS를 설치할 수 있다.
docker container는 하드웨어를 가상화하지 않고, Host OS에서 Guest OS를 isolation해주는 형태다. 다양한 종류의 OS에서 사용 가능한 VM과 달리, docker container는 linux 기반 OS에서만 수행할 수 있다.
이는 docker container 자체에는 kernel 등의 OS 이미지가 들어가 있지 않기 때문이다. kernel은 host OS의 kernel을 그대로 사용하기 때문에 container에서 명령어를 수행하면 실제로는 host OS에서 수행된다. host OS와 container OS에의 diff만 container에 같이 패키징하는 개념이다.
Ref https://bcho.tistory.com/805
datalist
태그datalist
태그는 다른 컨트롤에서 고를 수 있는 가능한, 혹은 추천하는 선택지를 나타내는 <option>
요소들을 담는다.
select
태그와 유사한 기능을 제공하지만, option으로 지정된 값 외에도 직접 타이핑하여 값을 입력할 수 있다는 점에서 특징적이다. 그래서 주로 input
태그와 함께 많이 쓰인다.
<label for="ice-cream-choice">Choose a flavor:</label>
<input list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice" />
<datalist id="ice-cream-flavors">
<option value="Chocolate">
<option value="Coconut">
<option value="Mint">
<option value="Strawberry">
<option value="Vanilla">
</datalist>
타이핑 중에 자동완성 기능을 통해 option list에 존재하는 매칭되는 결과를 보여주기 때문에 더욱 멋지다!
Ref https://developer.mozilla.org/ko/docs/Web/HTML/Element/datalist
.toPrecision(number)
.toPrecision(number)
은 JavaScript의 내장 메서드로, 앞에서부터 센 number의 자릿수 기준으로 반올림을 한다.
const num = 185;
num.toPrecision(1); // '2e+2'
num.toPrecision(2); // '1.9e+2'
반환값의 타입이 number가 아닌 string임에 주의하자!
그리고 소수점을 위한 .
이 들어갈 수 있기 때문에, 넘버 리터럴의 메소드 호출엔 .
을 두 개 사용해야 한다.
185.toPrecision(1) = ‘2e+2’; // 🚨 SyntaxError: Identifier directly after number.
185..toPrecision(1) = ‘2e+2’
Git 2.23 버전에서 checkout
명령어를 대신하는 switch
, restore가
새로 나왔다. (꽤 됐다..)
변경한 이유는 checkout 명령어가 가진 기능이 너무 많기 때문에 switch
, restore
로 분리했다.
checkout
: Switch branches or restore working tree filesswitch
: Switch branchesrestore
: Restore working tree filesmouseover
vs mouseenter
mouseover
는 직접 이벤트를 걸지않은 자식요소에 마우스 포인터가 와도 발생하지만 mouseenter
는 오로지 자기 자신에게 마우스 포인터가 와야만 발생한다.
mouseover
는 mouseout
과 짝꿍, mouseenter
는 mouseleave
와 짝꿍이다.
setState
에 함수를 넣으면리액트의 함수 컴포넌트에서 state
를 다루는 법은 조금 특별하다.
constructor()
에서 state
의 초기값을 지정해주는 클래스 컴포넌트는, 컴포넌트 리렌더링 시 기존 컴포넌트의 인스턴스를 재활용하기 때문에 state
가 무분별하게 재계산되지 않는다. 반면 함수 hook을 사용하는 함수 컴포넌트에서는 컴포넌트가 리렌더링될 때마다 함수를 새롭게 렌더링하기 때문에 불필요한 state
값이 재계산된다.
특히 state
의 초기값이 복잡한 계산의 결과이거나, props
를 바탕으로 한 값이라면 더욱 곤란해진다. 아래는 state
의 초기값으로 복잡한 계산(expensiveCalculation
)과 props
를 넣은 극단적인 예시다.
function NaiveHooksComponent(props) {
const [result, setResult] = useState(expensiveCalculation(props.arg));
// ...
}
이럴 때는 useState()
의 초기값에 함수를 넣어주는 방법을 사용해볼 수 있다!
function FunctionHooksComponent(props) {
const [result] = useState(() => expensiveCalculation(props.arg));
// ...
}
useState()
의 초기값으로 들어간 함수는 컴포넌트의 오직 첫 번째 렌더링에만 계산될 것이다.
Ref https://medium.com/@_m1010j_/how-to-avoid-this-react-hooks-performance-pitfall-28770ad9abe0
select
태그를 클릭했을 때 option
리스트들이 보여지는데, 이를 event로 직접 컨트롤 할 수 있는 방법은 없다. 즉 focus
, click
등과 같이 이벤트를 직접 적용해서 select
태그의 리스트를 열 수 있는 방법은 없다.미디엄 유료회원이 아니라 못 읽는다 ㅡㅡ
Ref https://junghan92.medium.com/번역-명확한-리액트-파일-디렉터리-구조-a5f03a174b9e
요소간 간격을 디테일하게 보여주는 크롬 익스텐션이다. 대박 짱 좋다. 스물 여섯 먹고 할 수 있는 최대의 감탄 표현이 ‘대박 짱’이라니 정말 한심스럽다. 아무튼 이걸 보고 디자이너 분들의 QA가 조금이나마 수월해지길 바란다!
Ref https://chrome.google.com/webstore/detail/css-peeper/mbnbehikldjhnfehhnaidhjhoofhpehk
이름부터 벌써 신난다. 내용이랑 무슨 상관이 있는지는 모르겠다.
JavaScript는 싱글 스레드라 서드파티 라이브러리의 로드로 인해 성능이 저하될 수밖에 없는 문제가 있었는데. 이를 Web Worker를 통해 불러올 수 있게 하여 웹 앱의 로딩 성능을 올려줄 수 있는 라이브러리라고 한다.
Ref https://github.com/BuilderIO/partytown
별게 다 있다. 유용하게 사용해볼 만한 것들은 아래와 같다.
<style></style>
태그 사이에 최소화 된 상태로 한 줄로 추가되어 임베딩 된다.포스팅에 참고 링크도 엄청 많다! 시간 내어 차근차근 읽어보기로.
Ref https://github.com/kesuskim/Front-End-Checklist
&&
대신 삼항 연산자Dodds 형님은 예기치 못한 falsy값 (예: 0
)이 렌더링되는 걸 방지하고자 일관되게 삼항 연산자를 사용하는 방법을 추천하고 있다. 하지만 나는 그냥 falsy값을 명확하게 boolean으로 치환한 후 (!!
) &&
연산자를 사용하고 싶다.
Ref https://kentcdodds.com/blog/use-ternaries-rather-than-and-and-in-jsx
그러하다. 드디어 올 것이 온다!
Ref https://twitter.com/reactjs/status/1506720582200705033?cxt=HHwWkoC-3d6Y-egpAAAA
우선 똥💩 느린 노션 code snippet부터 개선해줬으면 좋겠다~ 불편한 건 불편한 대로 그냥 사는 나조차도 노션을 대체할 도구가 나온다면 그걸 쓰리라 마음 먹었는데, 뭐가 더 화려해지고 있다. 졸업한 주제에 학교에서 주는 노션 무료 계정을 잘 써먹고 있는데, 돈 내라 하는 거 아닌지 몰라~
아무튼, Jira와 Slack 쓰레드가 노션과 연결된다는 건 정말 신기하다. 이렇게 얽히고설켜 하나가 망하면 우르르 망해버리는.. 어떤 CASCADING..의 효과가 나타나지 않을까. 하여간 나와 라포를 잘못 형성한 모든 것은 내게 부정적인 인상을 남긴다. 하지만 나는 그래도 노션을 좋아하는 편이다. (?)
오~ 대박짱신기~
스토리북도 정말 똥느렸는데~ 맥북에서는 램이 8GB만 되어도 때려쳐야 한다. 아니 M1 맥은 다르려나? 아무튼 스토리북은 딱 보기에도 느릴 수밖에 없어 보였다.
이번에 내놓은 새로운 builder를 도입하면 HMR(Hot Module Replacement)이 엄청나진다! 어머 이건 한번 해봐야 돼
Ref https://storybook.js.org/blog/storybook-for-vite/
월요일에는 새벽배포를 해봤다. 정말 얼마만에 새벽 5시 전에 일어난 건지… 그리고 다시 못잘 줄 알았는데, 비몽사몽하다가 조금 평화로워졌을 때 잠깐 눕는다는게 그대로 잠들었다. 꿀잠잤다. 쪽팔리다 🤷♀️
한 달에 한 권 책 읽기(개발서적 X) 실천 중이다. 이번 달 책, <불편한 편의점>도 완독! 가볍게 읽을 수 있는 내용이었다. 백엔드 크루였던 조이와 항상 존경하는 크루 하루가 추천해준 책도 한 권씩 샀다. 우리회사 갓복지
미장은 금리 인상에 대한 불확실성이 줄어들어서, 국내장은 새롭게 출범할 정부가 플랫폼 사업에 대한 규제를 풀어줄 예정이라 그런지 내 주식창도 웬일로 쭉쭉 오르고 있다. 정말 처음 보는 현상이라 오히려 더 불안하다. 역시 가진 자가 더 무섭다. 사실 아직 가진 돈도 아닌데. 까불지 말고 적당한 때에 팔아야겠다.
우테코 코치님을 만나러 판교까지 갔다왔다. 운전연습이 하고 싶어서 판교까지 간다 그랬다. 처음으로 쏘카를 빌려서 무사히 잘 다녀왔고, 차를 사고 싶어졌다… 🤦♀️ 아니 아무튼, 2개월 차 (ㅋㅋ) 개발자로서 여기서 내가 할 수 있는 일들을 적극적으로 찾아 해 나가야겠다는 생각을 했다. 평화로운 울타리 안에서 조금씩 nagaboza