JavaScript

Subverting control with weak references

JavaScript 의 비교적 최신 feature 인 WeakMap 을 간단히 설명하고 사용 예를 소개한다.

WeakMap 은 key/value 형식의 콜렉션인데, key 로는 객체 혹은 등록되지 않은 symbol 만 사용할 수 있다. key 로 등록된 객체에 대해 강한 참조를 생성하지 않기 때문에, key 로 등록된 객체가 더이상 참조되는 곳이 없어서 가비지 콜렉터에게 수집될 경우 해당 key 의 value 또한 가비지 콜렉터에게 수집될 수 있는 상태가 된다.

글쓴이는 이러한 WeakMap 의 가장 좋아하는 사용 예로 캐싱을 들며 설명한다. 실제로 해당 용도로 사용하게 될지는 잘 모르겠으나, 읽어볼만한, 알아둘만한 내용인 것 같다.

Hiding elements that require JavaScript without JavaScript

자바스크립트가 활성화되어있을 때만 보여주고 싶은 엘리먼트에 대한 처리를 어떻게 할 것인가, 에 관한 글.

자바스크립트가 비활성화되어있을 때는 <noscript> 태그를 쓰면 되지만 반대의 경우를 위한 태그는 없기 때문에 시작된 고민이다. 개인적으로는 "자바스크립트가 비활성화된 상황"을 굳이 고려하거나 대응하지 않는 편이기 때문에 별로 와닿는 고민은 아니지만, 이런 관점과 고민이 있을 수 있겠구나 라는 생각을 하며 읽었다. (물론 글이 짧아서 쉽게 읽은 것도 있다.)

결론만 인용하면 글쓴이는 아래와 같은 코드를 문서에 삽입해서 .d-js-required 클래스를 "자바스크립트가 활성화되어있을 때만 보여주고 싶은 엘리먼트"에 적용하는 방법을 사용한다.

<noscript>
  <style>
    .d-js-required {
      display: none;
    }
  </style>
</noscript>

React

There’s no such thing as an isomorphic layout effect

nextjs 등 SSR 환경에서 useLayoutEffect 를 사용할 때 발생하는 warning 을 피하기위해 흔히 작성하거나 설치하는 hook 인 useIsomorphicLayoutEffect 에 대한 비판글이다. (비난이 아니다.)

SSR 환경에서 발생하는 아래와 같은 warning 을 회피하기 위해

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.

흔히 아래와 같은 코드를 작성해서 사용한다.

import { useEffect, useLayoutEffect } from "react";
import isClient from "#is-client";

export default isClient ? useLayoutEffect : useEffect;

이를 대체로 useIsomorphicLayoutEffect 혹은 비슷한 이름으로 칭하는데, React Redux 에서 가장 먼저 사용한 형식으로 추정된다. React Redux 가 코드에 주석으로 남긴 내용을 보면 그들은 useEffect 가 서버사이드에서 실행되지 않는 hook 이고, 자신들의 코드가 단지 warning 을 피하기 위한 임시 코드임을 인지하고 있다.

하지만 이 코드가 해당 warning 을 피하기 위한 정석적인 코드로 남용되면서, 누군가 혹은 어딘가에서는 useIsomorphicLayoutEffect hook 이 SSR 에서도 실행되는 hook 으로 오해하는 경우가 생기기 시작했다.

물론 대부분의 경우 useIsomorphicLayoutEffect hook 을 사용하는 것은 문제가 되지 않는다. 하지만 useIsomorphicLayoutEffect 을 사용한 케이스 중 대부분은 서버에서 렌더링되지 않는 게 더 맞는 방향인 컴포넌트에서 사용한 케이스가 대부분이다.

특정 문제에 대한 해결책을 발견했을 때 그것의 원리를 파악하려 하지 않거나 비판적이지 않은 태도로 수용할 경우, 본질에서 멀어질 수 있다.

React Anti-Pattern: Stop Passing Setters Down the Components Tree

React 컴포넌트의 prop 으로 useState 의 setter 를 바로 전달하면 좋지 않은 점을 추상화 관점에서 설명하는 글이다.

아래 세 가지 이유를 들어 setter 를 prop 으로 전달하지 말라고 이야기한다.

  1. 해당 컴포넌트가 부모에게 종속적으로 묶인다.
  2. 해당 컴포넌트의 재사용성이 떨어진다.
  3. state 의 어떤 값을 어떻게 변경하려는 것인지 알기 어려워진다.

따라서 용도에 맞는 prop 을 만들고 캡슐화 해서 prop 을 전달하라고 말한다.

개인적으로 매우 동의하는 내용이고 실제로도 setter 를 웬만해서는 prop 으로 사용하지 않았다. 그런데 이 이유를 말이나 문장으로 정리해본 적이 없었는데 덕분에 좋은 리마인드가 된 것 같다.

Next.js

(번역) Next.js를 선택하기 전에 반드시 알아야 할 것들

vercel 이 최근에 있었던 nextjs 의 치명적인 보안 이슈에 얼마나 무책임하게 대응했는지에 대해 이야기한다.

글쓴이가 이러한 글을 쓴 이유는 vercel 이 nextjs 를 오픈소스로 운영 및 관리하면서 그 책임을 다하지 않았다고 생각하기 때문이다.

