[{"data":1,"prerenderedAt":948},["ShallowReactive",2],{"navigation_docs_ko":3,"-ko-project-brolog-vercel-deploy3-ai-integration":181,"-ko-project-brolog-vercel-deploy3-ai-integration-surround":943},[4,114,167],{"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],{"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},"Project (개발일지)","icon-park-solid:branch-two","\u002Fko\u002Fproject","ko\u002F2.project",[120],{"title":121,"icon":122,"path":123,"stem":124,"children":125,"page":27},"Brolog","custom:symbol","\u002Fko\u002Fproject\u002Fbrolog","ko\u002F2.project\u002F1.brolog",[126,130,134,138,142,146,150,154,159,163],{"title":127,"path":128,"stem":129,"icon":26},"Brolog 프로젝트 개요","\u002Fko\u002Fproject\u002Fbrolog\u002Foutline","ko\u002F2.project\u002F1.brolog\u002F1.outline",{"title":131,"path":132,"stem":133,"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":135,"path":136,"stem":137,"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":139,"path":140,"stem":141,"icon":26},"Brolog 프로젝트 구조","\u002Fko\u002Fproject\u002Fbrolog\u002Fstructure","ko\u002F2.project\u002F1.brolog\u002F2.structure",{"title":143,"path":144,"stem":145,"icon":26},"[Nuxt Content] 네비게이션 아이콘 커스텀 빌드","\u002Fko\u002Fproject\u002Fbrolog\u002Fcustom-icon","ko\u002F2.project\u002F1.brolog\u002F3.custom-icon",{"title":147,"path":148,"stem":149,"icon":26},"[Nuxt 4] Auto-imports 동작 원리와 자동 import 시스템 이해","\u002Fko\u002Fproject\u002Fbrolog\u002Fnuxt-auto-import","ko\u002F2.project\u002F1.brolog\u002F4.nuxt-auto-import",{"title":151,"path":152,"stem":153,"icon":26},"[Brolog] 개발 블로그 메인 페이지 구현","\u002Fko\u002Fproject\u002Fbrolog\u002Fdevelop-main","ko\u002F2.project\u002F1.brolog\u002F5.develop-main",{"title":155,"path":156,"stem":157,"icon":158},"[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":160,"path":161,"stem":162,"icon":26},"[Brolog] Nuxt Multi Layer 프로젝트 Vercel 배포 (1)","\u002Fko\u002Fproject\u002Fbrolog\u002Fvercel-deploy1","ko\u002F2.project\u002F1.brolog\u002F8.vercel-deploy1",{"title":164,"path":165,"stem":166,"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":168,"icon":169,"path":170,"stem":171,"children":172,"page":27},"Error (트러블슈팅)","emojione:stop-sign","\u002Fko\u002Ftrouble-shooting","ko\u002F3.trouble-shooting",[173],{"title":121,"icon":122,"path":174,"stem":175,"children":176,"page":27},"\u002Fko\u002Ftrouble-shooting\u002Fbrolog","ko\u002F3.trouble-shooting\u002F1.brolog",[177],{"title":178,"path":179,"stem":180,"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":182,"title":131,"body":183,"date":927,"description":928,"extension":929,"links":930,"meta":931,"navigation":938,"path":132,"seo":939,"stem":133,"__hash__":942},"docs_ko\u002Fko\u002F2.project\u002F1.brolog\u002F10.vercel-deploy3-ai-integration.md",{"type":184,"value":185,"toc":920},"minimark",[186,916],[187,188,190,195,204,209,220,226,229,276,279,282,285,288,297,302,305,308,311,314,317,321,326,333,339,342,345,351,358,361,364,367,374,377,380,382,386,389,394,397,400,403,406,409,412,415,418,421,424,426,430,433,436,439,446,449,452,455,458,461,464,467,470,473,476,478,482,485,488,516,519,526,529,532,535,538,541,591,594,596,600,604,607,610,613,620,623,626,629,632,634,638,641,644,647,654,657,660,663,670,673,676,679,681,685,688,691,698,701,704,707,710,713,716,718,722,725,732,735,738,741,744,747,759,762,764,768,771,774,790,793,796,803,806,809,816,819,822,825,839,842,845,847,851,854,861,864,871,874,876,879,882,885,888,891,894,897,900,907,910,913],"u-page-card",{":spotlight":189},"true",[191,192,194],"h1",{"id":193},"generate-배포-이후-발견한-runtime-문제","🚀 Generate 배포 이후 발견한 Runtime 문제",[196,197,198,199,203],"p",{},"이전 글에서는 Nuxt Multi Layer 구조로 구성된 Brolog 프로젝트를 Vercel에 배포하면서 발생한 ",[200,201,202],"code",{},"layer\u002F.nuxt"," 생성 오류를 분석하고,",[196,205,206],{},[200,207,208],{},"nuxi prepare",[196,210,211,212,215,216,219],{},"과정과 ",[200,213,214],{},"build",", ",[200,217,218],{},"generate"," 방식의 차이를 확인했다.",[196,221,222,223,225],{},"초기 배포 과정에서는 정적 콘텐츠 중심의 블로그라는 목적을 고려하여 ",[200,224,218],{}," 방식을 선택했다.",[196,227,228],{},"적용했던 Build Command는 다음과 같다.",[230,231,237],"pre",{"className":232,"code":233,"filename":234,"language":235,"meta":236,"style":236},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","npx nuxi prepare ..\u002Flayer && npx nuxi generate --extends ..\u002Flayer\n","Terminal","bash","",[200,238,239],{"__ignoreMap":236},[240,241,244,248,252,255,258,262,265,267,270,273],"span",{"class":242,"line":243},"line",1,[240,245,247],{"class":246},"sBMFI","npx",[240,249,251],{"class":250},"sfazB"," nuxi",[240,253,254],{"class":250}," prepare",[240,256,257],{"class":250}," ..\u002Flayer",[240,259,261],{"class":260},"sMK4o"," &&",[240,263,264],{"class":246}," npx",[240,266,251],{"class":250},[240,268,269],{"class":250}," generate",[240,271,272],{"class":250}," --extends",[240,274,275],{"class":250}," ..\u002Flayer\n",[196,277,278],{},"결과적으로 정적 페이지 생성과 배포 자체는 정상적으로 완료되었다.",[196,280,281],{},"하지만 실제 서비스 환경에서 기능을 확인하는 과정에서 예상하지 못한 문제가 발견되었다.",[196,283,284],{},"Brolog은 단순한 Markdown 기반 문서 사이트가 아니라,",[196,286,287],{},"다음과 같은 Nuxt Runtime 기반 기능을 함께 사용하고 있었다.",[230,289,295],{"className":290,"code":292,"filename":293,"language":294,"meta":236},[291],"language-text","Nuxt Content\n\n+\n\nNuxt OG Image\n\n+\n\nAI Assistant\n\n+\n\nNitro Runtime\n","Runtime Features","text",[200,296,292],{"__ignoreMap":236},[196,298,299,301],{},[200,300,218],{}," 방식은 정적 결과물을 생성하는 데에는 적합하지만,",[196,303,304],{},"빌드 이후에도 서버 실행 환경이 필요한 기능까지 동일하게 제공하지는 않는다.",[196,306,307],{},"이번 글에서는 generate 배포 이후 확인한 Runtime 기능 문제와,",[196,309,310],{},"이를 해결하기 위해 Build 방식으로 변경한 과정,",[196,312,313],{},"그리고 Google AI Studio 전환 과정에서 발생한 SDK 버전 충돌 해결 과정을 기록한다.",[315,316],"hr",{},[191,318,320],{"id":319},"_1-generate-배포-이후-확인한-문제","1. Generate 배포 이후 확인한 문제",[322,323,325],"h2",{"id":324},"nuxt-og-image-동작-확인","Nuxt OG Image 동작 확인",[196,327,328,329,332],{},"Brolog에서는 페이지 공유 시 사용할 Open Graph Image 생성을 위해 ",[200,330,331],{},"nuxt-og-image","를 사용하고 있다.",[196,334,335,336,338],{},"하지만 ",[200,337,218],{}," 방식으로 배포한 이후 Vercel Production Deployment Overview에서 확인되는 Preview Image가 정상적으로 생성되지 않는 현상을 확인했다.",[196,340,341],{},"처음에는 단순한 SEO 메타데이터 설정 문제라고 생각했지만,",[196,343,344],{},"구조를 확인하면서 원인은 배포 방식 차이에 있었다.",[196,346,347,348,350],{},"Nuxt의 ",[200,349,218],{}," 방식은 빌드 시점에 페이지를 렌더링하여 정적 결과물을 생성한다.",[230,352,356],{"className":353,"code":354,"filename":355,"language":294,"meta":236},[291],"Build Time\n\n↓\n\nHTML \u002F Asset 생성\n\n↓\n\nStatic Hosting\n","Generate Flow",[200,357,354],{"__ignoreMap":236},[196,359,360],{},"구조로 동작한다.",[196,362,363],{},"반면 Nuxt OG Image는 단순히 이미지 파일을 미리 생성하는 기능이 아니라,",[196,365,366],{},"요청 시점에 Nitro Runtime에서 이미지를 생성하는 방식으로 동작한다.",[230,368,372],{"className":369,"code":370,"filename":371,"language":294,"meta":236},[291],"Request\n\n↓\n\nNitro Server Route\n\n↓\n\nOG Image 생성\n\n↓\n\nResponse\n","OG Image Runtime Flow",[200,373,370],{"__ignoreMap":236},[196,375,376],{},"과정이 필요하다.",[196,378,379],{},"따라서 완전한 Static Output 환경에서는 Nitro Runtime 기반 기능들이 기대한 방식으로 동작하지 않을 수 있다는 점을 확인했다.",[315,381],{},[322,383,385],{"id":384},"ai-assistant-동작-문제","AI Assistant 동작 문제",[196,387,388],{},"또 다른 문제는 Docus에서 제공하는 AI Assistant 기능이었다.",[196,390,391,393],{},[200,392,218],{}," 방식으로 배포한 이후 AI Assistant를 실행했을 때 정상적인 답변 UI가 표시되지 않았다.",[196,395,396],{},"대신 화면을 덮는 형태의 비정상적인 팝업이 나타났고,",[196,398,399],{},"내부에는 HTML 코드 형태의 응답 내용이 그대로 노출되는 현상이 발생했다.",[196,401,402],{},"처음에는 AI Provider 설정 문제라고 판단했지만,",[196,404,405],{},"응답 흐름을 확인하면서 다른 원인을 확인했다.",[196,407,408],{},"AI Assistant 요청은 단순히 브라우저에서 외부 API를 직접 호출하는 구조가 아니라,",[196,410,411],{},"Nuxt Server Runtime을 통해 API 요청과 Response Stream 처리가 이루어진다.",[196,413,414],{},"하지만 Static Generate 환경에서는 이러한 Runtime Layer가 정상적으로 유지되지 않았고,",[196,416,417],{},"클라이언트는 AI SDK가 기대하는 Response Format이 아닌 HTML Error Response를 전달받고 있었다.",[196,419,420],{},"이를 통해 문제의 핵심은 단순 API Key 설정이 아니라,",[196,422,423],{},"배포 방식과 Runtime 요구사항의 불일치라는 점을 확인했다.",[315,425],{},[191,427,429],{"id":428},"_2-generate에서-build-방식으로-변경","2. Generate에서 Build 방식으로 변경",[196,431,432],{},"문제를 확인한 이후 현재 Brolog 프로젝트에서 필요한 실행 환경을 다시 판단했다.",[196,434,435],{},"처음에는 개발 블로그라는 목적 때문에 정적 생성 방식이 적합하다고 생각했다.",[196,437,438],{},"하지만 실제 사용하는 기능을 기준으로 보면:",[230,440,444],{"className":441,"code":442,"filename":443,"language":294,"meta":236},[291],"\nNuxt Content\n\n+\n\nOG Image Generator\n\n+\n\nAI Assistant\n\n+\n\nServer Runtime 기능\n","Runtime Requirements",[200,445,442],{"__ignoreMap":236},[196,447,448],{},"을 포함하고 있었다.",[196,450,451],{},"Nuxt 3\u002F4의 서버 실행 환경은 Nitro Runtime 기반으로 구성된다.",[196,453,454],{},"SSR 렌더링,",[196,456,457],{},"API Route,",[196,459,460],{},"Server Middleware,",[196,462,463],{},"Runtime Config,",[196,465,466],{},"OG Image Generator와 같은 기능들은 Nitro Runtime 위에서 실행된다.",[196,468,469],{},"따라서 이러한 기능을 사용하는 프로젝트에서는 단순히 정적 파일 생성 여부보다,",[196,471,472],{},"Runtime Layer가 필요한지 판단하는 것이 중요하다.",[196,474,475],{},"이번 프로젝트에서는 Static Output보다 Nitro Runtime이 포함되는 Build 방식이 더 적합하다고 판단했다.",[315,477],{},[191,479,481],{"id":480},"_3-build-방식-전환과-메모리-제한-해결","3. Build 방식 전환과 메모리 제한 해결",[196,483,484],{},"이전 글에서 확인했던 것처럼 일반적인 Nuxt Build 과정은 Vercel 환경에서 메모리 부족 문제가 발생했다.",[196,486,487],{},"기본 Build Command:",[230,489,491],{"className":232,"code":490,"filename":234,"language":235,"meta":236,"style":236},"npx nuxi prepare ..\u002Flayer && npx nuxi build --extends ..\u002Flayer\n",[200,492,493],{"__ignoreMap":236},[240,494,495,497,499,501,503,505,507,509,512,514],{"class":242,"line":243},[240,496,247],{"class":246},[240,498,251],{"class":250},[240,500,254],{"class":250},[240,502,257],{"class":250},[240,504,261],{"class":260},[240,506,264],{"class":246},[240,508,251],{"class":250},[240,510,511],{"class":250}," build",[240,513,272],{"class":250},[240,515,275],{"class":250},[196,517,518],{},"실행 결과:",[230,520,524],{"className":521,"code":522,"filename":523,"language":294,"meta":236},[291],"Error: Command exited with SIGKILL\n\nOut of Memory event was detected during the build.\n","Error Log",[200,525,522],{"__ignoreMap":236},[196,527,528],{},"Vercel Build Container 환경은 제한된 리소스에서 실행되기 때문에,",[196,530,531],{},"Nuxt Build 과정에서 생성되는 번들링 과정과 Nitro Server Bundle 생성 과정이 메모리 제한에 도달한 것으로 판단했다.",[196,533,534],{},"Brolog에서 사용하는 기능 특성상 Nitro Runtime이 필요한 기능들이 존재했고,",[196,536,537],{},"결국 Node 메모리 제한을 조정하는 방향으로 다시 시도했다.",[196,539,540],{},"최종 Build Command는 다음과 같다.",[230,542,544],{"className":232,"code":543,"filename":234,"language":235,"meta":236,"style":236},"export NODE_OPTIONS=\"--max-old-space-size=6144\" && npx nuxi prepare ..\u002Flayer && pnpm run build --extends ..\u002Flayer\n",[200,545,546],{"__ignoreMap":236},[240,547,548,552,556,559,562,565,567,569,571,573,575,577,579,582,585,587,589],{"class":242,"line":243},[240,549,551],{"class":550},"spNyl","export",[240,553,555],{"class":554},"sTEyZ"," NODE_OPTIONS",[240,557,558],{"class":260},"=",[240,560,561],{"class":260},"\"",[240,563,564],{"class":250},"--max-old-space-size=6144",[240,566,561],{"class":260},[240,568,261],{"class":260},[240,570,264],{"class":246},[240,572,251],{"class":250},[240,574,254],{"class":250},[240,576,257],{"class":250},[240,578,261],{"class":260},[240,580,581],{"class":246}," pnpm",[240,583,584],{"class":250}," run",[240,586,511],{"class":250},[240,588,272],{"class":250},[240,590,275],{"class":250},[196,592,593],{},"결과적으로 Vercel 환경에서 Build가 정상적으로 완료되었다.",[315,595],{},[191,597,599],{"id":598},"_4-build-전환-이후-확인한-변화","4. Build 전환 이후 확인한 변화",[322,601,603],{"id":602},"nuxt-og-image-정상-동작","Nuxt OG Image 정상 동작",[196,605,606],{},"Build 방식으로 전환한 이후 Vercel Production Deployment Overview에서 Preview Image가 정상적으로 생성되는 것을 확인했다.",[196,608,609],{},"기존 generate 방식에서는 확인되지 않았던 Brolog 메인 화면 기반 이미지가 정상적으로 표시되었다.",[196,611,612],{},"이 과정에서 확인한 핵심은 다음과 같다.",[230,614,618],{"className":615,"code":616,"filename":617,"language":294,"meta":236},[291],"\ngenerate\n\n↓\n\nStatic Output 생성\n\n↓\n\n정적 파일 제공\n\n\nbuild\n\n↓\n\nNitro Server Bundle 생성\n\n↓\n\nRuntime 요청 처리 가능\n","Generate vs Build",[200,619,616],{"__ignoreMap":236},[196,621,622],{},"Nuxt에서 사용하는 일부 기능은 단순히 페이지를 생성하는 것에서 끝나는 것이 아니라,",[196,624,625],{},"배포 이후 요청을 처리할 Runtime 환경을 필요로 한다.",[196,627,628],{},"이번 문제는 기능 자체의 오류라기보다,",[196,630,631],{},"프로젝트가 요구하는 Runtime 환경과 배포 방식의 차이에서 발생한 문제였다.",[315,633],{},[322,635,637],{"id":636},"ai-assistant-오류-형태-변경","AI Assistant 오류 형태 변경",[196,639,640],{},"Build 전환 이후 기존처럼 화면 전체를 덮는 HTML 팝업 형태의 문제는 사라졌다.",[196,642,643],{},"하지만 AI Assistant 요청은 여전히 정상적인 답변을 반환하지 않았다.",[196,645,646],{},"확인 결과 HTTP Status 자체는:",[230,648,652],{"className":649,"code":650,"filename":651,"language":294,"meta":236},[291],"200 OK\n","HTTP Status",[200,653,650],{"__ignoreMap":236},[196,655,656],{},"였지만,",[196,658,659],{},"Response Body 내부에는 오류 내용이 포함되어 있었다.",[196,661,662],{},"즉:",[230,664,668],{"className":665,"code":666,"filename":667,"language":294,"meta":236},[291],"\nHTTP Layer\n\n↓\n\n정상 응답\n\n↓\n\nAI Provider 요청 과정에서 Error 발생\n","Response Flow",[200,669,666],{"__ignoreMap":236},[196,671,672],{},"구조였다.",[196,674,675],{},"네트워크 요청 자체는 성공했지만,",[196,677,678],{},"AI Model Provider 연결 과정에서 문제가 발생하고 있었다.",[315,680],{},[191,682,684],{"id":683},"_5-vercel-ai-gateway-문제-확인","5. Vercel AI Gateway 문제 확인",[196,686,687],{},"로그를 확인하면서 AI 오류 원인을 추적했다.",[196,689,690],{},"기존 AI Assistant 구조는 다음과 같았다.",[230,692,696],{"className":693,"code":694,"filename":695,"language":294,"meta":236},[291],"\nBrolog AI Assistant\n\n↓\n\nVercel AI Gateway\n\n↓\n\nAI Model Provider\n","AI Flow",[200,697,694],{"__ignoreMap":236},[196,699,700],{},"문제는 Vercel AI Gateway 사용 조건이었다.",[196,702,703],{},"Vercel AI Gateway를 사용하기 위해서는 결제 수단 등록이 필요했다.",[196,705,706],{},"무료 사용 범위가 존재하더라도,",[196,708,709],{},"개인 프로젝트 환경에서는 예상하지 못한 과금 가능성을 관리하는 것이 중요하다고 판단했다.",[196,711,712],{},"따라서 AI Provider를 직접 관리하는 방식으로 변경하기로 했다.",[196,714,715],{},"최종적으로 Google AI Studio API를 사용하는 방향으로 변경했다.",[315,717],{},[191,719,721],{"id":720},"_6-google-ai-studio-provider-변경","6. Google AI Studio Provider 변경",[196,723,724],{},"변경 이후 구조는 다음과 같다.",[230,726,730],{"className":727,"code":728,"filename":729,"language":294,"meta":236},[291],"\nBrolog AI Assistant\n\n↓\n\nAI SDK\n\n↓\n\nGoogle AI Studio API\n\n↓\n\nGemini Model\n","AI Provider Architecture",[200,731,728],{"__ignoreMap":236},[196,733,734],{},"Google AI Studio에서는 무료 사용 가능한 모델을 제공하고 있었고,",[196,736,737],{},"개인 개발 블로그 환경에서는 충분히 활용 가능한 수준이라고 판단했다.",[196,739,740],{},"또한 제공되는 모델은 변경될 수 있기 때문에,",[196,742,743],{},"모델명을 코드 내부에 직접 작성하지 않고 환경 변수로 분리했다.",[196,745,746],{},"예:",[230,748,753],{"className":749,"code":750,"filename":751,"language":752,"meta":236,"style":236},"language-env shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","GOOGLE_AI_MODEL=gemini-model-name\n","Environment Variable","env",[200,754,755],{"__ignoreMap":236},[240,756,757],{"class":242,"line":243},[240,758,750],{},[196,760,761],{},"이렇게 구성하면 모델 변경이 필요할 때 코드 수정 없이 환경 변수만 변경하면 된다.",[315,763],{},[191,765,767],{"id":766},"_7-ai-sdk-provider-버전-충돌-해결","7. AI SDK Provider 버전 충돌 해결",[196,769,770],{},"Google Provider 적용 과정에서 새로운 문제가 발생했다.",[196,772,773],{},"Google AI Studio 연동을 위해 다음 패키지를 설치했다.",[230,775,777],{"className":232,"code":776,"filename":234,"language":235,"meta":236,"style":236},"pnpm add @ai-sdk\u002Fgoogle\n",[200,778,779],{"__ignoreMap":236},[240,780,781,784,787],{"class":242,"line":243},[240,782,783],{"class":246},"pnpm",[240,785,786],{"class":250}," add",[240,788,789],{"class":250}," @ai-sdk\u002Fgoogle\n",[196,791,792],{},"하지만 설치된 버전은 4.x 버전이었다.",[196,794,795],{},"기존 프로젝트에서는:",[230,797,801],{"className":798,"code":799,"filename":800,"language":294,"meta":236},[291],"ai@6\n","Installed Version",[200,802,799],{"__ignoreMap":236},[196,804,805],{},"버전을 사용하고 있었다.",[196,807,808],{},"확인 결과 내부 의존성 구조에서 차이가 있었다.",[230,810,814],{"className":811,"code":812,"filename":813,"language":294,"meta":236},[291],"\nai@6\n\n└── @ai-sdk\u002Fprovider@3\n\n\n@ai-sdk\u002Fgoogle@4\n\n└── @ai-sdk\u002Fprovider@4\n","Dependency Tree",[200,815,812],{"__ignoreMap":236},[196,817,818],{},"같은 AI SDK 생태계 패키지였지만,",[196,820,821],{},"Major Version 차이로 인해 내부 Provider Interface가 호환되지 않았다.",[196,823,824],{},"결과적으로 Google Provider 버전을 프로젝트의 AI SDK 버전에 맞춰 변경했다.",[230,826,828],{"className":232,"code":827,"filename":234,"language":235,"meta":236,"style":236},"pnpm add @ai-sdk\u002Fgoogle@3\n",[200,829,830],{"__ignoreMap":236},[240,831,832,834,836],{"class":242,"line":243},[240,833,783],{"class":246},[240,835,786],{"class":250},[240,837,838],{"class":250}," @ai-sdk\u002Fgoogle@3\n",[196,840,841],{},"이후 Provider Dependency 충돌이 해결되었고,",[196,843,844],{},"Google AI Studio 기반 AI Assistant가 정상적으로 동작했다.",[315,846],{},[191,848,850],{"id":849},"_8-현재-brolog-배포-구조","8. 현재 Brolog 배포 구조",[196,852,853],{},"현재 최종 배포 구조는 다음과 같다.",[230,855,859],{"className":856,"code":857,"filename":858,"language":294,"meta":236},[291],"\nVercel Build\n\n↓\n\nnuxi prepare ..\u002Flayer\n\n↓\n\nNuxt Build\n\n↓\n\nNitro Runtime Deployment\n\n↓\n\nGoogle AI Studio API\n","Final Architecture",[200,860,857],{"__ignoreMap":236},[196,862,863],{},"AI Model 설정은:",[230,865,869],{"className":866,"code":867,"filename":868,"language":294,"meta":236},[291],"\nEnvironment Variable\n\n↓\n\nModel 선택\n\n↓\n\nAI SDK Provider 연결\n","Model Management",[200,870,867],{"__ignoreMap":236},[196,872,873],{},"구조로 관리하고 있다.",[315,875],{},[191,877,878],{"id":878},"마무리",[196,880,881],{},"이번 배포 과정에서는 단순히 빌드 성공 여부보다,",[196,883,884],{},"프로젝트에서 사용하는 기능이 어떤 실행 환경을 요구하는지 확인하는 과정이 중요했다.",[196,886,887],{},"처음에는 블로그 서비스라는 목적 때문에 generate 방식이 적합하다고 판단했지만,",[196,889,890],{},"실제 사용하고 있는 기능이 Nitro Runtime 기반 기능을 포함하고 있었기 때문에 Build 방식이 더 적합했다.",[196,892,893],{},"또한 AI 기능 적용 과정에서는 단순히 API Provider만 변경하는 것이 아니라,",[196,895,896],{},"AI SDK 생태계 내부 Dependency와 Provider Version 호환성까지 함께 확인해야 했다.",[196,898,899],{},"최종적으로 Brolog은:",[230,901,905],{"className":902,"code":903,"filename":904,"language":294,"meta":236},[291],"\nNuxt Multi Layer\n\n+\n\nNuxt Build\n\n+\n\nNitro Runtime\n\n+\n\nGoogle AI Studio\n\n+\n\nEnvironment Variable 기반 Model 관리\n","Final Stack",[200,906,903],{"__ignoreMap":236},[196,908,909],{},"구조로 운영하게 되었다.",[196,911,912],{},"이번 과정은 단순한 배포 설정 변경이 아니라,",[196,914,915],{},"Nuxt 애플리케이션이 정적 생성과 Runtime 실행 환경 사이에서 어떻게 동작하는지 확인할 수 있었던 과정이었다.",[917,918,919],"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 pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":236,"searchDepth":921,"depth":921,"links":922},2,[923,924,925,926],{"id":324,"depth":921,"text":325},{"id":384,"depth":921,"text":385},{"id":602,"depth":921,"text":603},{"id":636,"depth":921,"text":637},"2026-07-23","Nuxt Multi Layer 프로젝트를 Vercel에 배포한 이후 발생한 Nuxt OG Image와 AI Assistant 문제를 분석하고 Build 방식 전환, Google AI Studio 적용 과정과 SDK 버전 충돌 해결 과정을 기록합니다.","md",null,{"tags":932,"image":937},[121,43,933,69,934,935,936],"Vercel","AI SDK","Google AI Studio","Deployment","\u002Fimages\u002Fbro-ai-thumbnail3.png",{"icon":26},{"title":940,"description":941},"Nuxt Multi Layer Vercel 배포 - Nuxt Runtime과 AI Assistant 문제 해결 과정","Nuxt generate 배포 이후 발생한 Runtime 기반 기능 문제를 분석하고 Nitro 기반 Build 전환, Vercel AI Gateway 변경, Google AI Studio 적용 과정을 정리합니다.","3iXXdXzhJhSX1jCW26my99O9UzuYF3whbTH5AkIKlEU",[944,946],{"title":127,"path":128,"stem":129,"description":945,"icon":26,"children":-1},"개발 기록을 위한 개인 블로그 프로젝트의 목적과 방향",{"title":135,"path":136,"stem":137,"description":947,"icon":26,"children":-1},"AI Assistant를 적용하면서 확인한 Agent 구조의 API 호출 흐름과 MCP Tool 사용 과정에서 발생하는 API 사용량 증가, 무료 API 환경에서 고려해야 할 운영 요소를 정리합니다.",1785297529327]