[{"data":1,"prerenderedAt":2520},["ShallowReactive",2],{"navigation_docs_ko":3,"-ko-project-brobean-brobean-dev-log-02":209,"-ko-project-brobean-brobean-dev-log-02-surround":2515},[4,124,195],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":27},"Note (개발 지식)","emojione-v1:note-pad","\u002Fko\u002Fnote","ko\u002F1.note",[10,28,42,68,78,88,104,114],{"title":11,"icon":12,"path":13,"stem":14,"children":15,"page":27},"Spring","logos:spring-icon","\u002Fko\u002Fnote\u002Fspring","ko\u002F1.note\u002F0.spring",[16],{"title":17,"icon":18,"path":19,"stem":20,"children":21,"page":27},"Spring Ai","custom:ai","\u002Fko\u002Fnote\u002Fspring\u002Fspring-ai","ko\u002F1.note\u002F0.spring\u002F1.spring-ai",[22],{"title":23,"path":24,"stem":25,"icon":26},"Spring AI 핵심 개념과 LLM 애플리케이션 구조 이해","\u002Fko\u002Fnote\u002Fspring\u002Fspring-ai\u002Fspring-ai","ko\u002F1.note\u002F0.spring\u002F1.spring-ai\u002F1.spring-ai","lucide:file-text",false,{"title":29,"icon":30,"path":31,"stem":32,"children":33,"page":27},"Javascript","skill-icons:javascript","\u002Fko\u002Fnote\u002Fjavascript","ko\u002F1.note\u002F1.javascript",[34,38],{"title":35,"path":36,"stem":37,"icon":26},"Promise.all과 구조 분해 할당을 활용한 데이터 처리 패턴","\u002Fko\u002Fnote\u002Fjavascript\u002Fdestructuring","ko\u002F1.note\u002F1.javascript\u002F1.destructuring",{"title":39,"path":40,"stem":41,"icon":26},"JavaScript 배열 고차 함수와 데이터 처리 패턴 이해","\u002Fko\u002Fnote\u002Fjavascript\u002Ffilter","ko\u002F1.note\u002F1.javascript\u002F2.filter",{"title":43,"icon":44,"path":45,"stem":46,"children":47,"page":27},"Nuxt4","logos:nuxt-icon","\u002Fko\u002Fnote\u002Fnuxt4","ko\u002F1.note\u002F2.nuxt4",[48,52,56,60,64],{"title":49,"path":50,"stem":51,"icon":26},"Nuxt 4를 선택한 이유와 아키텍처 및 실무 가이드","\u002Fko\u002Fnote\u002Fnuxt4\u002Fnuxt-info","ko\u002F1.note\u002F2.nuxt4\u002F1.nuxt-info",{"title":53,"path":54,"stem":55,"icon":26},"Nuxt useAsyncData 동작 원리와 SSR 데이터 페칭 최적화","\u002Fko\u002Fnote\u002Fnuxt4\u002Fnuxt-use_async_data","ko\u002F1.note\u002F2.nuxt4\u002F2.nuxt-use_async_data",{"title":57,"path":58,"stem":59,"icon":26},"Nuxt Content v3 데이터 모델과 Query 시스템 이해","\u002Fko\u002Fnote\u002Fnuxt4\u002Fnuxt-content-v3","ko\u002F1.note\u002F2.nuxt4\u002F3.nuxt-content-v3",{"title":61,"path":62,"stem":63,"icon":26},"Nuxt Auto-imports 내부 동작과 컴파일 과정 분석","\u002Fko\u002Fnote\u002Fnuxt4\u002Fnuxt-auto-import","ko\u002F1.note\u002F2.nuxt4\u002F4.nuxt-auto-import",{"title":65,"path":66,"stem":67,"icon":26},"Nuxt 렌더링 방식 이해: SSR, SSG, ISR, CSR 구현 방법","\u002Fko\u002Fnote\u002Fnuxt4\u002Fnuxt-rendering-strategy","ko\u002F1.note\u002F2.nuxt4\u002F5.nuxt-rendering-strategy",{"title":69,"icon":70,"path":71,"stem":72,"children":73,"page":27},"Nitro","unjs:nitro","\u002Fko\u002Fnote\u002Fnitro","ko\u002F1.note\u002F3.nitro",[74],{"title":75,"path":76,"stem":77,"icon":26},"Nitro 아키텍처와 서버 엔진 구조","\u002Fko\u002Fnote\u002Fnitro\u002Fnitro","ko\u002F1.note\u002F3.nitro\u002Fnitro",{"title":79,"icon":80,"path":81,"stem":82,"children":83,"page":27},"Devops","vscode-icons:file-type-pipeline","\u002Fko\u002Fnote\u002Fdevops","ko\u002F1.note\u002F4.devops",[84],{"title":85,"path":86,"stem":87,"icon":26},"서버사이드 WebAssembly(Wasm)와 차세대 실행 환경","\u002Fko\u002Fnote\u002Fdevops\u002Fwebassembly","ko\u002F1.note\u002F4.devops\u002F1.webAssembly",{"title":89,"icon":90,"path":91,"stem":92,"children":93,"page":27},"Tooling","lucide:wrench","\u002Fko\u002Fnote\u002Ftooling","ko\u002F1.note\u002F4.tooling",[94],{"title":95,"icon":96,"path":97,"stem":98,"children":99,"page":27},"Package Manager","devicon:npm","\u002Fko\u002Fnote\u002Ftooling\u002Fpackage-manager","ko\u002F1.note\u002F4.tooling\u002F1.package-manager",[100],{"title":101,"path":102,"stem":103,"icon":26},"Package Lock 파일의 역할과 의존성 관리 원리","\u002Fko\u002Fnote\u002Ftooling\u002Fpackage-manager\u002Fpackage-lock","ko\u002F1.note\u002F4.tooling\u002F1.package-manager\u002F1.package-lock",{"title":105,"icon":106,"path":107,"stem":108,"children":109,"page":27},"Web","streamline-plump:web","\u002Fko\u002Fnote\u002Fweb","ko\u002F1.note\u002F4.web",[110],{"title":111,"path":112,"stem":113,"icon":26},"웹 애플리케이션 렌더링 아키텍처 이해","\u002Fko\u002Fnote\u002Fweb\u002Frendering-modes","ko\u002F1.note\u002F4.web\u002F2.rendering-modes",{"title":115,"icon":116,"path":117,"stem":118,"children":119,"page":27},"SEO","icon-park-solid:seo","\u002Fko\u002Fnote\u002Fseo","ko\u002F1.note\u002F6.seo",[120],{"title":121,"path":122,"stem":123,"icon":26},"[SEO] 개발 블로그 검색 노출을 위한 robots.txt와 SEO 설정 가이드","\u002Fko\u002Fnote\u002Fseo\u002Fseo","ko\u002F1.note\u002F6.seo\u002F1.seo",{"title":125,"icon":126,"path":127,"stem":128,"children":129,"page":27},"Project (개발일지)","icon-park-solid:branch-two","\u002Fko\u002Fproject","ko\u002F2.project",[130,181],{"title":131,"icon":132,"path":133,"stem":134,"children":135,"page":27},"Brolog","custom:symbol","\u002Fko\u002Fproject\u002Fbrolog","ko\u002F2.project\u002F1.brolog",[136,140,144,148,152,156,160,164,168,173,177],{"title":137,"path":138,"stem":139,"icon":26},"[Brolog] 프로젝트 개요","\u002Fko\u002Fproject\u002Fbrolog\u002Foutline","ko\u002F2.project\u002F1.brolog\u002F1.outline",{"title":141,"path":142,"stem":143,"icon":26},"[Brolog] Nuxt Multi Layer 프로젝트 Vercel 배포 (3) - Runtime 기능 문제 분석과 AI Assistant 전환","\u002Fko\u002Fproject\u002Fbrolog\u002Fvercel-deploy3-ai-integration","ko\u002F2.project\u002F1.brolog\u002F10.vercel-deploy3-ai-integration",{"title":145,"path":146,"stem":147,"icon":26},"[Brolog] AI Assistant 적용 과정 - Agent 구조와 API 사용량 관리 시 고려사항","\u002Fko\u002Fproject\u002Fbrolog\u002Fai-assistant-application-process","ko\u002F2.project\u002F1.brolog\u002F11.ai-assistant-application-process",{"title":149,"path":150,"stem":151,"icon":26},"[Brolog] 검색 엔진 노출을 위한 SEO 적용 과정","\u002Fko\u002Fproject\u002Fbrolog\u002Fbrolog-seo","ko\u002F2.project\u002F1.brolog\u002F12.brolog-seo",{"title":153,"path":154,"stem":155,"icon":26},"[Brolog] 프로젝트 구조","\u002Fko\u002Fproject\u002Fbrolog\u002Fstructure","ko\u002F2.project\u002F1.brolog\u002F2.structure",{"title":157,"path":158,"stem":159,"icon":26},"[Brolog] Nuxt Content 네비게이션 아이콘 커스텀 빌드","\u002Fko\u002Fproject\u002Fbrolog\u002Fcustom-icon","ko\u002F2.project\u002F1.brolog\u002F3.custom-icon",{"title":161,"path":162,"stem":163,"icon":26},"[Brolog] Nuxt4 Auto-imports 동작 원리와 자동 import 시스템 이해","\u002Fko\u002Fproject\u002Fbrolog\u002Fnuxt-auto-import","ko\u002F2.project\u002F1.brolog\u002F4.nuxt-auto-import",{"title":165,"path":166,"stem":167,"icon":26},"[Brolog] 개발 블로그 메인 페이지 구현","\u002Fko\u002Fproject\u002Fbrolog\u002Fdevelop-main","ko\u002F2.project\u002F1.brolog\u002F5.develop-main",{"title":169,"path":170,"stem":171,"icon":172},"[Brolog] 브랜드 아이덴티티 적용 - Custom 404 페이지와 Default No Image 구현","\u002Fko\u002Fproject\u002Fbrolog\u002Fcustom-error-and-default-thumbnail","ko\u002F2.project\u002F1.brolog\u002F6.custom-error-and-default-thumbnail","lucide:image",{"title":174,"path":175,"stem":176,"icon":26},"[Brolog] Nuxt Multi Layer 프로젝트 Vercel 배포 (1)","\u002Fko\u002Fproject\u002Fbrolog\u002Fvercel-deploy1","ko\u002F2.project\u002F1.brolog\u002F8.vercel-deploy1",{"title":178,"path":179,"stem":180,"icon":26},"[Brolog] Nuxt Multi Layer 프로젝트 Vercel 배포 (2) - Build Pipeline 오류 분석과 Nuxt 실행 구조 이해","\u002Fko\u002Fproject\u002Fbrolog\u002Fvercel-deploy2-error-analyze","ko\u002F2.project\u002F1.brolog\u002F9.vercel-deploy2-error-analyze",{"title":182,"icon":183,"path":184,"stem":185,"children":186,"page":27},"Brobean","custom:brobean","\u002Fko\u002Fproject\u002Fbrobean","ko\u002F2.project\u002F2.brobean",[187,191],{"title":188,"path":189,"stem":190,"icon":26},"[BroBean] 연인과 함께 사용하는 가계부: BroBean - 프로젝트 기획과 이름의 탄생","\u002Fko\u002Fproject\u002Fbrobean\u002Fbrobean-dev-log-01","ko\u002F2.project\u002F2.brobean\u002F1.brobean-dev-log-01",{"title":192,"path":193,"stem":194,"icon":26},"[BroBean] 연인과 함께 사용하는 가계부: BroBean 프로젝트 시작 - Nuxt 4 기반 프론트 개발 환경 구축","\u002Fko\u002Fproject\u002Fbrobean\u002Fbrobean-dev-log-02","ko\u002F2.project\u002F2.brobean\u002F2.brobean-dev-log-02",{"title":196,"icon":197,"path":198,"stem":199,"children":200,"page":27},"Error (트러블슈팅)","emojione:stop-sign","\u002Fko\u002Ftrouble-shooting","ko\u002F3.trouble-shooting",[201],{"title":131,"icon":132,"path":202,"stem":203,"children":204,"page":27},"\u002Fko\u002Ftrouble-shooting\u002Fbrolog","ko\u002F3.trouble-shooting\u002F1.brolog",[205],{"title":206,"path":207,"stem":208,"icon":26},"[Nuxt Content] Nuxt Icon 오류 해결과 Custom Collection 기반 오프라인 아이콘 구성","\u002Fko\u002Ftrouble-shooting\u002Fbrolog\u002Fnuxt-icon-restricted-network-troubleshooting","ko\u002F3.trouble-shooting\u002F1.brolog\u002F1.nuxt-icon-restricted-network-troubleshooting",{"id":210,"title":192,"body":211,"date":2497,"description":2498,"extension":2499,"links":2500,"meta":2501,"navigation":2510,"path":193,"seo":2511,"stem":194,"__hash__":2514},"docs_ko\u002Fko\u002F2.project\u002F2.brobean\u002F2.brobean-dev-log-02.md",{"type":212,"value":213,"toc":2469},"minimark",[214,219,228,231,234,250,253,256,259,271,278,281,285,288,291,294,301,304,306,310,315,318,325,332,335,342,345,347,351,354,361,364,368,371,374,391,394,397,399,403,406,409,429,432,435,437,441,444,447,453,456,459,461,464,470,472,476,479,482,489,492,494,498,501,515,518,521,523,527,530,541,544,546,550,553,556,563,565,569,572,575,578,586,589,600,603,605,609,612,615,629,632,634,638,641,647,650,653,656,675,678,681,683,687,690,693,699,702,705,712,714,718,721,724,726,743,746,748,752,755,758,772,775,777,781,784,787,794,797,800,802,806,809,811,818,821,824,827,832,834,838,842,848,852,858,862,865,867,871,874,877,884,887,890,893,895,899,902,909,912,914,917,920,923,929,932,934,937,940,943,954,957,959,962,965,968,970,973,976,979,990,993,995,998,1001,1004,1006,1010,1013,1016,1019,1021,1025,1029,1032,1062,1065,1068,1074,1077,1079,1083,1086,1092,1095,1101,1104,1107,1114,1117,1119,1123,1126,1129,1136,1138,1142,1158,1161,1163,1167,1170,1187,1190,1197,1199,1203,1206,1232,1235,1295,1298,1300,1304,1307,1321,1324,1331,1333,1337,1340,1343,1349,1352,1354,1358,1361,1364,1366,1370,1373,1379,1382,1384,1390,1393,1396,1398,1402,1404,1410,1413,1416,1419,1421,1425,1427,1433,1436,1439,1457,1460,1463,1469,1472,1475,1477,1481,1483,1489,1492,1495,1498,1510,1513,1515,1519,1522,1525,1653,1656,1663,1666,1668,1672,1675,1678,1707,1710,1716,1719,1721,1725,1732,1738,1740,1746,1749,1755,1758,1761,1764,1789,1791,1795,1798,1805,1810,1812,1816,1819,1821,1827,1829,1832,1835,1838,1845,1847,1851,1854,1857,1860,2011,2013,2017,2020,2022,2029,2032,2064,2067,2070,2077,2080,2083,2085,2089,2092,2181,2183,2187,2190,2193,2200,2203,2214,2217,2220,2222,2226,2232,2235,2242,2244,2248,2251,2254,2260,2263,2266,2273,2276,2279,2285,2288,2290,2294,2297,2304,2306,2310,2313,2316,2318,2324,2327,2338,2340,2343,2346,2349,2351,2357,2359,2362,2365,2367,2373,2375,2378,2381,2383,2389,2392,2394,2398,2401,2408,2410,2414,2417,2420,2423,2425,2428,2435,2437,2440,2454,2457,2459,2462,2465],[215,216,218],"h1",{"id":217},"brobean-가계부-앱-프로젝트-시작","💰 BroBean 가계부 앱 프로젝트 시작",[220,221,222,223,227],"p",{},"이번 프로젝트는 연인이나 부부가 함께 사용할 수 있는 ",[224,225,226],"strong",{},"공유 가계부 서비스 BroBean"," 개발을 목표로 시작했다.",[220,229,230],{},"기존에는 개인 단위의 가계부 서비스가 많았지만, 실제 생활에서는 커플이나 부부처럼 두 명 이상의 사용자가 함께 소비 기록을 관리해야 하는 경우가 많다.",[220,232,233],{},"BroBean은 이러한 상황을 고려하여:",[235,236,237,241,244,247],"ul",{},[238,239,240],"li",{},"함께 사용하는 가계부",[238,242,243],{},"소비 기록 공유",[238,245,246],{},"공동 목표 관리",[238,248,249],{},"직관적인 모바일 중심 UI",[220,251,252],{},"를 목표로 개발하는 프로젝트다.",[220,254,255],{},"이번 프로젝트는 처음부터 완성된 서비스를 빠르게 만드는 것보다, 실제 서비스 개발 과정을 경험하는 것을 목표로 진행한다.",[220,257,258],{},"전체 개발 순서는 다음과 같이 계획했다.",[260,261,268],"pre",{"className":262,"code":264,"filename":265,"language":266,"meta":267},[263],"language-text","Frontend 개발\n\n↓\n\nUI \u002F Layout \u002F 기능 설계\n\n↓\n\nMock Data 기반 기능 구현\n\n↓\n\nDatabase 및 API 설계\n\n↓\n\nSpring Boot Backend 개발\n\n↓\n\n서비스 배포\n","Development Flow","text","",[269,270,264],"code",{"__ignoreMap":267},[220,272,273,274,277],{},"이번 첫 번째 단계에서는 ",[224,275,276],{},"프론트엔드 환경 구축과 기술 스택 선정 과정","을 기록한다.",[279,280],"hr",{},[215,282,284],{"id":283},"️-프로젝트-개발-방향","🏗️ 프로젝트 개발 방향",[220,286,287],{},"BroBean은 모바일 사용성을 가장 중요하게 고려했다.",[220,289,290],{},"가계부 서비스 특성상 사용자는 PC보다 모바일 환경에서 소비 내역을 빠르게 기록하는 경우가 많기 때문이다.",[220,292,293],{},"따라서 초기 개발 방향은 다음과 같이 설정했다.",[260,295,299],{"className":296,"code":297,"filename":298,"language":266,"meta":267},[263],"Mobile First UI\n\n↓\n\nResponsive Web\n\n↓\n\nHybrid App 확장 고려\n\n↓\n\nBackend API 연결\n","BroBean Development Direction",[269,300,297],{"__ignoreMap":267},[220,302,303],{},"처음부터 네이티브 앱으로 개발하기보다, 웹 기반으로 서비스를 제작한 이후 필요하다면 하이브리드 앱 형태로 확장하는 방향을 선택했다.",[279,305],{},[215,307,309],{"id":308},"️-frontend-기술-스택-선정-과정","⚙️ Frontend 기술 스택 선정 과정",[311,312,314],"h2",{"id":313},"후보군-검토","후보군 검토",[220,316,317],{},"프론트엔드 개발 환경을 결정하기 위해 다음 기술들을 검토했다.",[260,319,323],{"className":320,"code":321,"filename":322,"language":266,"meta":267},[263],"React + Next.js\n\nVue + Nuxt\n\nFlutter\n\nReact Native\n","Frontend Candidates",[269,324,321],{"__ignoreMap":267},[220,326,327,328,331],{},"모바일 환경까지 고려하면 Flutter나 React Native도 좋은 선택지가 될 수 있었지만, 이번 프로젝트의 방향은 ",[224,329,330],{},"모바일 웹 기반 서비스를 먼저 완성한 뒤 필요하다면 하이브리드 앱으로 확장하는 것","이었다.",[220,333,334],{},"또한 이전 Brolog 프로젝트를 개발하면서 Nuxt 생태계를 경험했고, SSR 구조와 Nuxt Content 기반 개발 환경을 활용해본 경험이 있었다.",[220,336,337,338,341],{},"Brolog에서는 Nuxt Docus Theme라는 기존 템플릿 위에서 프로젝트를 확장하는 방식으로 진행했다면, 이번 BroBean에서는 Nuxt 프로젝트를 직접 구성하면서 ",[224,339,340],{},"프레임워크의 구조와 동작 방식을 더 깊게 이해하는 것","을 목표로 했다.",[220,343,344],{},"이에 따라 최종적으로 Vue 기반 생태계를 활용할 수 있는 Nuxt를 선택했다.",[279,346],{},[215,348,350],{"id":349},"nuxt-선택-이유","🚀 Nuxt 선택 이유",[220,352,353],{},"최종 Frontend 기술 스택은 다음과 같이 결정했다.",[260,355,359],{"className":356,"code":357,"filename":358,"language":266,"meta":267},[263],"Nuxt 4\n\nVue 3\n\nTypeScript\n","Frontend Stack",[269,360,357],{"__ignoreMap":267},[220,362,363],{},"조합을 선택했다.",[311,365,367],{"id":366},"기존-경험을-기반으로-한-확장성","기존 경험을 기반으로 한 확장성",[220,369,370],{},"Brolog 프로젝트를 진행하면서 Nuxt 기반 개발 경험을 쌓았고, 실제 서비스 형태의 프로젝트에서 Nuxt가 제공하는 구조적인 장점을 확인할 수 있었다.",[220,372,373],{},"특히:",[235,375,376,379,382,385,388],{},[238,377,378],{},"자동 라우팅 시스템",[238,380,381],{},"Vue 기반 컴포넌트 구조",[238,383,384],{},"SSR \u002F SPA 선택 가능",[238,386,387],{},"Nuxt Module 생태계",[238,389,390],{},"TypeScript 지원",[220,392,393],{},"등은 장기적으로 서비스를 확장하는 데 적합하다고 판단했다.",[220,395,396],{},"하지만 이번 프로젝트에서는 기존처럼 준비된 템플릿이나 Theme를 활용하는 방식이 아니라, 프로젝트 생성부터 디렉토리 구조 설계, UI 구성, 상태 관리까지 직접 경험하는 것을 목표로 했다.",[279,398],{},[311,400,402],{"id":401},"vue-기반-개발-경험-활용","Vue 기반 개발 경험 활용",[220,404,405],{},"Vue 기반 개발 방식은 컴포넌트 구조가 직관적이고, UI 중심 서비스 개발과 잘 맞는다.",[220,407,408],{},"가계부 서비스는:",[235,410,411,414,417,420,423,426],{},[238,412,413],{},"거래 내역 목록",[238,415,416],{},"입력 Form",[238,418,419],{},"Modal",[238,421,422],{},"Chart",[238,424,425],{},"Category 관리",[238,427,428],{},"사용자별 상태 관리",[220,430,431],{},"등 다양한 UI 컴포넌트를 필요로 한다.",[220,433,434],{},"Vue의 컴포넌트 기반 구조와 Nuxt의 프로젝트 관리 방식은 이러한 서비스 구조를 설계하는 데 적합하다고 판단했다.",[279,436],{},[311,438,440],{"id":439},"모바일-웹-하이브리드-앱-확장-고려","모바일 웹 → 하이브리드 앱 확장 고려",[220,442,443],{},"BroBean은 처음부터 모바일 사용성을 고려한 가계부 서비스를 목표로 한다.",[220,445,446],{},"따라서:",[260,448,451],{"className":449,"code":450,"language":266,"meta":267},[263],"Mobile First Web\n\n↓\n\nResponsive UI\n\n↓\n\nHybrid App 확장\n",[269,452,450],{"__ignoreMap":267},[220,454,455],{},"방향으로 개발할 예정이다.",[220,457,458],{},"Nuxt는 웹 서비스 개발에 최적화되어 있지만, 모바일 환경을 고려한 UI 설계와 API 기반 구조를 구성한다면 추후 앱 형태로 확장하는 것도 충분히 고려할 수 있다.",[279,460],{},[220,462,463],{},"결과적으로 BroBean은 단순히 익숙한 기술을 선택한 것이 아니라,",[220,465,466,469],{},[224,467,468],{},"Brolog에서 경험한 Nuxt 생태계를 기반으로, 이번에는 프로젝트 초기 구성부터 직접 설계하며 Nuxt를 더 깊게 이해하기 위한 선택","으로 결정했다.",[279,471],{},[311,473,475],{"id":474},"ssr과-spa-모두-지원","SSR과 SPA 모두 지원",[220,477,478],{},"Nuxt는 하나의 프로젝트에서 다양한 렌더링 방식을 선택할 수 있다.",[220,480,481],{},"예:",[260,483,487],{"className":484,"code":485,"filename":486,"language":266,"meta":267},[263],"\nPublic Page\n\n→ SSR\n\n\nApp Page\n\n→ SPA\n\n\nStatic Content\n\n→ SSG\n","Rendering Strategy",[269,488,485],{"__ignoreMap":267},[220,490,491],{},"추후 각 페이지별 성격에 맞춰 유연하게 변경할 수 있다는 점이 장점이다.",[279,493],{},[311,495,497],{"id":496},"자동화된-프로젝트-구조","자동화된 프로젝트 구조",[220,499,500],{},"Nuxt는 기본적으로:",[235,502,503,506,509,512],{},[238,504,505],{},"라우팅",[238,507,508],{},"디렉토리 구조",[238,510,511],{},"서버 API 구조",[238,513,514],{},"빌드 환경",[220,516,517],{},"등을 프레임워크 레벨에서 제공한다.",[220,519,520],{},"따라서 초기 설정에 시간을 많이 사용하지 않고 서비스 개발에 집중할 수 있다.",[279,522],{},[311,524,526],{"id":525},"하이브리드-앱-확장-가능성","하이브리드 앱 확장 가능성",[220,528,529],{},"현재는 모바일 웹 형태로 개발하지만, 추후:",[235,531,532,535,538],{},[238,533,534],{},"Capacitor",[238,536,537],{},"WebView 기반 앱",[238,539,540],{},"PWA",[220,542,543],{},"등을 활용하여 앱 형태로 확장하는 가능성을 고려했다.",[279,545],{},[215,547,549],{"id":548},"ui-기술-스택-선정-과정","🎨 UI 기술 스택 선정 과정",[220,551,552],{},"Frontend UI 개발 방식도 여러 후보를 검토했다.",[311,554,555],{"id":555},"후보",[260,557,561],{"className":558,"code":559,"filename":560,"language":266,"meta":267},[263],"Bootstrap\n\nVuetify\n\nTailwind CSS\n\nMaterial UI\n","UI Candidates",[269,562,559],{"__ignoreMap":267},[279,564],{},[215,566,568],{"id":567},"bootstrap-검토","Bootstrap 검토",[220,570,571],{},"Bootstrap은 오랜 기간 사용된 UI Framework이며 빠르게 화면을 구성할 수 있다는 장점이 있다.",[220,573,574],{},"하지만 최근 신규 프로젝트에서는 다음과 같은 한계가 있었다.",[220,576,577],{},"장점:",[235,579,580,583],{},[238,581,582],{},"익숙함",[238,584,585],{},"빠른 개발 가능",[220,587,588],{},"단점:",[235,590,591,594,597],{},[238,592,593],{},"디자인 커스터마이징 제한",[238,595,596],{},"기존 Bootstrap 스타일 의존성 증가",[238,598,599],{},"독창적인 UI 구성 어려움",[220,601,602],{},"BroBean은 서비스 형태의 앱 UI를 목표로 하기 때문에 다른 선택지를 검토했다.",[279,604],{},[215,606,608],{"id":607},"tailwind-css-선택","Tailwind CSS 선택",[220,610,611],{},"최종적으로 Tailwind CSS를 선택했다.",[220,613,614],{},"선택 이유:",[235,616,617,620,623,626],{},[238,618,619],{},"최근 프론트 개발 트렌드와 적합",[238,621,622],{},"반응형 UI 구현 편리",[238,624,625],{},"디자인 시스템 구축 용이",[238,627,628],{},"컴포넌트 기반 개발과 궁합 우수",[220,630,631],{},"특히 모바일 우선 UI를 제작하는 과정에서 작은 화면부터 확장하는 방식과 잘 맞는다.",[279,633],{},[215,635,637],{"id":636},"nuxt-ui-선택","🧩 Nuxt UI 선택",[220,639,640],{},"Tailwind CSS와 함께:",[260,642,645],{"className":643,"code":644,"language":266,"meta":267},[263],"Nuxt UI\n\n+\n\nTailwind CSS\n",[269,646,644],{"__ignoreMap":267},[220,648,649],{},"조합을 사용하기로 결정했다.",[220,651,652],{},"Nuxt UI는 Nuxt 공식 생태계 기반 UI 라이브러리로 기본적인 서비스 UI 구성 요소를 제공한다.",[220,654,655],{},"제공 기능:",[235,657,658,661,664,667,669,672],{},[238,659,660],{},"Button",[238,662,663],{},"Card",[238,665,666],{},"Input",[238,668,419],{},[238,670,671],{},"Form",[238,673,674],{},"Navigation",[220,676,677],{},"등 다양한 Vue Component를 바로 활용할 수 있다.",[220,679,680],{},"이를 통해 직접 CSS를 작성하는 시간을 줄이고 서비스 기능 개발에 집중할 수 있다.",[279,682],{},[215,684,686],{"id":685},"backend-기술-방향","🔧 Backend 기술 방향",[220,688,689],{},"Backend 개발은 Frontend 기반 UI와 기능 설계가 완료된 이후 진행할 예정이다.",[220,691,692],{},"Frontend에서 먼저:",[260,694,697],{"className":695,"code":696,"filename":265,"language":266,"meta":267},[263],"\nUI \u002F UX 설계\n\n↓\n\nMock Data 기반 기능 구현\n\n↓\n\nAPI Interface 설계\n\n↓\n\nBackend 개발\n",[269,698,696],{"__ignoreMap":267},[220,700,701],{},"순서로 진행하며, 이후 Spring Boot 기반 Backend를 연결하는 방향으로 계획했다.",[220,703,704],{},"최종 Backend Stack은 다음과 같이 구성할 예정이다.",[260,706,710],{"className":707,"code":708,"filename":709,"language":266,"meta":267},[263],"\nSpring Boot\n\nJPA\n\nJWT\n\n...\n","Backend Stack",[269,711,708],{"__ignoreMap":267},[279,713],{},[215,715,717],{"id":716},"spring-boot-선택-이유","☕ Spring Boot 선택 이유",[220,719,720],{},"Spring Boot를 선택한 가장 큰 이유는 기존 개발 경험과 숙련도 때문이다.",[220,722,723],{},"기존에 Java 기반 Backend 개발 경험이 있기 때문에, 다른 Backend Framework를 새롭게 학습하는 것보다 익숙한 기술을 활용하여 서비스 설계와 구현 자체에 집중하는 방향이 더 적합하다고 판단했다.",[220,725,373],{},[235,727,728,731,734,737,740],{},[238,729,730],{},"API 설계",[238,732,733],{},"Database 모델링",[238,735,736],{},"인증 구조",[238,738,739],{},"서버 아키텍처",[238,741,742],{},"예외 처리",[220,744,745],{},"등 Backend 핵심 영역에서 기존 경험을 그대로 활용할 수 있다는 장점이 있다.",[279,747],{},[311,749,751],{"id":750},"검증된-생태계와-안정성","검증된 생태계와 안정성",[220,753,754],{},"Spring 생태계는 오랜 기간 다양한 서비스 환경에서 사용되어 왔으며, 안정적인 서버 개발 환경을 제공한다.",[220,756,757],{},"BroBean은 단순한 개인 테스트 프로젝트가 아니라:",[235,759,760,763,766,769],{},[238,761,762],{},"사용자 관리",[238,764,765],{},"거래 내역 저장",[238,767,768],{},"카테고리 관리",[238,770,771],{},"통계 데이터 처리",[220,773,774],{},"등 실제 서비스 형태를 고려하고 있기 때문에 안정적인 Backend Framework 선택이 중요했다.",[279,776],{},[311,778,780],{"id":779},"rest-api-기반-frontend-분리-구조","REST API 기반 Frontend 분리 구조",[220,782,783],{},"BroBean은 Frontend와 Backend를 분리하는 구조로 개발할 예정이다.",[220,785,786],{},"구성:",[260,788,792],{"className":789,"code":790,"filename":791,"language":266,"meta":267},[263],"\nNuxt Frontend\n\n↓\n\nREST API\n\n↓\n\nSpring Boot Backend\n\n↓\n\nDatabase\n","Architecture",[269,793,790],{"__ignoreMap":267},[220,795,796],{},"이러한 구조에서는 명확한 API 설계와 유지보수가 중요하다.",[220,798,799],{},"Spring Boot는 REST Controller 기반으로 API 서버를 구성하기 용이하며, Frontend와 독립적인 Backend 환경을 구축하기 적합하다.",[279,801],{},[311,803,805],{"id":804},"jpa-기반-데이터-모델링","JPA 기반 데이터 모델링",[220,807,808],{},"가계부 서비스는 다양한 관계형 데이터를 관리해야 한다.",[220,810,481],{},[260,812,816],{"className":813,"code":814,"filename":815,"language":266,"meta":267},[263],"\nUser\n\n↓\n\nCouple \u002F Group\n\n↓\n\nTransaction\n\n↓\n\nCategory\n\n↓\n\nBudget\n","Domain Model",[269,817,814],{"__ignoreMap":267},[220,819,820],{},"이처럼 사용자와 소비 데이터 사이에는 여러 관계가 존재한다.",[220,822,823],{},"Spring Boot와 JPA를 활용하면 객체 중심으로 Entity를 설계하고 데이터 관계를 관리할 수 있어, 서비스 규모가 커졌을 때 유지보수하기 좋은 구조를 만들 수 있다.",[220,825,826],{},"결과적으로 BroBean의 Backend는 단순히 유행하는 기술을 선택한 것이 아니라,",[220,828,829],{},[224,830,831],{},"기존 Java Backend 개발 경험을 활용하면서 안정성과 확장성을 확보할 수 있는 현실적인 선택으로 Spring Boot를 결정했다.",[279,833],{},[215,835,837],{"id":836},"최종-예상-기술-스택","📦 최종 예상 기술 스택",[311,839,841],{"id":840},"frontend","Frontend",[260,843,846],{"className":844,"code":845,"filename":358,"language":266,"meta":267},[263],"Nuxt 4\n\nVue 3\n\nTypeScript\n\nNuxt UI\n\nTailwind CSS\n\nPinia\n\nVueUse\n\nDayjs\n\nZod\n\nChart.js\n",[269,847,845],{"__ignoreMap":267},[311,849,851],{"id":850},"backend","Backend",[260,853,856],{"className":854,"code":855,"filename":709,"language":266,"meta":267},[263],"Spring Boot\n\nJPA\n\nJWT\n\n...\n",[269,857,855],{"__ignoreMap":267},[311,859,861],{"id":860},"database","Database",[220,863,864],{},"현재 미정이며 Backend 설계 과정에서 결정 예정이다.",[279,866],{},[215,868,870],{"id":869},"nuxt-4-프로젝트-생성-시작","🚀 Nuxt 4 프로젝트 생성 시작",[220,872,873],{},"Nuxt 4 프로젝트 생성을 진행했다.",[220,875,876],{},"생성 과정에서 확인한 CLI 버전:",[260,878,882],{"className":879,"code":880,"filename":881,"language":266,"meta":267},[263],"create-nuxt@3.37.0\n","CLI Version",[269,883,880],{"__ignoreMap":267},[220,885,886],{},"처음에는 Nuxt 4 프로젝트인데 왜 create-nuxt 3.x 버전이 표시되는지 의문이 있었지만,",[220,888,889],{},"이는 프로젝트 생성 CLI 패키지 버전이며 Nuxt Framework 버전과는 별개이다.",[220,891,892],{},"따라서 정상적인 동작이다.",[279,894],{},[215,896,898],{"id":897},"nuxt-template-선택","Nuxt Template 선택",[220,900,901],{},"생성 과정에서 여러 Template 옵션을 확인했다.",[260,903,907],{"className":904,"code":905,"filename":906,"language":266,"meta":267},[263],"\ncontent\n\nminimal\n\nmodule\n\nui\n\nv5-nightly\n","Nuxt Template",[269,908,905],{"__ignoreMap":267},[220,910,911],{},"각 Template의 목적은 다음과 같다.",[279,913],{},[311,915,916],{"id":916},"content",[220,918,919],{},"Content 기반 사이트 제작용 Template.",[220,921,922],{},"적합한 서비스:",[260,924,927],{"className":925,"code":926,"language":266,"meta":267},[263],"Blog\n\nDocumentation\n\nCMS Site\n",[269,928,926],{"__ignoreMap":267},[220,930,931],{},"Nuxt Content 기반 프로젝트에 적합하지만 BroBean과 같은 서비스 개발에는 필요하지 않았다.",[279,933],{},[311,935,936],{"id":936},"minimal",[220,938,939],{},"최종 선택한 Template이다.",[220,941,942],{},"특징:",[235,944,945,948,951],{},[238,946,947],{},"가장 기본적인 Nuxt 환경",[238,949,950],{},"필요한 모듈만 직접 추가 가능",[238,952,953],{},"프로젝트 구조 이해 용이",[220,955,956],{},"서비스 개발 목적에서는 불필요한 기능 없이 시작할 수 있다는 장점이 있다.",[279,958],{},[311,960,961],{"id":961},"module",[220,963,964],{},"Nuxt Module 개발 목적이다.",[220,966,967],{},"BroBean 서비스 개발과는 방향이 다르기 때문에 선택하지 않았다.",[279,969],{},[311,971,972],{"id":972},"ui",[220,974,975],{},"Nuxt UI가 포함된 Template이다.",[220,977,978],{},"처음에는 고려했지만:",[235,980,981,984,987],{},[238,982,983],{},"필요한 모듈 직접 관리",[238,985,986],{},"프로젝트 구조 이해",[238,988,989],{},"설치 과정 직접 경험",[220,991,992],{},"목적으로 minimal Template을 선택했다.",[279,994],{},[311,996,997],{"id":997},"v5-nightly",[220,999,1000],{},"Nuxt 5 테스트 버전이다.",[220,1002,1003],{},"안정적인 서비스 개발 목적이므로 사용하지 않았다.",[279,1005],{},[215,1007,1009],{"id":1008},"초기-패키지-설치-과정","📦 초기 패키지 설치 과정",[220,1011,1012],{},"Nuxt 프로젝트 생성 이후 필요한 라이브러리를 추가하는 과정을 진행했다.",[220,1014,1015],{},"처음에는 Nuxt에서 제공하는 Module 설치 방식을 활용하려고 했다.",[220,1017,1018],{},"하지만 현재 일부 네트워크가 제한된 개발 환경으로 인해 일부 Module 설치 과정에서 문제가 발생했다.",[279,1020],{},[215,1022,1024],{"id":1023},"️-프로젝트-생성-과정에서-발생한-네트워크-문제","⚠️ 프로젝트 생성 과정에서 발생한 네트워크 문제",[311,1026,1028],{"id":1027},"nuxt-module-추가-방식-변경","Nuxt Module 추가 방식 변경",[220,1030,1031],{},"Nuxt에서는 일반적으로 다음과 같은 방식으로 Module을 추가할 수 있다.",[260,1033,1038],{"className":1034,"code":1035,"filename":1036,"language":1037,"meta":267,"style":267},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","npx nuxi module add ui\n","Terminal","bash",[269,1039,1040],{"__ignoreMap":267},[1041,1042,1045,1049,1053,1056,1059],"span",{"class":1043,"line":1044},"line",1,[1041,1046,1048],{"class":1047},"sBMFI","npx",[1041,1050,1052],{"class":1051},"sfazB"," nuxi",[1041,1054,1055],{"class":1051}," module",[1041,1057,1058],{"class":1051}," add",[1041,1060,1061],{"class":1051}," ui\n",[220,1063,1064],{},"기존 방식대로 Nuxt UI Module 추가를 시도했다.",[220,1066,1067],{},"하지만 다음과 같은 오류가 발생했다.",[260,1069,1072],{"className":1070,"code":1071,"filename":1036,"language":266,"meta":267},[263],"Cannot search in the Nuxt Modules database\n\nFetchError:\nGET https:\u002F\u002Fapi.nuxt.com\u002Fmodules?version=all\n\nfetch failed\n\n\nIt seems that ui is not a Nuxt module.\n",[269,1073,1071],{"__ignoreMap":267},[220,1075,1076],{},"처음에는 Nuxt UI Module 자체가 문제가 있는 것으로 보였지만, 원인을 확인한 결과 다른 문제였다.",[279,1078],{},[215,1080,1082],{"id":1081},"문제-원인-확인","🔍 문제 원인 확인",[220,1084,1085],{},"오류 메시지를 분석한 결과:",[260,1087,1090],{"className":1088,"code":1089,"language":266,"meta":267},[263],"api.nuxt.com 접근 실패\n",[269,1091,1089],{"__ignoreMap":267},[220,1093,1094],{},"가 핵심 원인이었다.",[220,1096,1097,1100],{},[269,1098,1099],{},"nuxi module add"," 명령은 내부적으로 Nuxt Module Registry API를 조회하여 Module 정보를 확인한다.",[220,1102,1103],{},"하지만 현재 개발 환경에서는 외부 API 접근이 제한되어 있었기 때문에 Module 검색 과정에서 실패했다.",[220,1105,1106],{},"즉:",[260,1108,1112],{"className":1109,"code":1110,"filename":1111,"language":266,"meta":267},[263],"\nnuxi module add\n\n↓\n\nNuxt Module Registry 조회\n\n↓\n\napi.nuxt.com 접근\n\n↓\n\n실패\n","Module Install Flow",[269,1113,1110],{"__ignoreMap":267},[220,1115,1116],{},"상태였다.",[279,1118],{},[215,1120,1122],{"id":1121},"️-npm-install-방식으로-변경","🛠️ npm install 방식으로 변경",[220,1124,1125],{},"문제를 해결하기 위해 Nuxt Module도 일반 npm 패키지처럼 직접 설치하는 방식으로 변경했다.",[220,1127,1128],{},"최종 설치 방식:",[260,1130,1134],{"className":1131,"code":1132,"filename":1133,"language":266,"meta":267},[263],"\nNuxt Module\n\n→ npm install 직접 추가\n\n\n일반 Library\n\n→ npm install 직접 추가\n","Install Strategy",[269,1135,1132],{"__ignoreMap":267},[279,1137],{},[215,1139,1141],{"id":1140},"nuxt-ui-설치","🎨 Nuxt UI 설치",[260,1143,1145],{"className":1034,"code":1144,"filename":1036,"language":1037,"meta":267,"style":267},"npm install @nuxt\u002Fui\n",[269,1146,1147],{"__ignoreMap":267},[1041,1148,1149,1152,1155],{"class":1043,"line":1044},[1041,1150,1151],{"class":1047},"npm",[1041,1153,1154],{"class":1051}," install",[1041,1156,1157],{"class":1051}," @nuxt\u002Fui\n",[220,1159,1160],{},"Nuxt UI를 직접 설치했다.",[279,1162],{},[215,1164,1166],{"id":1165},"pinia-설치","📌 Pinia 설치",[220,1168,1169],{},"상태 관리를 위해 Pinia를 추가했다.",[260,1171,1173],{"className":1034,"code":1172,"filename":1036,"language":1037,"meta":267,"style":267},"npm install pinia @pinia\u002Fnuxt\n",[269,1174,1175],{"__ignoreMap":267},[1041,1176,1177,1179,1181,1184],{"class":1043,"line":1044},[1041,1178,1151],{"class":1047},[1041,1180,1154],{"class":1051},[1041,1182,1183],{"class":1051}," pinia",[1041,1185,1186],{"class":1051}," @pinia\u002Fnuxt\n",[220,1188,1189],{},"추후 관리 예정 상태:",[260,1191,1195],{"className":1192,"code":1193,"filename":1194,"language":266,"meta":267},[263],"\nUser State\n\n↓\n\nAuthentication\n\n↓\n\nLedger Data\n\n↓\n\nApplication State\n","Pinia Store",[269,1196,1193],{"__ignoreMap":267},[279,1198],{},[215,1200,1202],{"id":1201},"추가-library-설치","📚 추가 Library 설치",[220,1204,1205],{},"서비스 개발에 필요한 기본 Library를 추가했다.",[260,1207,1209],{"className":1034,"code":1208,"filename":1036,"language":1037,"meta":267,"style":267},"npm install @vueuse\u002Fcore dayjs zod chart.js vue-chartjs\n",[269,1210,1211],{"__ignoreMap":267},[1041,1212,1213,1215,1217,1220,1223,1226,1229],{"class":1043,"line":1044},[1041,1214,1151],{"class":1047},[1041,1216,1154],{"class":1051},[1041,1218,1219],{"class":1051}," @vueuse\u002Fcore",[1041,1221,1222],{"class":1051}," dayjs",[1041,1224,1225],{"class":1051}," zod",[1041,1227,1228],{"class":1051}," chart.js",[1041,1230,1231],{"class":1051}," vue-chartjs\n",[220,1233,1234],{},"각 Library의 역할:",[1236,1237,1238,1251],"table",{},[1239,1240,1241],"thead",{},[1242,1243,1244,1248],"tr",{},[1245,1246,1247],"th",{},"Library",[1245,1249,1250],{},"목적",[1252,1253,1254,1263,1271,1279,1287],"tbody",{},[1242,1255,1256,1260],{},[1257,1258,1259],"td",{},"VueUse",[1257,1261,1262],{},"Vue Composition API Utility",[1242,1264,1265,1268],{},[1257,1266,1267],{},"Dayjs",[1257,1269,1270],{},"날짜 처리",[1242,1272,1273,1276],{},[1257,1274,1275],{},"Zod",[1257,1277,1278],{},"데이터 Validation",[1242,1280,1281,1284],{},[1257,1282,1283],{},"Chart.js",[1257,1285,1286],{},"통계 그래프",[1242,1288,1289,1292],{},[1257,1290,1291],{},"Vue Chart.js",[1257,1293,1294],{},"Vue 기반 Chart Wrapper",[220,1296,1297],{},"가계부 서비스 특성상 날짜 처리와 통계 시각화 기능이 중요하기 때문에 초기 단계에서 추가했다.",[279,1299],{},[215,1301,1303],{"id":1302},"icon-library-추가","🎨 Icon Library 추가",[220,1305,1306],{},"UI 아이콘 사용을 위해 Iconify를 추가했다.",[260,1308,1310],{"className":1034,"code":1309,"filename":1036,"language":1037,"meta":267,"style":267},"npm install @iconify\u002Fvue\n",[269,1311,1312],{"__ignoreMap":267},[1041,1313,1314,1316,1318],{"class":1043,"line":1044},[1041,1315,1151],{"class":1047},[1041,1317,1154],{"class":1051},[1041,1319,1320],{"class":1051}," @iconify\u002Fvue\n",[220,1322,1323],{},"활용 예정:",[260,1325,1329],{"className":1326,"code":1327,"filename":1328,"language":266,"meta":267},[263],"\nNavigation Icon\n\n↓\n\nCategory Icon\n\n↓\n\nAction Button Icon\n","Icon Usage",[269,1330,1327],{"__ignoreMap":267},[279,1332],{},[215,1334,1336],{"id":1335},"npm-install-결과","✅ npm install 결과",[220,1338,1339],{},"모든 패키지 설치는 정상적으로 완료되었다.",[220,1341,1342],{},"설치 로그:",[260,1344,1347],{"className":1345,"code":1346,"filename":1036,"language":266,"meta":267},[263],"added 622 packages\n\nTypes generated in .nuxt\n",[269,1348,1346],{"__ignoreMap":267},[220,1350,1351],{},"Nuxt Type 생성까지 완료되면서 기본 개발 환경 구성이 끝났다.",[279,1353],{},[215,1355,1357],{"id":1356},"️-설치-과정에서-발생한-warning","⚠️ 설치 과정에서 발생한 Warning",[220,1359,1360],{},"설치 과정에서는 몇 가지 Warning이 발생했다.",[220,1362,1363],{},"대부분 직접적인 오류가 아닌 Dependency 또는 개발 환경 관련 메시지였다.",[279,1365],{},[215,1367,1369],{"id":1368},"_1-deprecated-dependency-warning","1. Deprecated Dependency Warning",[220,1371,1372],{},"발생 메시지:",[260,1374,1377],{"className":1375,"code":1376,"filename":1036,"language":266,"meta":267},[263],"npm warn deprecated glob@10.5.0\n",[269,1378,1376],{"__ignoreMap":267},[220,1380,1381],{},"확인 결과 직접 설치한 패키지가 아닌 내부 Dependency에서 발생한 경고였다.",[220,1383,1106],{},[260,1385,1388],{"className":1386,"code":1387,"language":266,"meta":267},[263],"BroBean\n\n↓\n\nNuxt\n\n↓\n\nInternal Dependency\n\n↓\n\nglob\n",[269,1389,1387],{"__ignoreMap":267},[220,1391,1392],{},"형태로 포함된 패키지였다.",[220,1394,1395],{},"현재 프로젝트 코드에서 직접 사용하는 패키지가 아니기 때문에 우선 무시했다.",[279,1397],{},[215,1399,1401],{"id":1400},"_2-nuxt-devtools-초기화-warning","2. Nuxt Devtools 초기화 Warning",[220,1403,1372],{},[260,1405,1408],{"className":1406,"code":1407,"filename":1036,"language":266,"meta":267},[263],"WARN [NUXT_B8014]\n\nModule @nuxt\u002Fdevtools was slow to set up\n",[269,1409,1407],{"__ignoreMap":267},[220,1411,1412],{},"Nuxt Devtools 초기화 시간이 오래 걸렸다는 의미다.",[220,1414,1415],{},"빌드 실패나 실행 오류가 아니며 개발 환경에서 발생하는 성능 관련 Warning이다.",[220,1417,1418],{},"현재 단계에서는 문제 없이 진행했다.",[279,1420],{},[215,1422,1424],{"id":1423},"_3-npm-audit-vulnerability-warning","3. npm audit Vulnerability Warning",[220,1426,1372],{},[260,1428,1431],{"className":1429,"code":1430,"filename":1036,"language":266,"meta":267},[263],"11 high severity vulnerabilities\n",[269,1432,1430],{"__ignoreMap":267},[220,1434,1435],{},"npm 설치 이후 Dependency 취약점 알림이 발생했다.",[220,1437,1438],{},"일반적으로:",[260,1440,1442],{"className":1034,"code":1441,"filename":1036,"language":1037,"meta":267,"style":267},"npm audit fix --force\n",[269,1443,1444],{"__ignoreMap":267},[1041,1445,1446,1448,1451,1454],{"class":1043,"line":1044},[1041,1447,1151],{"class":1047},[1041,1449,1450],{"class":1051}," audit",[1041,1452,1453],{"class":1051}," fix",[1041,1455,1456],{"class":1051}," --force\n",[220,1458,1459],{},"명령을 사용할 수 있지만 현재는 실행하지 않았다.",[220,1461,1462],{},"이유:",[260,1464,1467],{"className":1465,"code":1466,"language":266,"meta":267},[263],"npm audit fix --force\n\n↓\n\nDependency Version 변경\n\n↓\n\nNuxt Package 충돌 가능성\n",[269,1468,1466],{"__ignoreMap":267},[220,1470,1471],{},"이 있기 때문이다.",[220,1473,1474],{},"초기 프로젝트 단계에서는 안정적인 Dependency 상태 유지가 더 중요하다고 판단했다.",[279,1476],{},[215,1478,1480],{"id":1479},"_4-allow-scripts-warning","4. allow-scripts Warning",[220,1482,1372],{},[260,1484,1487],{"className":1485,"code":1486,"filename":1036,"language":266,"meta":267},[263],"npm warn allow-scripts\n\nesbuild\n",[269,1488,1486],{"__ignoreMap":267},[220,1490,1491],{},"npm의 보안 정책 관련 Warning이다.",[220,1493,1494],{},"일부 패키지는 설치 과정에서 Script 실행이 필요한데, 최근 npm은 보안을 위해 이를 제한한다.",[220,1496,1497],{},"필요한 경우:",[260,1499,1501],{"className":1034,"code":1500,"filename":1036,"language":1037,"meta":267,"style":267},"npm approve-scripts\n",[269,1502,1503],{"__ignoreMap":267},[1041,1504,1505,1507],{"class":1043,"line":1044},[1041,1506,1151],{"class":1047},[1041,1508,1509],{"class":1051}," approve-scripts\n",[220,1511,1512],{},"를 통해 허용할 수 있다.",[279,1514],{},[215,1516,1518],{"id":1517},"️-nuxt-config-초기-설정","⚙️ Nuxt Config 초기 설정",[220,1520,1521],{},"기본적인 Nuxt Module 설정을 추가했다.",[220,1523,1524],{},"현재 구성:",[260,1526,1531],{"className":1527,"code":1528,"filename":1529,"language":1530,"meta":267,"style":267},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n\n  modules: [\n    '@nuxt\u002Fui',\n    '@pinia\u002Fnuxt'\n  ],\n\n  css: [\n    '~\u002Fassets\u002Fcss\u002Fmain.css'\n  ]\n\n})\n","nuxt.config.ts","ts",[269,1532,1533,1554,1561,1574,1589,1600,1608,1613,1623,1633,1639,1644],{"__ignoreMap":267},[1041,1534,1535,1539,1542,1546,1550],{"class":1043,"line":1044},[1041,1536,1538],{"class":1537},"s7zQu","export",[1041,1540,1541],{"class":1537}," default",[1041,1543,1545],{"class":1544},"s2Zo4"," defineNuxtConfig",[1041,1547,1549],{"class":1548},"sTEyZ","(",[1041,1551,1553],{"class":1552},"sMK4o","{\n",[1041,1555,1557],{"class":1043,"line":1556},2,[1041,1558,1560],{"emptyLinePlaceholder":1559},true,"\n",[1041,1562,1564,1568,1571],{"class":1043,"line":1563},3,[1041,1565,1567],{"class":1566},"swJcz","  modules",[1041,1569,1570],{"class":1552},":",[1041,1572,1573],{"class":1548}," [\n",[1041,1575,1577,1580,1583,1586],{"class":1043,"line":1576},4,[1041,1578,1579],{"class":1552},"    '",[1041,1581,1582],{"class":1051},"@nuxt\u002Fui",[1041,1584,1585],{"class":1552},"'",[1041,1587,1588],{"class":1552},",\n",[1041,1590,1592,1594,1597],{"class":1043,"line":1591},5,[1041,1593,1579],{"class":1552},[1041,1595,1596],{"class":1051},"@pinia\u002Fnuxt",[1041,1598,1599],{"class":1552},"'\n",[1041,1601,1603,1606],{"class":1043,"line":1602},6,[1041,1604,1605],{"class":1548},"  ]",[1041,1607,1588],{"class":1552},[1041,1609,1611],{"class":1043,"line":1610},7,[1041,1612,1560],{"emptyLinePlaceholder":1559},[1041,1614,1616,1619,1621],{"class":1043,"line":1615},8,[1041,1617,1618],{"class":1566},"  css",[1041,1620,1570],{"class":1552},[1041,1622,1573],{"class":1548},[1041,1624,1626,1628,1631],{"class":1043,"line":1625},9,[1041,1627,1579],{"class":1552},[1041,1629,1630],{"class":1051},"~\u002Fassets\u002Fcss\u002Fmain.css",[1041,1632,1599],{"class":1552},[1041,1634,1636],{"class":1043,"line":1635},10,[1041,1637,1638],{"class":1548},"  ]\n",[1041,1640,1642],{"class":1043,"line":1641},11,[1041,1643,1560],{"emptyLinePlaceholder":1559},[1041,1645,1647,1650],{"class":1043,"line":1646},12,[1041,1648,1649],{"class":1552},"}",[1041,1651,1652],{"class":1548},")\n",[220,1654,1655],{},"사용 Module:",[260,1657,1661],{"className":1658,"code":1659,"filename":1660,"language":266,"meta":267},[263],"\n@nuxt\u002Fui\n\n↓\n\nUI Component\n\n\n@pinia\u002Fnuxt\n\n↓\n\nState Management\n","Nuxt Modules",[269,1662,1659],{"__ignoreMap":267},[220,1664,1665],{},"구조로 구성했다.",[279,1667],{},[215,1669,1671],{"id":1670},"css-경로-설정-문제-해결","🎨 CSS 경로 설정 문제 해결",[220,1673,1674],{},"초기 CSS 설정 과정에서 경로 오류가 발생했다.",[220,1676,1677],{},"작성했던 설정:",[260,1679,1681],{"className":1527,"code":1680,"language":1530,"meta":267,"style":267},"css: [\n  '~\u002Fapp\u002Fassets\u002Fcss\u002Fmain.css'\n]\n",[269,1682,1683,1692,1702],{"__ignoreMap":267},[1041,1684,1685,1688,1690],{"class":1043,"line":1044},[1041,1686,1687],{"class":1047},"css",[1041,1689,1570],{"class":1552},[1041,1691,1573],{"class":1548},[1041,1693,1694,1697,1700],{"class":1043,"line":1556},[1041,1695,1696],{"class":1552},"  '",[1041,1698,1699],{"class":1051},"~\u002Fapp\u002Fassets\u002Fcss\u002Fmain.css",[1041,1701,1599],{"class":1552},[1041,1703,1704],{"class":1043,"line":1563},[1041,1705,1706],{"class":1548},"]\n",[220,1708,1709],{},"실행 결과:",[260,1711,1714],{"className":1712,"code":1713,"language":266,"meta":267},[263],"Cannot find module '~\u002Fapp\u002Fassets\u002Fcss\u002Fmain.css'\n",[269,1715,1713],{"__ignoreMap":267},[220,1717,1718],{},"오류가 발생했다.",[279,1720],{},[215,1722,1724],{"id":1723},"원인-분석","🔍 원인 분석",[220,1726,1727,1728,1731],{},"Nuxt 4에서는 ",[269,1729,1730],{},"app"," 디렉토리를 사용하는 구조가 추가되었지만, Alias 경로에서는 혼동이 있었다.",[220,1733,1734,1737],{},[269,1735,1736],{},"~"," Alias는 프로젝트 Root 기준으로 동작한다.",[220,1739,446],{},[260,1741,1744],{"className":1742,"code":1743,"language":266,"meta":267},[263],"~\u002Fapp\u002Fassets\u002Fcss\u002Fmain.css\n",[269,1745,1743],{"__ignoreMap":267},[220,1747,1748],{},"는:",[260,1750,1753],{"className":1751,"code":1752,"language":266,"meta":267},[263],"Root\n\n↓\n\napp\n\n↓\n\nassets\n\n↓\n\ncss\n",[269,1754,1752],{"__ignoreMap":267},[220,1756,1757],{},"구조를 다시 탐색하게 된다.",[220,1759,1760],{},"하지만 CSS 설정에서는 Nuxt 4 권장 구조에 맞춰 다음과 같이 설정한다.",[220,1762,1763],{},"수정:",[260,1765,1767],{"className":1527,"code":1766,"language":1530,"meta":267,"style":267},"css: [\n  '~\u002Fassets\u002Fcss\u002Fmain.css'\n]\n",[269,1768,1769,1777,1785],{"__ignoreMap":267},[1041,1770,1771,1773,1775],{"class":1043,"line":1044},[1041,1772,1687],{"class":1047},[1041,1774,1570],{"class":1552},[1041,1776,1573],{"class":1548},[1041,1778,1779,1781,1783],{"class":1043,"line":1556},[1041,1780,1696],{"class":1552},[1041,1782,1630],{"class":1051},[1041,1784,1599],{"class":1552},[1041,1786,1787],{"class":1043,"line":1563},[1041,1788,1706],{"class":1548},[279,1790],{},[215,1792,1794],{"id":1793},"현재-css-구조","현재 CSS 구조",[220,1796,1797],{},"최종 구조:",[260,1799,1803],{"className":1800,"code":1801,"filename":1802,"language":266,"meta":267},[263],"app\u002F\n\n├── app.vue\n\n└── assets\u002F\n\n    └── css\u002F\n\n        └── main.css\n","Directory",[269,1804,1801],{"__ignoreMap":267},[220,1806,1727,1807,1809],{},[269,1808,1730],{}," 디렉토리 내부 구조와 Alias 사용 위치를 정확히 이해하는 것이 중요하다.",[279,1811],{},[215,1813,1815],{"id":1814},"font-관련-network-warning","🔤 Font 관련 Network Warning",[220,1817,1818],{},"개발 실행 과정에서 Font Provider 관련 Warning도 확인했다.",[220,1820,1372],{},[260,1822,1825],{"className":1823,"code":1824,"filename":1036,"language":266,"meta":267},[263],"Could not fetch from\nhttps:\u002F\u002Ffonts.google.com\u002Fmetadata\u002Ffonts\n\n\nCould not fetch from\nhttps:\u002F\u002Fapi.fontshare.com\u002Fv2\u002Ffonts\n\n\nCould not fetch from\nhttps:\u002F\u002Ffonts.bunny.net\u002Flist\n\n\nCould not fetch from\nhttps:\u002F\u002Fapi.fontsource.org\u002Fv1\u002Ffonts\n",[269,1826,1824],{"__ignoreMap":267},[279,1828],{},[215,1830,1831],{"id":1831},"원인",[220,1833,1834],{},"Nuxt UI 또는 관련 Provider가 외부 Font API 정보를 조회하려고 했지만 현재 개발 환경의 네트워크 제한으로 접근하지 못했다.",[220,1836,1837],{},"구조:",[260,1839,1843],{"className":1840,"code":1841,"filename":1842,"language":266,"meta":267},[263],"\nNuxt UI\n\n↓\n\nFont Provider 조회\n\n↓\n\nExternal API Request\n\n↓\n\nNetwork 제한\n\n↓\n\n실패\n","Font Loading Flow",[269,1844,1841],{"__ignoreMap":267},[279,1846],{},[215,1848,1850],{"id":1849},"대응-방향","대응 방향",[220,1852,1853],{},"외부 Font Provider 조회 문제는 단순히 Font 다운로드 실패 문제가 아니라, 개발 환경에서 불필요한 외부 API 요청이 발생하는 문제였다.",[220,1855,1856],{},"따라서 외부 Provider를 그대로 사용하는 방식 대신, 로컬 개발 환경에서는 외부 통신을 차단하고 설치된 패키지와 기본 설정을 활용하는 방향으로 변경했다.",[220,1858,1859],{},"수정한 Nuxt 설정:",[260,1861,1863],{"className":1527,"code":1862,"filename":1529,"language":1530,"meta":267,"style":267},"\u002F\u002F 아이콘 로컬 번들링 강제 지정\nicon: {\n  serverBundle: 'local',\n},\n\n\u002F\u002F 외부 Font Provider Metadata 조회 차단\nfonts: {\n  providers: {\n    google: false,\n    fontsource: false,\n    bunny: false,\n    googleicons: false,\n    fontshare: false,\n    adobe: false,\n  },\n},\n",[269,1864,1865,1871,1881,1898,1903,1907,1912,1921,1930,1943,1954,1965,1976,1988,2000,2006],{"__ignoreMap":267},[1041,1866,1867],{"class":1043,"line":1044},[1041,1868,1870],{"class":1869},"sHwdD","\u002F\u002F 아이콘 로컬 번들링 강제 지정\n",[1041,1872,1873,1876,1878],{"class":1043,"line":1556},[1041,1874,1875],{"class":1047},"icon",[1041,1877,1570],{"class":1552},[1041,1879,1880],{"class":1552}," {\n",[1041,1882,1883,1886,1888,1891,1894,1896],{"class":1043,"line":1563},[1041,1884,1885],{"class":1047},"  serverBundle",[1041,1887,1570],{"class":1552},[1041,1889,1890],{"class":1552}," '",[1041,1892,1893],{"class":1051},"local",[1041,1895,1585],{"class":1552},[1041,1897,1588],{"class":1552},[1041,1899,1900],{"class":1043,"line":1576},[1041,1901,1902],{"class":1552},"},\n",[1041,1904,1905],{"class":1043,"line":1591},[1041,1906,1560],{"emptyLinePlaceholder":1559},[1041,1908,1909],{"class":1043,"line":1602},[1041,1910,1911],{"class":1869},"\u002F\u002F 외부 Font Provider Metadata 조회 차단\n",[1041,1913,1914,1917,1919],{"class":1043,"line":1610},[1041,1915,1916],{"class":1047},"fonts",[1041,1918,1570],{"class":1552},[1041,1920,1880],{"class":1552},[1041,1922,1923,1926,1928],{"class":1043,"line":1615},[1041,1924,1925],{"class":1047},"  providers",[1041,1927,1570],{"class":1552},[1041,1929,1880],{"class":1552},[1041,1931,1932,1935,1937,1941],{"class":1043,"line":1625},[1041,1933,1934],{"class":1047},"    google",[1041,1936,1570],{"class":1552},[1041,1938,1940],{"class":1939},"sfNiH"," false",[1041,1942,1588],{"class":1552},[1041,1944,1945,1948,1950,1952],{"class":1043,"line":1635},[1041,1946,1947],{"class":1047},"    fontsource",[1041,1949,1570],{"class":1552},[1041,1951,1940],{"class":1939},[1041,1953,1588],{"class":1552},[1041,1955,1956,1959,1961,1963],{"class":1043,"line":1641},[1041,1957,1958],{"class":1047},"    bunny",[1041,1960,1570],{"class":1552},[1041,1962,1940],{"class":1939},[1041,1964,1588],{"class":1552},[1041,1966,1967,1970,1972,1974],{"class":1043,"line":1646},[1041,1968,1969],{"class":1047},"    googleicons",[1041,1971,1570],{"class":1552},[1041,1973,1940],{"class":1939},[1041,1975,1588],{"class":1552},[1041,1977,1979,1982,1984,1986],{"class":1043,"line":1978},13,[1041,1980,1981],{"class":1047},"    fontshare",[1041,1983,1570],{"class":1552},[1041,1985,1940],{"class":1939},[1041,1987,1588],{"class":1552},[1041,1989,1991,1994,1996,1998],{"class":1043,"line":1990},14,[1041,1992,1993],{"class":1047},"    adobe",[1041,1995,1570],{"class":1552},[1041,1997,1940],{"class":1939},[1041,1999,1588],{"class":1552},[1041,2001,2003],{"class":1043,"line":2002},15,[1041,2004,2005],{"class":1552},"  },\n",[1041,2007,2009],{"class":1043,"line":2008},16,[1041,2010,1902],{"class":1552},[279,2012],{},[311,2014,2016],{"id":2015},"icon-provider-로컬-번들링-적용","Icon Provider 로컬 번들링 적용",[220,2018,2019],{},"기존에는 Icon Provider가 외부 API를 통해 아이콘 정보를 조회하려고 했다.",[220,2021,1837],{},[260,2023,2027],{"className":2024,"code":2025,"filename":2026,"language":266,"meta":267},[263],"\nNuxt UI\n\n↓\n\nIcon Provider\n\n↓\n\nExternal API 요청\n\n↓\n\nNetwork 제한으로 실패\n","Before",[269,2028,2025],{"__ignoreMap":267},[220,2030,2031],{},"이를 해결하기 위해:",[260,2033,2035],{"className":1527,"code":2034,"language":1530,"meta":267,"style":267},"icon: {\n  serverBundle: 'local',\n}\n",[269,2036,2037,2045,2059],{"__ignoreMap":267},[1041,2038,2039,2041,2043],{"class":1043,"line":1044},[1041,2040,1875],{"class":1047},[1041,2042,1570],{"class":1552},[1041,2044,1880],{"class":1552},[1041,2046,2047,2049,2051,2053,2055,2057],{"class":1043,"line":1556},[1041,2048,1885],{"class":1047},[1041,2050,1570],{"class":1552},[1041,2052,1890],{"class":1552},[1041,2054,1893],{"class":1051},[1041,2056,1585],{"class":1552},[1041,2058,1588],{"class":1552},[1041,2060,2061],{"class":1043,"line":1563},[1041,2062,2063],{"class":1552},"}\n",[220,2065,2066],{},"설정을 추가했다.",[220,2068,2069],{},"변경 후:",[260,2071,2075],{"className":2072,"code":2073,"filename":2074,"language":266,"meta":267},[263],"\nNuxt UI\n\n↓\n\nLocal Icon Bundle\n\n↓\n\n설치된 Package 사용\n","After",[269,2076,2073],{"__ignoreMap":267},[220,2078,2079],{},"형태로 동작하도록 변경했다.",[220,2081,2082],{},"이를 통해 개발 환경에서 외부 Icon API 접근 없이 로컬 패키지만 사용하도록 구성했다.",[279,2084],{},[311,2086,2088],{"id":2087},"font-provider-비활성화","Font Provider 비활성화",[220,2090,2091],{},"Font 관련 Warning 역시 외부 Provider Metadata 조회 과정에서 발생했다. 이 문제를 해결하기 위해 사용하지 않는 Font Provider를 모두 비활성화했다.",[260,2093,2095],{"className":1527,"code":2094,"language":1530,"meta":267,"style":267},"fonts: {\n  providers: {\n    google: false,\n    fontsource: false,\n    bunny: false,\n    googleicons: false,\n    fontshare: false,\n    adobe: false,\n  },\n}\n",[269,2096,2097,2105,2113,2123,2133,2143,2153,2163,2173,2177],{"__ignoreMap":267},[1041,2098,2099,2101,2103],{"class":1043,"line":1044},[1041,2100,1916],{"class":1047},[1041,2102,1570],{"class":1552},[1041,2104,1880],{"class":1552},[1041,2106,2107,2109,2111],{"class":1043,"line":1556},[1041,2108,1925],{"class":1047},[1041,2110,1570],{"class":1552},[1041,2112,1880],{"class":1552},[1041,2114,2115,2117,2119,2121],{"class":1043,"line":1563},[1041,2116,1934],{"class":1047},[1041,2118,1570],{"class":1552},[1041,2120,1940],{"class":1939},[1041,2122,1588],{"class":1552},[1041,2124,2125,2127,2129,2131],{"class":1043,"line":1576},[1041,2126,1947],{"class":1047},[1041,2128,1570],{"class":1552},[1041,2130,1940],{"class":1939},[1041,2132,1588],{"class":1552},[1041,2134,2135,2137,2139,2141],{"class":1043,"line":1591},[1041,2136,1958],{"class":1047},[1041,2138,1570],{"class":1552},[1041,2140,1940],{"class":1939},[1041,2142,1588],{"class":1552},[1041,2144,2145,2147,2149,2151],{"class":1043,"line":1602},[1041,2146,1969],{"class":1047},[1041,2148,1570],{"class":1552},[1041,2150,1940],{"class":1939},[1041,2152,1588],{"class":1552},[1041,2154,2155,2157,2159,2161],{"class":1043,"line":1610},[1041,2156,1981],{"class":1047},[1041,2158,1570],{"class":1552},[1041,2160,1940],{"class":1939},[1041,2162,1588],{"class":1552},[1041,2164,2165,2167,2169,2171],{"class":1043,"line":1615},[1041,2166,1993],{"class":1047},[1041,2168,1570],{"class":1552},[1041,2170,1940],{"class":1939},[1041,2172,1588],{"class":1552},[1041,2174,2175],{"class":1043,"line":1625},[1041,2176,2005],{"class":1552},[1041,2178,2179],{"class":1043,"line":1635},[1041,2180,2063],{"class":1552},[279,2182],{},[215,2184,2186],{"id":2185},"최종-방향","최종 방향",[220,2188,2189],{},"현재 개발 단계에서는 디자인보다 서비스 구조와 기능 개발이 우선이기 때문에 외부 Font 의존성을 제거했다.",[220,2191,2192],{},"최종 방향:",[260,2194,2198],{"className":2195,"code":2196,"filename":2197,"language":266,"meta":267},[263],"\nExternal Font Provider\n\n❌ 사용하지 않음\n\n\nLocal Bundle\n\n✅ 사용\n\n\nSystem Font\n\n✅ 사용\n","Font Strategy",[269,2199,2196],{"__ignoreMap":267},[220,2201,2202],{},"추후 서비스 배포 단계에서 필요한 경우:",[235,2204,2205,2208,2211],{},[238,2206,2207],{},"자체 Font 파일 추가",[238,2209,2210],{},"CDN 기반 Font 적용",[238,2212,2213],{},"브랜드 아이덴티티에 맞는 Typography 적용",[220,2215,2216],{},"등을 검토할 예정이다.",[220,2218,2219],{},"현재는 외부 네트워크 환경에 영향을 받지 않는 안정적인 개발 환경 구성을 우선했다.",[279,2221],{},[215,2223,2225],{"id":2224},"nuxt-4-공식-디렉토리-구조-이해","📁 Nuxt 4 공식 디렉토리 구조 이해",[220,2227,2228,2229,2231],{},"Nuxt 4에서는 기존 Nuxt 3와 다르게 ",[269,2230,1730],{}," 디렉토리가 중심 구조가 된다.",[220,2233,2234],{},"기본 구조:",[260,2236,2240],{"className":2237,"code":2238,"filename":2239,"language":266,"meta":267},[263],"frontend\u002F\n\n├── app\u002F\n\n│   ├── app.vue\n│\n│   ├── assets\u002F\n│\n│   ├── components\u002F\n│\n│   ├── layouts\u002F\n│\n│   ├── pages\u002F\n│\n│   ├── composables\u002F\n│\n│   ├── middleware\u002F\n│\n│   ├── plugins\u002F\n│\n│   └── utils\u002F\n\n\n├── public\u002F\n\n├── server\u002F\n\n├── shared\u002F\n\n├── nuxt.config.ts\n\n└── package.json\n","Nuxt 4 Structure",[269,2241,2238],{"__ignoreMap":267},[279,2243],{},[215,2245,2247],{"id":2246},"처음-생성-시-폴더가-없는-이유","🤔 처음 생성 시 폴더가 없는 이유",[220,2249,2250],{},"Nuxt는 처음부터 모든 폴더를 생성하지 않는다.",[220,2252,2253],{},"Nuxt의 철학은:",[2255,2256,2257],"blockquote",{},[220,2258,2259],{},"필요한 기능이 추가될 때 구조를 생성한다.",[220,2261,2262],{},"이다.",[220,2264,2265],{},"예를 들어 처음 생성 상태:",[260,2267,2271],{"className":2268,"code":2269,"filename":2270,"language":266,"meta":267},[263],"app\u002F\n\n└── app.vue\n","Initial Structure",[269,2272,2269],{"__ignoreMap":267},[220,2274,2275],{},"만 존재해도 정상이다.",[220,2277,2278],{},"이후:",[260,2280,2283],{"className":2281,"code":2282,"language":266,"meta":267},[263],"app\u002Fpages\u002Findex.vue\n",[269,2284,2282],{"__ignoreMap":267},[220,2286,2287],{},"파일을 생성하면 자동으로 Routing 기능이 활성화된다.",[279,2289],{},[215,2291,2293],{"id":2292},"️-brobean-프로젝트-구조","🏗️ BroBean 프로젝트 구조",[220,2295,2296],{},"서비스 개발 방향에 맞춰 다음 구조를 계획했다.",[260,2298,2302],{"className":2299,"code":2300,"filename":2301,"language":266,"meta":267},[263],"frontend\u002F\n\n├── app\u002F\n\n│   ├── app.vue\n\n│   ├── assets\u002F\n\n│   │   └── css\u002F\n\n│   │       └── main.css\n\n│   │\n│   ├── components\u002F\n\n│   ├── layouts\u002F\n\n│   ├── pages\u002F\n\n│   ├── composables\u002F\n\n│   └── utils\u002F\n\n\n├── stores\u002F\n\n├── services\u002F\n\n├── types\u002F\n\n├── constants\u002F\n\n├── mock\u002F\n\n├── public\u002F\n\n├── server\u002F\n\n├── nuxt.config.ts\n","BroBean Structure",[269,2303,2300],{"__ignoreMap":267},[279,2305],{},[215,2307,2309],{"id":2308},"추가-폴더-설계-이유","📦 추가 폴더 설계 이유",[311,2311,2312],{"id":2312},"stores",[220,2314,2315],{},"Pinia 상태 관리 영역이다.",[220,2317,481],{},[260,2319,2322],{"className":2320,"code":2321,"filename":2312,"language":266,"meta":267},[263],"\nauth.ts\n\nuser.ts\n\nledger.ts\n",[269,2323,2321],{"__ignoreMap":267},[220,2325,2326],{},"관리 대상:",[235,2328,2329,2332,2335],{},[238,2330,2331],{},"로그인 상태",[238,2333,2334],{},"사용자 정보",[238,2336,2337],{},"가계부 데이터",[279,2339],{},[311,2341,2342],{"id":2342},"services",[220,2344,2345],{},"Backend API 통신 영역이다.",[220,2347,2348],{},"Spring Boot 연결 이후 사용한다.",[220,2350,481],{},[260,2352,2355],{"className":2353,"code":2354,"filename":2342,"language":266,"meta":267},[263],"\nauth.service.ts\n\nledger.service.ts\n",[269,2356,2354],{"__ignoreMap":267},[279,2358],{},[311,2360,2361],{"id":2361},"types",[220,2363,2364],{},"TypeScript 타입 정의 영역이다.",[220,2366,481],{},[260,2368,2371],{"className":2369,"code":2370,"filename":2361,"language":266,"meta":267},[263],"\nUser\n\nTransaction\n\nCategory\n",[269,2372,2370],{"__ignoreMap":267},[279,2374],{},[311,2376,2377],{"id":2377},"mock",[220,2379,2380],{},"Backend 개발 전 테스트 데이터를 관리한다.",[220,2382,481],{},[260,2384,2387],{"className":2385,"code":2386,"filename":2377,"language":266,"meta":267},[263],"\ntransactions.json\n\nusers.json\n",[269,2388,2386],{"__ignoreMap":267},[220,2390,2391],{},"Frontend 기능 검증을 위해 활용할 예정이다.",[279,2393],{},[215,2395,2397],{"id":2396},"현재-진행-상태","📍 현재 진행 상태",[220,2399,2400],{},"완료:",[260,2402,2406],{"className":2403,"code":2404,"filename":2405,"language":266,"meta":267},[263],"\n✅ Nuxt 4 프로젝트 생성\n\n✅ Vue 3 + TypeScript 구성\n\n✅ Nuxt UI 설치\n\n✅ Pinia 설치\n\n✅ 기본 구조 설계\n\n✅ Frontend 기술 스택 결정\n","Progress",[269,2407,2404],{"__ignoreMap":267},[279,2409],{},[215,2411,2413],{"id":2412},"프로젝트-시작을-마치며","📌 프로젝트 시작을 마치며",[220,2415,2416],{},"이번 글에서는 BroBean 서비스를 개발하기 위한 초기 환경 구성과 기술 스택 선정을 진행했다.",[220,2418,2419],{},"단순히 가계부 기능을 빠르게 구현하는 것보다, 장기적으로 유지 가능한 서비스 구조를 만드는 것을 목표로 프로젝트 방향을 설정했다.",[220,2421,2422],{},"특히 이번 프로젝트에서는 이전 Brolog 개발 경험과 다르게 준비된 템플릿이나 기존 구조에 의존하지 않고, 프로젝트 생성부터 디렉토리 구성, 라이브러리 선택, 개발 환경 설정까지 직접 설계하는 과정을 경험하는 것에 의미를 두었다.",[279,2424],{},[220,2426,2427],{},"현재까지 결정된 주요 방향은 다음과 같다.",[260,2429,2433],{"className":2430,"code":2431,"filename":2432,"language":266,"meta":267},[263],"\nFrontend\n\n→ Nuxt 4 + Vue 3 + TypeScript 기반 구축\n\n\nUI System\n\n→ Nuxt UI + Tailwind CSS\n\n\nState Management\n\n→ Pinia 기반 상태 관리\n\n\nBackend\n\n→ Spring Boot + JPA 기반 API 서버\n\n\nDatabase\n\n→ 서비스 설계 이후 결정\n","BroBean Direction",[269,2434,2431],{"__ignoreMap":267},[279,2436],{},[220,2438,2439],{},"앞으로 BroBean은 단순한 가계부 기능 구현을 넘어,",[235,2441,2442,2445,2448,2451],{},[238,2443,2444],{},"모바일 환경을 고려한 UI\u002FUX 설계",[238,2446,2447],{},"사용자와 연인이 함께 사용할 수 있는 데이터 구조",[238,2449,2450],{},"안정적인 Backend API 설계",[238,2452,2453],{},"실제 서비스 운영을 고려한 아키텍처 구성",[220,2455,2456],{},"까지 단계적으로 발전시키는 것을 목표로 한다.",[279,2458],{},[220,2460,2461],{},"현재는 Frontend 기반을 구축하는 단계이며, 이후 화면 구성과 주요 기능을 구현하면서 서비스의 전체적인 흐름을 구체화해 나갈 예정이다.",[220,2463,2464],{},"다음 개발 과정에서는 Nuxt UI와 Tailwind CSS를 활용한 모바일 중심 Layout 구성부터 시작하여, BroBean의 실제 화면과 사용자 경험을 만들어가는 과정을 기록한다.",[2466,2467,2468],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":267,"searchDepth":1556,"depth":1556,"links":2470},[2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496],{"id":313,"depth":1556,"text":314},{"id":366,"depth":1556,"text":367},{"id":401,"depth":1556,"text":402},{"id":439,"depth":1556,"text":440},{"id":474,"depth":1556,"text":475},{"id":496,"depth":1556,"text":497},{"id":525,"depth":1556,"text":526},{"id":555,"depth":1556,"text":555},{"id":750,"depth":1556,"text":751},{"id":779,"depth":1556,"text":780},{"id":804,"depth":1556,"text":805},{"id":840,"depth":1556,"text":841},{"id":850,"depth":1556,"text":851},{"id":860,"depth":1556,"text":861},{"id":916,"depth":1556,"text":916},{"id":936,"depth":1556,"text":936},{"id":961,"depth":1556,"text":961},{"id":972,"depth":1556,"text":972},{"id":997,"depth":1556,"text":997},{"id":1027,"depth":1556,"text":1028},{"id":2015,"depth":1556,"text":2016},{"id":2087,"depth":1556,"text":2088},{"id":2312,"depth":1556,"text":2312},{"id":2342,"depth":1556,"text":2342},{"id":2361,"depth":1556,"text":2361},{"id":2377,"depth":1556,"text":2377},"2026-07-31","연인과 부부가 함께 사용할 수 있는 가계부 서비스 BroBean 프로젝트를 시작하며, 프론트 기술 스택 선정 과정과 Nuxt 4 프로젝트 생성 및 초기 개발 환경 구축 과정을 기록합니다.","md",null,{"tags":2502,"image":2509},[2503,2504,2505,2506,2507,2508,841],"BroBean","Nuxt","Vue","TypeScript","Nuxt UI","Tailwind CSS","\u002Fimages\u002Fbro-thumbnail.png",{"icon":26},{"title":2512,"description":2513},"BroBean 가계부 앱 개발 시작 - Nuxt 4 프론트 프로젝트 구성 과정","Nuxt 4, Vue 3, TypeScript 기반으로 가계부 앱 프로젝트 BroBean을 시작하며 기술 스택 선택 이유와 프로젝트 초기 환경 설정 과정을 정리합니다.","fOpwrNIg-K6z8VK-CaPorQKYjiEtU5N8sQyCu-JeApE",[2516,2518],{"title":188,"path":189,"stem":190,"description":2517,"icon":26,"children":-1},"연인이나 부부가 함께 사용할 수 있는 가계부 서비스를 만들게 된 이유와 BroBean이라는 이름, 그리고 프로젝트를 대표하는 마스코트를 기획하게 된 과정을 소개합니다.",{"title":206,"path":207,"stem":208,"description":2519,"icon":26,"children":-1},"제한된 네트워크 환경에서 발생한 Nuxt Icon 모듈 오류 원인을 분석하고 Custom Collection을 활용해 로컬 아이콘 환경을 구성한 과정 정리",1785398665493]