1️⃣ headless ui의 <Menu> vs <ListBox>
오늘은 DropdownSelect 컴포넌트 구현에 headless ui를 적용해보면서, headless가 제공하는 `<Menu/>` 기반 드롭다운과 `<ListBox/>` 기반 드롭다운의 차이점을 알게 되었다.
<Menu/> 드롭다운
- 주로 사용자가 무언가를 선택하면 특정 동작이 실행되는 경우에 적합하다고 한다.
- 예: "로그아웃" 버튼 클릭 시 바로 로그아웃 실행
- '선택'보다는 '실행'의 목적
<ListBox/> 드롭다운
- 여러 옵션 중에서 하나의 값(또는 여러 값)을 선택해야 할 때 사용하며, 주로 셀렉트 박스(select box)나 콤보박스처럼 폼 입력 요소로 활용될 때 적절하다.
- '단순 선택' 목적
2️⃣ sharp를 이용한 저화질 이미지 제공에 관해
멘토님께 중요한 피드백을 받아서 꼭 기록해두고 싶었다. (사실 곧 까먹을 것 같았음)
서버에서 sharp를 사용해 화질이 저하된 blur 이미지 url을 반환하는 getBlurImage()를 썸네일 이미지 미리보기 제공하는 곳에 썼었는데, 이건 sharp를 적절하게 사용한 케이스가 아니었다.(!)
웹 성능에 가장 큰 영향을 미치는 게 이미지인데, 다수의 비동기 이미지 목록을 보여줘야 할 때는 그만큼 이미지 최적화가 중요해지고, 이때 next 서버에서는 자동으로 이미지 최적화를 해준다. 여기서 sharp의 연산을 모든 이미지를 불러올 때마다 추가로 실행시켜버리면 그만큼 서버가 또 일을 하게 되는 거고, 결과적으로는 서버 자원 낭비가 되는 것이다.
그래서 shrap는 일반 유저와 프리미엄 유저를 나눠서, 일반 유저에게는 저화질의 미리보기 이미지만 제공해야 하는 경우와 같이 '조건적으로 사용했을 때 좋은' 라이브러리라고 한다.
그리고 blur 이미지 미리보기는 아주 간단하게 css와 Image의 onLoad 속성만으로도 제공해줄 수 있다.
const ActivityItem = ({ item }: { item: Activity }) => {
const [isLoaded, setIsLoaded] = useState(false);
return (
<Image
...
className={`h-full w-full object-cover ${isLoaded ? 'blur-0 scale-100 opacity-100' : 'scale-105 opacity-60 blur-md'} `}
onLoad={() => setIsLoaded(true)}
/>
)
}'✨회고' 카테고리의 다른 글
| 9/1 회고 - zustand와 'use client' (0) | 2025.09.12 |
|---|---|
| 8/26 회고 - next.js에서의 초기 데이터 fetch + 무한 스크롤 (0) | 2025.09.12 |
| 8/23 회고 - debounce.ts (with TypeScript) (0) | 2025.09.12 |
| 자바스크립트 리팩토링 회고🔍 - 폼 유효성 검사 (0) | 2025.05.01 |