전체 글 29

AI 에이전트에게 레퍼런스 코드를 직접 참조시켜야 할까?

배경최근 shadcn/ui를 레퍼런스로 삼아 비슷한 컴포넌트 라이브러리를 Claude와 바이브코딩 하던 중, 한 가지 의문이 생겼다."로컬에 shadcn 레포를 클론해두고 AI가 매번 참조하게 하면 더 나은 결과물이 나올까?"결론부터 말하면, 대부분의 경우 토큰 낭비다.왜 불필요한가1. 이미 학습 데이터에 포함되어 있다shadcn/ui는 GitHub 스타 수만 해도 수만 개에 달하는 메이저 오픈소스 프로젝트다.LLM의 학습 데이터에 이미 충분히 포함되어 있기 때문에, 별도로 소스 코드를 읽히지 않아도 패턴을 잘 알고 있다.CVA 기반 variant 정의, cn() 유틸리티를 활용한 클래스 병합, React.forwardRef 패턴, barrel export 구조 등 — 이런 것들은 굳이 원본 코드를 보여..

dev.log/개발 2026.03.13

나는 ArgTypes에 집착하는 사람이다

들어가기에 앞서일을 하다보면 나도 모르게 작은 디테일에 집착하게 된다.그러다 문득 내가 너무 피곤한 스타일이 아닌가 싶고, 이런 것까지 신경쓰는 게 이상한 것 같다는 느낌을 받을 때가 있다.이런 기분이 자꾸만 드는 현 상황이 어느 정도 이해는 되지만, 동시에 아쉽고 답답하다. 그냥 그렇다구. 요즘 나는 회사에서 디자인시스템 한 놈만 패고 있다. 그렇게 된 지 좀 됐다. 그래서일까, 평소보다 집착병이 심해진 느낌이다.그 단적인 예를 보여주는 최근의 썰 하나를 풀어볼까 한다.문제는 나일지도...?스토리북이 기본적으로 제공하는 Doc blocks인 ArgTypes는 argTypes에 작성한 정보를 기반으로 컴포넌트의 API를 문서화해준다. 나는 이 블록을 컴포넌트의 propTypes에 작성한 타입과 주석(설..

daily.log 2025.07.21

[Vite] Storybook HMR 이슈 해결

1. 문제컴포넌트 소스 변경 시 스토리북에서 즉시 반영되지 않는 이슈 (HMR 동작하지 않음)기존 설정모노레포 구조apps/docs # 스토리북으로 구성된 디자인 시스템 문서├── .storybook├── src└── package.json # 스토리북 실행 (dev: storybook dev -p 6006)packages/ds-components # 디자인 시스템 컴포넌트├── src├── dist └── package.json # 라이브러리 빌드 (build: vite build)스토리 파일(apps/docs/src/stories/button.stories.jsx)import { Button } from '@ds/components..

dev.log/개발 2025.02.24

[TS] 유틸리티 타입들

참조(이미지 포함): Do You Really Know These 6 TypeScript Utilities? 1. Pick Pick을 사용하면 주어진 타입에서 원하는 키들을 골라 새로운 타입을 만들 수 있다. interface User { id: number; firstName: string; lastName: string; age: number; phone: string; } type UserName = Pick; /* (위와 동일) interface UserName { firstName: string; lastName: string; } */ const userName: UserName = { firstName: 'Gildong', lastName: 'Hong' } 2. ..

dev.log/개발 2022.10.09

[React] 똑똑하게 useMemo 사용하기

참조(이미지 포함): When to useCallback & useMemo hooks ? 이 글은 [React] 똑똑하게 useCallback 사용하기에서 이어지는 글이다. 리액트의 성능 최적화에 대한 이야기와 useCallback 훅을 사용해 최적화 한 예시를 보고 싶다면, 위 글을 먼저 보고 오기를 추천한다! useMemo란 useMemo는 재사용된(memoized) 값을 반환하는 훅이다. 이 훅은 데이터의 많은 가공이 필요할 때 적합하다. 예를 들면, 복잡한 수학적 계산이 사용되는 경우나 계산하는데 오랜 시간이 걸리는 로직을 다루는 경우가 이에 해당된다. 먼저 이 함수는 컴포넌트의 첫 렌더 때 실행되고, 이후 리렌더가 될 때마다 캐시된 데이터를 반환해 보여준다. 매번 함수를 실행해서 내부 로직을 다..

dev.log/개발 2022.10.09

[JS] JavaScript에서 HTML 요소를 만드는 3가지 방법

이 글은 3 Ways To Create HTML Element In JavaScript을 참고하여 작성된 글입니다. 자바스크립트를 통해 아래와 같은 구조를 갖는 DOM을 만드는 방법 3가지를 알아보자. Click Me! 1. createElement() 사용하기 먼저 body에 app 요소를 추가한다. const app = document.createElement('div'); app.id = 'app'; document.body.appendChild(div); 그리고 app에 button 요소를 추가한다. const button = document.createElement('button'); button.id = 'button'; button.i..

dev.log/개발 2022.10.02

[React] 똑똑하게 useCallback 사용하기

이 글은 When to useCallback & useMemo hooks ? 의 번역글입니다. (이미지 포함) 개발자의 숙명, 어플리케이션 성능 최적화 성능 최적화는 개발자라면 누구든 어플리케이션 빌드 이후 마주하게 되는 흔한 이슈이다. 하지만 개발할 때는 완벽하게 동작했던 시스템이 배포 후 운영 시에 더 느려지는 느낌이 드는 건 단순한 착각일까? 개발 모드일 때 더 빠르게 느껴지는 이유 어플리케이션이 개발 모드일 때는 모든 파일들이 로컬 머신 즉, 내 컴퓨터를 통해 로컬 포트 3000번(React 기준)에 호스팅이 된다. 로컬에서 개발을 하기 때문에 인터넷 속도에 그다지 영향을 받지 않는 경우, 번들 파일들을 다운로드 받는 것은 굉장히 효율적이며 빠르게 동작한다. 하지만 운영 시에는 인터넷이 굉장히 느..

dev.log/개발 2022.10.02

[TS] 빈 객체에 대한 올바른 타입

{} 을 타입으로 사용하지 않기 빈 객체에 {} 타입을 지정하면 @typescript-eslint/ban-types 경고가 발생한다. {} 타입은 null이 아닌 모든 값이라는 뜻이기 때문에 타입을 지정했음에도 컴파일 때 이 값이 객체인지 뭔지 알 방법이 없게 된다. 따라서 상황에 따라 구체적으로 타입을 지정해줄 필요가 있다. 정말로 빈 객체인 경우 Record 프로퍼티 값에 never를 지정함으로써 어떤 값도 담기지 않을 빈 객체임을 나타낸다. 객체인 경우 Record 프로퍼티 값에 unknown을 지정함으로써 모든 타입의 값이 할당될 수 있는 객체임을 명시해준다. 값인 경우 unknown 객체가 아닌 어떤 값이든 할당될 수 있다는 걸 의미한다.

dev.log/개발 2022.09.03

[react-youtube] videoId에 따라 영상이 변경되지 않을 때

react-youtube react-youtube는 YouTube IFrame Player API를 리액트 컴포넌트로서 구현한 패키지이다. 사용법은 너무나 간단하니 공식 문서를 참고하자. videoId가 바뀌어도 영상이 변경되지 않는다? 빠르게 유튜브 플레이어를 서비스에 포함시키고자 사용했는데, 몇 가지 이슈가 있었다. 그 중에 하나는 props로 내려받은 videoId에 따라 영상이 업데이트 되지 않는다는 거였다. 이해를 돕기 위해 공식 문서의 예제를 가져왔다. 여기서 우리는 videoId가 변경되면 Example 컴포넌트가 리렌더 되면서 영상이 변경될 것으로 예상할 수 있다. 하지만 영상이 변경되지 않았다! import YouTube from 'react-youtube'; functio..

dev.log/개발 2022.09.02

[JS] 클로저(Closure) 활용하기

클로저란 반환되는 함수가 반환시킨 함수의 변수 환경을 묶어서(closing) 기억하고 있는 개념을 말한다. 일반적인 경우 함수의 실행이 종료되어 콜 스택에서 제거되면 해당 함수 내부에 선언된 변수에 접근할 수 있는 방법이 없다. 하지만 반환된 함수는 자신을 반환시킨 함수가 콜 스택에서 제거되어도 여전히 그 스코프에 접근하여 변수를 참조할 수 있게 된다. 이는 반환된 함수는 자신이 호출될 때가 아니라 선언될 때의 환경(Lexical Environment)을 기억하고 클로저 스코프를 갖기 때문에 콜 스택에 반환시킨 함수가 없더라도 스코프 체인을 통해 변수를 참조할 수 있게 되는 것이다. 이해를 돕기 위한 간단한 예제이다. // inner 함수를 반환시키는 함수 function outer() { const o..

dev.log/개발 2022.08.28