[Nuxt Content] 네비게이션 아이콘 커스텀 빌드
🧐 1. 내가 직접 만든 이미지를 메뉴 아이콘으로 넣고 싶다


현재 개발 중인 brolog 프로젝트는 Nuxt 4 프레임워크와 Nuxt Content 모듈을 기반으로 구축된 기술 블로그/문서화 시스템이다. 이 환경에서는 사이드바 메뉴를 구성하기 위해 Nuxt Content가 제공하는 전용 네비게이션 설정 파일인 navigation.yml을 활용하게 된다.
메인 사이드바 메뉴 구조를 설계하던 중, 메뉴명 앞에 흔한 오픈소스 아이콘(lucide:*, mdi:*) 대신 내가 직접 디자인하고 제작한 brolog만의 전용 브랜드 로고와 커스텀 그래픽 이미지를 넣고 싶다는 니즈가 생겼다.
하지만 기본적으로 Nuxt Content의 navigation.yml 구조는 철저히 정형화된 외부 아이콘셋 명칭만 인식하는 스펙을 가지고 있다.
# navigation.yml (기존 형태)
- title: "대시보드"
path: /dashboard
icon: "lucide:layout" # 오픈소스 아이콘 이름만 지원됨
- title: "내가 만든 전용 로고 메뉴"
path: /brand
icon: "/images/my-logo.png" # ❌ 엑스박스 발생 및 컴포넌트 깨짐 현상
Nuxt Content 내부 스펙상 icon 필드는 무조건 @nuxt/icon 모듈의 <Icon name="..." /> 컴포넌트와 긴밀하게 결합해 내부적으로 파싱된다. 이 때문에 저 자리에 일반 이미지 웹 경로(png, jpg)를 무작정 적으면 렌더링 규격이 맞지 않아 아예 화면에 출려되지 않는 한계가 존재했다.
내부 컴포넌트를 커스텀하여 이미지도 사용이 가능하도록 수정하려다, 관점을 조금 바꾸어 보았다.
"기존 내장 컴포넌트 코드를 인위적으로 수정하여 이미지 태그 분기문으로 제어하는 대신, 내가 제작한 그래픽 리소스 자체를 Nuxt 아이콘 시스템이 다룰 수 있는 규격화된 아이콘 패키지로 빌드하여 매핑하는 방법이 없을까?" 라는 궁금증이 떠올랐고, 그에 맞는 해법을 찾아냈다.
🛠️ 2. 해결 전략: 내가 만든 이미지를 customCollections로 규격화
해답은 Nuxt 4의 핵심 아키텍처인 멀티 레이어 구조에서 풀렸다. 하위 레이어(layer/nuxt.config.ts)에 이미 마중물처럼 뚫려 있던 customCollections 인프라 설정을 발견하면서 명쾌하게 가닥이 잡혔다.
💡 핵심 메커니즘
내가 직접 만든 그래픽 이미지를 순수 SVG 포맷으로 저장한 뒤, 모듈이 지정한 로컬 아이콘 디렉토리에 정적 배치하는 방식이다. 이렇게 하면 Nuxt Icon 엔진이 빌드(또는 개발 서버 구동) 시점에 해당 폴더 안의 SVG 파일들을 스캔하여, 마치 Lucide나 Material Design Icons처럼 우리가 직접 커스텀한 독립 아이콘셋으로 빌드 컨텍스트에 포함시킨다.
📦 3. 실제 적용 및 해결 프로세스
① 1단계: 레이어 설정의 커스텀 디렉토리 경로 확인
Nuxt 4 구조에 맞게 세팅된 하위 레이어 설정 파일에 로컬 아이콘 소스 디렉토리가 다음과 같이 명시되어 있는 상태였다.
// layer/nuxt.config.ts
export default defineNuxtConfig({
icon: {
customCollections: [
{
prefix: 'custom', // 👈 내가 만든 아이콘들을 호출할 고유 접두사(네임스페이스)
dir: resolve('./app/assets/icons'), // 👈 내가 만든 SVG 파일들을 모아둘 보관소
},
],
clientBundle: {
scan: true,
includeCustomCollections: true, // 로컬 커스텀 번들에 포함 처리
}
},
})
② 2단계: 내가 만든 커스텀 SVG 파일 배치
메뉴 아이콘으로 사용하고 싶은 나만의 로고나 심볼 이미지를 피그마(Figma)나 일러스트레이터에서 순수 SVG 포맷으로 추출했다. 그 후 레이어에 지정된 로컬 경로(app/assets/icons/) 안에 원하는 아이콘 명칭으로 파일을 투하했다.
- 파일 저장 예시:
app/assets/icons/brolog-logo.svg,app/assets/icons/rocket-fire.svg
③ 3단계: navigation.yml에서 내 아이콘 호출하기
이제 일반 외부 오픈소스 아이콘을 불러 쓰던 방식과 100% 동일하게 설정한접두사(prefix):내가만든파일명 구조로 navigation.yml에 선언해 주기만 하면 끝이다.
# navigation.yml (최종 최적화 형태)
- title: "브랜드 소개"
path: /brand
icon: "custom:brolog-logo" # 👈 내가 만든 brolog-logo.svg가 시스템 아이콘처럼 완벽 매핑!
- title: "출시 가이드"
path: /launch
icon: "custom:rocket-fire" # 👈 직접 디자인한 전용 론칭 그래픽 SVG 즉시 적용
- title: "일반 설정"
path: /settings
icon: "lucide:settings" # 👈 기존 글로벌 오픈소스 아이콘과도 아무런 충돌 없이 혼용 가능
🧠 4. 경험을 통해 얻은 인사이트 및 결론
- Nuxt Content 컴포넌트 무결성 유지: 네비게이션 링크를 렌더링하는 Nuxt Content 모듈 내부의 복잡한 UI 소스 코드를 단 한 줄도 수정하거나 커스텀 오버라이딩하지 않고, 순수하게 설정과 정적 파일 배치만으로 원하는 커스텀 비주얼을 완벽히 녹여냈다.
- 디자인 시스템과의 융합: 일반 PNG/JPG 이미지를 썼을 때 발생하는 해상도 깨짐이나 크기 조절의 번거로움이 사라졌다. 내가 만든 이미지가 정식 벡터(SVG) 아이콘으로 취급되면서 기존 UI의 다크모드 대응이나 폰트 크기(
w-4 h-4등) 규칙에 유연하게 동기화되는 높은 완성도를 보여주었다. - Nuxt 4 멀티 레이어 기반의 프로젝트에서 전용 에셋을 서비스 전체에 가볍고 효율적으로 전파하고자 할 때, 일반 이미지를 아이콘 컬렉션으로 승격시키는 이 방식은 결합도를 낮추는 가장 영리한 해법임을 실무적으로 경험했다.