그들은 이슈를 알고 나서도 2주 이상 대처하지 않다가, 이후 자사의 플랫폼에서만 대처를 완료한 후에야 (무려 일주일 이상이 지난 후에야) 다른 nextjs 플랫폼 및 일반 사용자에도 해당 사실을 알렸다.

오픈소스라고 하면, 설령 그들이 그 코드를 소유했다고 하더라도 코드의 내용 및 이슈에 대해 언제나 숨김 없이 공유해야 하지만 그들은 그렇게 하지 못했다는 것이다.

더구나 그들은 평소에도 vercel 이외의 플랫폼에서는 nextjs 의 특정 기능을 사용하기 어렵도록 폐쇄적으로 만들고 문서화나 정보 공개도 하지 않은 채 운영해왔다.

참고로 글쓴이는 vercel 의 경쟁사인 netlify 에서 nextjs 를 플랫폼으로 제공하는 서비스를 관리 및 운영하고 있다. 경쟁사에 근무하기 때문에 이러한 의견을 내는 것을 조심스러워했지만, 이번과 같은 큰 이슈에 대해서는 사람들이 nextjs 를 사용하기로 결정하기 전에 알아야 한다고 생각해 공유한다고 밝혔다.

nextjs 는 뒤늦게 재발방지 및 폐쇄적인 기능을 완전히 제거 혹은 문서화하겠다고 밝혔다는데, 앞으로 정말 바뀔 수 있을지, 아니면 현재를 면피하기 위한 방편일 뿐인지 주목된다.

CSS

Top 5 CSS Navigation Menu Mistakes

네비게이션을 구현할 때 흔히 하는 실수들을 정리한 글. 간단히 요약하면 아래와 같다.

  1. 클릭 영역을 너무 작게 만든다.
  2. Flexbox 를 사용하는데 gap 을 사용하지 않는다.
  3. (마우스오버로 열리는) Dropdown 의 마우스오버 영역을 제대로 지정하지 않는다.
    • 열린 후에는 드랍다운 메뉴의 너비까지 고려해서 마우스오버 영역을 넓혀야 한다.
  4. (마우스오버로 열리는) Dropdown 의 영역에서 마우스가 빠져나왔을 때, 닫힐 때에 대한 딜레이가 없다.
    • 마우스가 빠져나왔을 때 바로 닫히는 것 보다는 어느 정도 딜레이 후에 닫히는 것이 사용성이 더 좋다.
  5. 페이지 내부로 이동하는 in-page anchor 를 눌렀을 때 스크롤 애니메이션 없이 이동한다.

Etc.

How Does Chrome Prioritize Image Requests?

크롬이 이미지 요청에 대한 우선순위를 어떻게 지정하는지에 대해 설명한다.

  1. 페이지 최초 로딩 시, 기본적으로 모든 이미지는 Low priority 로 설정된다. 다른 중요한 리소스들이 리로드된 후에야 이미지 로딩을 시작한다.
  2. 크롬 117 부터는, 가장 큰 다섯 이미지를 Medium proiority 로 자동 설정한다. 이는 LCP (Largest Contentful Paint) 점수 향상에 도움을 준다.
    • 10,000 픽셀^2 이상의 이미지를 큰 이미지로 판단한다.
    • 이미지가 10,000 픽셀^2 이 넘어도 img 태그에서 크기를 작게 지정하면 큰 이미지로 판단하지 않는다.
  3. 이미지는 뷰포트에 들어오는 순간 자동으로 우선순위가 High priority 로 재조정된다.
    • First Contentful Paint (FCP) 이후에 판단한다.
  4. fetchpriority 속성으로 우선순위를 강제 조정할 수 있다.
    • LCP 이미지에 fetchpriority="high" 를 설정하면 LCP 점수 향상에 도움이 된다.
  5. rel="preload" 속성에 의해 preload 되는 이미지도 기본적으로 Low priority 다.

'아크(Arc)' 브라우저는 왜 벌써 무덤으로 갔을까?

아크 브라우저의 업데이트 중단 결정에 대한 사설이다.

얼리어답터 사이에서 핫한 브라우저로 알고만 있었는데 벌써 업데이트 중단 결정을 내린지는 모르고 있다가 이 글을 보고 알게 되었다. 글쓴이는 아크 브라우저가 업데이트 중단을 결정하게 된 배경으로 아래와 같은 다섯 가지 의견을 내놓았는데

  1. 아크 브라우저는 소프트웨어 애호가들의 사랑을 받았지만, 대중성을 확보하기에는 어려운 제품이다.
  2. 개인정보 보호를 중시하는 틈새 브라우저로 돈을 벌기란 쉽지 않다.
  3. 시간이 지나며 아크 마케팅의 기대감과 제품 퀄리티 사이에 간극이 생기기 시작했다.
  4. 일상에서 늘 함께하는 브라우저는 안정성이 무척 중요하다.
  5. 더브라우저컴퍼니는 자동화에 초점을 맞춘 완전히 새로운 제품을 만들 계획이다.

일견 이해가 되는 내용이다.

역시 사업이나 프로젝트에서 가장 중요한 건 지속가능성이라는 걸 다시 느낀다.