Skip to main content

My Awesome ChatGPT

· 2 min read

Overview

  • The programmers who are good at asking questions and quickly determining if the answers are right or wrong will be the ones who survive.
  • Here's a list of repositories that can be used in the field, not just for development tips.

aicommits

src/utils/openai.ts#L7
const promptTemplate =
"Write an insightful but concise Git commit message in a complete sentence in present tense for the following diff without prefacing it with anything:";

node chatgpt

const completionParams = {
temperature: 0.7,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
};

tiktoken

  • You may need to get the exact number of tokens to use the openai API.
  • You should use openai/tiktoken, but it's Python.
  • dqbd/tiktoken already has a node wrapper already out there. 3.5 Turbo support
import { encoding_for_model as encodingForModel } from "@dqbd/tiktoken";

const encoder = encodingForModel("gpt-3.5-turbo");
const tokenLength = encoder.encode("YOUR_CHAT").length;

chatgpt-retrieval-plugin

openai/chatgpt-retrieval-plugin

  • ai-plugin.json in the .well-known path acts as a manifest.json
  • Openapi.yaml in the same path for this endpoint specification
  • There are four types of authentication: none | user_http | service_http | oauth.
  • For simple services, service_http seems to be sufficient, user_http requires the customer to enter an API key, and oauth requires additional permissions such as search:read.
  • It seems to use Vector DB for document similarity comparison, but there is no proper Node.js wrapper for it, so it can be implemented in Redis, but you need the Redisearch module.

The durable back over a hundread years

· 3 min read

백년허리

I got a herniated disc from Sumo-deadlift, and I think it would be good for many people to read this before it happens. If I had, I would have had a good posture before the disc between L5-S1 came out.

The overall content is a book review of 백년허리 to protect spinal hygiene.

Diagnosis

  • Vertebrae: Cervical, thoracic, lumbar, sacral, and coccyx
    • The cervical and lumbar vertebrae are curved forward, with cervical lordosis and lumbar lordosis.
  • Disc damage is the main cause of back pain
  • Discs: Nucleus pulposus, annulus fibrosus, and endplates
    • The posterior annulus fibrosus and endplates are most commonly injured
  • Muscles protect the torn disc.
    • When a disc tears, the muscles tighten to protect it.
    • Low back pain is a sign of a torn disc
  • Lumbar lordosis is a new posture.
  • A healthy disc creates a lumbar lordosis curve, and the lumbar lordosis curve protects the disc.
  • Sciatica is a typical symptom of a herniated disc and is a sign that the disc has herniated.

Treatment

  • The idea that you can cure a bad back by doing stronger back exercises is like saying that you can cure a broken arm by exercising the arm muscles.
  • The hip muscles and obliques are important.
  • You need to know exactly how much impact your workout will have on your back, and make sure your back can handle the strain.
  • Stretches that bend at the waist are very bad exercises for lumbar lordosis
  • Stiffness in the lower back when a disc injury is healing is a natural part of the process of the wound turning into scarring.
  • It's essential to regain lumbar lordosis through frequent standing and extension movements.
  • It is spinal hygiene to try to never re-tear a disc wound as it heals.
  • Maintaining lumbar lordosis 24 hours a day
  • If you suffer from sciatica when doing lumbar lordosis, you should treat the nerve root inflammation and practice good spinal hygiene.
  • Leaning on a backrest or cushion is an advantage.
  • The basics of spinal hygiene are maximum lumbar lordosis and extension movements.
  • If it hurts to do extension movements, lie on your stomach and do them frequently, for about 5 minutes, with your elbows under your shoulders.
  • Lumbar lordosis should not collapse when standing, sitting, or bending at the waist.
  • Your back is most comfortable when your knees are slightly lower than your pelvis.
  • There is no such thing as a bad back. Your back improves with good posture.
  • Standing lumbar lordosis: place your hands on your waist and hold for 5 seconds while breathing.
  • Standing Chest: Standing, lift your chest and grab your shoulder blades. No duckbills
  • Walking: keep both shoulder blades together, open chest, chin up, graceful chin and proud chest.
  • Sitting: knees should be lower than the pelvis. Sit with an upright chest.
    • The height of the screen should be high enough.
    • When sitting with good spinal alignment, you should be able to see the screen without bending your back and neck too much.
  • The best place for a lumbar strap is between the 3rd and 4th lumbar vertebrae.
  • Avoid the knees.

