Skip to main content

112 posts tagged with "javascript"

View All Tags

aggrid 디버깅

· One min read

AGGRID

  • 풀스펙을 지원하는 그리드
  • 대부분의 기능들은 엔터프라이즈 모듈로 분기되어있다.

모듈정보

  • Modules
    • ag-grid-react는 통 패키지
    • @ag-grid-community, @ag-grid-enterprise 스코프 하위는 모듈
  • Modules - Example

데이터 페칭

  • onGridReady 이후 실행
const onGridReady = useCallback((params: GridReadyEvent) => {
fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
.then((resp) => resp.json())
.then((data: IOlympicData[]) => setRowData(data));
}, []);

코드 예시

  • Full Spec
  • 여기서 보는 게 낫다. 문서가 최신화 되어있지 않다.

Atom-based state management and Valtio

· 3 min read

Overview

  • At one point, redux-saga seemed like a cool way to solve redux's tired state management, and then a combination of atomic states seemed like the way to go.
  • That's why I've mostly used recoil, but if you're using query or swr, you don't need such a complicated feature to manage local UI state.
  • recoil seems to be an almost abandoned project with only bug fixes in the meta. discussion#2171
  • Anyway, local UI state just needs to have a pub/sub pattern.
  • The winner of the 2023 state management library seems to be zustand.
    • If you're building an event/messaging based system, it makes sense to use that library with the Flux pattern.
    • If you're building an editor with action-based behavior for all front-end features, or if you're integrating with a chat system that receives function call requests, that's one thing.
  • But for a typical use case, Flux is overkill, except for cascading forms, badges, modals, etc.
  • If I were developing alone, I would want to separate the backend from the frontend, separate the Local, Dev, Stage, and Prod stages, and have a DB, scheduler, queue, API, and SSR stack.

atom

  • Read first; The new wave of React state management을 보자.
  • Atomic, pub/sub, and derived are possible.
  • Using derived state is also rarely necessary unless you need a new state per ID. For data, query already does the job.
  • Atomic design and atomic state management became a necessity.
  • With many developers working asynchronously, it was important to keep track of which files were atoms and what they were for.
  • We have a *.atom.ts file superfix and a *State variable name superfix.

valtio

  • Both jotai/atom and Recoil/atom manage atom-based state and propagate state.
  • valtio/proxy implements the same functionality using Proxy and Reflect.
  • Memory management is not the worst, as you can see from the Results for js web frameworks benchmark.
  • zustand, jotai, and valtio are all open source, covered by the pmndrs community, with the same person as a contributor and maintainer.
  • It just works, as his comments in valito/discussion#128 show.
  • valito/issues#141 Having spent a year on Redux and Redux-saga, and two years on Mobx POC and Recoil, this comment really resonated with me.
  • For the time being, I'm going to create several projects and try to use this state management library in all of them.

Migrate from yarn to pnpm

· 2 min read

Overview

  • Yarn berry was all the rage.
  • I tried it and found quite a few problems, which is why I ended up choosing pnpm.

Problems

zipfs

  • It stores all the packages and logs all the diffs. This is a major culprit for repository size. Difficult to manage images under 1GB.
  • If typescript goes up, yarn berry version should go up. I want to use the latest syntax in typescript right away, but I can't keep up.
  • I need to update the executable with yarn dlx @yarnpkg/sdks vscode whenever typescript, eslint, and prettier are released.
  • In a project with 20+ front-end developers, this is hard to enforce.
  • It is not possible to test this by making small changes to the source inside the package.

opensource

  • Monolithic tools like turbo, environments with postinstall hooks like prism, or preset configurators like create-* reference node_modules directly.
  • Often it won't even run, and you'll have to wait for an open issue in each repo. I'm not writing this to analyze yarn berry's pnp script.
  • In this case, I'd have to give it a nodeLinker and use it the same way I would with yarn 1, with no advantage.

workspaces

  • The yarn workspaces feature is cool, and yarnpkg/berry is a perfect example of it.
  • But it's only cool if you're only developing node.js libraries. Libraries for the frontend need a bundler, and there's no reference for that.

Benchmarks

  • Benchmark scores are managed by Pnpm on a daily basis.
  • Slowness is acceptable with pipeline cache and lock files enabled. It's a one-time slowdown, not a request/response slowdown, so it can be handled by probes anyway.

https://pnpm.io/benchmarks

Conclusion

  • The plugin features in yarn berry are cool, but they add more stress to dependency management.

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 등등..

패키지

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

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

nodejs alpine3.13 테스트

· 4 min read

