<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>CrowRish Blog</title>
    <description>개발 경험과 학습 내용을 기록하고 공유하는 공간입니다. 주로 프론트엔드 개발, 그리고 새로운 기술 스택에 대한 이야기를 다룹니다.</description>
    <link>https://crowrish.com</link>
    <language>ko</language>
    <lastBuildDate>Wed, 16 Sep 2026 06:29:38 GMT</lastBuildDate>
    <atom:link href="https://crowrish.com/rss" rel="self" type="application/rss+xml" />
    <image>
      <url>https://crowrish.com/og-image.png</url>
      <title>CrowRish Blog</title>
      <link>https://crowrish.com</link>
    </image>
    <item>
      <title>LLM AI로 간식 추천 서비스 만들기</title>
      <link>https://crowrish.com/blog/snacklink-gpt-chat</link>
      <guid isPermaLink="true">https://crowrish.com/blog/snacklink-gpt-chat</guid>
      <description>LLM API를 백엔드에 붙여 AI 간식 추천 챗을 만들고, 없는 간식을 추천하던 문제를 프롬프트와 DB 검증으로 잡은 기록</description>
      <dc:creator>CrowRish</dc:creator>
      <pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate>
      <media:content url="https://crowrish.com/blog/snacklink-gpt-chat/opengraph-image" medium="image" />
      <category>AI</category>
      <category>LLM</category>
      <category>React</category>
      <category>Next.js</category>
      <category>GPT</category>
      <content:encoded><![CDATA[<p>스낵링크는 사무실 간식 큐레이션 서비스였습니다. 회사 총무 담당자가 탕비실 간식을 고르는 데 생각보다 시간이 많이 드는데, 그걸 1분 안에 끝내 보자는 게 목표였어요.</p><p>AI 챗은 대표님의 오더로 시작했습니다. &quot;사무실 간식 5만원어치 알려줘&quot;처럼 말만 하면 간식 구성을 짜 주는 기능이요. 개발은 백엔드 개발자 한 분과 저, 둘이서 했습니다. GPT를 부르고 결과를 가공하는 건 백엔드, 그 응답을 받아 화면에 풀어내는 건 제 몫이었어요. 둘이서 서비스 전체를 만든 이야기는 따로 써 보려고 합니다.</p><p>이번 글은 그중 AI 챗 이야기입니다. 백엔드와 프론트가 LLM을 어떻게 나눠 맡았는지, 그리고 AI가 없는 간식을 추천하던 문제를 어떻게 잡았는지를 정리했습니다.</p><figure><img src="https://crowrish.com/blog-images/dd9e1210910b9275813c9e09effcc699.webp" alt="스낵링크 AI 추천 챗. 말로 요청하면 간식 구성이 돌아온다" /><figcaption>스낵링크 AI 추천 챗. 말로 요청하면 간식 구성이 돌아온다</figcaption></figure><blockquote><p>글에 실린 화면은 서비스 종료 후 만든 데모에서 다시 찍었습니다. UI는 원래 코드 그대로지만, 화면 속 답변 문장은 GPT가 아닌 데모용 모델이 만든 것입니다.</p></blockquote><h2>화면이 먼저 나왔습니다</h2><p>챗 화면은 GPT가 붙기 전에 먼저 만들었습니다. 2024년 10월 말, 백엔드에 아직 아무것도 없을 때 더미 데이터로 시작했어요.</p><p><a href="https://crowrish.com/blog/snacklink-gpt-chat">계속 읽기 →</a></p>]]></content:encoded>
    </item>
    <item>
      <title>LLM AI로 상품 큐레이션 도구 만들기</title>
      <link>https://crowrish.com/blog/curation-tool-gemini</link>
      <guid isPermaLink="true">https://crowrish.com/blog/curation-tool-gemini</guid>
      <description>서버 없는 상품 큐레이션 도구에 LLM API(Gemini)를 붙여 요구사항 문장으로 상품과 장바구니를 채우고, 응답 잘림·모델 교체·API 키 노출 문제를 다룬 기록</description>
      <dc:creator>CrowRish</dc:creator>
      <pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate>
      <media:content url="https://crowrish.com/blog/curation-tool-gemini/opengraph-image" medium="image" />
      <category>AI</category>
      <category>LLM</category>
      <category>React</category>
      <category>Vite</category>
      <category>Gemini</category>
      <content:encoded><![CDATA[<p>친하게 지내는 MD 동료의 부탁으로 만든 상품 큐레이션 도구가 있습니다. 화면 헤더에 &quot;for Awesome MDs&quot;라고 적어 둔 것도 그래서예요.</p><p>고객사별로 간식 구성을 짜는 웹앱인데요, 가격표와 운영 가능 상품, 고객사별 특별단가가 들어 있는 엑셀을 올리면 브라우저 안에 상품 DB가 만들어지고, 거기서 검색해 고객사 탭마다 장바구니를 채운 다음 정해진 양식의 엑셀로 내보냅니다.</p><p>서버는 없습니다. Vite + React로 만든 SPA이고, 데이터는 전부 브라우저의 IndexedDB(Dexie)에 들어갑니다. 여기에 LLM(Gemini)을 붙인 과정을 정리해 봤습니다.</p><blockquote><p>글의 화면은 촬영용으로 만든 샘플 엑셀(상품 164개, 고객사 5곳)로 다시 찍었습니다. 상품명·고객사·단가는 모두 가짜이고, AI 결과는 실제 Gemini 응답입니다.</p></blockquote><figure><img src="https://crowrish.com/blog-images/a7d62696aeaa8ba57300abbc234f757c.webp" alt="상품 큐레이션 도구. 위는 상품 검색, 아래는 고객사별 장바구니. 특별단가가 있는 고객사는 배지와 행 색으로 구분된다" /><figcaption>상품 큐레이션 도구. 위는 상품 검색, 아래는 고객사별 장바구니. 특별단가가 있는 고객사는 배지와 행 색으로 구분된다</figcaption></figure><figure><img src="https://crowrish.com/blog-images/b7ea7531df518d46804278eb3be01af7.webp" alt="엑셀을 올리면 시트별로 브라우저 안의 상품 DB가 된다" /><figcaption>엑셀을 올리면 시트별로 브라우저 안의 상품 DB가 된다</figcaption></figure><h2>규칙으로 할 수 있는 데까지</h2><p>AI부터 붙인 건 아닙니다. 추천 기능은 이렇게 늘어났어요.</p><p><a href="https://crowrish.com/blog/curation-tool-gemini">계속 읽기 →</a></p>]]></content:encoded>
    </item>
    <item>
      <title>React useMemo 꼭 사용해야할까?</title>
      <link>https://crowrish.com/blog/react-compiler-intro</link>
      <guid isPermaLink="true">https://crowrish.com/blog/react-compiler-intro</guid>
      <description>React 개발자라면 한 번쯤 고민해봤을 문제입니다. 그 문제 해결에 도움이 될 React Compiler를 소개합니다.</description>
      <dc:creator>CrowRish</dc:creator>
      <pubDate>Mon, 13 Oct 2025 00:00:00 GMT</pubDate>
      <media:content url="https://crowrish.com/blog/react-compiler-intro/opengraph-image" medium="image" />
      <category>React</category>
      <category>Next.js</category>
      <content:encoded><![CDATA[<h2>React Compiler: 메모이제이션 트렌드</h2><blockquote><p>&quot;useMemo와 useCallback을 꼭 사용해야 할까?&quot;</p></blockquote><p>React 개발자라면 한 번쯤 고민해봤을 문제입니다. 그 문제 해결에 도움이 될 React Compiler를 소개합니다.</p><h2>TL;DR</h2><ul><li>React Compiler는 빌드 타임에 자동으로 메모이제이션을 적용하는 도구</li><li>Next.js 16에서 안정화되어 프로덕션 사용 가능</li><li>Meta Quest Store에서 초기 로드 최대 12% 향상, 특정 인터랙션 2.5배 빠름</li><li>과도한 수동 메모이제이션은 오히려 생산성을 31-46% 저하</li><li>당분간은 &quot;성능 문제가 있을 때만 최적화&quot; 원칙 유지</li></ul><hr /><h2>배경: 메모이제이션의 딜레마</h2><p>React 개발을 하다 보면 필연적으로 만나는 고민이 있습니다.</p><pre><code>function ProductList({ products }) {
  const sortedProducts = products.sort((a, b) =&gt; a.price - b.price);

  const handleClick = (id) =&gt; {
    console.log(id);
  };

  return (
    &lt;div&gt;
      {sortedProducts.map(p =&gt; (
        &lt;ProductCard
          key={p.id}
          product={p}
          onClick={handleClick}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}
</code></pre><h3>이 코드를 메모이제이션 해야 할까요?</h3><p>&quot;최적화를 위해 <code>useMemo</code>와 <code>useCallback</code>을 써야 하나?&quot;라는 질문에 팀마다 다른 답을 가지고 있습니다:</p><ul><li>A: &quot;모든 걸 메모이제이션하자!&quot;</li><li>B: &quot;성능 문제가 생기면 그때 추가하자&quot;</li><li>C: &quot;...뭐가 맞는지 모르겠다&quot;</li></ul><p>그리고 많은 경우, A팀의 코드베이스는 점점 유지보수 지옥이 되어갑니다.</p><p><a href="https://crowrish.com/blog/react-compiler-intro">계속 읽기 →</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Fumadocs 한글 검색 기능 구현하기</title>
      <link>https://crowrish.com/blog/fumadocs-korean-search</link>
      <guid isPermaLink="true">https://crowrish.com/blog/fumadocs-korean-search</guid>
      <description>Fumadocs의 기본 검색 엔진인 Orama가 한글을 제대로 지원하지 않는 문제를 해결하기 위해 커스텀 한글 검색 엔진을 구현한 과정을 공유합니다.</description>
      <dc:creator>CrowRish</dc:creator>
      <pubDate>Mon, 18 Aug 2025 00:00:00 GMT</pubDate>
      <media:content url="https://crowrish.com/blog-images/d9acf0457ab75a4520a16b40c477e6c1.webp" medium="image" />
      <category>Fumadocs</category>
      <category>Next.js</category>
      <category>es-hangul</category>
      <content:encoded><![CDATA[<p><img src="https://crowrish.com/blog-images/617ef75114df52a023fb2cd79118278b.webp" alt="" /></p><p>문서 사이트를 운영하다 보면 검색 기능은 필수입니다. 특히 한국어 컨텐츠가 많은 사이트에서는 한글에 특화된 검색 기능이 중요합니다. 이번 글에서는 Fumadocs의 기본 검색 엔진인 Orama가 한글을 제대로 지원하지 않는 문제를 해결하기 위해 커스텀 한글 검색 엔진을 구현한 과정을 공유합니다.</p><h2>문제 발생</h2><blockquote><p>😮 : 한글 검색에 문제가 있나?</p></blockquote><p>Fumadocs를 사용해 문서 사이트를 구축했는데, 한 가지 큰 문제가 있었습니다. <strong>한글 검색이 제대로 작동하지 않는 것</strong>이었습니다.</p><h3>원인 분석</h3><p>Fumadocs는 기본적으로 <strong>Orama</strong>라는 검색 엔진을 사용하는데, 검색 결과 알게된 사실은…</p><p><a href="https://github.com/orgs/oramasearch/discussions/748"><strong>GitHub Discussion #748</strong></a>에서 Orama 팀의 답변:</p><p><a href="https://crowrish.com/blog/fumadocs-korean-search">계속 읽기 →</a></p>]]></content:encoded>
    </item>
  </channel>
</rss>