Prohibited positions

  • Squatting
  • Sitting long
  • Cross-legged
  • Slouching

ChatGPT use cases

· 2 min read

Overview

Here's a list of use cases where you can get past the hype and actually use it for something useful.

Extracting regular expressions

Creating regular expressions usually involves a lot of testing. I usually put the desired text in regexr, regex101, and match the negative/positive lookahead from memory, and use negative/positive lookbehind, but often find that negative lookbehind is not supported by different programming versions/languages.

Now I ask ChatGPT. Suppose you want to extract the package name from the package update history below.

Hello GPT.

Can you give me a regex pattern for getting to-be result?

as-is:
Orignal content


to-be:
Refined string #1
Refined string #2
...and so on.

It will get it for you.

Writing documentation with code

If you want your code to be documented, put it in and ask it to create a README.md.

Can you write a README.md with this code?

It will get it for you.

Create an Object Validation Schema with the interface

Let's create a Joi Schema with a TypeScript interface.

Create a Query DSL with Raw SQL

Pass in a raw query and ask it to create a query DSL and query helper syntax.

Create a DDL with Data

Pass in a query and ask it to generate a table schema query like the interface example above.

See

awesome is now live. https://github.com/f/awesome-chatgpt-prompts

Migrate a blog from hexo to docusaurus

· 4 min read

Overview

I've been using hexo since 2016, and I love it because it has a lot of plugins and themes. Since 2019. As there are many other Static Site Generators, the advantages of hexo are no longer available. The updates of ecosystem libraries such as theme and plugin development have also decreased.

The stack was theme-dependent: ejs -> njk, less -> sass -> stylus. Crucially, it's a nodejs-based core, so even if I uploaded a troubleshooting, it was a waste of resources.

Docusaurus didn't have algolia search when it was 1-2 alpha. There was a shovel to swizzle and use the local search community plugin to attach it, and Korean did not work normally.

In 2023, version 2 was launched, the frontend stack was unified based on React, and it seemed like it was okay to proceed with this work.

Troubleshooting

SEO

URI

  • hexo puts the date inside the front-matter syntax as date: 2023-01-10 09:00:00.
  • docusaurus should use the nested folder structure.
  • It will parse the front-matter.date in the md file and treat it like /2023/01/10/title in the URL.

Site Verification

  • I put it in the configuration without any problems.
docusaurus.config.js
{
"themeConfig": {
"metadata": [
// ? https://search.google.com/search-console
{
"name": "google-site-verification",
"content": "g"
}
]
}
}

hexo new

  • hexo new post "title" This command creates a post, but I needed a compatible command.
  • I used yarn cmd new title to generate what looks like blog/2023/01/10/title.mdx as of today.
  • For URL normalization, you can use import { slugize } from "hexo-util";.
    • slugify also removes Korean characters.

archive

  • The archive of hexo is Order by Created DESC, while docusaurus is ASC sorted.
  • There was an issue to provide this as a plugin option, but it was closed, and do it yourself was the answer.
  • I created one, overwrote the existing component, rearranged it, and linked it.
docusaurus.config.js
{
"presets": [
"classic",
{
"blog": {
// path.resolve needed
"blogArchiveComponent": "./src/component/BlogArchiveDescendingPage.tsx"
}
}
]
}

tag

  • A docusaurus tag is defined as tags: [tag1, tag2] and must satisfy this format.
  • I asked ChatGPT for a regular expression and replaced it with the whole thing.

github action

  • Set up the target repo and branch.
  • Issue a personal access token and insert the two values appropriately.
  • Run yarn build, yarn deploy and it should work fine.
docusaurus.config.js
{
"organizationName": "gracefullight",
"projectName": "gracefullight.github.io",
"deploymentBranch": "main",
"trailingSlash": true
}
workflows/main.yml
env:
GIT_USER: ${{ secrets.GIT_USER }}
GIT_PASS: ${{ secrets.GIT_PASS }}

dark only

  • Dark only, also deleted the switch.
docusaurus.config.js
{
"themeConfig": {
"colorMode": {
"defaultMode": "dark",
"disableSwitch": true
}
}
}

code block

  • has a different format, so I replaced it with a regular expression.