개요

  • docker nodejs base image 에 alpine3.13 에 대한 이미지가 있어서 릴리즈노트를 확인했다.
  • Node.js (LTS) is compiled with -O2 instead of -Os which noticeably improves performance. 란 구문이 눈에 띄었다.
  • noticeably improves 란 추상적인 표현은 호기심을 자극하기에 충분했다.

히스토리

  • 처음에 빌드 플래그 변경을 제안한 사람에 따르면, 빌드 플래그 수정으로 15% speedup 이 있을 것이라고 하였다.
  • 이에 몇몇 알파인 패키지들이 O2 로 전환되었고, Node.js도 2020-12-19 커밋에 포함되었다.
  • 여기엔 아래와 같은 코멘트가 달려있고, v8/web-tooling-benchmark를 사용한 것으로 보였다.
# Compiling with O2 instead of Os increases binary size by ~10%
# (53.1 MiB -> 58.6 MiB), but also increases performance by ~20%
# according to v8/web-tooling-benchmark

테스트1

  • 빌드 플래그의 변경으로 nodejs 유저가 베이스 이미지의 버전을 하나 올려주는 것만으로 어플리케이션의 성능을 20% 까지 올릴 수 있다는 이야기로 보였다.
  • fastify/benchmarks 레파지토리의 Express.js 를 아래처럼 도커라이징했다.

node:lts-alpine3.12

# 테스트 당시 LTS === 14
FROM node:lts-alpine3.12

RUN mkdir -p /usr/src/app \
&& chown node:node -R /usr/src/app

WORKDIR /usr/src/app
COPY --chown=node:node package*.json ./

USER node
RUN npm install && npm cache clean --force

COPY --chown=node:node . .
EXPOSE 3000
CMD [ "node", "server.js" ]

node:lts-alpine3.13

# 테스트 당시 LTS === 14
FROM node:lts-alpine3.13

RUN mkdir -p /usr/src/app \
&& chown node:node -R /usr/src/app

WORKDIR /usr/src/app
COPY --chown=node:node package*.json ./

USER node
RUN npm install && npm cache clean --force

COPY --chown=node:node . .
EXPOSE 3000
CMD [ "node", "server.js" ]

결과1

컨테이너는 테스트되는 이미지만을 띄웠고, docker 4CPUs, 6G RAM 에서 실행했다.

autocannon -c 100 -d 40 -p 10 localhost:3000

부푼 기대만큼 결과가 같게 나왔으면 좋겠지만 결과 추가를 못할만큼 Latency, Req/Sec, Bytes/Sec 모든 수치에서 엎치락 뒤치락하는 모습을 보였다.

테스트2

  • noticeably improves 는 CPU intensive Task 를 비교해봐야하는 것일까란 의문만 남았다.
  • node official image 를 확인해보니 nodejs.org의 배포본을 풀어 사용하는 것으로 보였다.
  • 따라서 이미지를 alpine 패키지를 사용할 수 있게 재구성하고 테스트했다.

alpine:3.13

FROM alpine:3.13

RUN apk add --update nodejs npm
RUN addgroup -g 1000 node \
&& adduser -u 1000 -G node -s /bin/sh -D node \
&& mkdir -p /usr/src/app \
&& chown node:node -R /usr/src/app

WORKDIR /usr/src/app
COPY --chown=node:node package*.json ./

USER node
RUN npm install && npm cache clean --force

COPY --chown=node:node . .
EXPOSE 3000
CMD [ "node", "server.js" ]

결과2

  • 더 느렸다.

결론

  • noticeably improves, ~20% 란 문구로 인해 fastify/benchmarks 로직으로 도커라이징하여 테스트해보았으나 비슷한 퍼포먼스를 보여주었다.
  • 위의 수치를 검증할 수 있는 테스트베드가 있다면 돌려보고 싶다. (링크 있으시면 공유부탁드립니다.)

참조

yarn berry 마이그레이션 체크리스트

· One min read

체크리스트

  • yarn set version berry
  • rm -rf node_modules package-lock.json
  • yarn
  • .gitignore 추가
  • package.scripts 에서 다른 스크립트를 실행하는 경우, yarn 을 붙혀서 실행
  • .husky 변경
    • package.scripts "postinstall": "husky install"
    • 실행 훅 스크립트를 npx --no-install 에서 yarn 으로 변경
  • Dockerfile 변경 (node 기본이미지에 yarn은 베이스로 설치되어 있음)
    • yarn build
    • entrypoint 커맨드
  • 의존관계 패키지 추가 설치
  • 테스트

여담