<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>pxd story</title>
    <link>https://story.pxd.co.kr/</link>
    <description>UX에 관한 pxd사람들의 진지하거나 소소한 수다</description>
    <language>ko</language>
    <pubDate>Tue, 9 Jun 2026 17:36:57 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>pxd story</managingEditor>
    <image>
      <title>pxd story</title>
      <url>https://tistory1.daumcdn.net/tistory/407306/attach/d438eeb35af843279a5afa727117655e</url>
      <link>https://story.pxd.co.kr</link>
    </image>
    <item>
      <title>검색엔진은 우리 사이트를 어떻게 발견할까?</title>
      <link>https://story.pxd.co.kr/1899</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 편에서 프론트엔드 개발자가 왜 SEO를 챙겨야 하는지, 그리고 GEO라는 새로운 관점이 왜 필요해졌는지 이야기했어요. 이번 편에서는 좀 더 실전적인 이야기를 해볼게요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색엔진이 우리 사이트를 검색 결과에 보여주려면, 먼저 우리 사이트를 &lt;b&gt;발견&lt;/b&gt;해야 하잖아요. 근데 이 &quot;발견&quot;이라는 과정이 생각보다 단순하지 않더라고요. SEO/GEO 분석 서비스를 만들면서 수많은 사이트를 들여다봤는데, 콘텐츠는 멀쩡한데 크롤러가 아예 접근을 못 하는 경우가 의외로 많았어요. 대기업 사이트에서도요.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이번 편에서는 검색엔진 크롤러가 우리 사이트를 발견하고 색인하는 과정을 프론트엔드 개발자 관점에서 풀어볼게요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;크롤링 &amp;rarr; 인덱싱 &amp;rarr; 랭킹, 이 흐름부터 잡자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색엔진이 검색 결과를 보여주기까지는 크게 세 단계를 거쳐요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;크롤링(Crawling)&lt;/b&gt; &amp;mdash; 크롤러가 웹을 돌아다니면서 페이지를 발견하고 수집하는 단계예요. 이때 크롤러는 링크를 따라가거나 sitemap을 참고해서 페이지를 찾아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인덱싱(Indexing)&lt;/b&gt; &amp;mdash; 수집한 페이지의 내용을 분석해서 데이터베이스에 저장하는 단계예요. 페이지 제목이 뭔지, 어떤 주제인지, 어떤 키워드가 포함됐는지 등을 파악해서 정리해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;랭킹(Ranking)&lt;/b&gt; &amp;mdash; 사용자가 검색했을 때, 인덱스에 저장된 페이지들 중에서 가장 적합한 걸 골라서 순서대로 보여주는 단계예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 핵심은, &lt;b&gt;크롤링이 안 되면 인덱싱도 안 되고, 인덱싱이 안 되면 랭킹에 아예 참여할 수 없다&lt;/b&gt;는 거예요. 아무리 좋은 콘텐츠를 만들어도 크롤러가 접근할 수 없으면 검색 결과에 나타나지 않아요. 그래서 기술적 SEO의 출발점은 항상 &quot;크롤러가 우리 사이트에 제대로 접근할 수 있는가&quot;예요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;robots.txt &amp;mdash; 크롤러에게 보내는 첫 번째 신호&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롤러가 어떤 사이트를 방문하면 가장 먼저 확인하는 파일이 robots.txt예요. 사이트 루트에 위치하는 텍스트 파일인데, &quot;이 사이트에서 어디를 탐색해도 되고, 어디는 안 되는지&quot;를 크롤러에게 알려주는 역할이에요.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;# 기본적인 robots.txt 예시


User-agent: *
Allow: /
Disallow: /admin/
Disallow: /api/
Sitemap: https://example.com/sitemap.xml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단해 보이지만, 이 파일 하나가 SEO에 미치는 영향이 꽤 커요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;robots.txt가 없거나 잘못 설정된 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 분석하다 보면 이런 케이스를 자주 만나요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;robots.txt 자체가 없는 경우&lt;/b&gt; &amp;mdash; 파일이 없더라도 크롤러는 일반적으로 모든 페이지에 접근 가능한 상태로 해석해요. 그래서 즉시 치명적인 문제가 생기지는 않을 수 있어요. 다만 robots.txt를 두면 sitemap 위치를 명시적으로 안내할 수 있고, 검색엔진 크롤러별 탐색 정책을 세밀하게 제어할 수 있어요. 특히 운영 환경에서는 관리 페이지나 불필요한 API 경로에 대한 크롤링을 제한하는 용도로 활용하는 경우가 많아요. 분석해본 사이트 중 꽤 많은 경우가 &quot;파일 자체를 몰랐거나, 초기에 깜빡하고 그냥 운영 들어간&quot; 경우였어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Disallow: /&lt;/b&gt;&lt;b&gt;로 전체 차단한 경우&lt;/b&gt; &amp;mdash; 이건 진짜 치명적이에요. 모든 검색엔진 크롤러를 사이트 전체에서 차단하겠다는 의미예요. 실제로 이런 설정이 된 사이트가 있었는데, 검색 결과에서 완전히 사라져 있더라고요. 개발 환경에서 설정해둔 걸 운영에 그대로 올린 거였어요. 결과적으로 멀쩡한 사이트가 몇 달 동안 검색 노출이 0이었던 케이스예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 디렉터리를 차단한 경우&lt;/b&gt; &amp;mdash; /product/나 /service/ 같은 중요한 경로를 Disallow에 넣어버리면, 정작 사용자에게 보여줘야 할 페이지가 검색 결과에서 빠져요. CMS 관련 경로를 막으려다가 실수로 전체 콘텐츠 경로를 막는 경우가 종종 있어요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프론트엔드 개발자가 챙겨야 할 포인트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js나 Nuxt 같은 프레임워크를 쓰고 있다면 robots.txt를 직접 관리해야 해요. Next.js의 경우 app/robots.ts에서 동적으로 생성할 수도 있고, public/robots.txt에 정적 파일로 놓을 수도 있어요.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// Next.js app/robots.ts 예시

import { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
  return {
    rules: {
      userAgent: '*',
      allow: '/',
      disallow: ['/admin/', '/api/', '/private/'],
    },
    sitemap: 'https://example.com/sitemap.xml',
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 건, 배포할 때 https://내도메인/robots.txt에 직접 접속해서 200 응답이 오는지, 내용이 의도한 대로 나오는지 눈으로 확인하는 거예요. 빌드 과정에서 빠지거나, 서버 설정에 따라 404가 뜨는 경우가 은근히 있거든요. 특히 배포 파이프라인 바꾼 직후에 한 번씩 꼭 확인하는 게 좋아요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Sitemap &amp;mdash; 사이트의 전체 지도를 건네주기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;robots.txt가 &quot;어디를 탐색해도 되는지&quot;를 알려준다면, sitemap은 &quot;우리 사이트에 어떤 페이지들이 있는지&quot;를 목록으로 알려주는 역할이에요.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;urlset xmlns=&quot;http://www.sitemaps.org/schemas/sitemap/0.9&quot;&amp;gt;
  &amp;lt;url&amp;gt;
    &amp;lt;loc&amp;gt;https://example.com/&amp;lt;/loc&amp;gt;
    &amp;lt;lastmod&amp;gt;2026-03-15&amp;lt;/lastmod&amp;gt;
  &amp;lt;/url&amp;gt;
  &amp;lt;url&amp;gt;
    &amp;lt;loc&amp;gt;https://example.com/products&amp;lt;/loc&amp;gt;
    &amp;lt;lastmod&amp;gt;2026-03-20&amp;lt;/lastmod&amp;gt;
  &amp;lt;/url&amp;gt;
&amp;lt;/urlset&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롤러는 링크를 따라가면서 페이지를 발견하기도 하지만, 사이트 규모가 커지면 링크만으로는 모든 페이지를 찾기 어려워요. sitemap이 있으면 크롤러가 사이트 전체 구조를 한눈에 파악할 수 있어서 크롤링 효율이 올라가요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;sitemap 관련 흔한 실수들&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;robots.txt에 sitemap 경로를 안 적은 경우&lt;/b&gt; &amp;mdash; sitemap 파일을 만들어놔도 robots.txt에서 경로를 알려주지 않으면 크롤러가 찾기 어려워요. Google Search Console에서 수동으로 제출할 수도 있지만, robots.txt에 한 줄 추가하는 게 가장 확실해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;sitemap URL이 깨진 경우&lt;/b&gt; &amp;mdash; sitemap에 등록된 URL이 실제로 404나 500을 반환하면 크롤러 입장에서 사이트 품질이 낮아 보여요. 특히 콘텐츠를 삭제하거나 URL 구조를 바꿀 때 sitemap을 업데이트하는 걸 빠뜨리는 경우가 많아요. sitemap에 있는 URL은 200 응답이 오는 유효한 페이지여야 해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;lastmod 날짜가 의미 없는 경우&lt;/b&gt; &amp;mdash; 모든 URL의 lastmod를 오늘 날짜로 일괄 설정해두는 사이트를 꽤 봤어요. 배포 스크립트에서 현재 날짜로 자동 채워지게 해둔 경우인데, 이러면 크롤러가 &quot;어떤 페이지가 실제로 업데이트됐는지&quot; 판단할 수 없어요. 실제 콘텐츠 수정 날짜를 넣는 게 중요해요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대규모 사이트는 sitemap index를 쓰자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sitemap 하나에는 URL 50,000개까지만 넣을 수 있어요. 그 이상이면 sitemap을 여러 개로 나누고, sitemap index 파일로 묶어야 해요.&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;sitemapindex xmlns=&quot;http://www.sitemaps.org/schemas/sitemap/0.9&quot;&amp;gt;
  &amp;lt;sitemap&amp;gt;
    &amp;lt;loc&amp;gt;https://example.com/sitemap-posts.xml&amp;lt;/loc&amp;gt;
  &amp;lt;/sitemap&amp;gt;
  &amp;lt;sitemap&amp;gt;
    &amp;lt;loc&amp;gt;https://example.com/sitemap-products.xml&amp;lt;/loc&amp;gt;
  &amp;lt;/sitemap&amp;gt;
&amp;lt;/sitemapindex&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js에서는 app/sitemap.ts에서 동적으로 생성할 수 있어요. 페이지가 추가되거나 변경될 때 sitemap도 자동으로 갱신되게 만들면 관리 부담이 줄어요.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// Next.js app/sitemap.ts 예시

import { MetadataRoute } from 'next'
export default async function sitemap(): Promise {
  // DB나 CMS에서 동적 페이지 목록을 가져오는 경우
  const posts = await fetchPosts()
  const postEntries = posts.map((post) =&amp;gt; ({
    url: `https://example.com/posts/${post.slug}`,
    lastModified: post.updatedAt,
  }))
  return [
    {
      url: 'https://example.com',
      lastModified: new Date('2026-01-15'), // 실제 최종 수정일을 넣어야 해요
    },
    {
      url: 'https://example.com/products',
      lastModified: new Date('2026-03-20'), // 실제 최종 수정일을 넣어야 해요
    },
    ...postEntries,
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 핵심은 lastModified에 실제 콘텐츠 수정 날짜를 넣는 거예요. 정적 페이지도 new Date()처럼 빌드 시점의 현재 날짜를 쓰면, 앞서 얘기한 &quot;모든 URL을 오늘 날짜로 일괄 설정하는 실수&quot;와 똑같은 문제가 생겨요. 동적 페이지처럼 실제 수정일을 명시하는 습관을 들이는 게 좋아요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;내부 링크 &amp;mdash; 크롤러가 실제로 페이지를 탐색하는 경로&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;robots.txt와 sitemap 얘기를 했는데, 사실 크롤러가 새 페이지를 발견하는 가장 기본적인 방식은 &lt;b&gt;링크를 타고 이동하는 것&lt;/b&gt;이에요. 이 부분을 빠뜨리면 크롤링 설명이 반쪽짜리가 돼요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;a href&amp;gt; vs JavaScript 이벤트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색 크롤러는 일반적으로 HTML의 &amp;lt;a href&amp;gt; 기반 링크를 가장 안정적으로 탐색해요. 반면 JavaScript 이벤트 기반 라우팅은 크롤러 종류와 렌더링 방식에 따라 링크로 인식되지 않거나 우선순위가 낮아질 수 있어요. 그래서 주요 탐색 경로는 가능하면 &amp;lt;a&amp;gt; 또는 프레임워크의 공식 Link 컴포넌트를 사용하는 것이 권장돼요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPA에서 라우팅을 처리할 때 이 부분을 놓치기 쉬워요. React Router나 Next.js의 &amp;lt;Link&amp;gt; 컴포넌트는 내부적으로 &amp;lt;a&amp;gt; 태그를 생성하기 때문에 괜찮지만, 커스텀 네비게이션을 만들 때는 확인이 필요해요.&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;// 크롤러가 안정적으로 따라갈 수 있는 링크
&amp;lt;a href=&quot;/products/123&quot;&amp;gt;상품 보기&amp;lt;/a&amp;gt;
&amp;lt;Link href=&quot;/products/123&quot;&amp;gt;상품 보기&amp;lt;/Link&amp;gt;

// 크롤러에 따라 인식되지 않거나 우선순위가 낮아질 수 있는 링크
&amp;lt;div onClick={() =&amp;gt; router.push('/products/123')}&amp;gt;상품 보기&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네비게이션과 푸터는 크롤러 입장에서 사이트 전체 구조를 파악하는 중요한 단서이기도 해요. 주요 페이지들이 이 영역에서 링크로 연결돼 있다면 크롤러가 사이트 구조를 더 빠르게 이해할 수 있어요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;크롤 예산 &amp;mdash; 크롤러에게도 한계가 있다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;robots.txt와 sitemap, 내부 링크로 크롤러를 잘 불러들였다면, 이제는 크롤러가 사이트 안에서 헤매지 않도록 URL 구조를 정리할 차례예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;크롤 예산&quot;이라는 말을 처음 들으면 다소 생소할 수 있어요. 간단히 말하면, Googlebot이 특정 사이트에 일정 기간 동안 할당하는 크롤링 자원의 한계예요. 사이트 규모, 서버 응답 속도, 링크 구조 등을 기반으로 결정돼요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 소규모 사이트에서는 크롤 예산이 크게 문제가 안 돼요. 근데 페이지 수가 수만 개 이상이거나, URL 구조가 지저분한 경우엔 크롤 예산이 생각보다 빨리 소진돼요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;크롤 예산을 낭비하는 주요 원인들&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무한한 URL 생성&lt;/b&gt; &amp;mdash; 필터링, 정렬, 검색 파라미터가 URL에 붙는 구조라면 조합이 기하급수적으로 늘어나요. ?sort=price&amp;amp;color=red&amp;amp;size=M 같은 조합이 무한히 생기면, 크롤러가 의미 없는 URL을 탐색하는 데 자원을 써버려요.&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;# 크롤 예산을 낭비하는 URL 패턴

/products?sort=price&amp;amp;page=1
/products?sort=price&amp;amp;page=2
/products?sort=name&amp;amp;page=1
/products?color=red&amp;amp;sort=price&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 경우에는 우선 rel=&quot;canonical&quot;로 원본 URL을 명확히 지정하고, 내부 링크와 sitemap도 표준 URL 기준으로 정리하는 것이 좋아요. 필요하다면 크롤링 부하를 줄이기 위해 일부 파라미터 URL에 대해 robots.txt로 접근을 제한할 수는 있지만, robots.txt는 canonical을 대신하는 수단은 아니에요. Google은 중복 URL 정리에는 canonical을, 크롤링 자체를 막을 때는 robots.txt를 구분해서 사용하도록 안내하고 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;세션 ID가 URL에 포함된 경우&lt;/b&gt; &amp;mdash; ?sessionid=abc123 같은 값이 URL에 붙으면, 같은 페이지가 수백만 개의 URL로 인식돼요. 요즘은 세션을 쿠키로 관리하는 게 일반적이지만, 레거시 시스템에서 종종 보여요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTPS와 리다이렉트 &amp;mdash; 크롤러가 길을 잃지 않게&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTTP에서 HTTPS로의 리다이렉트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 대부분의 사이트가 HTTPS를 쓰지만, HTTP로 접속했을 때 HTTPS로 제대로 리다이렉트되는지는 별도로 확인해야 해요. &lt;a href=&quot;http://example.com&quot;&gt;http://example.com&lt;/a&gt;으로 접속했을 때 &lt;a href=&quot;https://example.com&quot;&gt;https://example.com&lt;/a&gt;으로 301 리다이렉트가 돼야 해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 안 돼 있으면 검색엔진이 HTTP 버전과 HTTPS 버전을 별개의 페이지로 인식할 수 있어요. 같은 콘텐츠가 두 개의 URL에 존재하는 셈이 되니까 검색 노출이 분산돼요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;www vs non-www&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 맥락에서, &lt;a href=&quot;https://example.com&quot;&gt;https://example.com&lt;/a&gt;과 &lt;a href=&quot;https://www.example.com&quot;&gt;https://www.example.com&lt;/a&gt; 중 하나로 통일해야 해요. 둘 다 접근 가능한 상태라면 크롤러는 두 개의 다른 사이트로 인식할 수 있거든요. 어느 쪽을 쓸지 결정하고, 나머지는 301로 리다이렉트해두세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리다이렉트 체인 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A &amp;rarr; B &amp;rarr; C &amp;rarr; D 같은 식으로 리다이렉트가 여러 번 연쇄되는 경우가 있어요. Googlebot은 한 요청당 최대 10번의 리다이렉트 홉까지만 따라가고, 그걸 넘으면 Search Console의 페이지 색인 보고서에 리다이렉트 오류로 기록돼요. 한도 안이라도 홉이 늘어날수록 크롤링 효율이 떨어지고, 다른 크롤러는 더 일찍 포기할 수도 있어서 실무에서는 3~5회 이하로 유지하는 걸 목표로 잡는 게 안전해요. 리다이렉트는 가능하면 한 번에 최종 목적지로 보내는 게 좋아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리다이렉트 체인은 URL 구조를 바꿀 때 이전 리다이렉트를 그대로 두고 새 리다이렉트를 추가하는 과정이 반복되면서 생겨요. 주기적으로 점검하는 게 좋아요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;삭제된 페이지는 어떻게 처리할까&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지를 삭제했을 때 그냥 404로 두는 경우가 많은데, 유사한 콘텐츠로 연결할 수 있다면 301 리다이렉트를 설정하는 게 좋아요. 대체 페이지가 아예 없다면 410(Gone)으로 응답하면 크롤러에게 &quot;이 페이지는 의도적으로 삭제된 거야&quot;라고 명확하게 알려줄 수 있어요. 404와 달리 410은 크롤러가 재방문을 빠르게 포기해서 크롤 예산 낭비를 줄여줘요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Canonical 태그 &amp;mdash; &quot;이게 원본이야&quot;라고 선언하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드 개발을 하다 보면 같은 콘텐츠가 여러 URL에서 접근 가능한 경우가 자주 생겨요.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://example.com/products?sort=price&quot;&gt;https://example.com/products?sort=price&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://example.com/products?sort=price&amp;amp;page=1&quot;&gt;https://example.com/products?sort=price&amp;amp;page=1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://example.com/products&quot;&gt;https://example.com/products&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세 URL이 사실상 같은 상품 목록을 보여주고 있다면, 검색엔진은 어떤 URL을 검색 결과에 보여줘야 할지 헷갈려해요. canonical 태그는 이 중 하나를 &quot;원본&quot;으로 지정하는 역할이에요.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;&amp;lt;link rel=&quot;canonical&quot; href=&quot;https://example.com/products&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPA에서 쿼리 파라미터를 많이 쓰거나, 필터링&amp;middot;정렬 기능이 URL에 반영되는 사이트라면 canonical 태그 관리가 특히 중요해요. 이걸 제대로 안 하면 검색엔진이 같은 페이지를 여러 개로 인식해서 크롤 예산을 낭비하게 돼요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;self-canonical의 중요성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지가 하나뿐이더라도 canonical 태그를 자기 자신을 가리키도록 설정하는 걸 권장해요. 이걸 &quot;self-canonical&quot;이라고 하는데, 검색엔진에게 &quot;이 URL이 이 콘텐츠의 정식 주소야&quot;라고 명확히 알려주는 거예요. 외부에서 쿼리 파라미터를 붙여서 링크할 때 생길 수 있는 중복 문제를 예방할 수 있어요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CSR과 크롤링 &amp;mdash; JavaScript 의존도를 점검하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 React, Vue, Angular 같은 프레임워크로 SPA를 많이 만드는데, CSR(Client-Side Rendering)로만 돌아가는 사이트는 크롤링에서 불리할 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Googlebot은 JavaScript 렌더링을 적극적으로 지원하는 대표적인 검색 크롤러예요. 다만 렌더링에 시간이 걸리고 크롤 예산을 더 많이 소모하기 때문에, CSR에만 의존하면 크롤링 효율이 떨어질 수 있어요. 반면 GPTBot, ClaudeBot, PerplexityBot 등 주요 AI 크롤러는 JavaScript 실행 범위가 제한적이거나 상세 동작이 공개되지 않았어요. Vercel과 MERJ가 한 달간 약 5억 7천만 건의 GPTBot 요청을 분석한 결과, JavaScript 실행 흔적이 전혀 발견되지 않았어요. 같은 분석에서 OAI-SearchBot, ChatGPT-User, ClaudeBot도 모두 JavaScript를 실행하지 않는 것으로 확인됐어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 콘텐츠가 JavaScript 실행 없이는 HTML에 아예 존재하지 않는 구조라면, 크롤러가 그 콘텐츠를 인식하지 못할 수 있어요. Next.js의 SSR이나 SSG를 쓰는 이유가 여기에도 있는 거예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 확인하는 방법이 있어요. 브라우저에서 JavaScript를 끄고 우리 사이트에 접속해보는 거예요. 핵심 텍스트 콘텐츠가 보이는지, H1 태그가 있는지, 네비게이션 링크가 &amp;lt;a&amp;gt; 태그로 작동하는지 확인해보세요. 이걸로 크롤러가 보는 화면을 대략적으로 파악할 수 있어요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설정 다 했으면, 실제로 잘 됐는지 확인하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정을 다 했다면, 실제로 크롤러가 우리 사이트를 어떻게 보고 있는지 확인하는 도구가 필요해요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Google Search Console&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google Search Console(GSC)은 Google 크롤러 관점에서 사이트 상태를 확인할 수 있는 도구예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;URL 검사 도구&lt;/b&gt; &amp;mdash; 특정 URL이 색인됐는지, 색인 안 됐다면 이유가 뭔지 확인할 수 있어요. &quot;URL이 Google에 등록되어 있지 않음&quot;이 뜨면서 &quot;robots.txt에 의해 차단됨&quot;이라고 나온다면, 앞서 말한 robots.txt 문제를 바로 잡아낼 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Sitemap 제출 및 상태 확인&lt;/b&gt; &amp;mdash; sitemap을 등록하고 나면 GSC에서 &quot;읽힌 URL 수&quot;가 나와요. 내가 등록한 URL 수와 크게 차이가 난다면 sitemap에 유효하지 않은 URL이 섞여 있거나, 크롤러가 접근 못 하는 페이지가 있다는 신호예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;페이지 색인 보고서&lt;/b&gt; &amp;mdash; 색인된 페이지, 오류가 있는 페이지, 제외된 페이지를 한눈에 볼 수 있어요. (예전 명칭인 '커버리지 리포트'와 동일한 기능이에요.) &quot;제외됨&quot; 항목 중 &quot;중복, Google이 표준 페이지를 선택함&quot;이 많이 뜬다면 canonical 관리가 안 되고 있다는 신호예요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Bing Webmaster Tools&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google이 GSC를 제공하듯, Bing에도 동일한 역할의 도구가 있어요. &lt;b&gt;Bing Webmaster Tools&lt;/b&gt;(webmaster.bing.com)예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사이트를 등록하고 sitemap을 제출하면, Bing이 어떤 페이지를 색인했는지, 크롤링 오류는 없는지 확인할 수 있어요. 한국에서는 대부분 Bing은 아예 신경 안 쓰는 경우가 많은데, 뒤에서 다룰 ChatGPT 인용을 원한다면 여기도 한 번은 확인해두는 게 좋아요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;네이버 서치어드바이저&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국 서비스라면 네이버도 빠뜨릴 수 없어요. &lt;b&gt;네이버 서치어드바이저&lt;/b&gt;(searchadvisor.naver.com)는 네이버 검색 크롤러 관점에서 사이트 상태를 확인할 수 있는 도구예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GSC와 마찬가지로 sitemap을 등록하고, 크롤링 오류와 색인 상태를 확인할 수 있어요. 국내 B2C 서비스라면 특히 네이버 유입 비중이 높은 경우가 많아서, GSC만큼 주기적으로 들여다보는 게 좋아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버는 Googlebot과 별도로 &lt;b&gt;Yeti&lt;/b&gt;라는 자체 크롤러를 운영해요. User-agent: *에 대해 이미 접근을 허용하고 있다면 별도 설정이 꼭 필요한 건 아니에요. 다만 검색엔진별로 robots.txt를 다르게 운영하고 있다면, Yeti가 의도치 않게 차단되고 있지는 않은지 함께 확인해보는 게 좋아요.&lt;/p&gt;
&lt;pre class=&quot;ldif&quot;&gt;&lt;code&gt;# 검색엔진별로 다르게 운영할 때 Yeti 명시적 허용 예시

User-agent: Yeti
Allow: /&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 서비스를 배포하거나 URL 구조를 바꾼 직후에는 GSC, Bing Webmaster Tools, 네이버 서치어드바이저를 한 번씩 열어보는 습관을 들이면 좋아요. 크롤러가 사이트를 어떻게 인식하고 있는지 검색엔진별로 직접 피드백을 받을 수 있거든요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI 검색 시대, 크롤러 전략도 달라졌다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1편에서 GEO 이야기를 했었는데, 크롤링 단계에서 바로 연결되는 부분이 있어요. 근데 여기서 한 가지 구분을 짚고 넘어가는 게 중요해요. AI와 크롤링의 관계는 사실 두 가지가 섞여 있거든요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AI 봇은 이제 목적별로 분리되어 있다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 OpenAI와 Anthropic 모두 크롤러를 목적별로 분리해서 운영하기 시작했어요. 예전에는 &quot;GPTBot 허용하면 AI에서 인용된다&quot;는 식으로 단순하게 알려졌지만, 이제는 학습용과 검색 노출용이 완전히 다른 봇이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;OpenAI (ChatGPT)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GPTBot &amp;mdash; AI 모델 학습 데이터 수집용&lt;/li&gt;
&lt;li&gt;OAI-SearchBot &amp;mdash; ChatGPT 검색 결과 노출용&lt;/li&gt;
&lt;li&gt;ChatGPT-User &amp;mdash; 사용자가 직접 요청했을 때 페이지 접근용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Anthropic (Claude)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ClaudeBot &amp;mdash; AI 모델 학습 데이터 수집용&lt;/li&gt;
&lt;li&gt;Claude-SearchBot &amp;mdash; Claude 내 검색 결과 노출용&lt;/li&gt;
&lt;li&gt;Claude-User &amp;mdash; 사용자 질문에 답하기 위해 페이지 접근용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구분이 중요한 이유는, &quot;학습에 쓰이는 건 싫지만, AI 검색에서 인용은 되고 싶다&quot;는 선택이 이제 robots.txt로 분리 설정이 가능해졌기 때문이에요.&lt;/p&gt;
&lt;pre class=&quot;ldif&quot;&gt;&lt;code&gt;# 학습은 차단하고, 검색 노출은 허용하는 예시 (OpenAI)
User-agent: GPTBot
Disallow: /
User-agent: OAI-SearchBot
Allow: /

# Anthropic도 동일하게 분리 가능
User-agent: ClaudeBot
Disallow: /
User-agent: Claude-SearchBot
Allow: /&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실시간 인용은 결국 어떤 검색엔진 기반이냐가 핵심&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 서비스가 질문에 실시간으로 답할 때 인용하는 경로는 각 서비스마다 달라요.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ChatGPT&lt;/b&gt; &amp;mdash; 웹 검색은 Bing 인덱스를 포함한 외부 검색 소스를 활용하는 것으로 알려져 있어요. 검색 노출 관점에서는 Bing 색인 상태를 함께 확인하는 게 유리해요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Gemini&lt;/b&gt; &amp;mdash; Google이 만든 서비스라 Google 검색 색인을 사용해요. 평소 Google SEO를 잘 하고 있다면 Gemini 인용에 유리해요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Claude&lt;/b&gt; &amp;mdash; Claude-SearchBot이 검색 노출을 담당해요. 어떤 검색 색인을 기반으로 하는지는 공개되지 않았어요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Perplexity&lt;/b&gt; &amp;mdash; 자체 크롤링과 여러 검색엔진을 혼합해서 사용해요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 이래요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 서비스 검색 노출용 봇 실시간 검색 기반 챙겨야 할 것&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ChatGPT&lt;/td&gt;
&lt;td&gt;OAI-SearchBot&lt;/td&gt;
&lt;td&gt;Bing 포함 외부 소스&lt;/td&gt;
&lt;td&gt;Bing SEO, Bing Webmaster Tools 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini&lt;/td&gt;
&lt;td&gt;별도 봇 없음 (Google 검색 직접 활용)&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;Google SEO (기존 SEO와 동일)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude&lt;/td&gt;
&lt;td&gt;Claude-SearchBot&lt;/td&gt;
&lt;td&gt;미공개&lt;/td&gt;
&lt;td&gt;검색엔진 SEO 전반&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perplexity&lt;/td&gt;
&lt;td&gt;PerplexityBot&lt;/td&gt;
&lt;td&gt;자체 + 복수 검색엔진&lt;/td&gt;
&lt;td&gt;검색 노출 전반 + 콘텐츠 구조&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국 서비스들이 대부분 Google SEO만 신경 쓰는데, ChatGPT 인용까지 원한다면 Bing 색인 상태도 별도로 확인해볼 필요가 있어요. 위에서 소개한 Bing Webmaster Tools에서 바로 확인할 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;GPTBot 허용하면 AI가 우리 콘텐츠를 인용한다&quot;는 단순화는 이제 맞지 않아요. 학습 데이터 수집과 실시간 검색 노출은 다른 봇이 담당하고, 실시간 인용은 결국 각 서비스가 기반으로 삼는 검색엔진 SEO가 핵심이에요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 편에서 다룬 내용들은 하나하나는 어렵지 않아요. robots.txt 한 줄, sitemap 경로 한 줄, canonical 태그 한 줄. 근데 분석 서비스를 만들면서 수많은 사이트를 들여다봤을 때 공통적으로 느낀 게 있어요. 이 &quot;한 줄&quot;들이 빠져 있는 경우가 생각보다 훨씬 많다는 거예요. 콘텐츠는 정성껏 만들었는데, 크롤러는 그 페이지에 닿지도 못하는 상황이요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 SEO와 GEO의 출발점은 크게 다르지 않아요. 검색엔진이든 AI 서비스든, 먼저 우리 사이트를 안정적으로 발견하고 이해할 수 있어야 다음 단계로 넘어갈 수 있어요. robots.txt, sitemap, 내부 링크, canonical 같은 기술적 기반은 지금도 가장 중요한 출발점이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 콘텐츠를 만드는 것만큼, 그 콘텐츠가 크롤러에게 제대로 전달되는 구조를 만드는 일 역시 프론트엔드 개발자의 중요한 역할이라고 생각해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 편에서는 페이지가 발견된 이후, 검색엔진과 AI가 콘텐츠를 어떻게 해석하고 인용하는지, 그리고 어떤 구조가 GEO 관점에서 더 유리한지 살펴보려고 해요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 자료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developers.google.com/search/docs/crawling-indexing&quot;&gt;Google Search Central &amp;mdash; 크롤링 및 색인 생성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9309.html&quot;&gt;robots.txt 표준 &amp;mdash; RFC 9309&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.sitemaps.org/protocol.html&quot;&gt;Sitemaps.org &amp;mdash; Sitemap 프로토콜&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://nextjs.org/docs/app/api-reference/file-conventions/metadata/robots&quot;&gt;Next.js Docs &amp;mdash; Metadata Files: robots.txt&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://platform.openai.com/docs/bots&quot;&gt;OpenAI &amp;mdash; Overview of OpenAI Crawlers (GPTBot, OAI-SearchBot, ChatGPT-User)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://help.openai.com/en/articles/9237897-chatgpt-search&quot;&gt;OpenAI Help Center &amp;mdash; ChatGPT Search&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler&quot;&gt;Anthropic &amp;mdash; Does Anthropic crawl data from the web? (ClaudeBot, Claude-SearchBot, Claude-User)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ai.google.dev/gemini-api/docs/google-search&quot;&gt;Google AI for Developers &amp;mdash; Grounding with Google Search&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developers.google.com/search/blog/2026/03/crawler-blog-post&quot;&gt;Google Search Central Blog &amp;mdash; Inside Googlebot: demystifying crawling, fetching, and the bytes we process&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://vercel.com/blog/the-rise-of-the-ai-crawler&quot;&gt;Vercel Blog &amp;mdash; The rise of the AI crawler&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.perplexity.ai/help-center/en/articles/10352895-how-does-perplexity-work&quot;&gt;Perplexity Help Center &amp;mdash; How does Perplexity work?&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://searchadvisor.naver.com&quot;&gt;네이버 서치어드바이저 &amp;mdash; 웹마스터 도구&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;이 글은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a title=&quot;https://tech.pxd.co.kr/&quot; href=&quot;https://tech.pxd.co.kr/post/%EA%B2%80%EC%83%89%EC%97%94%EC%A7%84%EC%9D%80-%EC%9A%B0%EB%A6%AC-%EC%82%AC%EC%9D%B4%ED%8A%B8%EB%A5%BC-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%B0%9C%EA%B2%AC%ED%95%A0%EA%B9%8C-352&quot;&gt;https://tech.pxd.co.kr/&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;&amp;nbsp; 에서도 보실 수 있습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>UX Engineer 이야기</category>
      <author>shushushu</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1899</guid>
      <comments>https://story.pxd.co.kr/1899#entry1899comment</comments>
      <pubDate>Thu, 21 May 2026 07:50:10 +0900</pubDate>
    </item>
    <item>
      <title>AI 리서치 파트너, Affinity Bubble 서포터즈 1기를 모집합니다</title>
      <link>https://story.pxd.co.kr/1898</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;방대한 인터뷰와 설문 데이터 속에서 의미 있는 인사이트를 찾기 위해 고군분투해 오셨나요? pxd의 UX 노하우를 담아 정성 데이터 분석의 새 길을 열어가는 어피니티버블(Affinity Bubble)이 더 강력해진 v1.1 업데이트와 함께, 서비스의 완성도를 함께 높여갈 서포터즈 1기를 모집합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어피니티버블은 인터뷰, 앱 리뷰, 설문 등 흩어진 정성 데이터를 AI로 분석해 어피니티 다이어그램 형태의 버블 시각화로 보여주는 도구입니다. 어피니티버블이 실무자분들에게 정말 유용한 도구로 진화할 수 있도록, 여러분의 현장감 넘치는 의견을 들려주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1️⃣&amp;nbsp; 서포터즈는 어떤 활동을 하나요?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어피니티버블 서포터즈 1기의 자격 유지 및 활동 조건은 아래와 같습니다. 부담 갖기보다는 어피니티버블과 함께 즐겁게 연구하고 소통해 주시면 됩니다!&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;어피니티버블로 만든 분석 결과를 SNS에 공유하기 (월 2회)&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어피니티버블을 쓰며 발견한 흥미로운 데이터 분석 결과를 개인 SNS 채널에 공유해 주세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;활용 가능한 SNS:&lt;/b&gt; 링크드인, 브런치, 티스토리, 네이버 블로그, 인스타그램, X(트위터), 페이스북&lt;/li&gt;
&lt;li&gt;&lt;b&gt;필수 해시태그:&lt;/b&gt; #어피니티버블 #AffinityBubble #데이터분석&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;분석이 필요한 주변 동료들에게 즐겁게 추천하기&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동료 리서처, 기획자, 마케터 분들에게 어피니티버블을 널리 알려주세요.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3개월 활동 종료 시점 피드백 설문 참여&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;활동이 마무리되는 시점에 어피니티버블의 발전을 위한 솔직한 피드백 설문에 참여해 주세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분이 SNS에 공유해 주신 소중한 포스트는 어피니티버블 공식 계정에서 적극적으로 공유하고, 월간 우수 사례는 공식 SNS에 소개됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2️⃣ 서포터즈 분들을 위해 준비한 혜택&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서포터즈 분들이 데이터 분석과 연구에 몰입하실 수 있도록 다채로운 혜택을 지원합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Business 플랜 지원&lt;/b&gt;&lt;br /&gt;대량 데이터 분석이 가능한 최고 요금제(매월 59,800원 상당)를 서포터즈 자격 유지 동안 무상으로 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;지인 추천 쿠폰 매월 3장 지급&lt;/b&gt;&lt;br /&gt;주변 동료들에게 선물할 수 있는 'Standard 플랜 30일 무료 사용권' 쿠폰을 매달 3장씩 챙겨드립니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;신기능 선사용 혜택&lt;/b&gt;&lt;br /&gt;신기능 정식 출시 전, 유용한 기능들을 가장 먼저 테스트해 보고 피드백에 참여할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;온오프라인 밋업 우선 초대&lt;/b&gt;&lt;br /&gt;어피니티버블만의 인사이트 공유 밋업 및 네트워킹 행사를 최우선으로 안내해 드립니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3️⃣ 모집 일정 및 안내&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;신청 기간:&lt;/b&gt; 5월 19일(화) ~ 5월 31일(일)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;선정 결과 발표:&lt;/b&gt; 6월 8일(월) (개별 안내)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;신청 링크: &lt;/b&gt;(모집이 마감되었습니다. 감사합니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정성 조사의 규모와 속도, 인사이트를 함께 키워갈 리서처, 기획자, 마케터 분들의 많은 관심과 참여를 기다립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 및 서포터즈 관련 문의는 support@affinitybubble.com 으로 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;a href=&quot;https://forms.gle/R3K9TX1cVgZKHCg58&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;어피니티버블 서포터즈 1기 신청&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;a href=&quot;http://affinitybubble.com/affinitybubble&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;어피니티버블 사용하러 가기&lt;/a&gt;&lt;/p&gt;</description>
      <category>pxd AI툴 이야기</category>
      <author>yewon.jang</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1898</guid>
      <comments>https://story.pxd.co.kr/1898#entry1898comment</comments>
      <pubDate>Tue, 19 May 2026 07:50:02 +0900</pubDate>
    </item>
    <item>
      <title>컬러 토큰 설계 3가지 방식 (스케일 / 시멘틱 / 하이브리드)</title>
      <link>https://story.pxd.co.kr/1888</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ChatGPT Image 2026년 3월 10일 오후 12_49_06.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beDcN4/dJMcaibsR6n/8DSQNRpcPyj7Ga29aWyJs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beDcN4/dJMcaibsR6n/8DSQNRpcPyj7Ga29aWyJs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beDcN4/dJMcaibsR6n/8DSQNRpcPyj7Ga29aWyJs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeDcN4%2FdJMcaibsR6n%2F8DSQNRpcPyj7Ga29aWyJs0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1536&quot; height=&quot;1024&quot; data-filename=&quot;ChatGPT Image 2026년 3월 10일 오후 12_49_06.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;AI의 등장과 디자인 자동화가 본격화되면서, 이제는 작업 속도 자체보다 그 속도 안에서도 서비스의 일관성을 끝까지 유지할 수 있는지가 더 중요해졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 때는 정말 픽셀 하나, 간격 하나에 목숨 걸며 그 정교함이 디자인의 실력을 가늠하는 기준처럼 여겨지던 시절도 있었는데요. &lt;br /&gt;이제는 손으로 어떻게 만들었는지보다, 어떤 기준을 세워 그 결과가 나오도록 만들었는지가 더 중요해졌다는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 변화 속에서 디자인 시스템은 서비스를 안정적으로 운용하기 위한 핵심 인프라로 자리 잡았으며, 이를 전담 조직으로 운영하는 기업 역시 빠르게 늘어나고 있습니다.&lt;br /&gt;그렇다면 디자인 시스템 중에서도 가장 기초이면서도, 동시에 가장 큰 영향을 미치는 컬러 토큰 설계는 어떤 관점에서 접근해야 할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 진행했던 프로젝트에서 컬러 토큰 체계를 새롭게 구축하는 과정에서 얻은 경험과 인사이트를 바탕으로, 컬러 토큰 설계를 어떤 관점에서 선택하고 구조화할 수 있는지 공유해보려고 합니다.&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;  컬러 토큰의 기본 개념은 아래 글을 참고하세요 :)&lt;/b&gt;&lt;br /&gt;&lt;a href=&quot;https://story.pxd.co.kr/1805&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;3. 유연함을 갖춘 시맨틱 컬러 시스템&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://story.pxd.co.kr/1801&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;4. 균일한 대비값을 가진 스케일 컬러 시스템&lt;/a&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컬러 토큰 설계 방식 살펴보기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 토큰은 '무엇(Scale)'인지와 '어디(Semantic)'에 쓰이는지에 따라 &lt;b&gt;스케일 중심, 시멘틱 중심, 그리고 두 방식을 접목한 하이브리드 구조&lt;/b&gt;로 설계할 수 있어요.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1) 스케일 토큰 : 가장 직관적이고 빠른 시작&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스케일&lt;span&gt; &lt;/span&gt;토큰의&lt;span&gt; &lt;/span&gt;가장&lt;span&gt; &lt;/span&gt;큰&lt;span&gt; &lt;/span&gt;장점은&lt;span&gt; &lt;b&gt;'&lt;/b&gt;&lt;/span&gt;&lt;b&gt;무엇&lt;/b&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;기초값&lt;/b&gt;&lt;span&gt;&lt;b&gt;)'&lt;/b&gt;&lt;/span&gt;인지를&lt;span&gt; &lt;/span&gt;바로&lt;span&gt; &lt;/span&gt;이야기&lt;span&gt; &lt;/span&gt;하기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;별도의&lt;span&gt; &lt;/span&gt;해석이나&lt;span&gt; &lt;/span&gt;학습&lt;span&gt;, &lt;/span&gt;합의&lt;span&gt; &lt;/span&gt;같은&lt;span&gt; &lt;/span&gt;과정이&lt;span&gt; &lt;/span&gt;필요없다는&lt;span&gt; &lt;/span&gt;거예요&lt;span&gt;. &lt;/span&gt;이는&lt;span&gt; &lt;/span&gt;스케일&lt;span&gt; &lt;/span&gt;토큰이&lt;span&gt; &lt;/span&gt;디자인&lt;span&gt; &lt;/span&gt;과정에서&lt;span&gt; &lt;/span&gt;만들어지는&lt;span&gt; &lt;/span&gt;공통&lt;span&gt; &lt;/span&gt;컬러&lt;span&gt; &lt;/span&gt;팔레트를&lt;span&gt; &lt;/span&gt;구조화&lt;span&gt; &lt;/span&gt;하고&lt;span&gt;, &lt;/span&gt;이를&lt;span&gt; &lt;/span&gt;코드화해&lt;span&gt; &lt;/span&gt;관리하는&lt;span&gt; &lt;/span&gt;방식이기&lt;span&gt; &lt;/span&gt;때문이죠&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;864&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gt9C7/dJMcaaEvez4/XG4pX0YI2xY2v8kk4zKBtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gt9C7/dJMcaaEvez4/XG4pX0YI2xY2v8kk4zKBtk/img.png&quot; data-alt=&quot;스케일 토큰&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gt9C7/dJMcaaEvez4/XG4pX0YI2xY2v8kk4zKBtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGt9C7%2FdJMcaaEvez4%2FXG4pX0YI2xY2v8kk4zKBtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1536&quot; height=&quot;864&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;864&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스케일 토큰&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를&lt;span&gt; &lt;/span&gt;들어&lt;span&gt; &lt;/span&gt;포인트&lt;span&gt; &lt;/span&gt;컬러로&lt;span&gt; &lt;b&gt;#1244C5&lt;/b&gt;(Hex&lt;/span&gt;값&lt;span&gt;)&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;사용하는&lt;span&gt; Blue&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;있다면&lt;span&gt;, &lt;/span&gt;이&lt;span&gt; &lt;/span&gt;값을&lt;span&gt; &lt;/span&gt;기준으로&lt;span&gt; &lt;/span&gt;밝기와&lt;span&gt; &lt;/span&gt;톤을&lt;span&gt; &lt;/span&gt;조정해&lt;span&gt; &lt;/span&gt;컬러&lt;span&gt; &lt;/span&gt;스케일을&lt;span&gt; &lt;/span&gt;정의하고&lt;span&gt; &lt;b&gt;$blue-100&lt;/b&gt;, &lt;b&gt;$blue-300&lt;/b&gt;, &lt;b&gt;$blue-500&lt;/b&gt;&lt;/span&gt;처럼&lt;span&gt; &lt;/span&gt;단계별&lt;span&gt; &lt;/span&gt;값으로&lt;span&gt; &lt;/span&gt;관리하는거죠&lt;span&gt;. &lt;/span&gt;이렇게&lt;span&gt; &lt;/span&gt;정의된&lt;span&gt; &lt;/span&gt;스케일&lt;span&gt; &lt;/span&gt;토큰을&lt;span&gt; &lt;b&gt;&amp;ldquo;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;주요&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;액션&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;버튼에는&lt;/b&gt;&lt;span&gt;&lt;b&gt; $blue-500&lt;/b&gt;&lt;/span&gt;&lt;b&gt;을&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;사용한다&lt;/b&gt;&lt;span&gt;&lt;b&gt;&amp;rdquo;&lt;/b&gt;&lt;/span&gt;와&lt;span&gt; &lt;/span&gt;같은&lt;span&gt; &lt;/span&gt;가이드를&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; &lt;/span&gt;디자이너와&lt;span&gt; &lt;/span&gt;개발자&lt;span&gt; &lt;/span&gt;간에&lt;span&gt; &lt;/span&gt;바로&lt;span&gt; &lt;/span&gt;커뮤니케이션될&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있어요&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만&lt;span&gt; &lt;/span&gt;서비스의&lt;span&gt; &lt;/span&gt;복잡도가&lt;span&gt; &lt;/span&gt;높아진다면&lt;span&gt; &lt;/span&gt;이야기는&lt;span&gt; &lt;/span&gt;달라지죠&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기초값으로만&lt;span&gt; &lt;/span&gt;정의되어&lt;span&gt; &lt;/span&gt;있기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;그&lt;span&gt; &lt;/span&gt;색을&lt;span&gt; &amp;lsquo;&lt;/span&gt;왜&lt;span&gt;' &lt;/span&gt;여기에&lt;span&gt; &lt;/span&gt;썼는지&lt;span&gt; &lt;/span&gt;맥락이&lt;span&gt; &lt;/span&gt;남아있지&lt;span&gt; &lt;/span&gt;않은&lt;span&gt; &lt;/span&gt;상태로&lt;span&gt; &lt;/span&gt;존재하게&lt;span&gt; &lt;/span&gt;되는데요&lt;span&gt;.&lt;br /&gt;&lt;/span&gt;이로인해&lt;span&gt; &lt;/span&gt;서비스의&lt;span&gt; &lt;/span&gt;확장이&lt;span&gt; &lt;/span&gt;어려울&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있어요&lt;span&gt;. &lt;/span&gt;의미와&lt;span&gt; &lt;/span&gt;목적이&lt;span&gt; &lt;/span&gt;명시되어&lt;span&gt; &lt;/span&gt;있지&lt;span&gt; &lt;/span&gt;않기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;기존&lt;span&gt; &lt;/span&gt;화면을&lt;span&gt; &lt;/span&gt;다시&lt;span&gt; &lt;/span&gt;분석하거나&lt;span&gt;, &lt;/span&gt;히스토리&lt;span&gt; &lt;/span&gt;추적을&lt;span&gt; &lt;/span&gt;해야하는&lt;span&gt; &lt;/span&gt;불필요한&lt;span&gt; &lt;/span&gt;공수가&lt;span&gt; &lt;/span&gt;발생하게&lt;span&gt; &lt;/span&gt;되죠&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;또한&lt;span&gt; &lt;/span&gt;공통&lt;span&gt; &lt;/span&gt;수정이&lt;span&gt; &lt;/span&gt;필요한&lt;span&gt; &lt;/span&gt;경우에도&lt;span&gt; &lt;/span&gt;해당&lt;span&gt; &lt;/span&gt;색이&lt;span&gt; &lt;/span&gt;사용된&lt;span&gt; &lt;/span&gt;화면을&lt;span&gt; &lt;/span&gt;직접&lt;span&gt; &lt;/span&gt;찾아&lt;span&gt; &lt;/span&gt;맥락을&lt;span&gt; &lt;/span&gt;파악하고&lt;span&gt;, &lt;/span&gt;코드까지&lt;span&gt; &lt;/span&gt;함께&lt;span&gt; &lt;/span&gt;수정해야&lt;span&gt; &lt;/span&gt;하는&lt;span&gt; &lt;/span&gt;상황이&lt;span&gt; &lt;/span&gt;반복되며&lt;span&gt; &lt;/span&gt;시간이&lt;span&gt; &lt;/span&gt;지날수록&lt;span&gt; &lt;/span&gt;누적되어&lt;span&gt; &lt;/span&gt;부채로&lt;span&gt; &lt;/span&gt;남게&lt;span&gt; &lt;/span&gt;되기도&lt;span&gt; &lt;/span&gt;합니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서&lt;span&gt; &lt;/span&gt;관리자는&lt;span&gt; &lt;/span&gt;서비스의&lt;span&gt; &lt;/span&gt;방향성과&lt;span&gt; &lt;/span&gt;디자인&lt;span&gt; &lt;/span&gt;맥락을&lt;span&gt; &lt;/span&gt;충분히&lt;span&gt; &lt;/span&gt;이해한&lt;span&gt; &lt;/span&gt;상태에서&lt;span&gt;, &lt;/span&gt;새로운&lt;span&gt; &lt;/span&gt;색이&lt;span&gt; &lt;/span&gt;언제&lt;span&gt;, &lt;/span&gt;어떤&lt;span&gt; &lt;/span&gt;기준으로&lt;span&gt; &lt;/span&gt;스케일에&lt;span&gt; &lt;/span&gt;편입되는지를&lt;span&gt; &lt;/span&gt;꾸준히&lt;span&gt; &lt;/span&gt;트래킹하고&lt;span&gt; &lt;/span&gt;관리해야&lt;span&gt; &lt;/span&gt;해요&lt;span&gt;. &lt;/span&gt;관리자의&lt;span&gt; &lt;/span&gt;판단이&lt;span&gt; &lt;/span&gt;서비스의&lt;span&gt; &lt;/span&gt;품질과&lt;span&gt; &lt;/span&gt;확장&lt;span&gt; &lt;/span&gt;비용에&lt;span&gt; &lt;/span&gt;직접적인&lt;span&gt; &lt;/span&gt;영향을&lt;span&gt; &lt;/span&gt;미치기&lt;span&gt; &lt;/span&gt;때문이죠&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런&lt;span&gt; &lt;/span&gt;이유로&lt;span&gt; &lt;/span&gt;스케일&lt;span&gt; &lt;/span&gt;토큰&lt;span&gt; &lt;/span&gt;중심&lt;span&gt; &lt;/span&gt;설계는&lt;span&gt; &lt;/span&gt;설계에&lt;span&gt; &lt;/span&gt;투입할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있는&lt;span&gt; &lt;/span&gt;리소스가&lt;span&gt; &lt;/span&gt;제한된&lt;span&gt; &lt;/span&gt;초기&lt;span&gt; &lt;/span&gt;프로젝트나&lt;span&gt;, &lt;/span&gt;최소한의&lt;span&gt; &lt;/span&gt;브랜드&lt;span&gt; &lt;/span&gt;컬러를&lt;span&gt; &lt;/span&gt;중심으로&lt;span&gt; &lt;/span&gt;빠른&lt;span&gt; &lt;/span&gt;대응이&lt;span&gt; &lt;/span&gt;필요한&lt;span&gt; &lt;/span&gt;서비스&lt;span&gt;, &lt;/span&gt;혹은&lt;span&gt; &lt;/span&gt;브랜드&lt;span&gt; &lt;/span&gt;아이덴티티를&lt;span&gt; &lt;/span&gt;깊이&lt;span&gt; &lt;/span&gt;이해한&lt;span&gt; &lt;/span&gt;디자이너가&lt;span&gt; &lt;/span&gt;주도하는&lt;span&gt; &lt;/span&gt;소규모&lt;span&gt; &lt;/span&gt;팀에&lt;span&gt; &lt;/span&gt;적합한&lt;span&gt; &lt;/span&gt;구조라고&lt;span&gt; &lt;/span&gt;볼&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있어요&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2) &lt;/b&gt;&lt;b&gt;시멘틱 토큰 : 다양한 환경에 유연한 대응&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시멘틱 토큰 중심 설계는 색상 값 자체보다, 그 색이 어떤 역할과 상태를 가지는지를 먼저 정의하는 방식입니다.&lt;br /&gt;UI 맥락에 맞는 토큰명을 먼저 정하고, 그 안에 실제 Hex 값을 연결해 사용하는 구조라고 볼 수 있어요. 이렇게 설계하면 디자인과 개발 모두가 색을 값이 아니라 역할과 맥락의 관점에서 다루게 돼요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ChatGPT Image 2026년 3월 10일 오후 01_30_15.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2fWPj/dJMcah4Gqt6/oFnWHolbkW3EYONIh1P4T0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2fWPj/dJMcah4Gqt6/oFnWHolbkW3EYONIh1P4T0/img.png&quot; data-alt=&quot;시멘틱 토큰&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2fWPj/dJMcah4Gqt6/oFnWHolbkW3EYONIh1P4T0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2fWPj%2FdJMcah4Gqt6%2FoFnWHolbkW3EYONIh1P4T0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1536&quot; height=&quot;1024&quot; data-filename=&quot;ChatGPT Image 2026년 3월 10일 오후 01_30_15.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시멘틱 토큰&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 &amp;ldquo;블루를 사용한다&amp;rdquo;가 아니라 &amp;ldquo;이 블루는 버튼에 사용한다&quot; 라고 말해주는 거라고 보면 쉬워요. 색 자체보다, 어디에 쓰이는지 목적을 명확히 해주는거죠. 이처럼 공통으로 합의된 의미로 소통하기 때문에 각자의 해석이 개입할 수 없다는 점이 가장 큰 장점이에요. 그 결과 시스템 전반의 일관성을 비교적 안정적으로 관리할 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 시멘틱 토큰 중심 설계는 멀티 테마를 운영하거나, 접근성 기준을 체계적으로 반영해야하는 서비스에서 특히 효과적으로 활용할 수 있어요. 색에 대한 합의가 구조 안에 들어가면서 커뮤니케이션 비용일 확실히 줄어들어요.&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;이미 코드에는 '의미'로 부여되어 있기 때문에 &lt;b&gt;&quot;버튼의 배경색을 라이트 모드에서는 블루를 쓰고, 다크 모드에서는 화이트를 써.&quot;&lt;/b&gt; 처럼 의도만 전달해주면 구체적인 색상 값은 시스템이 알아서 처리하는거죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 시멘틱 토큰 중심 설계는 초기 설계와 합의 과정에 드는 비용이 비교적 큰 편이에요. &lt;br /&gt;각 컬러가 어떤 역할을 하고, 어디까지 사용될 수 있는지를 미리 정의해야하고, 토큰 이름 하나하나에도 조직 차원의 합의가 필요하기 때문이죠. 이 과정이 충분하지 않으면 의미가 모호한 토큰만 늘어나게 되고, 결국 관리하기 어려운 구조로 이어지면서 코드 부채가 쌓이게 될 가능성도 커져요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시멘틱 토큰은 &quot;결정론적 디자인&quot;이라고 볼 수 있어요. &lt;br /&gt;어떠한 상황에서도 시스템이 예측 가능한 결과물을 내놓아야한다는게 기본 전제죠. &lt;br /&gt;그렇다 보니 디자인은 제한적일 수 밖에 없고, 디자이너의 역할 역시 그 기준 안에서 판단하고 적용하는 오퍼레이터의 역할로 축소되죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 시멘틱 토큰 중심 설계는 브랜딩이 강한 서비스보다 Hexagrid와 같이 다국어, 다중 테마 등과 같이 유연하게 대응해야 하는 서비스에서 활용도가 높아요. 일관된 기준을 유지한 채로 변화를 관리해야 하는 경우에 강점을 발휘하는 방식이라고 볼 수 있어요.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3) &lt;/b&gt;&lt;b&gt;스케일과 시멘틱의 하이브리드 : 변화에 강한 시스템 구조&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2394&quot; data-origin-height=&quot;1654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcnNmr/dJMcagEJQ9r/H1DDLKKUpoAZCCnaJHLdb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcnNmr/dJMcagEJQ9r/H1DDLKKUpoAZCCnaJHLdb1/img.png&quot; data-alt=&quot;스캐일과 시멘틱 토큰의 관계&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcnNmr/dJMcagEJQ9r/H1DDLKKUpoAZCCnaJHLdb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcnNmr%2FdJMcagEJQ9r%2FH1DDLKKUpoAZCCnaJHLdb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2394&quot; height=&quot;1654&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2394&quot; data-origin-height=&quot;1654&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스캐일과 시멘틱 토큰의 관계&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하이브리드 구조는 스케일 토큰과 시멘틱 토큰의 강점을 접목해서 설계하는 방식이라고 볼 수 있어요. &lt;br /&gt;디자인 컬러값은 스케일 토큰으로 설계해 디자인 유연성을 열어두고, 소통은 의미와 맥락을 담아 시멘틱 토큰으로 적용해 소통과 운영을 구조화하는 방식이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &lt;b&gt;$blue-100&lt;/b&gt;, &lt;b&gt;$blue-300&lt;/b&gt;, &lt;b&gt;$blue-500 등 &lt;/b&gt;과 같은 스케일 토큰을 정의한 뒤, 이를 &lt;b&gt;$fill/brand/primary&lt;/b&gt;처럼 역할이 명확한 시멘틱 토큰에 연결해 사용하는 방식이에요. 화면과 디자인 커뮤니케이션에서는 의미를 담고 있는 시멘틱 토큰명으로 소통하고, 실제 색상 값의 변경이나 조정은 스케일 토큰 단계에서 관리를 하게 되는 구조죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조의 가장 큰 장점은 유연성과 확장성을 동시에 가져갈 수 있다는 거에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리브랜딩처럼 컬러 조정이 필요할 경우, 스케일 토큰 값만 변경하면 이와 연결된 시멘틱 토큰도 자동으로 업데이트되면서 제품 전반에 한 번에 반영할 수 있죠.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;컬러 테마를 추가할 경우도 마찬가지예요. 이미 시멘틱 토큰 기준으로 구조가 잡혀 있기 때문에, 테마별로 참조하는 컬러 스케일만 정의해주면 새로운 테마도 비교적 수월하게 확장할 수 있어요. 이 덕분에 컬러 변경이 화면 수정이 아니라, 구조를 조정하는 작업으로 바뀌게 되는거죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 이유로 서비스의 확장성과 유연성을 동시에 만족해야 하는 기업들에서는 하이브리드 구조를 많이 선택하고 있어요.&lt;br /&gt;실제로 당근이나 토스처럼 서비스 규모가 크고, 다양한 환경과 사용 맥락을 함께 고려해야 하는 경우에 이 구조가 효과적으로 활용되고 있는 것으로 알려져 있어요. 특히 당근의 사례를 보면, 시멘틱 토큰 단계에서 가독성과 대비 기준을 함께 고려하는 접근을 취하고 있고, &lt;b&gt;APCA 알고리즘* &lt;/b&gt;과 같은 지각 대비 기준을 참고해 기기 모드나 환경에 따라 컬러 명도가 자연스럽게 조정될 수 있는 적응형 컬러 구조를 설계한 것으로 소개되고 있어요.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;※ APCA 알고리즘 이란?&lt;/b&gt;&lt;br /&gt;APCA는 단순한 명도 차이가 아니라, 사람이 실제로 인식하는 가독성을 기준으로 텍스트와 배경의 대비를 계산하는 알고리즘이에요. &lt;br /&gt;기존의 WCAG 대비 비율이 숫자 중심의 기준이었다면, APCA는 글자의 크기, 두께, 화면 환경까지&amp;nbsp;고려해 &amp;ldquo;이 텍스트가 읽히는가&amp;rdquo;를 판단하는 데 초점을 둡니다. 그래서 다크 모드나 다양한 기기 환경에서도 보다&amp;nbsp;안정적인 가독성을 확보하는 데 활용되고 있어요.&lt;br /&gt;또한 현재 개발 중인 WCAG 3.0에서 이 APCA를 새로운 색상 대비 표준으로 채택할 예정이라고 해요.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 구조에서는 스케일 토큰이 변경될 때, 대비 부족으로 인해 가독성이 떨어질 가능성을 화면 단위가 아니라 토큰 단계에서 미리 발견하고 조정할 수 있어요. 이게 가능한 이유는 스케일 토큰으로 컬러가 묶여져 있고, 이 값이 시멘틱 토큰을 통해 어디에, 어떤 목적으로 사용되는지 명확하게 정의되어 있기 때문이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 하이브리드 구조는 단일 구조로 설계할 때보다 초기 설계 비용이 더 많이 드는 방식이기도 합니다.&lt;br /&gt;스케일 토큰과 시멘틱 토큰을 각각 설계해야 할 뿐만 아니라, 두 계층을 어떻게 연결할지에 대한 구조까지 함께 고민해야 하기 때문이에요.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 설계가 충분히 정리되지 않은 상태에서 하이브리드 구조를 도입하면, 값과 의미가 동시에 늘어나면서 토큰 수가 과도하게 증가하는 이른바 &amp;lsquo;토큰 스프롤(Token Sprawl)&amp;rsquo; 상태로 이어질 수 있습니다.&lt;br /&gt;이 경우 문제는 문서나 구조에만 머무르지 않고, 색의 일관성 저하나 가독성, 속도 문제처럼 서비스 품질로 바로 체감되기 시작하죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 하이브리드 구조에서는 새로운 토큰을 추가할 때마다 &amp;ldquo;이건 새로운 값의 문제인가, 아니면 새로운 의미의 문제인가&amp;rdquo;를 먼저 판단하는 과정이 중요해요. 이 기준이 명확할수록 토큰 구조는 불필요하게 비대해지지 않고, 확장성과 안정성을 비교적 균형 있게 유지할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;그래서, 어떤 선택이 우리에게 맞을까&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컬러 토큰 체계를 도입할 때, 서비스가 지금 어떤 단계에 있는지, 무엇을 가장 우선해야 하는지를 분명히 짚고 넘어가야 합니다. &lt;br /&gt;당연한 이야기처럼 들릴 수 있지만, 방향이 정리되지 않은 상태에서 특정 &amp;lsquo;방식&amp;rsquo;부터 선택해버리면 이후에 감당해야 할 리스크는 생각보다 훨씬 커져요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 함께 조직의 구조와 성격도 아주 중요한 고려사항이에요. &lt;br /&gt;디자인 중심의 의사결정이 중요한 조직인지, 개발 중심으로 빠른 구현이 우선되는 환경인지, 혹은 협업과 유연함을 얼마나 중시하는지에 따라 적합한 설계 방식을 채택해야하죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 무엇보다 중요한 건, 그 선택을 팀 안에서 하나의 &amp;lsquo;약속&amp;rsquo;으로 명확히 공유하는 일이라고 생각해요. &lt;br /&gt;컬러 토큰은 개인의 취향이나 노하우가 아니라, 함께 일하는 사람들이 같은 기준으로 판단하고 움직이기 위해 합의한 구조이기 때문입니다. 결국 컬러 토큰 설계의 완성도는 어떤 방식을 선택했느냐보다, 그 기준을 팀이 얼마나 일관되게 이해하고 지켜나가느냐에 달려 있습니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>UX 가벼운 이야기</category>
      <category>디자인시스템</category>
      <category>스케일토큰</category>
      <category>시멘틱토큰</category>
      <category>컬러토큰체계</category>
      <category>하이브리드구조</category>
      <author>워킹맘 루나</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1888</guid>
      <comments>https://story.pxd.co.kr/1888#entry1888comment</comments>
      <pubDate>Mon, 18 May 2026 07:50:07 +0900</pubDate>
    </item>
    <item>
      <title>서울 시민의 목소리를 시각화하기</title>
      <link>https://story.pxd.co.kr/1897</link>
      <description>&lt;h2 id=&quot;%EC%8B%9C%EB%AF%BC%EC%9D%98-%EB%AA%A9%EC%86%8C%EB%A6%AC%EB%A5%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A1%9C&quot; style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;2&quot; data-ke-size=&quot;size26&quot;&gt;시민의 목소리를 데이터로&lt;/h2&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;UI 디자인을 할 때 늘 부딪히는 문제가 있습니다. 다양한 의견을 가진 사용자의 목소리를 어떻게 정리하고 전달할까. 개개인의 목소리에 집중하면 맥락과 목표가 저마다 다른 모두를 만족시키기 어렵고, 그렇다고 평균을 내면 누구도 대표하지 못해 모두가 만족하지 못하는 디자인이 됩니다. 그래서 보통 퍼소나로 사용자를 몇 가지 유형으로 나눠 접근하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정원오 서울시장 후보가 만든 '&lt;a href=&quot;https://www.seoulvoice.net/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;서울의 목소리&lt;/a&gt;'는 비슷한 문제를 도시 단위로 마주하고 있습니다. 서울 시민의 불편과 고충을 수집해 데이터 기반 해법을 찾고, 그 데이터를 공공데이터로 모두에게 공개하고 있습니다. 수천명의 시민 목소리를 어떻게 정리해 보여주고 있는지, 거기에서 어떤 정보를 얻어낼 수 있는지 시각화 측면에서 살펴보았습니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;6&quot;&gt;설문을 통해 시민의 의견을 수집하는데, 세개의 주관식 문항이 주된 질문입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #3b3b3b; text-align: start;&quot; data-line=&quot;8&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-line=&quot;8&quot;&gt;서울 생활에서의 고충&lt;/li&gt;
&lt;li data-line=&quot;9&quot;&gt;차기 서울시장에게 바라는 점&lt;/li&gt;
&lt;li data-line=&quot;10&quot;&gt;서울하면 떠오르는 키워드&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;%ED%98%84%EC%9E%AC-%EC%82%AC%EC%9D%B4%ED%8A%B8%EA%B0%80-%EB%B3%B4%EC%97%AC%EC%A3%BC%EB%8A%94-%EB%B0%A9%EC%8B%9D&quot; style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;14&quot; data-ke-size=&quot;size26&quot;&gt;정성 데이터를 보여주는 방식&lt;/h2&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;서울의목소리 사이트는 데이터를 두 갈래로 보여줍니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;개별 목소리를 그대로 보여주는&lt;span&gt;&amp;nbsp;&lt;/span&gt;방식과&amp;nbsp;통계로 보여주는&lt;span&gt;&amp;nbsp;&lt;/span&gt;방식입니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;18&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개별 목소리&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #3b3b3b; text-align: start;&quot; data-line=&quot;20&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-line=&quot;20&quot;&gt;&lt;b&gt;지도 위 시각화&lt;/b&gt;: 응답한 위치마다 카테고리별 픽토그램과 색으로 구분된 마커를 띄우고, 클릭하면 한 명 한 명의 글을 읽을 수 있습니다.&lt;/li&gt;
&lt;li data-line=&quot;21&quot;&gt;&lt;b&gt;카드 목록&lt;/b&gt;: 의견을 카드 형태로 나열해 훑어볼 수 있게 했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2302&quot; data-origin-height=&quot;1254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxifYk/dJMcadvbpq4/OmEFc7fuhhN1rmPUkJ5KY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxifYk/dJMcadvbpq4/OmEFc7fuhhN1rmPUkJ5KY0/img.png&quot; data-alt=&quot;공간 맵핑&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxifYk/dJMcadvbpq4/OmEFc7fuhhN1rmPUkJ5KY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxifYk%2FdJMcadvbpq4%2FOmEFc7fuhhN1rmPUkJ5KY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;395&quot; height=&quot;1254&quot; data-origin-width=&quot;2302&quot; data-origin-height=&quot;1254&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;공간 맵핑&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;SCR-20260514-plyq.png&quot; data-origin-width=&quot;2326&quot; data-origin-height=&quot;1544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Dn1m8/dJMcadIHdZr/oKEsdzVmGeyKYEisDkY3h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Dn1m8/dJMcadIHdZr/oKEsdzVmGeyKYEisDkY3h0/img.png&quot; data-alt=&quot;카드형 시각화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Dn1m8/dJMcadIHdZr/oKEsdzVmGeyKYEisDkY3h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDn1m8%2FdJMcadIHdZr%2FoKEsdzVmGeyKYEisDkY3h0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;390&quot; height=&quot;1544&quot; data-filename=&quot;SCR-20260514-plyq.png&quot; data-origin-width=&quot;2326&quot; data-origin-height=&quot;1544&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;카드형 시각화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;23&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;시민 개개인의 목소리가 단위입니다. 개개인의 목소리가 흐려지지 않고 그대로 전달된다는 장점이 있지만, 수천개나 되는 모든 의견을 모두 읽기는 어렵고 전체 그림이 전달되지는 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;통계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #3b3b3b; text-align: start;&quot; data-line=&quot;27&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-line=&quot;27&quot;&gt;&lt;b&gt;막대 그래프, 파이 차트&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;- 범주별 빈도 (전체와 세분화)&lt;/li&gt;
&lt;li data-line=&quot;28&quot;&gt;&lt;b&gt;버블 차트&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(키워드 빈도, 워드클라우드의 변형)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2320&quot; data-origin-height=&quot;1214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UDafo/dJMcacb2HyA/adtfiAI3k81fp0QBoWuC7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UDafo/dJMcacb2HyA/adtfiAI3k81fp0QBoWuC7k/img.png&quot; data-alt=&quot;범주형 바 그래프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UDafo/dJMcacb2HyA/adtfiAI3k81fp0QBoWuC7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUDafo%2FdJMcacb2HyA%2FadtfiAI3k81fp0QBoWuC7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;404&quot; height=&quot;211&quot; data-origin-width=&quot;2320&quot; data-origin-height=&quot;1214&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;범주형 바 그래프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2332&quot; data-origin-height=&quot;1102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpNt6Z/dJMcagrYmcV/GPsowU9Ov8UMI7Z8aGkpZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpNt6Z/dJMcagrYmcV/GPsowU9Ov8UMI7Z8aGkpZk/img.png&quot; data-alt=&quot;세그먼트별 범주 차트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpNt6Z/dJMcagrYmcV/GPsowU9Ov8UMI7Z8aGkpZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpNt6Z%2FdJMcagrYmcV%2FGPsowU9Ov8UMI7Z8aGkpZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;415&quot; height=&quot;1102&quot; data-origin-width=&quot;2332&quot; data-origin-height=&quot;1102&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;세그먼트별 범주 차트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;30&quot; data-ke-size=&quot;size16&quot;&gt;카테고리, 성별, 세대, 지역구처럼 정해진 값을 가지는 범주형 변수는 비율을 계산할 수 있으니 막대 그래프나 파이 차트 같은 시각화 방법을 많이 사용합니다. 그리고 세대나 성별 같은 범주로 세분화하여 어떤 차이가 있는지 세그먼트 분석도 많이 합니다. 여기에서는 범주를 하나 하나를 바꿔가며 비교하는 (stacked in time) 방식을 사용하였는데, 공간에 펼쳐놓으면 (&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://story.pxd.co.kr/539&quot;&gt;adjacent in space&lt;/a&gt;) 한눈에 비교할 수 있어 좋습니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;30&quot;&gt;아래는 고충 카테고리를 연령별로 순위 변화를 띠 형태로 쌓아놓은&amp;nbsp;&lt;b&gt;충적도(Alluvial Diagram)&lt;/b&gt;로 그린 것입니다. 연령대라는 변수에 따라 어떤 고충이 있는지 교차분석할 수 있습니다. 순위가 바뀌면 단층처럼 끊어져 보여 변화가 강조됩니다. 남성은 거의 모든 연령대에서 집값에 대한 고민이 가장 많고. 40대까지는 출퇴근 교통에 대한 고충이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;2위였지만 50대부터는 낮아지고 물가 생활비가 x자로 교차하며 더 높아지는 것이&amp;nbsp; 보입니다. 은퇴 연령대를 생각하면 납득이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;SCR-20260514-raal.png&quot; data-origin-width=&quot;1754&quot; data-origin-height=&quot;1246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKsQAF/dJMcafGC16z/FFnnuh4ean3aCn4tTCNsfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKsQAF/dJMcafGC16z/FFnnuh4ean3aCn4tTCNsfK/img.png&quot; data-alt=&quot;남성 연령대별 고충 충적도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKsQAF/dJMcafGC16z/FFnnuh4ean3aCn4tTCNsfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKsQAF%2FdJMcafGC16z%2FFFnnuh4ean3aCn4tTCNsfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1754&quot; height=&quot;1246&quot; data-filename=&quot;SCR-20260514-raal.png&quot; data-origin-width=&quot;1754&quot; data-origin-height=&quot;1246&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;남성 연령대별 고충 충적도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 20,30 대 여성에서는 전혀 다른 모습인데요. 남성 응답에서는 거의 보이지 않는 안전&amp;middot;치안에 대한 고충이 가장 높습니다. 특히 20대에서는 71%가 안전&amp;middot;치안을 서울의 가장 큰 고충으로 얘기하면서 여성을 대상으로 하는 범죄와 차별에 대해 큰 목소리를 내고 있습니다. 남성과 여성이 전혀 다른 서울에 살고 있는 셈입니다. 이 차이는 뒤에서 좀 더 자세히 살펴 보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;SCR-20260514-racm.png&quot; data-origin-width=&quot;1740&quot; data-origin-height=&quot;1254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QS369/dJMcaaFkOr0/Qv1s3Wiqkw5W0AKxqcDEv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QS369/dJMcaaFkOr0/Qv1s3Wiqkw5W0AKxqcDEv0/img.png&quot; data-alt=&quot;여성 연령대별 고충 충적도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QS369/dJMcaaFkOr0/Qv1s3Wiqkw5W0AKxqcDEv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQS369%2FdJMcaaFkOr0%2FQv1s3Wiqkw5W0AKxqcDEv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1740&quot; height=&quot;1254&quot; data-filename=&quot;SCR-20260514-racm.png&quot; data-origin-width=&quot;1740&quot; data-origin-height=&quot;1254&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;여성 연령대별 고충 충적도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주관식 응답의 시각화&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;시각화는 보통&lt;span&gt;&amp;nbsp;&lt;/span&gt;정량 데이터를 다룹니다. 빈도, 비율, 추세 처럼 수치화 할 수 있는 데이터는 막대&amp;middot;선&amp;middot;지도 같은 익숙한 형태로 옮길 수 있습니다. 반면&lt;span&gt;&amp;nbsp;&lt;/span&gt;정성 데이터를 시각화하는 일은 훨씬 까다롭습니다. 가장 익숙한 방식이 워드클라우드인데, 단어를 세어&lt;span&gt;&amp;nbsp;&lt;/span&gt;정성을 정량으로 환원하는 방식으로 기계적으로 쉽게 처리할 수 있기 때문입니다. 하지만 그 과정에서 위계도 맥락도 담기지 않는 문제가 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;주관식 설문 같은 자유 응답을 분석할 때는 응답에 레이블링을 하고 이를 토대로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;귀납적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;범주를 만드는 코딩 작업을 거칩니다. 빈도를 계산하면 위에서와 같은 범주형 데이터를 시각화하는 방식을 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;1036&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oXtjw/dJMcad22bvw/DYnGk5YsbqOfTcf3W8ZuqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oXtjw/dJMcad22bvw/DYnGk5YsbqOfTcf3W8ZuqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oXtjw/dJMcad22bvw/DYnGk5YsbqOfTcf3W8ZuqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoXtjw%2FdJMcad22bvw%2FDYnGk5YsbqOfTcf3W8ZuqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1848&quot; height=&quot;1036&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;1036&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;32&quot; data-ke-size=&quot;size16&quot;&gt;서울하면 떠오르는 키워드 같은 열려있는 질문에 대해서 버블 차트 형태로 Top 10 키워드를 보여주고 있습니다. 보통 워드클라우드를 많이 사용하는데 빈도에 따라&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;단순히&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;글자 크기를 다르게 하면 같은 빈도라도 긴 단어는 시각적으로 더 커보여서 왜곡할 수 있습니다. 이런 경우 버블의 크기로 나타내면 정량적인 정보를 더 잘 가늠할 수 있습니다. 이때 정량값이 시각적 면적에 비례하도록 그리는 게 중요합니다. 여론조사 꽃이 후보 적합도를 &lt;a href=&quot;https://www.goodmorningcc.com/news/articleView.html?idxno=302617&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지름에 비례&lt;/a&gt;하게 그리는데요. 지름을 값에 맞추면 면적은 제곱에 비례해 커지기 때문에, 실제 차이보다 훨씬 크게 인식됩니다. 차이를 강조하려는 의도일 수도 있지만, 그 강조가 인지를 왜곡하기도 합니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;32&quot;&gt;키워드를 보여주는 방식은 최상위 빈도 일부를 보여주는데 그치는 경우가 많습니다. 표준분포에서는 주요 값이 과반을 차지하는 것과 다르게 이런 정성값은 긴 꼬리 분포가 되는 경우가 많아 상위 일부에 그칩니다. 이 데이터에서도 상위 10개가 전체의 약 30% 만을 설명합니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;32&quot;&gt;전체의 큰 모습을 보여주면서도 개별 목소리의 디테일을 잃지 않는 시각화는 가능할까요? 이 빈자리를 어떻게 메울 수 있을지 살펴보겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;32&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;%EC%84%9C%EC%9A%B8-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%A7%80%EB%8F%84--%EC%9B%8C%EB%93%9C%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EC%9D%98-%EB%8C%80%EC%95%88&quot; style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;42&quot; data-ke-size=&quot;size26&quot;&gt;서울 키워드 지도 - 워드클라우드의 대안&lt;/h2&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;46&quot; data-ke-size=&quot;size16&quot;&gt;모든 키워드를 표시하면서도 복잡해 보이지 않으려면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;시각적 위계&lt;/b&gt;를 갖추는 것이 핵심입니다. 정보량이 많더라도 위계가 있으면 인지 부담을 줄일 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;44&quot;&gt;정보 위계를 만들기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://affinitybubble.com/affinitybubble&quot;&gt;어피니티버블&lt;/a&gt;을 사용했습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;임베딩 클러스터링과 LLM을 이용해 사람이 하는 범주화 코딩 작업을 간소화한 도구입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;비슷한 키워드를 묶어 레이블을 붙이고, 한 번 더 큰 도메인으로 분류해 3단계의 계층을 만들었습니다. 그렇게 정리한 데이터를 가지고 개별 키워드 하나하나가 드러나도록 force 시뮬레이션으로 키워드가 겹치지 않게 배치했습니다. 워드클라우드는 단어를 무작위로 배치하는 반면에 의미가 가까운 키워드가 자연스럽게 모이도록&lt;span&gt;&amp;nbsp;&lt;/span&gt;공간의 위치가 정보값을 가지도록 했습니다. 가장 큰 위계는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;색상으로 구분되어&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;쉽게 인지할 수 있습니다. 비슷한 의미 덩어리를 묶고 요약 레이블을 붙여 주었습니다. 클러스터 안에는 개별 키워드가 모두 살아 있어 확대하면 확인할 수 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;어피니티버블이 보로노이트리맵으로 위계와 크기로 정량적 비율을 잘 나타내는데 초점을 맞추었다면 워드맵은 위계를 조금 흐리게 하는 대신 개별 텍스트와 공간적인 위치정보를 강조한 자매 시각화 방법입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;SCR-20260514-qdbr.png&quot; data-origin-width=&quot;2236&quot; data-origin-height=&quot;1694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1fVfE/dJMcabRG2OR/6R23iUBLWTv9AiL4V748lK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1fVfE/dJMcabRG2OR/6R23iUBLWTv9AiL4V748lK/img.png&quot; data-alt=&quot;서울 키워드 지도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1fVfE/dJMcabRG2OR/6R23iUBLWTv9AiL4V748lK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1fVfE%2FdJMcabRG2OR%2F6R23iUBLWTv9AiL4V748lK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2236&quot; height=&quot;1694&quot; data-filename=&quot;SCR-20260514-qdbr.png&quot; data-origin-width=&quot;2236&quot; data-origin-height=&quot;1694&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서울 키워드 지도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;54&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 보면&lt;span&gt;&amp;nbsp;&lt;/span&gt;전체의 시각적 위계와&lt;span&gt;&amp;nbsp;&lt;/span&gt;의미 유사도가 함께 드러나는 키워드 지도가 됩니다. 키워드에는 숨겨진 맥락이나 여러 의미가 있을 수 있어서 분류가 완벽하게 객관적이지는 않습니다. 다른 관점으로 해석할 여지도 있고 기계 분석의 한계도 있습니다. 하지만 빠르게 전체적인 지형도를 파악할 수 있다는 장점이 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;52&quot;&gt;여기서 저는 한강을 남산, 경복궁, 광화문 등과 함께&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;서울의 랜드마크&lt;/b&gt;로 묶었습니다. 글로벌, 다양성, 인프라, 편리함 등은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;역동적 정체성&lt;/b&gt;으로, 수도&amp;middot;중심 같은 단어는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;수도 상징성&lt;/b&gt;으로 묶었습니다. 이 세 범주는 서울의 긍정적인 부분에 해당합니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;54&quot;&gt;나머지는 부정적인 이미지를 나타내고 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;각박하고 복잡한 대도시&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;범죄의 위험&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;차갑고 삭막하고 불평등한 도시&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;인구 과밀로 인한 복잡함&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;교통 혼잡&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;비싼 집값&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;같은 키워드들이 서울의 이미지를 만들고 있었습니다. 상위 10개의 키워드로는 보이지 않던&lt;span&gt;&amp;nbsp;&lt;/span&gt;서울의 양면성이 지도에 드러납니다. 긍부정 분석에 따라 컬러 맵핑을 해보아도 차이가 보입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;SCR-20260514-qkaw.png&quot; data-origin-width=&quot;2034&quot; data-origin-height=&quot;1492&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/efRRd9/dJMb99TUThG/zuw8DLFzUBdwmXktVkl9A0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/efRRd9/dJMb99TUThG/zuw8DLFzUBdwmXktVkl9A0/img.png&quot; data-alt=&quot;긍부정분석 컬러 맵핑&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/efRRd9/dJMb99TUThG/zuw8DLFzUBdwmXktVkl9A0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FefRRd9%2FdJMb99TUThG%2Fzuw8DLFzUBdwmXktVkl9A0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;413&quot; height=&quot;303&quot; data-filename=&quot;SCR-20260514-qkaw.png&quot; data-origin-width=&quot;2034&quot; data-origin-height=&quot;1492&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;긍부정분석 컬러 맵핑&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;54&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;%EC%84%B8%EB%8C%80%EB%B3%84%EB%A1%9C-%EA%B0%88%EB%A6%AC%EB%8A%94-%EC%84%9C%EC%9A%B8%EC%9D%98-%EC%9D%B4%EB%AF%B8%EC%A7%80&quot; style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;56&quot; data-ke-size=&quot;size26&quot;&gt;세대별로 갈리는 서울의 이미지&lt;/h2&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;60&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;전체 오버뷰 말고 집단을 세분화해 보면 또 다른 발견이 보입니다. 세대별로 교차 분석을 하면&lt;/span&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;40대 이상은 서울을 눈에 보이는 랜드마크로 많이 인식하지만, 20대는 사회적 불평등과 과밀된 도시를 더 많이 떠올립니다.&lt;/b&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;같은 도시에서 세대에 따라 서울의 인상이 다릅니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;SCR-20260514-qwha.png&quot; data-origin-width=&quot;1762&quot; data-origin-height=&quot;1248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q9Snu/dJMcad22oQ2/ipC26v6m30Tvo45tZkPfGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q9Snu/dJMcad22oQ2/ipC26v6m30Tvo45tZkPfGk/img.png&quot; data-alt=&quot;세대별 서울 연상 키워드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q9Snu/dJMcad22oQ2/ipC26v6m30Tvo45tZkPfGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ9Snu%2FdJMcad22oQ2%2FipC26v6m30Tvo45tZkPfGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1762&quot; height=&quot;1248&quot; data-filename=&quot;SCR-20260514-qwha.png&quot; data-origin-width=&quot;1762&quot; data-origin-height=&quot;1248&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;세대별 서울 연상 키워드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;62&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-line=&quot;68&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%EC%9D%98-%ED%95%9C%EA%B3%84--%EC%9E%90%EB%B0%9C%EC%A0%81-%EC%9D%91%EB%8B%B5%EC%9D%98-%ED%8E%B8%ED%96%A5&quot; style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;70&quot; data-ke-size=&quot;size26&quot;&gt;데이터 분석의 한계 &amp;mdash; 자발적 응답의 편향&lt;/h2&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;78&quot; data-ke-size=&quot;size16&quot;&gt;여론조사처럼 무작위로 표집한 것이 아니라 응답자가 자발적으로 참여한 설문이라&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;선택편향(self-selection bias)&lt;/b&gt;이 있습니다. 자발적 참여의 편향은 보통 두 갈래로 나뉩니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;74&quot;&gt;&lt;b&gt;동기 편향&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 불편을 크게 느끼는 사람일수록 응답 동기가 큽니다. 별로 불편한 게 없는 시민은 굳이 시간을 들여 길게 답을 쓰지 않습니다. 그래서 응답자 풀은&lt;span&gt;&amp;nbsp;&lt;/span&gt;불만의 강도가 평균 이상인 시민&lt;span&gt;&amp;nbsp;&lt;/span&gt;쪽으로 쏠립니다. 정책 입안 입장에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;시급한 문제를 잘 잡아내는&lt;span&gt;&amp;nbsp;&lt;/span&gt;장점이지만, 동시에&lt;span&gt;&amp;nbsp;&lt;/span&gt;문제의 보편성을 과대평가할&lt;span&gt;&amp;nbsp;&lt;/span&gt;위험이 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;76&quot;&gt;&lt;b&gt;도달 편향&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 사이트에 닿을 수 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;경로&lt;span&gt;&amp;nbsp;&lt;/span&gt;자체가 한정되어 있습니다. 어떤 채널로 홍보됐는지에 따라 응답자 풀의 인구 구성이 달라져 모집단을 충분히 대표하지 못하게 됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;78&quot;&gt;응답자 성별 연령별 분포를&lt;span&gt;&amp;nbsp;보면&amp;nbsp;&lt;/span&gt;서울 시민 인구와는 구성이 많이 다릅니다. 20대에서 여성이 과표집되고 남성은 과소표집되었습니다. 온라인 설문 참여다 보니 60, 70대에서의 의견은 충분히 반영되지 않은 것 같습니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;84&quot;&gt;[응답자 vs 서울 인구 분포 비교 차트]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1884&quot; data-origin-height=&quot;812&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lKpb0/dJMcaipNybE/tw4NOBX7Chv35rozA1E1IK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lKpb0/dJMcaipNybE/tw4NOBX7Chv35rozA1E1IK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lKpb0/dJMcaipNybE/tw4NOBX7Chv35rozA1E1IK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlKpb0%2FdJMcaipNybE%2Ftw4NOBX7Chv35rozA1E1IK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1884&quot; height=&quot;812&quot; data-origin-width=&quot;1884&quot; data-origin-height=&quot;812&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-line=&quot;78&quot;&gt;타임라인을 보면 이유를 알 수 있는데요. 4월 23일 정원오 후보가 트위터에 사이트를 알린 당일과 다음날 응답이 폭발적으로 증가했는데, 대부분이 20대 여성이었습니다. 특정 네트워크 안에서 리트윗과 노출이 일어나며 응답자 구성 자체가 한쪽으로 치우친 것으로 보입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;서울 시민에게 골고루 도달한&lt;span&gt;&amp;nbsp;&lt;/span&gt;채널이 아니라&lt;span&gt;&amp;nbsp;&lt;/span&gt;특정 커뮤니티에 집중된&lt;span&gt;&amp;nbsp;&lt;/span&gt;채널이 되면, 그 채널의 인구 구성이 데이터의 인구 구성을 그대로 결정해 버립니다.&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;80&quot; data-ke-size=&quot;size16&quot;&gt;[타임라인 + 성-연령 히트맵]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2278&quot; data-origin-height=&quot;916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAesIc/dJMcah5wwPq/SmGtqzFwENQDrj6W6pDiSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAesIc/dJMcah5wwPq/SmGtqzFwENQDrj6W6pDiSK/img.png&quot; data-alt=&quot;일자별 응답자 수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAesIc/dJMcah5wwPq/SmGtqzFwENQDrj6W6pDiSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAesIc%2FdJMcah5wwPq%2FSmGtqzFwENQDrj6W6pDiSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2278&quot; height=&quot;916&quot; data-origin-width=&quot;2278&quot; data-origin-height=&quot;916&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;일자별 응답자 수&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;82&quot; data-ke-size=&quot;size16&quot;&gt;여론조사에서는 이런 경우 응답자 분포를 인구 분포에 맞추는 셀 가중치를 적용해 보정합니다. 그런데 자발적 참여 데이터에 같은 방법을 적용하면 오히려 정밀도 과잉을 만들어 낼 수 있습니다. 가중치는 셀 안의 응답자가 비응답자를 대표한다고 가정하는데, 응답자 안에 이미 편향이 남아 있으면 가중치만으로는 그 집단을 대표하게 만들 수 없습니다.&amp;nbsp;아래 차이를 보면, 응답자 안에서도 응답이 폭증했던 이틀간의 20대 여성은 다른 날의 응답자와도 결이 다르다는 걸 알 수 있습니다. 하지만 앞에서 살펴본 20대 여성의 안전&amp;middot;치안에 대한 고충은 편향을 감안하더라도 보편적인 신호라는 것 역시 분명합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;1256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bidUos/dJMcaipNXAY/3B17CzXHZKMZySRHIOqmBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bidUos/dJMcaipNXAY/3B17CzXHZKMZySRHIOqmBk/img.png&quot; data-alt=&quot;응답이 많았던 이틀간 응답자의 편향&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bidUos/dJMcaipNXAY/3B17CzXHZKMZySRHIOqmBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbidUos%2FdJMcaipNXAY%2F3B17CzXHZKMZySRHIOqmBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1752&quot; height=&quot;1256&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;1256&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;응답이 많았던 이틀간 응답자의 편향&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;90&quot; data-ke-size=&quot;size16&quot;&gt;그래서 이 데이터는 서울 시민 전체의 목소리를 대표한다기보다 &lt;b&gt;참여한 사람들의 목소리&lt;/b&gt;로 읽는 게 좋겠습니다. 비율과 순위 같은 정량 수치를 일반화하려 하기보다, 어떤 목소리가 어떤 결로 모이는지 정성적인 측면에 초점을 맞춰 보는 것입니다. 이어지는 범주별 분석도 그런 시선으로 보면 좋겠습니다.&lt;/p&gt;
&lt;hr data-line=&quot;92&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;94&quot; data-ke-size=&quot;size26&quot;&gt;주요 범주별 서울 시민 고충 어피니티버블&amp;nbsp;&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;SCR-20260515-hqng.png&quot; data-origin-width=&quot;2170&quot; data-origin-height=&quot;1652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OdLSb/dJMb99M7JNy/723jG73VuQ5gdut8fhK0U0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OdLSb/dJMb99M7JNy/723jG73VuQ5gdut8fhK0U0/img.png&quot; data-alt=&quot;안전, 치안&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OdLSb/dJMb99M7JNy/723jG73VuQ5gdut8fhK0U0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOdLSb%2FdJMb99M7JNy%2F723jG73VuQ5gdut8fhK0U0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2170&quot; height=&quot;1652&quot; data-filename=&quot;SCR-20260515-hqng.png&quot; data-origin-width=&quot;2170&quot; data-origin-height=&quot;1652&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;안전, 치안&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;안전&amp;middot;치안&amp;nbsp;카테고리에서는 여성 응답자가 압도적으로 많았습니다. 많은 여성이 여성 대상 범죄와 유해환경과 치안에 대해 불안해 하고 있습니다. 남성과 여성의 안전에 대한 체감이 확연히 다릅니다.&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;개별 시민의 목소리는 &lt;a href=&quot;https://affinitybubble.com/shared-bubble?id=nXGtnwNRnP9Y7Yme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;어피니티버블에서&lt;/a&gt; 확인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;SCR-20260515-hvkf.png&quot; data-origin-width=&quot;2168&quot; data-origin-height=&quot;1612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGxKlK/dJMcaipNY9y/Ny3FDOfukZvnygAXUSOk9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGxKlK/dJMcaipNY9y/Ny3FDOfukZvnygAXUSOk9k/img.png&quot; data-alt=&quot;물가,생활비&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGxKlK/dJMcaipNY9y/Ny3FDOfukZvnygAXUSOk9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGxKlK%2FdJMcaipNY9y%2FNy3FDOfukZvnygAXUSOk9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2168&quot; height=&quot;1612&quot; data-filename=&quot;SCR-20260515-hvkf.png&quot; data-origin-width=&quot;2168&quot; data-origin-height=&quot;1612&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;물가,생활비&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이 범주는 성별&amp;middot;세대 구분 없이 고르게 응답이 모였습니다. 임금 대비 물가와 생활비가 급격하게 오르는 데 대한 고충이 공통된 목소리입니다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;개별 시민의 목소리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://affinitybubble.com/shared-bubble?id=sbxUutdWYabfDAWs&quot;&gt;어피니티버블에서&lt;/a&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;확인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;SCR-20260515-htpu.png&quot; data-origin-width=&quot;2042&quot; data-origin-height=&quot;1572&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9pMsb/dJMcacwm9BF/nzSMcjjXPwFgeoncULyOy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9pMsb/dJMcacwm9BF/nzSMcjjXPwFgeoncULyOy1/img.png&quot; data-alt=&quot;출퇴근,교통&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9pMsb/dJMcacwm9BF/nzSMcjjXPwFgeoncULyOy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9pMsb%2FdJMcacwm9BF%2FnzSMcjjXPwFgeoncULyOy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2042&quot; height=&quot;1572&quot; data-filename=&quot;SCR-20260515-htpu.png&quot; data-origin-width=&quot;2042&quot; data-origin-height=&quot;1572&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출퇴근,교통&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교통 범주는 다른 범주보다 구체적인 요구가 많이 보입니다. 지하철 혼잡, 도로 정체, 버스 배차, 철도 역 신설에 대한 요구가 큰 줄기를 이루고, 장애인 이동권 보장에 대한 목소리도 함께 들어볼 필요가 있습니다.&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;개별 시민의 목소리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://affinitybubble.com/shared-bubble?id=wRxMRKDePjVDLtjz&quot;&gt;어피니티버블에서&lt;/a&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;확인할 수 있습니다.&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정성 데이터에 어울리는 시각화를 향해&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 정성 데이터의 시각화가 워드클라우드 같은 단순한 방식에 머물러 있었던 데는 이유가 있습니다. 응답 하나하나를 사람이 직접 읽고 범주를 만들고 코딩하는 일이 까다로웠기 때문입니다. 그래서 빈도라는 단일 축으로 환원하는 처리가 쉬운 방식을 택해, 맥락은 사라지고 위계와 의미의 인접성은 드러나지 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임베딩과 LLM은 그 코딩 작업을 상당 부분 자동화해 줍니다. 분석이 쉬워진 만큼 시각화도 한 걸음 더 나아갈 수 있습니다. 어피니티버블이나 워드맵처럼 정보를 위계화하고 위치에 의미를 담는 시각화는 그 빈자리를 채울 수 있습니다. 전체 지형도를 한눈에 보여주면서도 개별 목소리의 디테일을 잃지 않습니다. 시민의 의견을 데이터로 모으는 일도 중요하지만, 그 데이터를 다시 정리해 시민에게 잘 전달하는 일도 그만큼 중요합니다. 시민의 목소리든 사용자의 응답이든, 정성 데이터를 다루는 자리라면 이런 시각화를 한 번 시도해 볼 만합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 id=&quot;%EC%9E%AC%EB%AF%B8%EB%A1%9C-%EB%B3%B4%EB%8A%94-%EC%A7%80%EB%8F%84--%ED%95%9C%EA%B0%95-%ED%82%A4%EC%9B%8C%EB%93%9C%EB%8A%94-%ED%95%9C%EA%B0%95-%EC%98%86-%EC%82%AC%EB%9E%8C%EC%9D%B4-%EB%A7%8E%EC%9D%B4-%EC%93%B8%EA%B9%8C&quot; style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;94&quot; data-ke-size=&quot;size26&quot;&gt;한강을 떠올린 사람은 한강 근처에 살까?&lt;/h2&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;96&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로 가볍게 정성과 공간을 엮어보는 관찰 하나로 마무리하겠습니다. 키워드 데이터를 보다 보니 가벼운 호기심이 생겼습니다. 한강을 키워드로 뽑은 사람들은 한강 가까이 살고 있을까?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1483&quot; data-origin-height=&quot;1034&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/up627/dJMcafNqlpL/W2TK2yB817S4WgkPYHfMz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/up627/dJMcafNqlpL/W2TK2yB817S4WgkPYHfMz0/img.png&quot; data-alt=&quot;한강 키워드 응답 구별 코로플레스맵&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/up627/dJMcafNqlpL/W2TK2yB817S4WgkPYHfMz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fup627%2FdJMcafNqlpL%2FW2TK2yB817S4WgkPYHfMz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1483&quot; height=&quot;1034&quot; data-origin-width=&quot;1483&quot; data-origin-height=&quot;1034&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;한강 키워드 응답 구별 코로플레스맵&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #3b3b3b; text-align: start;&quot; data-line=&quot;100&quot; data-ke-size=&quot;size16&quot;&gt;응답자 중 &lt;b&gt;한강 인접 11개 구의 한강 키워드 응답 비율은 11.1%&lt;/b&gt;, &lt;b&gt;비인접 14개 구는 6.3%&lt;/b&gt;로 실제 응답에서도 약 &lt;b&gt;1.8배&lt;/b&gt; 차이가 났습니다. 다만&lt;span&gt;&amp;nbsp;&lt;/span&gt;동 단위까지 좁히면 경향이 약해집니다. 표본이 작아져 노이즈도 있겠고, &lt;span style=&quot;color: #3b3b3b; text-align: start;&quot;&gt;거주지와 상관없이 학교나 직장에 따라 매일 한강을 지나거나 주말에 한강을 자주 찾을 수도 있으니 강한 상관관계가 있지는 않을텐데요. 그래도 한강을 연상하는데 영향이 있긴 한 것 같습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Re-design!</category>
      <category>서울의목소리</category>
      <category>서울키워드지도</category>
      <category>정보디자인</category>
      <author>無異</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1897</guid>
      <comments>https://story.pxd.co.kr/1897#entry1897comment</comments>
      <pubDate>Thu, 14 May 2026 19:46:44 +0900</pubDate>
    </item>
    <item>
      <title>하네스 엔지니어링</title>
      <link>https://story.pxd.co.kr/1896</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;OpenAI의 엔지니어링 팀이 5개월 동안 약 100만 줄의 프로덕션 코드를 만들었다. 놀라운 건 규모가 아니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;수동으로 작성한 소스코드가 단 한 줄도 없다&lt;/b&gt;는 점이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;소수의 엔지니어가 Codex 에이전트에게 작업을 지시하고, PR을 검토하고, CI 파이프라인을 관리했을 뿐이다. 애플리케이션 로직, 문서, CI 설정, 모니터링 설정까지 전부 AI 에이전트가 만들었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 실험에서 OpenAI가 얻은 가장 중요한 교훈은 이것이다:&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;어려운 건 AI 에이전트가 아니다. 에이전트가 일할&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;환경(harness)&lt;/b&gt;이 어렵다.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 환경을 설계하는 분야가 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;하네스 엔지니어링(Harness Engineering)&lt;/b&gt;이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;하네스 엔지니어링이란?&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;비유로 이해하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&quot;하네스(harness)&quot;는 말에게 씌우는 마구(馬具)다. 말이 아무리 빠르고 강해도, 고삐 없이는 짐을 나를 수 없고 밭을 갈 수도 없다. 방향을 잡아주고, 힘을 전달하고, 안전하게 제어하는 것이 마구의 역할이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;AI 에이전트도 마찬가지다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- GPT-5든 Claude든, 에이전트 자체는 이미 충분히 강력하다&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 하지만 고삐 없이 풀어놓으면&amp;nbsp;&lt;b&gt;엉뚱한 코드, 아키텍처 위반, 스타일 불일치&lt;/b&gt;가 쏟아진다&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 하네스 엔지니어링은 이&amp;nbsp;&lt;b&gt;고삐를 설계하는 기술&lt;/b&gt;이다&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;정의&lt;/h3&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하네스 엔지니어링&lt;/b&gt;: AI 에이전트가 대규모로 안정적이고 일관된 결과물을 만들어내도록 환경, 제약, 피드백 루프를 설계하는 엔지니어링 분야&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;핵심은&amp;nbsp;&lt;b&gt;에이전트를 바꾸는 것이 아니라 환경을 바꾸는 것&lt;/b&gt;이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;왜 지금 필요한가?&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2025년의 전형적인 실패 패턴&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;개발자: &quot;결제 모듈 만들어줘&quot;
에이전트: (코드 생성)


문제들:
- 프로젝트 코딩 컨벤션 무시
- 이미 있는 유틸 함수를 중복 생성
- 아키텍처 레이어 경계를 넘나듦
- 테스트는 통과하지만 기존 모듈과 스타일이 불일치
- 3일 후, 다른 에이전트가 같은 파일을 다른 방식으로 수정&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;에이전트 하나가 한 번 작업하는 건 어떻게든 된다. 문제는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;규모가 커질 때&lt;/b&gt;다. 10개의 에이전트가 동시에 100개의 파일을 수정하면, 제약 없이는 카오스가 된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;프롬프트 엔지니어링의 한계&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&quot;코딩 컨벤션을 지켜줘&quot;, &quot;아키텍처 레이어를 위반하지 마&quot; 같은 프롬프트를 아무리 정교하게 써도, 에이전트는 잊거나 무시한다. 프롬프트는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;부탁&lt;/b&gt;이고, 하네스는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;강제&lt;/b&gt;다.&lt;/p&gt;
&lt;pre class=&quot;gcode&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;프롬프트 엔지니어링: &quot;이 규칙을 지켜주세요&quot; (부탁)

하네스 엔지니어링: 규칙을 위반하면 CI가 실패한다 (강제)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;LangChain 팀은 이를 정량적으로 증명했다. 에이전트 모델은 그대로 두고&amp;nbsp;&lt;b&gt;하네스만 개선&lt;/b&gt;했더니, 벤치마크 성과가&amp;nbsp;&lt;b&gt;52.8%에서 66.5%로 향상&lt;/b&gt;되었다. 순위로는 Top 30에서 Top 5로 뛰었다. 에이전트를 바꾸지 않고도, 환경을 바꾸는 것만으로 이 정도 차이가 난다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;하네스 엔지니어링의 3가지 핵심 기둥&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. 컨텍스트 엔지니어링 (Context Engineering)&lt;/h3&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;에이전트에게 추측시키지 말고, 읽게 하라&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 올바른 결과물을 만들려면, 프로젝트의 규칙과 상태를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;알아야&lt;/b&gt;&amp;nbsp;한다. 컨텍스트 엔지니어링은 이 정보를 머신이 읽을 수 있는 형태로 구조화하는 것이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정적 컨텍스트: 규칙 파일&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;markdown&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# AGENTS.md (또는 CLAUDE.md)

## 아키텍처 규칙
- 모든 API 엔드포인트는 /api/v1/ 하위에 위치
- 데이터베이스 접근은 반드시 Repository 레이어를 통해서만
- UI 컴포넌트에서 직접 API를 호출하지 않음

## 코딩 컨벤션
- 함수명: camelCase
- 파일명: kebab-case
- 테스트 파일: *.test.ts

## 금지 패턴
- console.log 사용 금지 (logger 사용)
- any 타입 사용 금지
- 인라인 스타일 금지&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 파일은 에이전트가 작업을 시작할 때&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;자동으로 로드&lt;/b&gt;된다. 사람에게 온보딩 문서를 주듯이, 에이전트에게도 &quot;입사 첫날 읽어야 할 문서&quot;를 주는 것이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동적 컨텍스트: 실시간 상태&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CI/CD 파이프라인 상태&lt;/li&gt;
&lt;li&gt;로그, 메트릭, 에러 추적&lt;/li&gt;
&lt;li&gt;현재 진행 중인 PR과 이슈&lt;/li&gt;
&lt;li&gt;최근 변경된 파일과 그 이유&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 원칙: 저장소가 단일 진실 소스(Single Source of Truth)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;모든 정보는 코드 저장소 안에 있어야 한다. 위키, 노션, 슬랙 대화에 흩어진 정보는 에이전트가 읽을 수 없다. 저장소에 넣어야 에이전트의 컨텍스트가 된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 아키텍처 제약 (Architectural Constraints)&lt;/h3&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;자유롭게 코드를 쓰되, 정해진 경계 안에서만&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;컨텍스트가 &quot;무엇을 해야 하는가&quot;라면, 아키텍처 제약은&amp;nbsp;&lt;b&gt;&quot;무엇을 해서는 안 되는가&quot;&lt;/b&gt;다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;의존성 방향 강제&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;OpenAI는 코드베이스의 의존성 방향을 이렇게 정의했다:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;Types &amp;rarr; Config &amp;rarr; Repository &amp;rarr; Service &amp;rarr; Runtime &amp;rarr; UI&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UI는 Service를 호출할 수 있지만, Service는 UI를 참조할 수 없다&lt;/li&gt;
&lt;li&gt;Repository는 Config를 읽을 수 있지만, Config는 Repository를 모른다&lt;/li&gt;
&lt;li&gt;이 규칙을 위반하는 import가 있으면 **빌드가 실패**한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이것은 프롬프트로 &quot;지켜줘&quot;라고 부탁하는 것이 아니다. 린터와 구조 테스트가&amp;nbsp;&lt;b&gt;자동으로 차단&lt;/b&gt;하는 것이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구현 예시&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;// architecture.test.ts &amp;mdash; 아키텍처 제약 테스트

describe('Architecture constraints', () =&amp;gt; {
  test('UI layer must not import from Repository', () =&amp;gt; {
    const uiFiles = getFilesIn('src/ui/');

    for (const file of uiFiles) {
      const imports = getImports(file);
      expect(imports).not.toContainPath('src/repository/');
    }
  });

  test('Service layer must not import from UI', () =&amp;gt; {
    const serviceFiles = getFilesIn('src/service/');

    for (const file of serviceFiles) {
      const imports = getImports(file);
      expect(imports).not.toContainPath('src/ui/');
    }
  });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;에이전트가 아무리 &quot;이렇게 하는 게 더 효율적인데&quot;라고 생각해도, 이 테스트가 실패하면 코드는 머지되지 않는다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Pre-commit 훅&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# .husky/pre-commit
npx lint-staged          # 코드 스타일 강제
npm run test:architecture  # 아키텍처 규칙 검증
npm run test:types         # 타입 안전성 확인&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;커밋 자체가 되지 않으므로, 잘못된 코드가 저장소에 들어갈 수 없다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 엔트로피 관리 (Entropy Management)&lt;/h3&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;AI가 만든 코드는 시간이 지나면 부패한다&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Martin Fowler는 이 현상을&amp;nbsp;&lt;b&gt;&quot;코드 부패(code rot)&quot;&lt;/b&gt;에 비유하면서, 하네스 엔지니어링의 엔트로피 관리를 프로그래밍 언어의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;가비지 컬렉션(GC)&lt;/b&gt;에 빗대었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가비지 컬렉션이 메모리 누수를 자동으로 정리하듯, 엔트로피 관리는 코드베이스의&amp;nbsp;&lt;b&gt;일관성 붕괴를 자동으로 탐지하고 복구&lt;/b&gt;한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 엔트로피가 증가하는가?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;에이전트 A가 유틸 함수를 만들고, 에이전트 B가 같은 기능의 함수를 또 만든다. 에이전트 C는 이전 버전의 패턴을 사용한다. 10개의 에이전트가 동시에 작업하면, 각각은 올바르더라도&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;전체적으로는 불일치&lt;/b&gt;가 쌓인다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대응 방법&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;정리 에이전트(Cleanup Agent)를 주기적으로 실행:
  1. 문서와 코드의 불일치 탐지
  2. 중복 함수/모듈 발견
  3. 사용되지 않는 코드 식별
  4. 네이밍 패턴 위반 스캔
  5. 순환 의존성 감지&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이것은 &quot;한 번 설정하면 끝&quot;이 아니다.&amp;nbsp;&lt;b&gt;지속적이고 반복적인 프로세스&lt;/b&gt;다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;실제 사례로 보는 하네스 엔지니어링&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;OpenAI: 100만 줄의 무인 코드&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구성:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소수의 엔지니어 + 다수의 Codex 에이전트&lt;/li&gt;
&lt;li&gt;모든 아키텍처 규칙을 머신 가독형 문서로 명세&lt;/li&gt;
&lt;li&gt;관찰성(observability) 데이터로 에이전트 성과 모니터링&lt;/li&gt;
&lt;li&gt;구조화된 PR 리뷰 워크플로우&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;5개월, 약 100만 줄의 프로덕션 베타 제품&lt;/li&gt;
&lt;li&gt;수동 작성 코드 0줄&lt;/li&gt;
&lt;li&gt;애플리케이션 로직 + 문서 + CI + 모니터링 전부 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 교훈:&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;에이전트에게 &quot;좋은 코드를 써줘&quot;라고 하지 않았다. 대신&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;좋은 코드만 통과할 수 있는 환경&lt;/b&gt;을 만들었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Stripe: 주당 1,000개 PR&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Stripe의 &quot;Minions&quot; 에이전트 시스템:&lt;/p&gt;
&lt;pre class=&quot;stata&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;Slack에서 작업 요청
  &amp;rarr; 에이전트가 자동으로 코드 작성
  &amp;rarr; CI 파이프라인 통과 확인
  &amp;rarr; PR 자동 생성
  &amp;rarr; 인간 엔지니어가 최종 리뷰
  &amp;rarr; 머지&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;주당 1,000개 이상의 PR이 이 파이프라인을 통해 머지된다. 핵심은 에이전트가 만든 코드가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;기존 코드와 동일한 품질 게이트&lt;/b&gt;를 통과해야 한다는 점이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;LangChain: 하네스 변경만으로 벤치마크 점프&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;LangChain 팀은 에이전트 모델(Claude, GPT)은 전혀 바꾸지 않고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;미들웨어 구조만 개선&lt;/b&gt;했다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;LocalContextMiddleware&lt;/b&gt;: 코드베이스 매핑 자동 생성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LoopDetectionMiddleware&lt;/b&gt;: 에이전트 반복 루프 감지 및 중단&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ReasoningSandwichMiddleware&lt;/b&gt;: 추론 단계 최적화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PreCompletionChecklistMiddleware&lt;/b&gt;: 완료 전 검증 강제&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결과: 벤치마크&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;52.8% &amp;rarr; 66.5%&lt;/b&gt;, 순위&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Top 30 &amp;rarr; Top 5&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 사례가 증명하는 것:&amp;nbsp;&lt;b&gt;&quot;더 좋은 AI&quot;보다 &quot;더 좋은 환경&quot;이 성과를 좌우한다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;도입 가이드: 3단계로 시작하기&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Level 1: 개인 프로젝트&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가장 가성비 좋은 시작점이다.&lt;/p&gt;
&lt;pre class=&quot;vala&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# 1. CLAUDE.md (또는 AGENTS.md) 작성
프로젝트 규칙, 컨벤션, 금지 패턴 정의

# 2. Pre-commit 훅 설정
코드 스타일과 기본 규칙 자동 검증

# 3. 테스트 작성
에이전트가 만든 코드가 기존 테스트를 깨뜨리지 않는지 확인&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이것만으로도 에이전트의 결과물 품질이 체감될 정도로 달라진다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Level 2: 소규모 팀&lt;/h3&gt;
&lt;pre class=&quot;vala&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# 1. AGENTS.md 고도화
아키텍처 다이어그램, 모듈 경계, 의존성 규칙 포함

# 2. CI 파이프라인에 아키텍처 테스트 추가
레이어 위반, 순환 의존성 자동 탐지

# 3. PR 검토 체크리스트
에이전트 생성 코드에 대한 표준 리뷰 절차 수립

# 4. 린터 규칙 강화
프로젝트 전용 커스텀 린터 규칙 추가&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Level 3: 조직 규모&lt;/h3&gt;
&lt;pre class=&quot;vala&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# 1. 미들웨어 레이어 구축
에이전트 요청/응답 파이프라인에 검증 단계 삽입

# 2. 관찰성(Observability) 시스템
에이전트 성과 메트릭 수집 및 대시보드

# 3. 엔트로피 관리 자동화
정리 에이전트 주기적 실행, 코드 건강도 리포트

# 4. 버전 관리된 하네스 설정
하네스 자체를 코드로 관리, 변경 이력 추적&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;흔한 실수 5가지&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. 과도한 제어 흐름 설계&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;에이전트의 모든 행동을 미리 정의하려는 유혹이 있다. 하지만 LLM은 빠르게 진화한다. 너무 세밀한 제어 흐름은 모델이 업데이트될 때마다 깨진다.&amp;nbsp;&lt;b&gt;큰 경계만 정하고, 경계 안에서는 자유를 주는 것&lt;/b&gt;이 더 견고하다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 정적 하네스&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;한 번 만들어놓고 방치하는 하네스는 금방 쓸모없어진다. 모델이 진화하면 하네스도 함께 진화해야 한다. 하네스 자체를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;코드로 관리하고 버전 관리&lt;/b&gt;해야 하는 이유다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 문서화 경시&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&quot;AGENTS.md 대충 써도 되겠지&quot;는 위험한 생각이다. 에이전트는 당신의 의도를 추론하지 않는다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;명확하지 않으면 추측하고, 추측은 틀린다.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;규칙 파일의 품질이 곧 에이전트 결과물의 품질이다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. 피드백 루프 부재&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;에이전트가 성공했는지 실패했는지 모르면 개선할 수 없다. 어떤 에이전트가 어떤 작업에서 어떤 이유로 실패했는지를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;추적하고 기록&lt;/b&gt;해야 한다. 이 데이터가 하네스를 개선하는 연료다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. 저장소 밖에 정보 저장&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&quot;이건 노션에 있어&quot;, &quot;그건 슬랙에서 공유했어&quot; &amp;mdash; 에이전트는 이런 정보에 접근할 수 없다.&amp;nbsp;&lt;b&gt;저장소 안에 없으면 존재하지 않는 것&lt;/b&gt;이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;프롬프트 엔지니어링 &amp;rarr; 하네스 엔지니어링으로의 전환&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2023~2024년의 키워드가 &quot;프롬프트 엔지니어링&quot;이었다면, 2025~2026년의 키워드는 &quot;하네스 엔지니어링&quot;이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프롬프트 엔지니어링:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AI에게&amp;nbsp;&lt;b&gt;무엇을 하라고 말하는&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;기술&lt;/li&gt;
&lt;li&gt;한 번의 대화, 한 번의 결과물에 집중&lt;/li&gt;
&lt;li&gt;개인 스킬에 의존&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하네스 엔지니어링:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AI가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;올바르게 작동하는 환경을 만드는&lt;/b&gt;&amp;nbsp;기술&lt;/li&gt;
&lt;li&gt;수천 번의 반복 실행에서 일관된 품질을 보장&lt;/li&gt;
&lt;li&gt;시스템적이고 팀 전체에 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프롬프트 엔지니어링이 &quot;좋은 질문하는 법&quot;이라면, 하네스 엔지니어링은 &quot;좋은 답만 나올 수밖에 없는 구조를 만드는 법&quot;이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하네스 엔지니어링은 결국 개발자의 역할에 대한 질문이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&quot;당신은 코드를 쓰는 사람인가, 코드가 만들어지는 환경을 설계하는 사람인가?&quot;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 코드를 작성하는 속도와 품질은 계속 좋아질 것이다. 하지만 아무리 좋은 에이전트도 잘못된 환경에서는 잘못된 결과를 낸다. 반대로, 적절한 하네스 안에서는 평범한 에이전트도 놀라운 결과를 만든다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2026년의 시니어 엔지니어에게 기대되는 역량은 더 이상 &quot;복잡한 알고리즘을 얼마나 잘 구현하느냐&quot;가 아니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&quot;AI 에이전트가 복잡한 시스템을 안정적으로 구축할 수 있는 환경을 얼마나 잘 설계하느냐&quot;&lt;/b&gt;로 무게중심이 옮겨가고 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;코드를 쓰는 시대가 끝나는 게 아니다. 코드를 쓰는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;방식&lt;/b&gt;이 바뀌는 것이다. 그리고 그 변화의 중심에 하네스 엔지니어링이 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;이 글은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://tech.pxd.co.kr/post/%ED%95%98%EB%84%A4%EC%8A%A4-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81-341&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://tech.pxd.co.kr/&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;&amp;nbsp; 에서도 보실 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #1a1a1a;&quot; href=&quot;https://openai.com/ko-KR/index/harness-engineering/&quot;&gt;OpenAI &amp;mdash; 하네스 엔지니어링: 에이전트 우선 세계에서 Codex 활용하기&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #1a1a1a;&quot; href=&quot;https://martinfowler.com/articles/exploring-gen-ai/harness-engineering.html&quot;&gt;Martin Fowler &amp;mdash; Harness Engineering&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #1a1a1a;&quot; href=&quot;https://www.nxcode.io/resources/news/harness-engineering-complete-guide-ai-agent-codex-2026&quot;&gt;NxCode &amp;mdash; Harness Engineering: The Complete Guide&lt;/a&gt;&lt;/p&gt;</description>
      <category>UX Engineer 이야기</category>
      <author>doworld</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1896</guid>
      <comments>https://story.pxd.co.kr/1896#entry1896comment</comments>
      <pubDate>Mon, 11 May 2026 07:50:18 +0900</pubDate>
    </item>
    <item>
      <title>shadcn과 함께 UI 컴포넌트를 AI 에이전트와 더 잘쓰는 방법</title>
      <link>https://story.pxd.co.kr/1895</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;AI 코딩 에이전트에게 &quot;로그인 폼 만들어줘&quot;라고 했더니, 있지도 않는 props를 쓰고, import 경로를 틀리고, 프로젝트 테마와 전혀 안 맞는 결과물이 나온 경험이 있나요?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;shadcn/ui가 더 확실하고 사용하기 쉽게 shadcn/cli v4로 업데이트 되었어요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;shadcn/ui가 AI 시대에 주목받는 이유&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;shadcn/ui는 이미 주목을 많이 받았던 UI 프레임워크이지만 AI시대가 되며 더더욱 많이 주목받고 활용되고 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일반적인 컴포넌트 라이브러리와 다르죠. npm에서 패키지를 설치하는 방식이 아니라,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;컴포넌트 코드를 직접 프로젝트에 복사&lt;/b&gt;하는 구조입니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;npx shadcn@latest add button

# &amp;rarr; src/components/ui/button.tsx 파일이 생성됨&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 &quot;코드 소유&quot; 방식이 AI와 합이 좋아요:&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- AI가 컴포넌트 코드를&amp;nbsp;&lt;b&gt;직접 읽고 이해&lt;/b&gt;할 수 있다&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 숨겨진 추상화 없이&amp;nbsp;&lt;b&gt;모든 구현이 투명&lt;/b&gt;하다&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 프로젝트에 맞게&amp;nbsp;&lt;b&gt;자유롭게 수정&lt;/b&gt;&amp;nbsp;가능하다&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 AI가 &quot;shadcn/ui를 안다&quot;고 해도,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;내 프로젝트에서 어떻게 설정되어 있는지&lt;/b&gt;는 모른다는 점에서 문제가 종종 발생해요. CLI v4가 이 문제를 해결해줍니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;CLI v4의 핵심: AI 에이전트를 위한 3가지 설정&lt;/h3&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;1. Skills &amp;mdash; &quot;AI에게 내 프로젝트를 알려주는 법&quot;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code나 Codex 같은 AI 에이전트는 학습 데이터에 의존하죠. 하지만 shadcn/ui는 빠르게 업데이트되고, 프로젝트마다 설정이 다릅니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결과적으로:&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 컴포넌트 API를 잘못 사용&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 테마 토큰이 불일치&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- import 경로 오류&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 올바른 props를 찾느라 시간 낭비&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결: shadcn/skills&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;npx skills add shadcn/ui&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 한 줄이면 AI 에이전트가 내 프로젝트에 대해 자동으로 파악을 합니다:&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;components.json&amp;nbsp;설정 (프레임워크, CSS 변수, 경로 등)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- Tailwind 설정&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 설치된 컴포넌트 목록&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 아이콘 라이브러리 종류&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 프레임워크 타입과 버전&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설정 전 vs 설정 후&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;clean&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# Skills 설정 전

// AI가 추측으로 생성한 코드
import { Button } from &quot;shadcn/button&quot;  // 경로 틀림
&amp;lt;Button variant=&quot;solid&quot;&amp;gt;              // 존재하지 않는 variant


# Skills 설정 후

// AI가 실제 설정을 읽고 생성한 코드
import { Button } from &quot;@/components/ui/button&quot;  // 정확한 경로
&amp;lt;Button variant=&quot;default&quot;&amp;gt;                       // 올바른 variant
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Skills는 AI에게 &quot;추측하지 말고 읽어라&quot;를 가능하게 만듭니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2. MCP Server &amp;mdash; &quot;AI가 실시간으로 문서를 찾아보는 법&quot;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;AI의 학습 데이터에는 시점이 있죠. shadcn/ui가 어제 업데이트 했다면 Data Table의 새로운 정렬 API를 AI는 모릅니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결: shadcn MCP 서버&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;claude mcp add shadcn -- npx shadcn@latest mcp&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;MCP(Model Context Protocol)는 AI 에이전트가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;실시간으로 shadcn/ui 레지스트리에 접근&lt;/b&gt;할 수 있게 해줍니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;AI가 할 수 있게 되는 것:&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 컴포넌트 문서와 예제를 실시간 조회&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 최신 API와 props 확인&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 설치 명령어 자동 생성&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 커뮤니티 레지스트리 검색&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실제 사용 예시&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;gams&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;개발자: &quot;Data Table에 정렬 기능 추가해줘&quot;

AI (MCP 없이): 학습 데이터 기반으로 추측 &amp;rarr; 구버전 API 사용 &amp;rarr; 에러

AI (MCP 있음): shadcn 레지스트리에서 최신 Data Table 문서 조회
              &amp;rarr; 현재 버전의 정확한 정렬 API 확인
              &amp;rarr; 올바른 구현 코드 생성&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;VS Code에서 설정하기&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;.vscode/mcp.json&amp;nbsp;파일에 추가:&lt;/p&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;{
  &quot;servers&quot;: {
    &quot;shadcn&quot;: {
      &quot;command&quot;: &quot;npx&quot;,
      &quot;args&quot;: [&quot;shadcn@latest&quot;, &quot;mcp&quot;]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;3. Preset &amp;mdash; &quot;디자인 시스템을 한 줄로 전달하는 법&quot;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;AI가 컴포넌트를 올바르게 생성해도, 색상이 프로젝트 테마와 안 맞고, 폰트가 다르고, border-radius가 일관성 없는 경우가 흔하게 일어납니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결: 프리셋 코드&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프리셋은 디자인 시스템 전체를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;짧은 코드 한 줄&lt;/b&gt;로 압축합니다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;npx shadcn@latest init --preset a1Dg5eFl&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 코드 안에 담기는 것:&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 색상 팔레트 (라이트/다크 모드 포함)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 테마 설정&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 아이콘 라이브러리&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 폰트&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- Border radius&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프리셋 만드는 법&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #1a1a1a;&quot; href=&quot;https://ui.shadcn.com/create&quot;&gt;shadcn/create&lt;/a&gt;에 접속&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. 시각적으로 색상, 폰트, 반경 등을 조정&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3. 실제 UI 컴포넌트로 미리보기&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;4. 프리셋 코드 생성 (예:&lt;span&gt;&amp;nbsp;&lt;/span&gt;a1Dg5eFl)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;5. 팀에 공유하거나 AI에게 전달&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;활용 시나리오&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;팀 프로젝트:&lt;/p&gt;
&lt;pre class=&quot;1c&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;&quot;이 프리셋 코드로 프로젝트 초기화해줘: a1Dg5eFl&quot;
&amp;rarr; 모든 팀원이 동일한 디자인 시스템을 즉시 적용&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;AI에게 디자인 시스템 전달:&lt;/p&gt;
&lt;pre class=&quot;1c&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;&quot;이 프리셋 기반으로 대시보드 페이지 만들어줘&quot;
&amp;rarr; AI가 프리셋의 정확한 색상, 폰트, 스타일을 사용하여 일관된 UI 생성&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;CLI v4의 그 외 유용한 기능들&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;--dry-run,&lt;span&gt;&amp;nbsp;&lt;/span&gt;--diff,&lt;span&gt;&amp;nbsp;&lt;/span&gt;--view: 변경 전 확인&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;AI 에이전트가 컴포넌트를 추가하기 전에, 어떤 파일이 어떻게 바뀌는지 미리 볼 수 있어요.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# 실제 변경 없이 미리보기
npx shadcn@latest add button --dry-run

# 기존 코드와 차이점 비교
npx shadcn@latest add button --diff

# 컴포넌트 코드만 보기
npx shadcn@latest add button --view&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이것은 AI가 자율적으로 작업할 때 특히 중요해요. &quot;일단 추가하고 보자&quot;가 아니라,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;확인 후 적용&lt;/b&gt;이 가능해지기 때문이죠.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;shadcn docs: 터미널에서 문서 조회&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;npx shadcn@latest docs combobox&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;브라우저를 열 필요 없이 CLI에서 바로 컴포넌트 문서, 예제 코드, 사용법을 확인할 수 있어요. AI 에이전트도 이 명령어로 필요한 정보를 즉시 가져올 수 있고요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;shadcn info: 프로젝트 진단&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;npx shadcn@latest info&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;현재 프로젝트의 프레임워크, 버전, CSS 변수, 설치된 컴포넌트 등 전체 현황을 출력합니다. AI에게 &quot;내 프로젝트 상태 알려줘&quot;를 자동화한 것이에요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;shadcn init --template: 프로젝트 스캐폴딩&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;autoit&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# Next.js 프로젝트 한 번에 생성
npx shadcn@latest init -t next

# 모노레포 구조
npx shadcn@latest init -t next --monorepo&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Next.js, Vite, Laravel, React Router, Astro, TanStack Start를 지원합니다. 다크 모드 설정도 자동으로 포함되요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;shadcn init --base: 프리미티브 선택&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;npx shadcn@latest init --base radix    # Radix UI 기반
npx shadcn@latest init --base base-ui  # Base UI 기반&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트에 맞는 headless UI 프리미티브를 선택할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;실전 워크플로우: 처음부터 끝까지&lt;/h3&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Step 1: 프로젝트 초기화\&lt;/h4&gt;
&lt;pre class=&quot;autoit&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# 프리셋 포함 Next.js 프로젝트 생성
npx shadcn@latest init -t next --preset a1Dg5eFl&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Step 2: AI 에이전트 연동&lt;/h4&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# Skills 설치 (프로젝트 컨텍스트)
npx skills add shadcn/ui

# MCP 서버 연결 (실시간 문서)
claude mcp add shadcn -- npx shadcn@latest mcp&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Step 3: AI와 함께 개발&lt;/h4&gt;
&lt;pre class=&quot;markdown&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;개발자: &quot;사용자 프로필 페이지를 만들어줘.
        Avatar, Card, Badge, Tabs 컴포넌트를 써서.&quot;

AI 에이전트:
  1. Skills로 프로젝트 설정 확인
  2. MCP로 각 컴포넌트 최신 API 조회
  3. 프리셋 기반 테마에 맞는 코드 생성
  4. --diff로 변경사항 확인 후 적용&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(물론 실제로 X만들어줘. 하진 않죠...)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Step 4: 검증&lt;/h4&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# 컴포넌트가 올바르게 추가되었는지 확인
npx shadcn@latest info&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;왜 이 조합이 좋을까요?&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이전에는 AI에게 UI를 맡기면...?&lt;/p&gt;
&lt;pre class=&quot;1c&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;AI가 코드 생성 &amp;rarr; 에러 발생 &amp;rarr; 수동으로 수정 &amp;rarr; 다시 요청 &amp;rarr; 또 에러
&amp;rarr; 결국 직접 작성 &amp;rarr; &quot;AI 쓰느니 직접 하는 게 낫다&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Skills + MCP + Preset 조합은...!&lt;/p&gt;
&lt;pre class=&quot;gcode&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;AI가 프로젝트 설정 읽음 (Skills)
&amp;rarr; 최신 문서 확인 (MCP)
&amp;rarr; 디자인 시스템에 맞게 생성 (Preset)
&amp;rarr; 변경 전 검증 (--diff)
&amp;rarr; 한 번에 올바른 결과물&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;핵심은 AI에게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;컨텍스트&lt;/b&gt;를 주는 것이에요. 똑똑한 AI에게 정보를 안 주면 추측할 수밖에 없고, 추측은 항상 옳지는 않아요. 정보를 주면 그만큼 정확해지죠. 당연한 이야기지만, shadcn/cli v4는 이 &quot;정보 전달&quot;을 자동화했다는 점에서 의미가 큰 것 같아요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;기존 프로젝트에도 적용 가능한가?&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가능합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;components.json이 존재하는 프로젝트라면 Skills가 자동으로 감지해요. 새 프로젝트를 만들 필요 없이, 기존 shadcn/ui 프로젝트에 바로 적용할 수 있어요.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;# 기존 프로젝트에서
npx skills add shadcn/ui              # Skills 추가
claude mcp add shadcn -- npx shadcn@latest mcp  # MCP 연결
# 끝. 바로 사용 가능.&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;registry:base와 registry:font&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CLI v4에서 레지스트리도 크게 강화되었어요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;registry:base&lt;/b&gt;는 전체 디자인 시스템을 하나의 페이로드로 배포할 수 있게 해요. 컴포넌트, 의존성, CSS 변수, 폰트, 설정 파일을 한 번의 설치로 모두 가져옵니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;registry:font&lt;/b&gt;는 폰트를 1급 레지스트리 타입으로 승격되었어요. 컴포넌트를 설치하듯이 폰트를 설치하고 관리할 수 있어요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;회사나 팀이 자체 디자인 시스템을 만들어&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;사내 레지스트리로 배포&lt;/b&gt;하면, 새 프로젝트를 시작할 때 명령어 하나로 전체 디자인 시스템으로 설정할 수 있어요. AI 에이전트도 이 레지스트리를 참조하여 일관된 코드를 생성할 수 있고요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;shadcn/ui의 철학은 처음부터 &quot;코드를 소유하라(own the code)&quot;였어요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;npm 패키지에 의존하지 말고, 컴포넌트 코드를 직접 가져와서 원하는 대로 수정하라는 것이죠.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CLI v4는 이 철학을 AI 시대에 맞게 확장했다고 볼 수 있어요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이상 shadcn 업데이트 관련 소식을 마칩니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;긴 글 읽어주셔서 감사합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;이 글은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://tech.pxd.co.kr/post/shadcn%EA%B3%BC-%ED%95%A8%EA%BB%98-UI-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%A5%BC-AI-%EC%97%90%EC%9D%B4%EC%A0%84%ED%8A%B8%EC%99%80-%EB%8D%94-%EC%9E%98%EC%93%B0%EB%8A%94-%EB%B0%A9%EB%B2%95-340&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://tech.pxd.co.kr/&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;&amp;nbsp; 에서도 보실 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://ui.shadcn.com/docs/changelog/2026-03-cli-v4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;shadcn/cli v4 공식 체인지로그&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/_46ea277e677b888e0cd13/shadcnui-claude-code-3-settings-that-fix-ai-generated-ui-quality-2dea&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;shadcn/ui + Claude Code: 3 Settings That Fix AI-Generated UI Quality&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ui.shadcn.com/docs/mcp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;shadcn MCP Server 공식 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.logrocket.com/ai-shadcn-components/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;How to use AI to build accurate ShadCN components &amp;mdash; LogRocket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ui.shadcn.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;shadcn/ui&amp;nbsp;공식&amp;nbsp;사이트&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>UX Engineer 이야기</category>
      <author>doworld</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1895</guid>
      <comments>https://story.pxd.co.kr/1895#entry1895comment</comments>
      <pubDate>Mon, 20 Apr 2026 07:50:18 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 기초 간단하게 살펴보기</title>
      <link>https://story.pxd.co.kr/1884</link>
      <description>&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;들어가며&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;저는 마크업과 프론트엔드 작업을 하고 있어서 파이썬을 사용할 일이 없었습니다. 그러다 팀 과제를 하면서 제가 작성한 코드가 제대로 동작하는지 테스트해보고 싶어졌고, 방법을 찾다가 파이썬을 알게 되었습니다. 처음엔 낯선 언어여서 AI의 도움을 받아 코드를 작성하고 테스트를 해봤는데 결과를 바로바로 확인할 수 있어서 정말 편하더라고요. 그러면서 파이썬이 궁금해져서 알아보기 시작했습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;작업하면서 저처럼 스쳐 지나가듯 파이썬을 경험해 보신 분들이나, 저처럼 아예 몰랐던 분들께 조금이나마 도움이 될까 싶어 공부한 내용을 정리해봤습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;(참고로 저는 &quot;100 Days of Code: The Complete Python Pro Bootcamp&quot;라는 강의를 듣고 있습니다.)&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;파이썬 설치하기&lt;/b&gt;&lt;/h3&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;코드를 작성하려면 먼저 파이썬을 설치해야 하겠죠?&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;Mac을 쓰시는 분이라면 이미 파이썬이 깔려 있을 수 있습니다. 터미널을 열어서 아래 명령어를 입력했을 때,&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;python3 --version&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;Python 3.x.x&lt;span&gt;&amp;nbsp;&lt;/span&gt;같은 버전 정보가 나오면 이미 설치되어 있는 겁니다. 나오지 않는다면 아래 단계를 따라 설치하면 됩니다.&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;설치 방법&lt;/b&gt;&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;a style=&quot;color: #1a1a1a;&quot; href=&quot;https://www.python.org/downloads/&quot;&gt;python.org&lt;/a&gt;에 접속해서 운영체제에 맞는 최신 버전을 다운로드하면 됩니다. 설치 과정은 일반적인 프로그램 설치와 동일합니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;Windows를 사용하시는 분은 설치할 때&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&quot;Add Python to PATH&quot;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;체크박스가 보이면 꼭 체크해 주세요. 이걸 빠뜨리면 터미널에서 파이썬을 실행할 수 없습니다.&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;코드 실행 해보기&lt;/b&gt;&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;에디터에서 파일을 하나 만들고 (예:&amp;nbsp;hello.py) 아래 코드를 작성한 뒤에&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;b&gt;print(&quot;Hello World&quot;)&lt;/b&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;터미널에서 다음과 같이 실행하면,&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;b&gt;python3 hello.py&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;Hello World가 출력되는 것을 확인하실 수 있을 것입니다.&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;파이썬 시작하기&lt;/b&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. print와 input&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;print()&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;먼저 살펴볼 건 print()입니다. 코드를 작성하다 보면 &quot;이 값이 지금 뭐지?&quot;, &quot;여기까지 제대로 실행된 건가?&quot; 같은 순간이 자주 오는데, 그때 print()로 값을 출력해 보면 바로 확인할 수 있습니다. 결과를 눈으로 확인하는 가장 기본적인 방법이라 제일 먼저 알아두면 좋습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre id=&quot;code_1773895695245&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(&quot;Hello World&quot;)​&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;이렇게 쓰면 화면에&lt;span&gt;&amp;nbsp;&lt;/span&gt;Hello World가 출력됩니다.&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;input()&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;input()은 프로그램 실행 중에 사용자로부터 값을 입력받는 함수입니다. 예를 들어 이름을 물어보고, 그 이름을 활용해서 인사를 출력하는 식으로 쓸 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;name = input(&quot;이름이 뭐예요? &quot;)
print(&quot;안녕하세요, &quot; + name + &quot;!&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;여기서&amp;nbsp;name은&amp;nbsp;&lt;b&gt;변수&lt;/b&gt;인데, 입력받은 값을 담아두는 역할을 합니다. 나중에&amp;nbsp;name이라고 쓰면 그 안에 저장된 값을 꺼내 쓸 수 있습니다.&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 타입과 연산&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;타입&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;파이썬에서 다루는 데이터에는 여러&amp;nbsp;&lt;b&gt;타입(종류)&lt;/b&gt;이 있습니다. 숫자끼리 계산해야 할 때도 있고, 글자를 다뤄야 할 때도 있는데, 파이썬은 이걸 타입으로 구분합니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;타입&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;설명&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;예시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;문자열(String)&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;글자들의 모음&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;&quot;Hello&quot;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;안녕&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;정수(Integer)&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;소수점 없는 숫자&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;1,&lt;span&gt;&amp;nbsp;&lt;/span&gt;42,&lt;span&gt;&amp;nbsp;&lt;/span&gt;100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;실수(Float)&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;소수점 있는 숫자&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;3.14,&lt;span&gt;&amp;nbsp;&lt;/span&gt;0.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;불린(Boolean)&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;참 또는 거짓&lt;/td&gt;
&lt;td style=&quot;background-color: #f2f2f2;&quot;&gt;True,&lt;span&gt;&amp;nbsp;&lt;/span&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;지금 다루고 있는 데이터가 어떤 타입인지 확인하고 싶을 때는&amp;nbsp;type()을 사용하면 됩니다. 뭔가 타입을 보면 자바스크립트 같기도, 자바 같기도...&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;print(type(&quot;Hello&quot;)) # &amp;lt;class 'str'&amp;gt;
print(type(123)) # &amp;lt;class 'int'&amp;gt;
print(type(3.14)) # &amp;lt;class 'float'&amp;gt;
print(type(True)) # &amp;lt;class 'bool'&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;문자열 다루기&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;저희에겐 너무 익숙한 문자열인데요. 스크립트와 사용법이 유사합니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;&quot;Hello&quot;[0] # &quot;H&quot; - 첫 번째 글자
&quot;Hello&quot;[-1] # &quot;o&quot; - 마지막 글자
len(&quot;Hello&quot;) # 5 - 글자 수&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;예시 코드를 보면&lt;span&gt;&amp;nbsp;&lt;/span&gt;len()이라는 내장 함수가 보이시나요? 자바스크립트의&amp;nbsp;.length와 같습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;그리고 문자열을 변환하는 메서드도 있는데요. 보시면 메서드들이 익숙하실 것 같습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;&quot;hello&quot;.upper() # &quot;HELLO&quot; - 대문자로
&quot;HELLO&quot;.lower() # &quot;hello&quot; - 소문자로
&quot; hi &quot;.strip() # &quot;hi&quot; - 앞뒤 공백 제거&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;.lower()는 위에 설명한&amp;nbsp;input()을 사용하여 사용자 입력을 받을 때 유용합니다. 예를 들어 &quot;yes&quot;를 입력받아야 하는데 사용자가 &quot;YES&quot;나 &quot;Yes&quot;라고 입력할 수도 있잖아요. 이럴 때&lt;span&gt;&amp;nbsp;&lt;/span&gt;.lower()로 소문자로 통일하면 모든 경우를 처리할 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;answer = input(&quot;계속하시겠습니까? (yes/no) &quot;).lower()
if answer == &quot;yes&quot;:
    print(&quot;계속합니다!&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;타입 변환하기&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;문자를 숫자로, 숫자를 문자로 바꿀 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;hsp&quot;&gt;&lt;code&gt;str(123) # &quot;123&quot; - 숫자를 문자로
int(&quot;456&quot;) # 456 - 문자를 정수로
float(&quot;3.14&quot;) # 3.14 - 문자를 실수로&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;이게 왜 필요하냐면...&amp;nbsp;input()으로 받은 건&amp;nbsp;&lt;b&gt;무조건 문자열&lt;/b&gt;이기 때문입니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;예를 들어 숫자&amp;nbsp;123을 입력해도&amp;nbsp;&quot;123&quot;처럼 문자로 들어옵니다. 그래서 계산하려면&amp;nbsp;int()로 바꿔줘야 합니다.&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;연산자&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;파이썬에서는 기본적인 사칙연산 외에도 다양한 연산자를 지원합니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(3 + 5) # 8 (더하기)
print(7 - 4) # 3 (빼기)
print(3 * 2) # 6 (곱하기)
print(6 / 3) # 2.0 (나누기 - 항상 소수점이 나옵니다!)
print(6 // 3) # 2 (나누기 - 정수만)
print(2 ** 3) # 8 (제곱 - 2의 3승)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;참고로&amp;nbsp;/로 나누면&amp;nbsp;&lt;b&gt;무조건 소수점&lt;/b&gt;이 나옵니다.&amp;nbsp;6 / 3을 해도&amp;nbsp;2.0이 나옵니다. 정수로 받고 싶으면&amp;nbsp;//를 써야 합니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;그 외 유용한 함수들&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;round(3.14159, 2) # 3.14 (소수점 둘째 자리까지 반올림)
abs(-5) # 5 (절대값)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;f-string&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;변수 값을 문자열 안에 넣고 싶을 때&amp;nbsp;+로 일일이 연결하면 코드가 길어지고 읽기도 불편합니다. f-string을 쓰면&amp;nbsp;f&quot;...&quot;&lt;span&gt;&amp;nbsp;&lt;/span&gt;안에&lt;span&gt;&amp;nbsp;&lt;/span&gt;{변수}를 바로 넣을 수 있어서 훨씬 깔끔합니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;${}&amp;nbsp;와 같은 코드라고 보시면 될 것 같아요. (저는 이 부분이 조금 신기했습니다 ㅎ)&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;name = &quot;혜름&quot;
age = 25
print(f&quot;제 이름은 {name}이고, 나이는 {age}살입니다.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 조건문&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;if, elif, else&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;코드를 작성하다 보면 특정 조건에 따라 다른 동작을 하게 만들어야 할 때가 있습니다. 예를 들어 사용자의 입력값에 따라 다른 결과를 보여준다거나, 특정 값이 기준을 넘는지 확인하는 경우입니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;height = int(input(&quot;키가 몇 cm예요? &quot;))

if height &amp;gt;= 120:
    print(&quot;놀이기구 탑승 가능&quot;)
else:
    print(&quot;놀이기구 탑승 불가&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;if&lt;span&gt;&amp;nbsp;&lt;/span&gt;다음에 조건을 쓰고, 그게 맞으면(참이면) 아래 코드가 실행됩니다. 아니면&lt;span&gt;&amp;nbsp;&lt;/span&gt;else&amp;nbsp;쪽이 실행됩니다&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;조건이 여러 개면&amp;nbsp;elif를 씁니다. (자바스크립트에 비해 축약이 된 느낌이에요.)&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;age = int(input(&quot;나이가 몇 살이에요? &quot;))

if age &amp;lt; 20:
    print(&quot;미성년자입니다&quot;)
elif age &amp;lt; 65:
    print(&quot;성인입니다&quot;)
else:
    print(&quot;경로 우대 대상입니다&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;파이썬에서는&amp;nbsp;&lt;b&gt;들여쓰기&lt;/b&gt;가 정말 중요합니다. 해당 코드가 어디에 속하는지를 들여쓰기로 구분하기 때문에, 꼭 확인해주어야 할 부분이에요. (중요!!)&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 리스트와 랜덤&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;리스트&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;여러 개의 데이터를 하나의 변수에 묶어서 관리하고 싶을 때 리스트를 사용합니다. 예를 들어 과일 이름 세 개를 각각 변수로 만들면 번거롭지만, 리스트로 묶으면 하나로 관리할 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;hsp&quot;&gt;&lt;code&gt;fruits = [&quot;사과&quot;, &quot;배&quot;, &quot;포도&quot;]
print(fruits[0]) # &quot;사과&quot; - 첫 번째
print(fruits[-1]) # &quot;포도&quot; - 마지막&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;[0]처럼&amp;nbsp;&lt;b&gt;인덱스&lt;/b&gt;로 특정 위치의 값을 꺼낼 수 있고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;-1을 쓰면 마지막 값을 바로 가져올 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;hsp&quot;&gt;&lt;code&gt;fruits.append(&quot;딸기&quot;) # 마지막에 추가
print(fruits) # [&quot;사과&quot;, &quot;배&quot;, &quot;포도&quot;, &quot;딸기&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;리스트에서 특정 값의 위치를 찾을 수도 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;fruits = [&quot;사과&quot;, &quot;배&quot;, &quot;포도&quot;]
fruits.index(&quot;배&quot;) # 1 - &quot;배&quot;가 몇 번째에 있는지&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;이건 암호화 같은 걸 만들 때 유용합니다. 알파벳 리스트에서 특정 글자의 위치를 찾고, 그 위치를 이동시켜서 다른 글자로 바꾸는 식으로요.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;리스트 안에 리스트를 넣을 수도 있습니다 (중첩 리스트).&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;matrix = [
    [1, 2, 3],
    [4, 5, 6]
]
print(matrix[0][1]) # 2 - 첫 번째 리스트의 두 번째 값&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;random 모듈&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;무작위 값이 필요할 때 사용하는 모듈입니다. 비밀번호 생성기처럼 랜덤한 값을 뽑아야 하거나, 리스트의 순서를 섞어야 할 때 유용합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;import random을 먼저 써야 사용할 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;import에 대한 부분은 8.모듈 쪽에 설명해두었습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;import random

random.randint(1, 10) # 1~10 중 무작위 정수
random.random() # 0~1 사이 무작위 실수
random.choice(fruits) # 리스트에서 무작위로 하나 선택
random.shuffle(fruits) # 리스트 순서를 섞기&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. for와 while&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;for&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;(아시는 것이겠지만...) 같은 작업을 여러 번 해야 할 때 일일이 코드를 반복해서 쓰면 비효율적입니다.&amp;nbsp;for를 쓰면 리스트에 있는 값들을 하나씩 꺼내면서 같은 작업을 반복할 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;fruits = [&quot;사과&quot;, &quot;배&quot;, &quot;포도&quot;]

for fruit in fruits:
    print(fruit)
# 사과
# 배
# 포도&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;range()와 같이 쓰면 숫자로 반복할 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;for i in range(5):
    print(i)  # 0, 1, 2, 3, 4

for i in range(1, 11):
    print(i)  # 1부터 10까지

for i in range(1, 11, 2):
    print(i)  # 1, 3, 5, 7, 9 (2씩 증가)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;while&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;for는 반복 횟수가 정해져 있을 때 쓰지만,&amp;nbsp;while은 특정 조건이 만족되는 동안 계속 반복합니다. 예를 들어 사용자가 &quot;종료&quot;를 입력할 때까지 프로그램을 계속 실행시키고 싶을 때 사용할 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;count = 0
while count &amp;lt; 5:
    print(count)
    count += 1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;다만 조건이 영원히 참이면&amp;nbsp;&lt;b&gt;무한 반복&lt;/b&gt;에 빠지기 때문에, 반복이 끝나는 조건을 잘 설정해야 합니다.&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. 함수&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;함수 정의하기&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;같은 코드를 여러 곳에서 반복해서 쓰고 있다면, 함수로 만들어두면 한 번 정의해놓고 필요할 때마다 호출해서 쓸 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def greet():
    print(&quot;안녕하세요!&quot;)
    print(&quot;반갑습니다!&quot;)

greet()  # 함수 호출
greet()  # 또 호출 가능&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;매개변수&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;함수를 호출할 때 값을 넘겨주면, 함수 안에서 그 값을 사용할 수 있습니다. 이때 넘겨주는 값을&amp;nbsp;&lt;b&gt;매개변수&lt;/b&gt;라고 합니다. (어디에나 동일한 개념이죠.)&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def greet(name):
    print(f&quot;안녕하세요, {name}님!&quot;)

greet(&quot;혜름&quot;)  # &quot;안녕하세요, 혜름님!&quot;
greet(&quot;연주&quot;)  # &quot;안녕하세요, 연주님!&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;매개변수는 여러 개도 가능합니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def greet(name, time):
    print(f&quot;{time}이에요, {name}님!&quot;)

# 위치로 구분 (positional arguments)
greet(&quot;혜름&quot;, &quot;아침&quot;)

# 이름으로 지정 (keyword arguments)
greet(time=&quot;저녁&quot;, name=&quot;연주&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;return&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;함수가 단순히&lt;span&gt;&amp;nbsp;&lt;/span&gt;print()로 출력만 하는 게 아니라, 처리한 결과를 돌려줘야 할 때가 있습니다. 그때&lt;span&gt;&amp;nbsp;&lt;/span&gt;return을 사용합니다. 돌려받은 값은 변수에 저장해서 다른 곳에서 활용할 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;def add(a, b):
    return a + b

result = add(3, 5)
print(result)  # 8&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;7. 딕셔너리&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Key-Value 쌍&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;리스트는 데이터를 순서대로 저장하지만, 데이터에 의미 있는 이름을 붙여서 관리하고 싶을 때는 딕셔너리가 더 적합합니다. 딕셔너리는&amp;nbsp;&lt;b&gt;키(key)&lt;/b&gt;와&amp;nbsp;&lt;b&gt;값(value)&lt;/b&gt;을 쌍으로 저장합니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;자바스크립트와 명칭이 다를 뿐, 오브젝트와 같다고 이해하시면 될 것 같아요.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;hsp&quot;&gt;&lt;code&gt;student = {
    &quot;이름&quot;: &quot;혜름&quot;,
    &quot;나이&quot;: 20,
    &quot;성적&quot;: 85
}

print(student[&quot;이름&quot;])  # &quot;혜름&quot;
print(student[&quot;나이&quot;])  # 20&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;리스트는&lt;span&gt;&amp;nbsp;&lt;/span&gt;[0],&lt;span&gt;&amp;nbsp;&lt;/span&gt;[1]처럼 순서로 접근하지만, 딕셔너리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;[&quot;이름&quot;]처럼 키로 접근합니다. 값을 추가하거나 수정하는 것도 간단합니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;student[&quot;주소&quot;] = &quot;서울&quot;  # 추가
student[&quot;나이&quot;] = 21      # 수정&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;딕셔너리 안에 딕셔너리를 넣을 수도 있습니다 (중첩 딕셔너리).&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;users = {
    &quot;혜름&quot;: {
        &quot;나이&quot;: 20,
        &quot;취미&quot;: [&quot;필라테스&quot;, &quot;게임&quot;]
    },
    &quot;연주&quot;: {
        &quot;나이&quot;: 22,
        &quot;취미&quot;: [&quot;필라테스&quot;]
    }
}
print(users[&quot;혜름&quot;][&quot;나이&quot;])  # 20
print(users[&quot;연주&quot;][&quot;취미&quot;][0])  # &quot;필라테스&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;딕셔너리 순회하기&lt;/h4&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;code&gt;for key in student:
    print(f&quot;{key}: {student[key]}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;8. 모듈&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;import&lt;/h4&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;파이썬에는 이미 만들어진 기능들이 많은데, 필요할 때&amp;nbsp;import로 가져다 쓸 수 있습니다. 앞에서 살펴본&amp;nbsp;random도 이런 식으로 불러온 모듈입니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;import random
random.randint(1, 10)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;파이썬이 기본으로 제공하는 모듈 외에, 직접 만든 파일도 모듈로 사용할 수 있습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;pre class=&quot;monkey&quot;&gt;&lt;code&gt;# my_data.py 파일
pi = 3.14159

# main.py 파일
import my_data
print(my_data.pi)  # 3.14159

# 또는 특정 변수/함수만 가져오기
from my_data import pi
print(pi)  # 3.14159&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마치며&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;이번 글에서는 print, input부터 시작해서 데이터 타입, 조건문, 반복문, 함수, 딕셔너리, 모듈까지 파이썬의 기초적인 문법들을 살펴봤습니다. 공부를 계속하면서 새로 알게 되는 내용이 있으면 이어서 정리해보겠습니다.&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;부족한 글 읽어주셔서 감사합니다. &amp;zwj;♀️&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;그럼 안녕히&amp;hellip; &lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;이 글은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://tech.pxd.co.kr/post/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EA%B8%B0%EC%B4%88-%EA%B0%84%EB%8B%A8%ED%95%98%EA%B2%8C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0-335&quot;&gt;https://tech.pxd.co.kr/&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;&amp;nbsp; 에서도 보실 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;b&gt;참고 자료&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #1a1a1a;&quot; href=&quot;https://www.udemy.com/course/100-days-of-code/&quot;&gt;100 Days of Code: The Complete Python Pro Bootcamp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description>
      <category>UX Engineer 이야기</category>
      <author>ny.back</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1884</guid>
      <comments>https://story.pxd.co.kr/1884#entry1884comment</comments>
      <pubDate>Mon, 13 Apr 2026 07:50:41 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;AI에게 우리를 소개하고 싶었습니다&amp;quot;, UX 전문 기업이 GEO 서비스를 만든 이유</title>
      <link>https://story.pxd.co.kr/1892</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시작은 하나의 질문이었습니다&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;pxd는 대한민국에서 UX/UI 분야를 대표하는 사용자경험(UX) 디자인 전문 기업입니다. AI에게 &lt;i&gt;&lt;b&gt;&quot;대한민국에서 UX/UI 컨설팅 잘하는 업체 추천해줘&quot;&lt;/b&gt;&lt;/i&gt;라고 물으면, pxd는 빠지지 않고 언급됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그런데 한 가지 의문이 생겼습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;화면 UI 개발을 잘하는 회사는?&quot; &amp;mdash; pxd, 언급 없음.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;프론트엔드 개발을 잘하는 회사는?&quot; &amp;mdash; pxd, 역시 언급 없음.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;2002년에 설립된 &lt;/span&gt;pxd는 2019년부터 UX 컨설팅 및 리서치, 설계, 디자인 뿐만 아니라 UI개발 및 프론트엔드개발까지 수행하는 회사가 되었습니다. 그런데 AI는 그 사실을 모르고 있었습니다. 왜일까요?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 질문을 파고들면서 저희는 &lt;b&gt;GEO(Generative Engine Optimization)와 AIEO(AI Engine Optimization)&lt;/b&gt;라는 영역을 발견했습니다. AI에게 잘 인용되려면 단순히 좋은 콘텐츠를 만드는 것만으로는 부족하다는 것, AI가 이해하고 신뢰할 수 있는 구조로 콘텐츠를 제공해야 한다는 것을 알게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 생각했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;우리만 이 문제를 겪고 있는 건 아닐 거야. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;좋은 서비스나 상품을 제공하고 있거나 만들고도 AI에게 제대로 소개되지 못하는 곳이 얼마나 많을까? &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그렇다면, AI에게 잘 인용될 수 있는 방법을 알려주자.&quot;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이것이 GEONIQ(지오닉)의 시작이었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;369&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DZ6Dd/dJMcadIeQp4/Gm9pFtLgXmxBvumrNqSS5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DZ6Dd/dJMcadIeQp4/Gm9pFtLgXmxBvumrNqSS5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DZ6Dd/dJMcadIeQp4/Gm9pFtLgXmxBvumrNqSS5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDZ6Dd%2FdJMcadIeQp4%2FGm9pFtLgXmxBvumrNqSS5K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;369&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;369&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 2025년 11월, 그 고민을 담아 &lt;/span&gt;&lt;a href=&quot;https://story.pxd.co.kr/1862&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&quot;AI 검색 시대의 새로운 기준, GEONIQ(지오닉)을 소개합니다&quot;&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #000000;&quot;&gt;라는 글과 함께 베타 서비스를 세상에 공개했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그로부터 약 4개월. 수많은 피드백과 개선을 거쳐, &lt;b&gt;오늘 GEONIQ이 정식 서비스로 오픈합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;베타 오픈 전 진행한 예비 사용자 조사에서 다음과 같은 피드백들을 받았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;국내에 GEO(AIEO)까지 포함한 통합 SEO 진단 도구가 없었는데, 한국어 환경에 맞게 최적화해 제공하는 점이 좋습니다.&quot; &amp;mdash; 6년 경력 스타트업 퍼포먼스 마케터&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;유사한 국내 서비스와 비교했을 때, UI&amp;middot;UX 완성도와 리포트 품질이 압도적으로 높습니다.&quot; &amp;mdash; 10년 경력 대기업 퍼포먼스 마케터&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 목소리들이 정식 오픈을 준비하면서 저희가 가장 집중한 방향이기도 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;베타에서 정식 오픈까지, 지오닉은 어떻게 달라졌을까?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #434343;&quot;&gt;스스로를 진단하며 성장했습니다&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-02 오전 11.54.13.png&quot; data-origin-width=&quot;2710&quot; data-origin-height=&quot;916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KlA5j/dJMcahcPI6l/olEafdWKK8p5bgkV0Y6T3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KlA5j/dJMcahcPI6l/olEafdWKK8p5bgkV0Y6T3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KlA5j/dJMcahcPI6l/olEafdWKK8p5bgkV0Y6T3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKlA5j%2FdJMcahcPI6l%2FolEafdWKK8p5bgkV0Y6T3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2710&quot; height=&quot;916&quot; data-filename=&quot;스크린샷 2026-04-02 오전 11.54.13.png&quot; data-origin-width=&quot;2710&quot; data-origin-height=&quot;916&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정식 오픈 전, 먼저 우리 자신부터 진단했습니다. geoniq.ai를 GEONIQ으로 지속적으로 분석하고, 개선 가이드를 따라 고치고, 다시 진단하는 과정을 반복했습니다. 그 결과를 숫자로 보여드립니다.&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;베타 (2025.11)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;현재 (2026.04)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;종합 점수&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;60점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;98점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기술 최적화&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;40점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;콘텐츠 품질&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;85점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 및 사용자 경험&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;콘텐츠 신뢰성&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;26점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;77점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 및 정책 준수&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;44점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;95점&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정상 항목&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;37개&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;62개&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;조치 필요 항목&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;24개&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0개&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;b&gt;&lt;/b&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;진단하고, 가이드를 따라 고치고, 다시 진단하는 과정을 반복하며 조치가 필요한 항목을 모두 해결했습니다. 저희가 만든 도구로 저희 서비스를 직접 개선한 것, 이것이 실 검증된&amp;nbsp; GEONIQ의 가치입니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI가 GEONIQ을 알아보기 시작했습니다&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z2M9x/dJMcaipis18/yxqttsflBzLq9RWhImCda0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z2M9x/dJMcaipis18/yxqttsflBzLq9RWhImCda0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z2M9x/dJMcaipis18/yxqttsflBzLq9RWhImCda0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ2M9x%2FdJMcaipis18%2FyxqttsflBzLq9RWhImCda0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;838&quot; height=&quot;58&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;58&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GEONIQ이 SEO/GEO 개선에 실제 효과가 있는지 확인하기 위해 &lt;b&gt;&lt;i&gt;&quot;SEO, GEO(AIEO) 검증하는 국내 사이트 추천해줘&quot;&lt;/i&gt;&lt;/b&gt;라는 질문을 다양한 AI에게 직접 던져봤습니다. 베타 초기에는 어떤 AI도 GEONIQ을 언급하지 않았습니다. 하지만 시간이 지나면서 변화가 시작됐습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(아래 결과는 사용자 편향을 최소화하기 위해 각 플랫폼에서 신규 계정을 생성한 후, &lt;b&gt;&amp;ldquo;SEO, GEO(AIEO) 검증이 가능한 국내 사이트를 추천해줘&amp;rdquo;&lt;/b&gt;라는 동일한 질문을 한 달 간격으로 반복하여 얻은 것입니다.)&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #434343;&quot;&gt;ChatGPT의 답변 (2026년 1월)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-02 오전 11.57.44.png&quot; data-origin-width=&quot;1598&quot; data-origin-height=&quot;1104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/efkLoS/dJMcaf0m6g4/7Qwfw7bYhKnMgIlkNBZvu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/efkLoS/dJMcaf0m6g4/7Qwfw7bYhKnMgIlkNBZvu1/img.png&quot; data-alt=&quot;gpt 답변 내용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/efkLoS/dJMcaf0m6g4/7Qwfw7bYhKnMgIlkNBZvu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FefkLoS%2FdJMcaf0m6g4%2F7Qwfw7bYhKnMgIlkNBZvu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1598&quot; height=&quot;1104&quot; data-filename=&quot;스크린샷 2026-04-02 오전 11.57.44.png&quot; data-origin-width=&quot;1598&quot; data-origin-height=&quot;1104&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;gpt 답변 내용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ChatGPT는 GEONIQ을 국내 SEO+GEO 도구 추천 목록의 첫 번째로 소개했습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #434343;&quot;&gt;Perplexity의 답변 (2026년 2월)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-02 오전 11.56.38.png&quot; data-origin-width=&quot;1464&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yhP4c/dJMcaduF94i/1PaKJWrcPpVqX4RedWXvo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yhP4c/dJMcaduF94i/1PaKJWrcPpVqX4RedWXvo0/img.png&quot; data-alt=&quot;perplexity 답변 내용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yhP4c/dJMcaduF94i/1PaKJWrcPpVqX4RedWXvo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyhP4c%2FdJMcaduF94i%2F1PaKJWrcPpVqX4RedWXvo0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1464&quot; height=&quot;506&quot; data-filename=&quot;스크린샷 2026-04-02 오전 11.56.38.png&quot; data-origin-width=&quot;1464&quot; data-origin-height=&quot;506&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;perplexity 답변 내용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Perplexity 역시 GEO 진단 도구를 추천하면서 GEONIQ을 가장 먼저 언급했습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #434343;&quot;&gt;Gemini의 답변 (2026년 3월)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x460x/dJMcahqn1In/k4zUbjLFK996F3SVLNcVk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x460x/dJMcahqn1In/k4zUbjLFK996F3SVLNcVk0/img.png&quot; data-alt=&quot;gemini 답변 내용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x460x/dJMcahqn1In/k4zUbjLFK996F3SVLNcVk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx460x%2FdJMcahqn1In%2Fk4zUbjLFK996F3SVLNcVk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1430&quot; height=&quot;766&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;766&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;gemini 답변 내용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini 또한 GEONIQ을 국내 GEO/AIEO 특화 진단 솔루션으로 첫 번째로 소개했습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;AI에게 우리를 소개하고 싶다&quot;는 바람에서 시작한 서비스가, 이제 AI로부터 직접 추천받고 있습니다. GEONIQ이 추구하는 가치가 실제로 작동하고 있음을 보여주는 결과입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정식 오픈, 새로운 기능과 더 고도화된 분석&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-04-02 오후 2.38.32.png&quot; data-origin-width=&quot;3054&quot; data-origin-height=&quot;2438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXpD7q/dJMcafTDWJU/ANG5pvMKgykjg4lmqTDFX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXpD7q/dJMcafTDWJU/ANG5pvMKgykjg4lmqTDFX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXpD7q/dJMcafTDWJU/ANG5pvMKgykjg4lmqTDFX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXpD7q%2FdJMcafTDWJU%2FANG5pvMKgykjg4lmqTDFX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3054&quot; height=&quot;2438&quot; data-filename=&quot;스크린샷 2026-04-02 오후 2.38.32.png&quot; data-origin-width=&quot;3054&quot; data-origin-height=&quot;2438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;베타에서 정식 오픈까지, GEONIQ은 단순 수정이나 개선 가이드 제시를 넘어 서비스 전반을 한 단계 끌어올렸습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #434343;&quot;&gt;1. 마이페이지: 내 사이트를 체계적으로 관리&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;453&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rLLtr/dJMcaax2iHO/8bWeg0Dx20teFnx6K7NmhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rLLtr/dJMcaax2iHO/8bWeg0Dx20teFnx6K7NmhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rLLtr/dJMcaax2iHO/8bWeg0Dx20teFnx6K7NmhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrLLtr%2FdJMcaax2iHO%2F8bWeg0Dx20teFnx6K7NmhK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;453&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;베타에서는 분석 결과를 한 번 보고 끝이었습니다. 이제는 다릅니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;대시보드:&lt;/b&gt; 주요 사이트를 고정하고 점수 변화를 한눈에 추적합니다. 이전 대비 몇 점이 올랐는지, 어떤 항목이 개선됐는지 시각적으로 확인할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;점수 추이 차트:&lt;/b&gt; 시간에 따른 점수 변화를 라인 차트로 시각화합니다. 개선 작업의 효과를 데이터로 확인하세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사이트 비교:&lt;/b&gt; 경쟁 사이트와 나란히 비교합니다. 카테고리별 점수를 바 차트로 비교해 우리 사이트의 강점과 약점을 파악할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;분석 이력 관리:&lt;/b&gt; 모든 분석 기록이 사이트별로 그룹핑되어 저장됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #434343;&quot;&gt;2. AI 개선 가이드 강화&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U1E1n/dJMcaax2iIB/HZynW6gTlEDWQDDueQxcj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U1E1n/dJMcaax2iIB/HZynW6gTlEDWQDDueQxcj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U1E1n/dJMcaax2iIB/HZynW6gTlEDWQDDueQxcj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU1E1n%2FdJMcaax2iIB%2FHZynW6gTlEDWQDDueQxcj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;517&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;517&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;베타에서도 제공하던 AI 기반 개선 제안이 더욱 정밀해졌습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;As-Is / To-Be 코드 비교:&lt;/b&gt; 현재 코드와 개선된 코드를 나란히 보여줍니다. 무엇을 어떻게 고쳐야 하는지 개발자가 아니어도 이해하고 수정할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;연관 검사 안내:&lt;/b&gt; &quot;이 항목을 개선하려면 먼저 이 항목을 확인하세요&quot;와 같은 선행 개선 조건을 안내합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #434343;&quot;&gt;3. PDF 리포트: 공유하고, 보고하고, 실행하는 보고서&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dsPwdN/dJMcaaY407V/KKKPiYnwqrD50TJGqeX4H0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dsPwdN/dJMcaaY407V/KKKPiYnwqrD50TJGqeX4H0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dsPwdN/dJMcaaY407V/KKKPiYnwqrD50TJGqeX4H0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdsPwdN%2FdJMcaaY407V%2FKKKPiYnwqrD50TJGqeX4H0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;370&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;진단 결과를 체계적인 PDF 보고서로 다운로드할 수 있습니다. 사내 보고나 고객 제안서에 바로 활용하세요.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;즉시 프린트 가능한 보고서:&lt;/b&gt; 종합 점수, 카테고리별 분석, 개선 제안이 담긴 체계적인 PDF 보고서를 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #434343;&quot;&gt;4. 팀 협업: 같은 데이터를 함께 보며 함께 개선&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;혼자만 보는 리포트가 아니라, 팀과 함께 보는 리포트가 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;팀원을 이메일로 초대하여 분석 결과를 공유&lt;/li&gt;
&lt;li&gt;마케터, 개발자, 기획자 등이 같은 데이터를 보며 개선 방향을 논의&lt;/li&gt;
&lt;li&gt;외부 이해관계자에게도 URL로 간편하게 전달 공유 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #434343;&quot;&gt;5. 진단 정확도 &amp;amp; 성능 개선&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GEONIQ만의 체크리스트 항목의 검증 로직을 지속적으로 고도화&lt;/li&gt;
&lt;li&gt;분석 속도 최적화 (병렬 처리, 캐싱 전략 개선)&lt;/li&gt;
&lt;li&gt;SPA/CSR 사이트 분석 정확도 향상&lt;/li&gt;
&lt;li&gt;리포트 UI/UX 전면 개편으로 가독성 향상&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플랜 안내&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GEONIQ은 체험부터 기업 맞춤까지, 운영 규모에 맞는 4가지 플랜을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Starter &amp;mdash; GEONIQ을 처음 체험해보고 싶다면&lt;/li&gt;
&lt;li&gt;Basic &amp;mdash; 개인&amp;middot;실무 중심의 일반 운영&lt;/li&gt;
&lt;li&gt;Pro &amp;mdash; 전문가&amp;middot;팀 중심의 확장 운영&lt;/li&gt;
&lt;li&gt;Enterprise &amp;mdash; 기관&amp;middot;기업 전용 맞춤형 통합 플랜&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무료 회원도 진단 기능을 이용할 수 있습니다. 단, 일부 제한이 있을 수 있으며, 유료 플랜 사용자에게 전체 개선 가이드, 대시보드, 사이트 비교, 팀 공유 기능 등이 제공됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 플랜의 상세 내용은 &lt;a href=&quot;https://www.geoniq.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;geoniq.ai&lt;/a&gt;에서 확인하세요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앞으로의 GEONIQ&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정식 오픈은 끝이 아닌, 새로운 시작이라 생각합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;i&gt;&quot;AI에게 우리를 소개하고 싶다&quot;&lt;/i&gt;&lt;/b&gt;는 하나의 질문에서 출발한 GEONIQ은, 이제 모든 서비스가 다양한 AI 엔진들에게 발견되고 신뢰받을 수 있도록 돕는 도구로 성장하려고 합니다. AI 검색 환경의 변화에 맞춰 분석 항목과 로직을 지속적으로 업데이트 하며 고도화해 나갈 예정입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google의 AI Overviews가 확대되고, ChatGPT와 Perplexity의 검색 기능이 고도화되면서, &quot;AI에게 이해되고 인용되는 콘텐츠&quot;의 중요성은 앞으로 더 커질 것입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GEONIQ은 이 변화의 속도를 따라가며, 여러분의 사이트가 어디에서든 인용되고 신뢰받을 수 있도록 돕겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지금 시작하세요&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;URL을 입력하는 것만으로 진단을 시작할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;검색엔진과 생성형 AI가 이해하고 신뢰하는 콘텐츠 구조, 사람이 신뢰하는 경험, 그 연결의 기준을 GEONIQ이 제시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러분의 사이트는 지금, AI에게 어떻게 보이고 있나요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>pxd AI툴 이야기</category>
      <author>GEONIQ</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1892</guid>
      <comments>https://story.pxd.co.kr/1892#entry1892comment</comments>
      <pubDate>Tue, 7 Apr 2026 17:12:27 +0900</pubDate>
    </item>
    <item>
      <title>Next.js App Router에서 프록시 레이어를 둔 이유</title>
      <link>https://story.pxd.co.kr/1889</link>
      <description>&lt;h1 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;들어가며&lt;/h1&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #1a1a1a;&quot; href=&quot;https://www.geoniq.ai/&quot;&gt;GEONIQ&lt;/a&gt;(SEO/GEO(AI Engine Optimization)를 분석해주는 서비스) 개발에 저도 같이 참여하게 되었는데 프론트엔드는 Next.js의 App Router, 백엔드는 FastAPI로 구성되어 있어 프론트엔드에서 백엔드 API를 호출할 일이 많았습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;처음에는 프론트엔드에서 백엔드를 직접 호출하는 단순한 구조로 시작했지만, 개발을 진행하면서 CORS 문제라든지, 작업 환경에 따라 URL이 각각 바뀌는 것에 의해 필연적으로 &amp;rdquo;중간에 서버인 Proxy 서버 &amp;rdquo;가 필요해 졌습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 Next.js API Routes를 활용해 API 프록시 레이어를 만들게 된 과정과, 만들고 나서 느낀 점을 이야기해 보려고 합니다&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;프론트엔드가 백엔드를 직접 호출하면 안 되나?&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실제로 많은 프로젝트가 프론트엔드에서 백엔드 API를 직접 호출합니다. 하지만 직접 호출로는 해결하기 어려운 문제들이 하나둘 생기기 시작했습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;문제 1: CORS&lt;/b&gt;&lt;br /&gt;프론트엔드(localhost:3000)에서 백엔드(localhost:8001)를 직접 호출하면 CORS 설정이 필요합니다. 백엔드에서 &amp;ldquo;Access-Control-Allow-Origin:*&amp;rdquo;와 같이 추가해서 관리하면 되지만, 환경이 늘어날 때마다 양쪽을 맞춰줘야 합니다. (별거 아닌 것 같지만, 개발 중에 CORS 오류로 시간을 쓰지 않아도 된다는 건 생각보다 편합니다 :-))&lt;br /&gt;&lt;br /&gt;이런 필요들이&amp;nbsp;모여서&amp;nbsp;만들어진 API&amp;nbsp;라우트&amp;nbsp;구조는&amp;nbsp;이렇습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;app/api/&lt;br /&gt;├─ [...path]/route.ts&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;larr; catch-all 프록시&lt;br /&gt;└─ auth/&lt;br /&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;├─ set-tokens/route.ts&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;larr; 토큰 저장 (쿠키 관리)&lt;br /&gt;&lt;span&gt;&amp;nbsp; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;├─ refresh/route.ts&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;larr; 토큰 갱신&lt;br /&gt;&lt;span&gt;&amp;nbsp; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;├─ me/route.ts&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;larr; 사용자 정보 조회&lt;br /&gt;&lt;span&gt;&amp;nbsp; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;└─ logout/route.ts&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;larr; 로그아웃&lt;/p&gt;
&lt;pre id=&quot;code_1773932458515&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function proxyRequest(
  request: NextRequest,
  params: Promise&amp;lt;{ path: string[] }&amp;gt;,
  method: string,
) {
  const { path } = await params;
  const accessToken = request.cookies.get(&quot;access_token&quot;)?.value;
  if (!accessToken) {
    return NextResponse.json({ error: &quot;Unauthorized&quot; }, { status: 401 });
  }

  // 경로 조합: /api/example/123 &amp;rarr; 백엔드의 /test-api/example/123
  const { searchParams } = new URL(request.url);
  const queryString = searchParams.toString();
  const apiPath = path.join(&quot;/&quot;);
  const url = `${API_BASE}/admin/${apiPath}${queryString ? `?${queryString}` : &quot;&quot;}`;
  const body = method !== &quot;GET&quot; &amp;amp;&amp;amp; method !== &quot;DELETE&quot; ? await request.text() : undefined;
  const response = await fetch(url, {
    method,
    headers: {
      Authorization: `Bearer ${accessToken}`,
      &quot;Content-Type&quot;: &quot;application/json&quot;,
    },
    body,
    signal: controller.signal,
  });

  const data = await response.json();
  return NextResponse.json(data, { status: response.status });
}
// 모든 HTTP 메서드를 동일한 함수로 처리
export async function GET(req, { params }) {
  return proxyRequest(req, params, &quot;GET&quot;);
}

export async function POST(req, { params }) {
  return proxyRequest(req, params, &quot;POST&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;httpOnly 쿠키에서 access_token을 꺼낸다.&lt;/li&gt;
&lt;li&gt;요청 경로 앞에 /test-api/을 붙여 백엔드 URL을 조합한다.&lt;/li&gt;
&lt;li&gt;Authorization 헤더에 토큰을 실어 백엔드로 전달한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 2: 백엔드 URL이&amp;nbsp;환경마다 다르다&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;관리자 백엔드는 localhost:8001(개발)과 프로덕션 서버가 다릅니다. 클라이언트에서 직접 호출하면 이 URL이 브라우저에 그대로 노출되는데 관리자 API의 주소가 외부에 드러나는 건 보안상 좋지 않아 서버 사이드에서 URL을 결정하면, 보안상의 문제도 해결할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1773932474949&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 환경변수로 백엔드 URL 결정 (서버 사이드에서만 접근)

const API_BASE =
  process.env.API_BASE_URL ||
  process.env.NEXT_PUBLIC_API_BASE_URL ||
  &quot;http://localhost:8001&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;문제 3: 인증 토큰을 안전하게 관리해야 한다&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;관리자 사이트는&amp;nbsp;Google&amp;nbsp;OAuth로&amp;nbsp;로그인합니다. 백엔드에서 받은 JWT&amp;nbsp;토큰을 어디에&amp;nbsp;저장할&amp;nbsp;것인가의&amp;nbsp;문제가&amp;nbsp;있었습니다.&amp;nbsp;localStorage에&amp;nbsp;넣으면 XSS에 취약하고, 일반 쿠키는 JavaScript에서 접근&amp;nbsp;가능합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결국 httpOnly 쿠키를 사용하게 되었는데 이 쿠키는 브라우저 JavaScript에서 읽을 수 없으므로, 서버에서 꺼내 백엔드로 전달하는 중간 레이어가 필요해졌습니다. 이것이 API 프록시 레이어가 필요한 가장 직접적인 이유였습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;프록시 서버를 이용한 장점 1 : 코드가 깔끔해진다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;클라이언트 코드의 단순함입니다. 백엔드 URL도 모르고, 토큰 관리도 신경 쓸 필요가 없습니다.토큰 전달도 없이 그냥 /api/로 호출하여 간단히 작성했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1773932486848&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const getTextAPI = async (params): Promise&amp;lt;TTextListResponse&amp;gt; =&amp;gt; {
  const response = await fetch(`/test-api/test?${searchParams.toString()}`, {
    credentials: &quot;include&quot;,  // 쿠키 자동 전송
  });
  return response.json();
};

export const patchTextAPI = async (id, data) =&amp;gt; {
  const response = await fetch(`/test-api/test/${id}/`, {
    method: &quot;PATCH&quot;,
    credentials: &quot;include&quot;,
    headers: { &quot;Content-Type&quot;: &quot;application/json&quot; },
    body: JSON.stringify(data),

  });
  return response.json();
};&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;/api/test &amp;rarr; catch-all이 /test-api/test로 변환 &amp;rarr; 쿠키에서 토큰 꺼내서 Authorization 헤더에 주입 &amp;rarr; 백엔드로 전달. 이 모든 과정이 프록시 레이어 안에서 자동으로 일어납니다.&amp;nbsp;새 기능이 추가될 때도 클라이언트에서 /api/test2를 호출하는 함수만 추가하면 되고 프록시 쪽은 건드릴 필요가 없어 좋습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프록시 서버를 이용한 장점 2&amp;nbsp;: OAuth&amp;nbsp;콜백&amp;nbsp;흐름&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;인증 전체 흐름을 보면 프록시 레이어의 역할이 좀 더 명확졌던 것 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 &quot;Google 로그인&quot; 클릭&lt;/li&gt;
&lt;li&gt;백엔드(admin-api)의 OAuth URL로 이동&lt;/li&gt;
&lt;li&gt;Google 인증 완료 &amp;rarr; 백엔드가 콜백 처리&lt;/li&gt;
&lt;li&gt;백엔드가 프론트엔드로 리다이렉트 (URL에 토큰 포함)&lt;br /&gt;&amp;rarr; /auth/callback/google?access_token=xxx&amp;amp;refresh_token=yyy&lt;/li&gt;
&lt;li&gt;콜백 페이지에서 /test-api/test-auth/tokens 호출 (BFF)&lt;br /&gt;&amp;rarr; httpOnly 쿠키에 토큰 저장&lt;/li&gt;
&lt;li&gt;/test-api/test-auth/is-admin 호출해서 관리자 권한 확인&lt;/li&gt;
&lt;li&gt;대시보드로 이동&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;토큰이 URL 파라미터로 잠깐 노출되긴 하지만, 곧바로 httpOnly 쿠키에 저장되고 URL에서 사라집니다. 이후 모든 요청은 쿠키가 자동 전송되므로, 클라이언트 코드에서 토큰을 직접 다룰 일이 없습니다.&lt;/p&gt;
&lt;h1 style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;마치며&lt;/h1&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;사실 이 API 프록시 레이어는 &quot;좋은 아키텍처를 설계하겠다&quot;는 의도보다, 보안이나 CORS 같은 실무적인 문제를 풀기 위해 자연스럽게 만들어진 결과물이었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Next.js App Router를 사용하고 계신다면, API Routes가 단순한 서버리스 함수가 아니라 프론트엔드와 백엔드 사이의 유용한 중간 레이어가 될 수 있다는 점을 한번 고려해 보시면 좋겠습니다. 특히 [...path] catch-all 라우트 하나로 일반 프록시를 처리하고, 보안이 필요한 라우트만 개별로 분리하는 패턴은 코드 양 대비 꽤 실용적이었다고 생각합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;읽어주셔서 감사합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;이 글은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://tech.pxd.co.kr/post/Next-js-App-Router%EC%97%90%EC%84%9C-%ED%94%84%EB%A1%9D%EC%8B%9C-%EB%A0%88%EC%9D%B4%EC%96%B4%EB%A5%BC-%EB%91%94-%EC%9D%B4%EC%9C%A0-337&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://tech.pxd.co.kr/&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;&amp;nbsp; 에서도 보실 수 있습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>UX Engineer 이야기</category>
      <author>seonju.lee</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1889</guid>
      <comments>https://story.pxd.co.kr/1889#entry1889comment</comments>
      <pubDate>Mon, 6 Apr 2026 10:00:17 +0900</pubDate>
    </item>
    <item>
      <title>GEONIQ Integrated Insight Report &amp;mdash; 여행&amp;middot;숙박 플랫폼 (Vol.3 선택이 이어지는 구조 조건 분석)</title>
      <link>https://story.pxd.co.kr/1894</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리포트는 GEO(AIEO)와 SEO를 한 번에 통합 분석해주는 GEONIQ의 진단 기준에 따라 국내 주요 여행&amp;middot;숙박 플랫폼의 페이지 구조와 정보 구성 방식을 분석하고 AI&amp;middot;검색 환경에서 숙소 상품이 선택 단계로 이어지기 위해 필요한 구조적 조건을 관찰&amp;middot;정리한 분석 보고서이다.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;thumbnail-10.png&quot; data-origin-width=&quot;1297&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OpYcG/dJMcagES1TI/ZNSUihPohiahAwH2yGvlQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OpYcG/dJMcagES1TI/ZNSUihPohiahAwH2yGvlQ0/img.png&quot; data-alt=&quot;좌측부터 우측 방향으로 네이버 여행, 야놀자, 여기어때 메인 페이지 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OpYcG/dJMcagES1TI/ZNSUihPohiahAwH2yGvlQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOpYcG%2FdJMcagES1TI%2FZNSUihPohiahAwH2yGvlQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1297&quot; height=&quot;306&quot; data-filename=&quot;thumbnail-10.png&quot; data-origin-width=&quot;1297&quot; data-origin-height=&quot;306&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;좌측부터 우측 방향으로 네이버 여행, 야놀자, 여기어때 메인 페이지 이미지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1) 이번 분석의 관점과 범위&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vol.1에서는 숙소 정보가 AI검색(GEO) 환경에서 어떤 단위로 인식되는지를 살펴봤다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vol.2에서는 그 인식이 왜 선택으로 이어지지 않는지를 선택 시도&amp;ndash;비교&amp;ndash;검증 흐름을 기준으로 관찰했다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 Vol.3에서는 앞선 두 편의 관찰을 전제로 선택이 실제로 이어지기 위해 필요한 구조적 조건을 정리한다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 조건은 특정 기능이나 UI의 문제가 아니라 여러 플랫폼에서 반복적으로 확인되는 구조적 패턴을 기준으로 도출된다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2)&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;AI검색(GEO) 관점에서의 선택&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 리포트에서 말하는 선택은 단순한 예약 행위를 의미하지 않는다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI검색(GEO) 관점에서의 선택은 여러 숙소가 동일한 기준 위에서 연결되고, 그 중 하나가 상대적 맥락 안에서 판단되는 상태를 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GEO(AIEO) 환경에서는 숙소 간 관계가 구조적으로 드러날 때 선택이 형성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3)&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 발견 (Key Findings)&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Key Finding 1&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택은 &amp;lsquo;후보 집합&amp;rsquo;이 형성될 때 시작된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 구조에서는 숙소가 개별 정보 단위로 분리되어 인식된다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그 결과 여러 숙소가 존재하더라도 하나의 선택 후보 집합으로 묶이지 않는다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택은 개별 정보가 아니라 서로 비교 가능한 후보 집합이 형성될 때 시작된다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Key Finding 2&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택은 &amp;lsquo;비교 기준이 구조로 드러날 때&amp;rsquo; 형성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가격, 평점, 위치와 같은 정보는 대부분 존재하지만, 이 정보들이 동일 기준 위에서 정렬된 구조로 표현되지 않으면 비교는 형성되지 않는다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택은 정보의 양이 아니라 비교 기준이 구조로 표현될 때 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Key Finding 3&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택은 &amp;lsquo;흐름이 유지되는 구조&amp;rsquo;에서 이어진다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자는 여러 숙소를 탐색하고 비교한다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러나 상세 페이지 진입 이후 다른 후보와의 연결이 단절되면 선택 과정은 반복적으로 끊긴다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택은 단일 페이지에서 완결되지 않는다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;후보 간 이동과 비교가 유지되는 흐름 안에서 이어진다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4) &lt;span style=&quot;color: #000000;&quot;&gt;구조적 조건으로 본 선택 가능 상태&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GEONIQ 진단 결과를 기준으로 보면 AI검색(GEO) 환경에서 선택이 형성되기 위해서는 다음 조건이 함께 충족되어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #424242;&quot;&gt;①&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 후보 집합 구조&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 숙소가 단순 나열이 아니라 동일 조건 기반의 후보 집합으로 묶여 있어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동일 지역&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동일 일정&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동일 인원 조건&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 조건이 구조적으로 유지될 때 숙소는 비교 가능한 단위로 인식된다.&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #424242;&quot;&gt;②&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 비교 기준 구조&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 숙소의 정보는 개별적으로 존재하는 것이 아니라 동일 기준 위에서 정렬 가능한 형태로 표현되어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가격&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;평점&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위치&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예약 가능 여부&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 기준이 구조로 드러날 때 비교는 자연스럽게 형성된다.&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #424242;&quot;&gt;③&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 흐름 유지 구조&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하나의 숙소를 확인한 이후에도 다른 후보와의 관계가 유지되는 흐름이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;유사 숙소 연결&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동일 조건 기반 후보 이동&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이전 후보 집합으로의 복귀 흐름&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 흐름이 유지될 때 선택은 단절되지 않고 이어진다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5)&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;구조 관점에서의 정리&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 분석을 통해 확인된 것은 여행&amp;middot;숙박 플랫폼의 기능 부족이 아니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다음 요소들은 이미 충분히 갖춰져 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;숙소 정보는 충분히 제공된다&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 탐색 흐름은 안정적으로 설계되어 있다&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SEO 관점에서의 노출 구조도 확보되어 있다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러나 동시에 다음 조건이 함께 나타난다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;숙소가 후보 집합으로 묶이지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비교 기준이 구조로 표현되지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;탐색 이후 흐름이 유지되지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 구조에서는 정보는 충분하지만 선택은 이어지지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 70px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;text-align: center; height: 19px; width: 99.3023%;&quot; colspan=&quot;3&quot;&gt;&lt;b&gt;지오닉 검증 결과 바로가기&lt;/b&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;text-align: center; width: 31.1628%; height: 17px;&quot;&gt;&lt;a href=&quot;https://www.geoniq.ai/result/589babf7-630d-466a-868d-b35ac5c905b0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;네이버 여행 메인&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; width: 34.8837%; height: 17px;&quot;&gt;&lt;a href=&quot;https://www.geoniq.ai/result/e764bdcc-2870-419f-969f-0a8d5eec4cb2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;야놀자 메인&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; width: 33.2558%; height: 17px;&quot;&gt;&lt;a href=&quot;https://www.geoniq.ai/result/00f91f0c-b1f1-4ddb-a725-50548ffa3227&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기어때 메인이자 목록&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;text-align: center; width: 31.1628%; height: 17px;&quot;&gt;&lt;a href=&quot;https://www.geoniq.ai/result/1371fdbd-a834-478b-bd4f-8e29913a753f&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;네이버 여행 목록&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; width: 34.8837%; height: 17px;&quot;&gt;&lt;a href=&quot;https://www.geoniq.ai/result/7031d31c-9cfb-437d-8ea2-7338da002d59&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;야놀자 목록&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 17px; width: 33.2558%;&quot;&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;text-align: center; width: 31.1628%; height: 17px;&quot;&gt;&lt;a href=&quot;https://www.geoniq.ai/result/248e6296-67aa-4926-bace-938852ce3792&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;네이버 여행 상세&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; width: 34.8837%; height: 17px;&quot;&gt;&lt;a href=&quot;https://www.geoniq.ai/result/edab976a-be93-4882-af12-761e5338d4ef&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;야놀자 상세&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; width: 33.2558%; height: 17px;&quot;&gt;&lt;a href=&quot;https://www.geoniq.ai/result/50b48614-5ec3-4bea-83fd-617afeaafd1c&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기어때 상세&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;pxdAX 관찰 노트 (종합)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 여행&amp;middot;숙박 플랫폼 연재에서 확인된 것은 정보의 부족이 아니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vol.1에서는 숙소가 어떻게 인식되는지를 살펴봤다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;숙소는 분명히 보이고 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vol.2에서는 그 다음 단계를 확인했다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택은 시작되지만 구조적으로 이어지지 않았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vol.3에서는 그 이유를 구조의 관점에서 정리했다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택은 정보의 양이 아니라 구조적 조건이 형성될 때 비로소 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;숙소는 이미 충분히 설명되어 있다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러나 그 정보는 사람의 탐색을 기준으로 배열되어 있을 뿐, AI검색(GEO) 환경에서 선택으로 이어지는 구조로 정리되어 있지는 않다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그 결과 보이는 것과 선택되는 것 사이에는 간극이 남는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그 간극은 기능으로 채워지지 않는다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그 간극은 구조로만 연결된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정보는 이미 충분하다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보이는 것과 선택되는 것의 차이는 정보의 양이 아니라 구조의 문제이다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택은 더 많은 정보를 통해 만들어지는 것이 아니라 비교와 흐름이 가능한 구조가 형성될 때 비로소 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 필요한 것은 정보를 더하는 것이 아니라&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택이 이어지는 구조를 만드는 일이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.geoniq.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GEONIQ 서비스 바로가기&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;GEONIQ Integrated Insight Report는&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.geoniq.ai/insight/여행&amp;middot;숙박-플랫폼-Vol-3-선택이-이어지는-구조-조건-분석-350&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GEONIQ&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://pxdstory.tistory.com/1894&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;pxd story&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://tech.pxd.co.kr/post/GEONIQ-Integrated-Insight-Report-&amp;mdash;-여행&amp;middot;숙박-플랫폼-Vol-3-선택이-이어지는-구조-조건-분석-350&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;xe group tech blog&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;에서 동시 발행 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>pxd AI툴 이야기</category>
      <category>AIEO</category>
      <category>Geo</category>
      <category>GEONIQ</category>
      <category>pxdax</category>
      <category>SEO</category>
      <category>네이버여행</category>
      <category>숙소예약</category>
      <category>야놀자</category>
      <category>여기어때</category>
      <category>여행플랫폼</category>
      <author>GEONIQ</author>
      <guid isPermaLink="true">https://story.pxd.co.kr/1894</guid>
      <comments>https://story.pxd.co.kr/1894#entry1894comment</comments>
      <pubDate>Mon, 6 Apr 2026 07:50:27 +0900</pubDate>
    </item>
  </channel>
</rss>