# hexo
\`\`\`language title

# docusaurus
\`\`\`language title="title"

comment

  • I don't have time to answer questions about the comment feature.
  • I tried to delete it, but I customized it and integrated gitalk.
  • I requested free indexing because algolia is not an open source documentation, but the ticket status didn't change.
  • I used @easyops-cn/docusaurus-search-local, but it doesn't support mobile.
docusaurus.config.js
{
"themes": [
"@easyops-cn/docusaurus-search-local",
/** @type {import("@easyops-cn/docusaurus-search-local").PluginOptions} */
{
"indexDocs": false,
"blogRouteBasePath": "/",
"hashed": true,
"language": ["en", "ko"]
}
]
}
  • After about a week, algolia replied and the indexing was successfully completed.

Result

  • LGTM
  • I think I need to build typesense first, so it won't be easy.
  • If you don't need to view it on mobile, the above plugin should be enough.

Nextjs App Directory

· 4 min read

개요

  • nextjs 13버전에서 app 디렉토리가 생기면서 client/server 컴포넌트를 쉽게 사용할 수 있는 환경이 되었다.
  • getStaticProps, getServerSideProps 와 같은 메소드가 사라졌고, 양쪽이 fetch 로 통합이 되었다.
  • 페이지별 상태 초기화를 위한 HOC 중첩을 가져가지 않아도 될 것 같았다.

App

Node.js + React DOM Renderer

app 내의 모든 로직은 Node.js 이다. 따라서 이런 로직이 가능하다.

app/page.tsx
import { hostname } from "os";

export default function Main() {
return <div>{hostname()}</div>;
}

이벤트를 바인딩할 수 없다.

app/page.tsx
import type { SyntheticEvent } from "react";

export default function Main() {
const handleSubmit = (event: SyntheticEvent<HTMLFormElement>) => {
console.log("submitting");
};

return (
<form onSubmit={handleSubmit}>
<button type="submit">submit</button>
</form>
);
}
Error: Event handlers cannot be passed to Client Component props.
<form onSubmit="{function}" children="...">
^^^^^^^^^^ If you need interactivity, consider converting part of this to a
Client Component.
</form>

Design system

대부분의 디자인 시스템 라이브러리는 ThemeProvider 로 테마 상태를 공유하고 Baseline StyleSheet를 전역에 넣어준다. 스타일시트를 위해 RootStyleRegistry 란 HOC 만들어 Baseline StyleSheet 를 동적으로 넣어주면 초기화는 가능하지만,

문제는 Server Component 내에서 use 을 사용할 수 없으니 ThemeProvider 로 기능동작이 불가능하다. 어찌저찌 'use-client' directive 로 Client Component 로 설정한다고 하여도 Provider 로 인해 하위 모든 컴포넌트가 Client Component 로 동작해야할 것이다.

그래서 문서에서 다음과 같이 표기가 된 것으로 보인다.

If you want to style Server Components, we recommend using CSS Modules or other solutions that output CSS files, like PostCSS or Tailwind CSS.

위 방식으로 mui/material-ui/examples/material-next-app-router-ts 예시가 추가되었지만, 이렇게 쓸바에 pages 폴더 라우트와 다를 게 없다고 생각한다.

결론

  • 아직 app 폴더를 사용하기엔 이르다.
  • vercel/app-playground에 충분한 예시가 갖춰지고, 생태계가 React Server Component 를 충분히 지원할 때까지는 프로덕션에서 사용은 불가능하다고 보인다.

사견

개인적으로는 왜 이렇게 많이 클라이언트에서 렌더링해야해? 그냥 필요한 영역만 클라이언트에서 그려주면 되잖아? 라는 접근방식은 디버깅 관점에서 마음에 들진 않는다. 웹을 하나의 Client 관점에서 본다면, 설치의 유무만 다를 뿐 앱에서 서버에서 렌더링된 HTML을 받고 일정부분만을 Server Driven UI 로 가는거와 마찬가지다. 복잡도가 크게 증가한다.

이러한 시도는 이미 Dotnet, Laravel Livewire 등 다른 언어에서 많이 진행되어왔고, Remix 에서는 이미 잘 동작 중이다. 단지 React 를 서버에서 쓰기 위해 다시 MVC 시절로 회귀하려는지 모르겠다.

yarn, ts 스타터 체크리스트

· One min read

개요

벤치마킹, 툴 테스팅, 엑셀 스트리밍, 맵 리듀스 등 여러가지 테스트를 위해서 빈 레파지토리를 시작해야하는 경우가 많다. 복사해서 사용하기 위해 기록해두자.

CMD

yarn init -2
yarn add -D typescript ts-node @types/node
yarn tsc --init

touch src/index.ts
code .

# package.json
"start": "ts-node src/index.ts"

협업 여부에 따라 commitlint, eslint, yarn plugins 등등..

패키지

node-redis vs ioredis

· 5 min read

전제조건

  • 보통 IOredis 가 퍼포먼스면에서 더 빠르다고 알고 있는데, node-redis가 4버전으로 올라오면서 바뀌었는지 궁금했다.
  • 먼저 IOredis 의 벤치마크 문서 에는 node-redis 와의 비교는 없고 enableAutoPipelining 옵션을 켜라는 말만 나온다.
  • 다른 참고할만한 자료는 Ably: Migrating from Node Redis to Ioredis: a slightly bumpy but faster road 인데 몇 버전의 라이브러리로 비교를 했는지는 나오지 않는다.
  • 최신 node-redis 라이브러리와 비교를 해야했다.

node-redis

  • 버전 4에서 호환되지 않는 메소드가 많은데 Breaking Changes 나 v3 to v4 마이그레이션 가이드에 추가가 되어있지 않다. 😡
  • 열려있는 이슈는 다음과 같다.
    • #1765: hgetall, hget, hset, hmset, setex
    • #1796: batch
  • 레디스 사의 레파지토리가 맞는지 의문이 든다.

벤치마크

테스트

docker-compose.yml
version: "3.9"
services:
redis:
image: "redis:6.2-alpine"
ports:
- "6379:6379"

띄워놓고 진행했다. IOredis 의 options.dropBufferSupport 옵션을 켜면 퍼포먼스가 향상된다라고 나와있어서 두 경우를 모두 테스트했다.

dropBufferSuppport: true

ioredis

  • node-redis (avg): 9586.215
  • ioredis (avg): 9488.689
Operationnode-redis(ms)node-redis with multi(ms)node-redis with pipeline(ms)
set26525.039170.461112.881
get26334.277252.904183.610
hset26461.201224.977133.728
hgetall31394.670389.773306.851
incr28580.127206.482116.846
keys29647.691772.989737.362
Operationioredis(ms)ioredis with multi(ms)ioredis with pipeline(ms)
set25684.449260.598173.958
get25720.408290.935226.623
hmset25857.690338.286200.380
hgetall31666.897480.690380.761
incr28392.304257.203150.187
keys29061.574915.112738.331

dropBufferSuppport: false

node-redis

  • node-redis (avg): 9764.244
  • ioredis (avg): 9993.67
Operationnode-redis(ms)node-redis with multi(ms)node-redis with pipeline(ms)
set29100.469176.660126.425
get28317.308321.528189.664
hset28963.134194.640139.163
hgetall29219.324406.834357.909
incr29009.774211.714133.763
keys27309.474847.218731.385
Operationioredis(ms)ioredis with multi(ms)ioredis with pipeline(ms)
set27995.198265.654160.538
get30821.817335.706245.901
hmset28127.822288.023216.563
hgetall28732.957406.565372.790
incr30576.902277.081133.760
keys29278.756863.351786.658

결론

  • IOredis 를 쓰려면 dropBufferSupport: true 를 권장
  • 두 라이브러리의 퍼포먼스 차이는 미미하다.
  • node-redis 는 공식 라이브러리이지만 아직 문서가 완벽하지 않다.
  • redis 에서 제공하는 RedisJson, RediSearch 의 확장성을 위해 node-redis 를 선택할 것 같다.
  • 영속성을 위한 aof, rdb 설정은 둘 다 사용하라 문서에 나와있다.
  • Redis/redis-om-nodeRedisJson, RediSearch 를 다 사용한다면 BFF 모델을 쉽게 만들 수 있을 것 같다. 레퍼런스는 아직 없는듯...
  • RedisJSON/RedisJson/Dockerfile 에 두 모듈이 모두 설치되어있다.

TypeScript 협업

· 10 min read

써본 사람은 빠져나올 수 없지만 안 써본 사람에게 필요성과 타입스크립트가 어렵지않다라는 것을 어필하기 위한 삽질기랄까..

앞서

  • 프로그래밍 언어를 잘 쓴 다는 건 그 언어에 대한 API (man)에 익숙해지고, 업데이트 이력을 꾸준히 팔로잉 하는 것이다.
  • 언어는 컴퓨터공학 (운영체제, 네트워크, 자료구조) 위에 올라간 표현의 수단이니 한 언어에 익숙하다면 다른 언어가 어렵다라고 느껴지지는 않아야한다 하지만 그렇지 않은 경우가 생각보다 많다.

도입 전

동향 관련

  • StackOverflow Developer Survey 2021: Most popular Technologies 1
  • MS, Google 2
  • Kakao 3, Naver 4, Toss 5

데이터

  • To Type or Not to Type: Quantifying Detectable Bugs in JavaScript: 타입스크립트 사용시 자바스크립트 프로젝트에서 발견된 버그의 15%를 컴파일 시점에 미리 방지 가능 (UCL, MS 연구) 6
  • JSConf Hawaii 2019 (Airbnb): 진행된 프로젝트의 사후 분석 결과, 발견된 버그의 38%가 타입스크립트에서는 방지할 수 있었던 것 7

유지보수

  • param, return type 주석 필요 없음
  • 헝가리안 표기법 필요 없음
  • 타입 검증으로 컴파일시 사전 오류 제거
  • 항상 최신 자바스크립트 문법 지원
    • 자바스크립트의 경우 stage 를 모니터링하고 바벨 플러그인을 유지보수 해야하나, 타입스크립트는 stage-3 이상 지원 8
    • 타입스크립트의 릴리즈노트만 팔로잉
  • IDE 내에서 라이브러리 인터페이스 확인 가능 (d.ts)

도입 후

도입 후는 항상 타입관련 문제가 많다.

tsconfig

  • noImplicityAny: true 를 켜야 말아야하나는 소모적인 논쟁이라 생각한다.
    • any 는 마이그레이션 단계에서만 허용되어야한다. 그 경우 any[], { [id: string]: any } 로 더 구체적으로 정의하는 게 낫다.
    • 모르는 타입에 대해선 unknown 으로 정의할 수 있고, 이를 사용하는 측에서 타입 단언으로 처리할 수 있다.
  • strict: true 를 항상 켜야한다. 9
  • target 은 es2017 이상으로 한다. 더 낮은 브라우저 지원이 필요한 경우 한 벌 더 빌드한다. 10

type vs interface

interface 를 사용한다.

  • OCP: interface 는 확장에 열려있다. 11
  • 교차 타입에서 퍼포먼스적으로 좋다. 12
  • 핸드북에서 권장된다. You should prefer interface. Use type when you need specific features. 13

I prefix

인터페이스의 I prefix 는 제거한다.

  • 개인적으로 이건 자바의 잔재라고 생각한다.
  • typescript-eslint/recommeneded 룰에서 삭제되었다. 14
  • MS/Typescript 컨트리뷰트 가이드라인에서 권장된다. 15
  • Bad naming 룰이다. 16

type-only import/export

타입을 명시적으로 import/export 한다.

  • import 가 반 페이지를 넘어가다보면 어떤게 class 인지, interface 인지 한 눈에 파악하기 힘드나, type-only import 구문을 사용하면 해결 된다. 17
  • 런타임 코드 사이즈를 줄일 수 있다. 18

Array<Type> vs Type[]

typescript-eslint/array-type: array-simple 룰을 따른다.

  • Array with simple type: number[]
  • Array with non-simple type: Array<Foo & Bar>
  • Readonly array with simple type: readonly number[]
  • Readonly array with non-simple type: readonly Array<Foo & Bar> 19

as const vs enum vs const enum

as const 를 사용한다.

  • 상수 속성으로 사용하기 위한다면 as const 으로 충분하다.
    • as const 는 상수 내 재할당을 금지 (readonly property로 선언, deeply const)
    • enum 은 참조코드 생김
    • const enum 은 값이 할당
input
// const
export const timezone = {
KR: "Asia/Seoul",
JP: "Asia/Tokyo",
VN: "Asia/Ho_Chi_Minh",
PH: "Asia/Manila",
} as const;

// enum
export enum TimezoneAsEnum {
KR = "Asia/Seoul",
JP = "Asia/Tokyo",
VN = "Asia/Ho_Chi_Minh",
PH = "Asia/Manila",
}

// const enum
export const enum TimezoneAsConstEnum {
KR = "Asia/Seoul",
JP = "Asia/Tokyo",
VN = "Asia/Ho_Chi_Minh",
PH = "Asia/Manila",
}

// const
console.log(timezone.KR);

// enum
console.log(TimezoneAsEnum.KR);

// const enum
console.log(TimezoneAsConstEnum.KR);
output
// const
export const timezone = {
KR: "Asia/Seoul",
JP: "Asia/Tokyo",
VN: "Asia/Ho_Chi_Minh",
PH: "Asia/Manila",
};

// enum
export let TimezoneAsEnum;

(function (TimezoneAsEnum) {
TimezoneAsEnum["KR"] = "Asia/Seoul";
TimezoneAsEnum["JP"] = "Asia/Tokyo";
TimezoneAsEnum["VN"] = "Asia/Ho_Chi_Minh";
TimezoneAsEnum["PH"] = "Asia/Manila";
})(TimezoneAsEnum || (TimezoneAsEnum = {}));
// const
console.log(timezone.KR);

// enum
console.log(TimezoneAsEnum.KR);

// const enum
console.log("Asia/Seoul" /* KR */);
  • Proposal for ECMAScript enums 이 채택될 때를 위해 enum 을 사용해야한다는 주장이 있다. 20, 21

역참조

enums 의 역참조를 사용하는 경우는 다음과 같다.

// enum 을 역참조하는 경우
enum Color {
RED = 0,
ORANGE = 1,
}

// let red = Color.RED;
// Color[0] === "RED"

문자열 열거형

JS와 TS의 동작이 달라질 수 있으므로 (런타임에서 사용방법이 달라질 수 있으므로) 리터럴의 유니온을 사용하는 게 낫다.

// type Timezone = "Asia/Seoul" | "Asia/Tokyo" | "Asia/Ho_Chi_Minh" | "Asia/Manila";
export enum Timezone {
KR = "Asia/Seoul",
JP = "Asia/Tokyo",
VN = "Asia/Ho_Chi_Minh",
PH = "Asia/Manila",
}

// getTimezone(timezone: Timezone);
// JS 에서는 정상
// TS 에서는 Asia/Seoul 형식은 Timezone 형식의 매개변수에 할당될 수 없습니다.
getTimezone("Asia/Seoul");

// import 해야 정상
import { Timezone } from "./enums";
getTimezone(Timezone.KR);

ES6 Private vs Private accessor

Private accessor 를 사용한다.

  • ES6 private 은 구현을 WeakSet 으로 해놨으므로 특별한 경우가 아니라면 (윈도우에서 접근 불가능하게 해야하는 경우) 접근자로도 충분하다.
input
class Test {
// #es6Private() {}

private accessorPrivate() {}
}
output
let _Test_instances, _Test_es6Private;

class Test {
constructor() {
_Test_instances.add(this);
}
accessorPrivate() {}
}

(_Test_instances = new WeakSet()),
(_Test_es6Private = function _Test_es6Private() {});

DOM

TypeExample
EventTargetwindow, XMLHttpRequest
Nodedocument, Text, comment
ElementHTMLElement, SVGElement
HTMLElement<b>, <i>
HTML*ElementHTMLButtonElement, HTMLInputElement
  • 브라우저에 라이브러리를 만드는 경우나 ref 를 사용하는 경우는 위 DOM 구조를 확실히 알아야한다.
  • 이벤트 핸들러를 구현할 시 인라인함수로 만들면 타입스크립트가 타입추론을 더 쉽게 할 수 있다.
  • g-plane/typed-query-selector이 타입을 추가하여 DOM 엘레먼트 선택시 타입을 바로 반환받을 수 있다.

유틸리티 라이브러리

Lodash 와 같은 유틸리티 라이브러리를 사용하자.

  • 타입 흐름을 개선하고, 가독성을 높이고, 명시적인 타입 구문의 필요성을 줄이기 위해 유틸 메소드를 직접 구현하는 것보단 유틸 라이브러리를 사용하는 것이 낫다.
  • LodashRxJS가 있다.

유틸리티 타입

  • 새로운 유틸리티 타입을 지정하기 전에 sindresorhus/type-fest에서 사용할 수 있는 유틸리티 타입이 있는지 확인하자.
  • 왠만한 케이스는 커버가 가능하다.

export internal interface

어차피 사용측에서 가져갈 수 있으므로 미리 내보낸다.

// 선언측
interface Name {
first: string;
last: string;
}

interface Employee {
name: Name;
joined: Date;
}

export function getEmployee(name: Name): Employee;

// 사용측
type Employee = ReturnType<typeof getEmployee>;
type Name = Parameters<typeof getEmployee>[0];
  • 위처럼 사용측에서 가져갈 수 있다.
  • 내부 인터페이스는 export interface 로 내보내주자.

마이그레이션

  • 의존성 관계도를 뽑아서 바텀업으로 마이그레이션한다. 첫 번째 모듈은 유틸리티 모듈일 것이다. 툴은 madge
  • 자동으로 도전해보고 싶다면 airbnb/ts-migrate
  • 점진적으로 진행하여 타입커버리지를 직접 확인하고 싶은 경우 plaintain-00/type-coverage

여담

  • 추가할 게 생긴다면 계속 추가해볼 예정이다.
  • Typescript/Playground 로 코드를 공유하면 시간절약이 가능하다.

Chrome dev summit 2021 빠르게 훑기

· 3 min read

Workshop 섹션때문인지, 재택환경 때문인지 작년보다 내용이 없었다.

Building a more private web

  • New privacy-Preserving Technologies
  • FLoC 관련 이라 앞부분 스킵
  • UA-CH (User Agent Client Hints API): 유저 브라우저 핑거프린팅 방지

How leading developers build innovative web experiences

최신 기술 쓴 회사 소개

https://www.youtube.com/watch?v=1vGVrC03_jo

  • KAPWING: 온라인 비디오 에디터
    • Indexed DB
    • Web Socket API
    • Web Audio API
    • Media Recorder API
    • Web Workers
    • PWA
    • (+) Web Codecs
    • (+) WebGL
    • (+) Media Source Extensions
  • Zoom
    • PWA Desktop Web Codes API 로 Chrome OS 지원
    • 런칭 후 16.9M 유저 증가 (전년대비 7M 증가)
  • Google Meet
    • PWA: Custom background using WASM SIMD and WebGL.
  • Youtube Primium.
    • PWA: SW, CacheStorage, IndexedDB, Web Share API, Navigation Preload.
  • Tiktok: creating a multi-form-factor, frictionless experience.
    • Workbox to Prefetch videos.
    • expand PWA desktop.
    • 트래픽 10배 상승
  • Adobe Photoshop Web
    • Chrome 과 웹플랫폼팀과 코웤
    • wasm 을 사용해서 퍼포먼스 패널티 기능 구현.
    • Storage Foundation API.
    • 피드백 환영

Understanding performance with Core Web Vitals

https://www.youtube.com/watch?v=F0NYT7DIlDQ

  • 구글과 자바스크립트 프레임워크 간의 퍼포먼스 협업 Aurora
  • PageSpeed Insights 리뉴얼
  • 라이트하우스에서 유저 플로우 측정 가능
    • Warm load 나 스크롤 등을 시뮬레이션하고 테스트 가능
  • 개발자모드 Recorder 탭에서 puppteer 테스트를 만들어서 export 할 수 있다.

The new responsive design

https://www.youtube.com/watch?v=dhrX_biPH8c

feconf 2021

· 7 min read

A1: Do more, with less

UI 개발의 일반적인 문제

화면마다 매번 새로 디자인 되는 컴포넌트: UI의 파편화로 생산성 감소 새로 구현하는게 맘편해요...

디자인 일관성 다운 -> 중복코드 파편화 -> 유지보수가 어려운 UI 코드 무한루프

디자인시스템 구성요소

  • 토큰: 컬러, 타이포그래피, 사이즈, 여백, 트랜지션…
  • 컴포넌트: 토큰을 가지고 컴포넌트의 생김새 정의
    • Primary, fill, normal, disabled…
  • 패턴: Danger fill > 한 화면에 하나만 사용, 경고용도로 사용

스펙을 가지고 스토리북 생성

디자인 시스템 가이드 정의 > 디자인과 개발에 동일한 컴포넌트 구현 및 사용 > 커뮤니케이션 비용 다운, 효율성 일관성, 퀄리티 증가

100명 이상 소통하기에 다른 문제가 생겼다.

  • 코드를 디자인에 일치시키는 어려움 (14:25)
  • 비주얼 중심의 디자이너 언어 <-> 기능 중심의 개발자 언어
    • Blue: Primary
    • Red: Danger
  • 엄격함과 유연함 사이에 절충이 필요했다.

스케치로 만들고 직접 리액트 컴포넌트를 수동으로 만들었다.

  • 휴먼 에러가 생기고, 스케치컴포넌트와 리액트컴포넌트를 서로 비교해야했다.
  • 디자인과 코드 사이에 의존 관계를 만들어야한다.
  • 기존 디자인툴은 모든 프롭의 조합을 그려놓아야한다. (스티커 붙히기) 파워포인트로 디자인만들기 급..
    • 디자인 툴에서도 코드를 사용할 수 있으면 좋을텐데.. > 프레이머로 전환

프레이머

  • 모든 요소가 리액트 컴포넌트로 이루어짐 22:17분
  • 디자이너가 프롭을 정의하고 입력할 수 있음
  • 컨셉 검증을 위해 리액트로 작성된 라이브러리를 프레이머로 옮김
  • 리액트 컴포넌트 수정시 디자인 컴포넌트도 수정되어 코드 동기화가 완료됨

언어가 다른것

  • 제플린, 피그마에서 디자인한건지 디자인시스템컴포넌트인지를 확인하려면 일일히 눌러봐야함
    • 토스에서는 손가락 이모지를 앞에 넣어서 명시적으로 이름을 바꿧음
      • button-1. fill-medium-primary (style, size, color)
    • 박스에 버튼이 있는경우, 알 수가 없음.. 박스에 들어가는 버튼인지 버튼만을 넣는것인지... (29:49)

왜 디자인을 다시 개발해야하는가? 프레이머로 커스텀 핸드오프 기능 구현

  • 클릭시 전체 자식 노드의 프롭 정보를 노출시킴 (32:09)
  • 개발자와 디자이너의 언어도 일치시킴

DST (Design Syntax Tree)

  • 리액트 노드의 형태를 모방해서 기계가 파싱가능한 트리구조로 추상화 (33:41)
  • DST Element (34:22) -> DST React Renderer (35:20) (35:38)
{
"elementType": "AmountTop",
"properties": {
"title": "",
"subtitle": "",
"button": {
"elementType": "button",
"properties": {
"Title": "",
"Type": "",
"Style": "fill"
}
}
}
}

디자인을 바로 코드로 옮기는 목표 달성

엄격함과 유연함

  • 디자인 시스템에 컴포넌트가 있는줄 몰랐어요
  • 구멍인 줄은 알았는데 자유롭게 쓰고 싶었어요
  • 컴포넌트를 쓰긴 했는데 패턴을 어긴지 몰랐어요 등등..
  • 커스텀 컴포넌트 계속 만들면 디자인시스템 도입 이전하고 똑같음
  • 리스트 컴포넌트 스펙 참조 (41:21)
    • 디자이너가 컴포넌트 목록을 잘 몰라서 새로 만드는 경우
    • 가이드가 힘들었음 (43:26)
    • 디자인 시스템 관리자가 매번 패턴 점검 필요

디자인 린터 (디자인 시스템 커버리지 계산기)

  • 권장 패턴이 아닌 경우 알림
  • DST 를 통해 디자인 분석
  • 크롬 확장프로그램으로
    • 프레이머 웹사이트의 html 에서 Dst 정보 파싱
    • DST 에서 컴포넌트 관계 분석
    • 권장 패턴에 맞게 사용중인지 계산 (권장 패턴 요소 개수 / 전체 요소 개수) (44:50)
    • 학습비용과 전파비용을 극복함

React + DST (46:20)

  • DST 의 스펙만 확장시키면 됨
  • Server driven UI 나 다른 언어 컴포넌트로 전환도 가능해보임.

A6: swc

  • 많은 벤더가 전환 중

개인적인 의견: 엄청 빨라짐, 아직 롤업 플러그인 지원은 미비, 모든 Node 생태계가 러스트로 이동 중, swcpack 프로덕션 기대

B1: recoil

개인적인 의견: 인포그래픽 아름다워서 공유용으로 적합.