<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>주현 - AX | Backend/Frontend Developer</title>
    <link>https://series.tistory.com/</link>
    <description>주현 - AX | Backend/Frontend Developer</description>
    <language>ko</language>
    <pubDate>Sun, 26 Jul 2026 17:40:07 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>RichLegend</managingEditor>
    <image>
      <title>주현 - AX | Backend/Frontend Developer</title>
      <url>https://tistory1.daumcdn.net/tistory/76315/attach/649cba5a1ed243d5861dad5a34016630</url>
      <link>https://series.tistory.com</link>
    </image>
    <item>
      <title>백엔드 개발자를 위한 RAG 설계: 청킹, 임베딩, 벡터 검색 쉽게 이해하기</title>
      <link>https://series.tistory.com/entry/%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-RAG-%EC%84%A4%EA%B3%84-%EC%B2%AD%ED%82%B9-%EC%9E%84%EB%B2%A0%EB%94%A9-%EB%B2%A1%ED%84%B0-%EA%B2%80%EC%83%89-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
      <description>&lt;h1&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;백엔드 개발자를 위한 RAG 설계: 청킹, 임베딩, 벡터 검색 쉽게 이해하기&lt;/b&gt;&lt;span style=&quot;color: #333333; font-size: 16px; letter-spacing: 0px;&quot;&gt;RAG가 문서를 찾는 순서부터 청킹 크기, 임베딩 모델, HNSW 설정, 검색 품질 평가까지 실무에 필요한 내용만 쉽게 정리했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;RAG는 LLM이 답변하기 전에 관련 문서를 찾아 주는 구조입니다. 사용자가 질문하면 사내 문서나 기술 문서에서 근거를 찾고, 그 내용을 LLM에 전달합니다. LLM은 전달받은 근거를 바탕으로 답변합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;처음에는 문서를 잘라 벡터 DB에 넣고 가까운 내용을 검색하면 됩니다. 하지만 실제 서비스에서는 다른 문제가 생깁니다. 표현만 조금 바꿔도 검색 결과가 달라지고, 제품 코드나 오류 번호를 놓치기도 합니다. 수정 전 문서가 계속 검색되거나 권한이 없는 문서가 결과에 포함될 수도 있습니다.&lt;/span&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;벡터 DB부터 고르기보다 검색 결과를 어떻게 평가할지 먼저 정해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;청킹 크기나 임베딩 모델, HNSW 설정은 문서와 질문에 따라 결과가 달라집니다. 다른 서비스에서 잘 동작한 설정도 우리 데이터에서는 같은 결과가 나오지 않을 수 있습니다. 이 글에서는 실제 질문으로 검색 품질을 확인하고, 그 결과에 맞춰 설정을 조정하는 순서를 설명합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p 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;캡처_2026-07-17_12-31-50.jpg&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GfifR/dJMcaic5IRt/ck5lWMs7vB5xz7RZh1uOGk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GfifR/dJMcaic5IRt/ck5lWMs7vB5xz7RZh1uOGk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GfifR/dJMcaic5IRt/ck5lWMs7vB5xz7RZh1uOGk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGfifR%2FdJMcaic5IRt%2Fck5lWMs7vB5xz7RZh1uOGk%2Fimg.jpg&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;896&quot; height=&quot;590&quot; data-filename=&quot;캡처_2026-07-17_12-31-50.jpg&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;590&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;먼저 알아둘 용어&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;청크:&lt;/b&gt; 검색하기 좋게 나눈 문서 조각&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;청킹:&lt;/b&gt; 문서를 청크로 나누는 작업&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;임베딩:&lt;/b&gt; 문장이나 문서를 숫자 배열로 바꾸는 작업&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;벡터 검색:&lt;/b&gt; 숫자로 바꾼 문장 사이의 거리를 계산해 의미가 가까운 내용을 찾는 검색&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;BM25:&lt;/b&gt; 제품 코드나 오류 번호처럼 정확한 단어를 잘 찾는 검색&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;재정렬:&lt;/b&gt; 검색된 후보를 질문과 다시 비교해 순서를 바꾸는 작업&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;Recall@k:&lt;/b&gt; 관련 문서가 상위 k개 검색 결과에 포함된 비율&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;색인:&lt;/b&gt; 문서를 빠르게 검색할 수 있도록 정리해 저장한 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;근사 검색:&lt;/b&gt; 모든 벡터를 비교하지 않고 가까울 가능성이 높은 벡터만 빠르게 찾는 검색&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;RAG는 두 단계로 나누면 이해하기 쉽습니다&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;RAG는 문서를 미리 저장하는 단계와 사용자의 질문을 처리하는 단계로 나눌 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;문서를 저장할 때&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;PDF, 웹 문서, 코드 같은 원문을 가져옵니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;제목과 문단 구조를 살려 문서를 나눕니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;각 청크를 임베딩합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;벡터와 문서 정보를 검색 시스템에 저장합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;질문을 받을 때&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;사용자 질문과 접근 권한을 확인합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;벡터 검색과 BM25로 관련 문서를 찾습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;필요하면 검색 결과를 재정렬합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;상위 청크를 LLM에 전달합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;답변과 출처를 사용자에게 보여 줍니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;문서 저장 단계와 질문 처리 단계를 분리하면 변경 작업이 쉬워집니다. 임베딩 모델을 바꿀 때 원문을 다시 수집할 필요가 없습니다. 문서가 수정됐을 때는 바뀐 문서만 다시 청킹하고 색인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;원문 ID와 청크 ID&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;문서 버전 또는 수정 시각&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;제목과 소제목 위치&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;출처 URL&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;임베딩 모델과 버전&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;사용자나 부서의 접근 권한&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;권한은 답변을 만든 뒤 확인하면 늦습니다. 검색 단계에서 권한이 없는 문서를 제외해야 로그와 재정렬 요청에도 민감한 내용이 들어가지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;청킹은 문서의 의미를 지키는 작업입니다&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;청크가 너무 짧으면 질문에 답할 정보가 부족합니다. 너무 길면 서로 다른 주제가 한 청크에 섞여 검색 정확도가 떨어지고 LLM 비용도 늘어납니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;예를 들어 &lt;code&gt;이 기간에는 환불이 불가능합니다&lt;/code&gt;라는 문장만 저장하면 어떤 상품과 기간을 말하는지 알 수 없습니다. 표의 한 행만 저장하면 열 제목이 사라집니다. 코드도 메서드 본문만 잘라 놓으면 클래스 정보를 놓칠 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;일반 문서: 제목, 문단, 목록을 가능한 한 유지합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;API 문서: 엔드포인트별 요청과 응답 예제를 함께 둡니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;코드: 함수나 클래스 단위로 나눕니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;정책 문서: 조항 번호와 적용 대상을 함께 저장합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;표: 제목과 열 이름이 데이터와 함께 검색되도록 만듭니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Azure AI Search는 512토큰과 25% 겹침을 초기 설정값으로 제안합니다. 모든 문서에 그대로 적용할 값은 아니므로 문서 종류별로 비교해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;짧은 FAQ와 오류 메시지: 150에서 350토큰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;일반 기술 문서와 업무 문서: 400에서 800토큰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;정책과 매뉴얼: 조항이나 절 단위로 나눈 뒤 최대 길이 제한&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;코드: 함수나 클래스 단위로 나누고 상위 클래스 이름을 함께 저장&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;청크를 겹치면 문장이 경계에서 잘리는 문제를 줄일 수 있습니다. 하지만 겹침이 많으면 같은 문장이 여러 번 검색됩니다. 저장 공간과 검색 비용도 늘어납니다. 먼저 문단 경계를 지키고 제목 정보를 붙인 뒤, 정보가 계속 잘릴 때만 겹침을 늘리는 편이 낫습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Anthropic의 Contextual Retrieval은 각 청크에 문서 제목과 섹션 정보를 짧게 붙이는 방식입니다. Anthropic이 공개한 내부 실험에서는 검색 실패가 49% 줄었고 재정렬을 함께 사용했을 때 67% 줄었습니다. 공급사 내부 데이터로 측정한 결과이므로 같은 수치가 나온다고 볼 수는 없습니다. 다만 제목과 상위 문맥을 청크에 추가하는 방법은 직접 시험해 볼 만합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;임베딩 모델은 실제 질문으로 비교합니다&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;임베딩 모델은 문장을 숫자 좌표로 바꿉니다. 의미가 비슷한 문장은 가까운 위치에 놓이도록 학습됩니다. 그래서 표현이 달라도 의미가 비슷한 문서를 찾을 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;리더보드 점수만으로 모델을 고르기는 어렵습니다. MTEB 연구에서도 모든 작업에 가장 좋은 단일 모델은 없었습니다. 한국어 문장, 영문 API 이름, 상품 코드가 섞인 데이터는 일반 영어 문서와 검색 조건이 다릅니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;관리형 API를 사용하면 모델 서버를 직접 운영하지 않아도 됩니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;OpenAI &lt;code&gt;text-embedding-3-small&lt;/code&gt;: 기본 1536차원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;OpenAI &lt;code&gt;text-embedding-3-large&lt;/code&gt;: 기본 3072차원, 차원 축소 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Gemini Embedding: 기본 3072차원, 768과 1536차원도 권장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Cohere &lt;code&gt;embed-v4.0&lt;/code&gt;: 텍스트와 이미지가 섞인 문서 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Voyage 4: 문서와 질문의 입력 유형을 구분하고 여러 차원 지원&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;외부 전송이 어려운 문서라면 직접 운영하는 모델도 검토할 수 있습니다. BGE-M3는 벡터 검색과 키워드 검색을 함께 지원하며 100개가 넘는 언어를 다룬다고 공개되어 있습니다. 다만 GPU와 CPU 비용, 모델 서버 운영, 장애 대응까지 직접 맡아야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;띄어쓰기나 맞춤법이 틀린 한국어 질문&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;한국어와 영문 API 경로가 섞인 질문&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;상품 코드, 버전, 오류 번호를 찾는 질문&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;사내 약어와 정식 명칭을 섞은 질문&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;답이 없거나 접근 권한이 없는 질문&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;같은 문서와 질문으로 Recall@k, 검색 시간, 색인 크기, 비용을 비교하면 됩니다. 모델마다 문장을 숫자로 바꾸는 방식이 다르므로 임베딩 모델을 바꾸면 대부분 전체 문서를 다시 임베딩해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;벡터 검색과 BM25를 함께 사용합니다&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;벡터 검색은 &lt;code&gt;로그인이 안 돼요&lt;/code&gt;와 &lt;code&gt;인증 실패 해결 방법&lt;/code&gt;처럼 표현이 달라도 의미가 비슷한 문장을 찾는 데 강합니다. 반면 &lt;code&gt;ERR-1024&lt;/code&gt;, 상품 코드, API 경로처럼 글자가 정확히 일치해야 하는 검색에는 약할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;BM25는 정확한 단어를 찾는 데 강합니다. 두 검색을 함께 사용하면 의미 검색과 키워드 검색의 장점을 모두 활용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;같은 질문을 벡터 검색과 BM25에 보냅니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;두 검색에서 후보 문서를 가져옵니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;각 검색 결과의 순위를 기준으로 합치는 RRF를 적용합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;재정렬 모델이 질문과 후보를 다시 읽고 순서를 바꿉니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;상위 문서만 LLM에 전달합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;처음에는 30개에서 100개 정도를 찾은 뒤 5개에서 10개로 줄이는 구성을 시험할 수 있습니다. 후보가 많을수록 재정렬 비용과 응답 시간이 늘어나므로 실제 질문으로 조정해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;검색 필터는 보안과 품질에 모두 필요합니다&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;문서에는 부서, 사용자, 문서 종류, 언어, 공개 범위 같은 정보가 있습니다. 이 값을 검색 조건으로 사용해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;필터가 없으면 권한이 없는 문서까지 검색될 수 있습니다. 반대로 필터가 너무 강하거나 문서 정보가 빠져 있으면 필요한 문서를 놓칩니다. 검색에 사용한 필터와 제외된 문서 수를 로그에 남기면 원인을 찾기 쉽습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Qdrant는 문서 속성을 빠르게 거르는 payload index를 데이터 적재 전에 만들도록 권장합니다. pgvector는 필터 때문에 검색 결과가 부족할 때 검색 범위를 단계적으로 넓히는 iterative scan 옵션을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;HNSW와 IVFFlat의 차이&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;벡터가 많아지면 모든 벡터를 하나씩 비교하기 어렵습니다. HNSW와 IVFFlat은 가까울 가능성이 높은 벡터만 빠르게 확인하는 근사 검색 인덱스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;근사 검색을 적용하기 전에는 데이터가 적을 때 정확 검색으로 기준을 만듭니다. 정확 검색 결과와 비교해야 HNSW나 IVFFlat이 관련 문서를 얼마나 놓치는지 알 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;HNSW&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;HNSW는 벡터 사이의 연결 그래프를 만듭니다. 검색 속도가 빠르고 관련 문서를 놓치는 비율도 낮은 편입니다. 데이터가 계속 추가되는 서비스에서 많이 사용하지만 인덱스를 만드는 시간이 길고 메모리를 더 사용합니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;code&gt;m&lt;/code&gt;: 각 벡터가 연결되는 수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;code&gt;ef_construction&lt;/code&gt;: 인덱스를 만들 때 확인할 후보 수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;code&gt;ef_search&lt;/code&gt;: 검색할 때 확인할 후보 수&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;code&gt;ef_search&lt;/code&gt;를 높이면 관련 문서를 찾을 가능성이 커지지만 검색 시간도 늘어납니다. Qdrant의 &lt;code&gt;hnsw_ef&lt;/code&gt;도 같은 방식으로 조정합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;IVFFlat&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;IVFFlat은 벡터를 여러 묶음으로 나눈 뒤 질문과 가까운 묶음부터 검색합니다. HNSW보다 인덱스를 빠르게 만들 수 있고 메모리 부담도 낮을 수 있습니다. 다만 데이터 분포를 먼저 학습해야 하므로 데이터가 쌓인 뒤 만드는 편이 좋습니다.&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;code&gt;lists&lt;/code&gt;: 벡터를 나눌 묶음 수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;code&gt;probes&lt;/code&gt;: 검색할 때 확인할 묶음 수&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;code&gt;probes&lt;/code&gt;를 높이면 더 많은 묶음을 확인하므로 재현율과 검색 시간이 함께 늘어납니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;인덱스를 비교할 때는 벡터 수, 검색량, 삽입량, 메모리, 필터 비율, 허용 응답 시간을 함께 확인합니다. 데이터가 자주 추가된다면 HNSW가 편할 수 있습니다. 메모리가 부족하고 데이터를 한 번에 적재한다면 IVFFlat도 좋은 선택입니다. 최종 선택은 같은 평가 질문으로 비교하여 정합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;검색과 답변을 따로 평가합니다&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;답변이 틀렸을 때 LLM만 바꾸면 원인을 찾기 어렵습니다. 먼저 관련 문서가 검색됐는지 확인해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Recall@k: 관련 문서가 상위 k개 안에 들어왔는지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Precision@k: 검색된 문서 중 실제 관련 문서의 비율&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;MRR: 첫 번째 관련 문서가 얼마나 앞에 있는지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;검색과 재정렬에 걸린 시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;필터 때문에 결과가 0개가 된 비율&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&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;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;답변이 검색된 문서에 근거했는지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;질문에 필요한 내용을 직접 답했는지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;표시한 출처가 실제 근거와 일치하는지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;근거가 없을 때 답변을 거절하는지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;토큰 사용량과 비용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Ragas는 검색 문맥의 정확성(Context Precision), 누락 여부(Context Recall), 답변 관련성(Response Relevancy), 근거 충실도(Faithfulness)를 평가할 수 있습니다. 자동 평가는 반복 테스트에 유용하지만 중요한 질문과 실패 사례는 사람이 함께 확인해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;운영 로그에는 원본 질문, 적용한 권한 필터, 검색 후보 ID, 재정렬 순위, LLM에 전달한 청크 ID, 문서 버전, 단계별 처리 시간을 남깁니다. 원문 전체나 개인정보를 무조건 저장하지는 않습니다. 문제를 추적하는 데 필요한 ID와 마스킹된 정보만 보존합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;처음 구현할 때는 이 순서로 진행합니다&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;실제 질문과 관련 문서를 묶어 평가용 질문을 만듭니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;문서의 제목과 문단을 살려 청킹합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;데이터가 적을 때 정확 벡터 검색으로 첫 결과를 확인합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;임베딩 모델 두세 개를 같은 질문으로 비교합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;코드나 고유명사가 많다면 BM25를 추가합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;관련 문서는 찾았지만 순위가 낮을 때 재정렬을 추가합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;검색 시간이 길어지면 HNSW와 IVFFlat을 비교합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;권한 필터가 있는 상태에서 검색 결과가 줄어드는지 확인합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;운영에서 실패한 질문을 평가 목록에 계속 추가합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;새 기능은 문제가 생긴 단계에 추가해야 합니다. 관련 문서가 청크로 만들어지지 않았다면 재정렬 모델을 바꿔도 해결되지 않습니다. 관련 문서는 검색됐지만 순위가 낮다면 청킹 전체를 바꾸기보다 재정렬부터 시험할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;자주 묻는 질문&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;청크는 몇 토큰이 좋은가요?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;문서마다 다릅니다. 일반 문서는 400에서 800토큰을 먼저 비교할 수 있습니다. FAQ는 더 짧게 나누고 정책 문서는 조항 단위를 우선합니다. 최소 두세 가지 크기를 같은 질문으로 비교하세요.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;처음부터 Semantic Chunking을 써야 하나요?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;필수는 아닙니다. 먼저 제목과 문단을 살린 청킹으로 시작합니다. 관련 정보가 청크 경계에서 계속 잘릴 때 Semantic Chunking과 비교해도 늦지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;PostgreSQL과 pgvector로 시작해도 되나요?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이미 PostgreSQL을 운영하고 있고 벡터 수와 검색량을 감당할 수 있다면 pgvector로 시작해도 됩니다. 벡터 규모가 매우 크거나 복잡한 혼합 검색이 필요해질 때 전용 검색 시스템을 비교할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;임베딩 모델만 바꾸고 기존 벡터를 유지할 수 있나요?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;대부분 어렵습니다. 모델마다 벡터 공간이 다르기 때문에 문서와 질문을 새 모델로 다시 임베딩해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;답변이 틀리면 LLM부터 바꿔야 하나요?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;관련 문서가 검색됐는지 먼저 확인합니다. 관련 문서가 없다면 청킹이나 검색 문제입니다. 관련 문서가 있는데 답변이 틀렸다면 LLM에 전달한 문맥과 프롬프트를 확인합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;정리&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;RAG는 문서를 검색하고 그 근거로 답변하는 백엔드 시스템입니다. 청킹은 문서의 의미가 끊기지 않도록 나눕니다. 임베딩 모델은 실제 질문으로 비교합니다. 벡터 검색과 BM25를 함께 사용하면 의미가 비슷한 문장과 정확한 코드 검색을 모두 처리하기 좋습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;처음부터 복잡한 기능을 모두 넣을 필요는 없습니다. 평가용 질문을 먼저 만들고 청킹, 검색, 재정렬, 인덱스를 순서대로 추가하면 어떤 변경이 도움이 됐는지 확인하기 쉽습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;태그: RAG 아키텍처, 백엔드 개발자, Chunking 전략, 임베딩 모델 비교, Vector DB, HNSW, IVFFlat, pgvector, 하이브리드 검색, Reranking, LLM, 생성형 AI, AI Agent&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/756</guid>
      <comments>https://series.tistory.com/entry/%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-RAG-%EC%84%A4%EA%B3%84-%EC%B2%AD%ED%82%B9-%EC%9E%84%EB%B2%A0%EB%94%A9-%EB%B2%A1%ED%84%B0-%EA%B2%80%EC%83%89-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0#entry756comment</comments>
      <pubDate>Fri, 17 Jul 2026 12:34:51 +0900</pubDate>
    </item>
    <item>
      <title>GPT-5.6이 나왔다. GPT-5.6 Sol&amp;middot;Terra&amp;middot;Luna, 어떤 작업에 써야 할까</title>
      <link>https://series.tistory.com/entry/GPT-56%EC%9D%B4-%EB%82%98%EC%99%94%EB%8B%A4-GPT-56-Sol%C2%B7Terra%C2%B7Luna-%EC%96%B4%EB%96%A4-%EC%9E%91%EC%97%85%EC%97%90-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C</link>
      <description>&lt;h1&gt;GPT-5.6이 나왔다. 벤치마크 성능표보다 중요한 건 따로 있다&lt;/h1&gt;
&lt;p&gt;새 모델이 얼마나 똑똑한지보다, 실제 작업에서 몇 번이나 다시 설명해야 하는지가 더 궁금하다.&lt;/p&gt;
&lt;p&gt;GPT-5.6가 정식으로 공개됐다. 플래그십 모델인 Sol, 성능과 비용을 절충한 Terra, 저렴하게 쓸 수 있는 Luna까지 세 종류다. 코딩과 과학, 보안 분야의 점수도 올랐고, 여러 에이전트를 동시에 움직이는 ultra 모드도 추가됐다.&lt;/p&gt;
&lt;p&gt;발표 자료만 보면 확인할 것이 많다. 그런데 AI 코딩 도구를 실제 업무에 붙여 쓰는 입장에서 궁금한 건 조금 다르다. 요구사항을 한 번에 얼마나 잘 알아듣는지, 수정하다가 멀쩡한 코드를 건드리지는 않는지, 끝났다고 했을 때 테스트까지 제대로 통과했는지. 이런 부분이 좋아졌다면 점수 몇 점이 오른 것보다 훨씬 반갑다.&lt;/p&gt;
&lt;h2&gt;이번 발표에서 눈에 들어온 건 토큰 효율이었다&lt;/h2&gt;
&lt;p&gt;GPT-5.6의 메시지는 같은 수준의 결과를 더 적은 토큰으로 만들고, 작업에 따라 모델을 나눠 비용을 낮추겠다는 쪽에 가깝다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sol은 설계나 복잡한 디버깅처럼 판단이 많이 필요한 작업에 어울린다.&lt;/li&gt;
&lt;li&gt;Terra는 일반적인 기능 개발이나 문서 작업처럼 자주 하는 일에 맞춰져 있다.&lt;/li&gt;
&lt;li&gt;Luna는 분류, 형식 변환, 전처리처럼 결과를 바로 확인하기 쉬운 작업에 부담이 적다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;API 가격은 100만 토큰 기준으로 Sol이 입력 5달러, 출력 30달러다. Terra는 2.5달러와 15달러, Luna는 1달러와 6달러다.&lt;/p&gt;
&lt;p&gt;가격만 보면 Luna부터 쓰는 게 당연해 보인다. 하지만 모델이 놓친 내용을 사람이 계속 고쳐야 한다면 계산이 달라진다. 토큰 비용은 줄어도 작업 시간은 늘 수 있다. 반대로 중요한 작업에 Sol을 쓰고 수정 횟수를 줄일 수 있다면 비싼 모델이 오히려 나은 선택일 수 있다.&lt;/p&gt;
&lt;h2&gt;개발자가 체감하는 성능은 다른 곳에서 드러난다&lt;/h2&gt;
&lt;p&gt;온라인 반응 중에 재미있는 표현이 하나 있었다. 모델 성능을 “Codex에게 욕한 횟수”로 평가했다는 이야기다. GPT-5.5를 쓸 때보다 GPT-5.6 Sol을 쓸 때 그 횟수가 줄었다고 했다.&lt;/p&gt;
&lt;p&gt;농담이지만 무슨 뜻인지는 바로 이해된다. AI 코딩을 하다 보면 틀린 답보다 애매하게 맞는 답이 더 피곤할 때가 있다. 요구사항 다섯 개 중 네 개만 처리하거나, 한 곳을 고치면서 다른 곳을 깨뜨리거나, 테스트하지 않은 코드를 완성됐다고 내놓는 경우다.&lt;/p&gt;
&lt;p&gt;모델이 좋아졌는지는 결국 다시 설명한 횟수, 되돌린 코드, 직접 고친 시간에서 드러난다.&lt;/p&gt;
&lt;p&gt;벤치마크가 필요 없다는 이야기는 아니다. 어떤 작업에서 강한지 빠르게 파악하려면 점수가 필요하다. 다만 내 코드베이스에서 잘하는지는 직접 확인해야 한다. 프로젝트 구조와 사용 언어, 프롬프트 작성 방식이 사람마다 다르기 때문이다.&lt;/p&gt;
&lt;h2&gt;프롬프트를 짧게 쓰라는 말은 조금 조심해서 들어야 한다&lt;/h2&gt;
&lt;p&gt;GPT-5.6은 사용자의 의도와 기대 수준을 이전보다 잘 파악한다고 한다. 긴 시스템 프롬프트를 줄였더니 내부 평가 점수는 10&lt;del&gt;15% 좋아지고, 전체 토큰은 41&lt;/del&gt;66%, 비용은 33~67% 줄었다는 내용도 공개됐다.&lt;/p&gt;
&lt;p&gt;그렇다고 모든 설명을 지우면 안 된다. 프롬프트가 짧아져도 수정 범위, 성공 조건, 승인 없이 하면 안 되는 일은 남겨야 한다. 모델이 알아서 채워도 되는 설명과 사람이 직접 정해야 하는 기준은 다르다.&lt;/p&gt;
&lt;p&gt;예를 들어 “짧게 답해줘”라고 쓰는 것보다 “수정한 파일, 변경 이유, 테스트 결과만 알려줘”라고 쓰는 편이 낫다. 답변 길이만 줄이는 게 아니라 무엇을 받아야 하는지 정해 주기 때문이다.&lt;/p&gt;
&lt;h2&gt;Codex와 Claude Code, 하나만 고를 필요는 없다&lt;/h2&gt;
&lt;p&gt;새 모델이 나올 때마다 Codex와 Claude Code 중 무엇이 더 좋은지 묻게 된다. 여기에 하나의 정답은 없다. 모델의 코딩 실력만 비교해서 끝나는 문제가 아니기 때문이다.&lt;/p&gt;
&lt;p&gt;도구가 안정적으로 동작하는지, 사용량을 얼마나 주는지, 원격으로 작업을 확인할 수 있는지, 긴 세션에서 앞의 맥락을 얼마나 잘 이어가는지도 중요하다. 같은 모델을 써도 프로젝트에 따라 체감이 달라진다.&lt;/p&gt;
&lt;p&gt;예산이 허용한다면 둘을 경쟁시키는 방법도 괜찮다. 같은 요구사항으로 설계를 각각 받아 보거나, 한쪽이 작성한 코드를 다른 쪽에 검토하게 하면 각 모델의 장단점이 빨리 드러난다.&lt;/p&gt;
&lt;h2&gt;새 모델은 같은 작업으로 비교해 보면 된다&lt;/h2&gt;
&lt;p&gt;GPT-5.6를 써 볼 생각이라면 평소 자주 하는 작업 하나를 정해 두는 게 좋다. 새 기능 하나, 실제 버그 하나, 오래된 코드의 작은 리팩터링 정도면 충분하다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;첫 결과에서 요구사항을 몇 개나 놓쳤는지&lt;/li&gt;
&lt;li&gt;수정 지시 뒤에 기존 동작을 깨뜨렸는지&lt;/li&gt;
&lt;li&gt;테스트를 직접 실행하고 결과를 확인했는지&lt;/li&gt;
&lt;li&gt;사람이 다시 설명하고 고치는 데 몇 분이 들었는지&lt;/li&gt;
&lt;li&gt;한 작업을 끝내는 데 실제로 얼마를 썼는지&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;며칠만 기록해도 Sol을 써야 할 작업과 Terra로 충분한 작업, Luna에 맡겨도 되는 작업이 나뉜다. 모델 이름보다 내 작업에서 나온 기록이 훨씬 믿을 만하다.&lt;/p&gt;
&lt;h2&gt;GPT-5.6에서 기대하는 건 화려한 답이 아니다&lt;/h2&gt;
&lt;p&gt;AI 코딩 도구에 바라는 것은 점점 단순해지고 있다. 말을 길게 잘하는 것보다 앞에서 정한 조건을 잊지 않았으면 한다. 수정한 뒤에는 테스트를 돌리고, 문제가 생기면 원인을 찾아 끝까지 고쳤으면 한다.&lt;/p&gt;
&lt;p&gt;GPT-5.6가 이런 기본적인 답답함을 줄여 준다면 충분히 좋은 업그레이드다. 성능표는 그다음에 봐도 늦지 않다.&lt;/p&gt;
&lt;p&gt;태그: GPT-5.6, Codex, Claude Code, AI 코딩, OpenAI, LLM, 프롬프트, 개발 생산성, AI 에이전트&lt;/p&gt;
&lt;p&gt;참고 자료&lt;br&gt;&lt;a href=&quot;https://news.hada.io/topic?id=31275&quot;&gt;https://news.hada.io/topic?id=31275&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://openai.com/index/gpt-5-6/&quot;&gt;https://openai.com/index/gpt-5-6/&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI AX</category>
      <category>ai 에이전트</category>
      <category>AI 코딩</category>
      <category>claude code</category>
      <category>codex</category>
      <category>GPT-5.6</category>
      <category>LLM</category>
      <category>openai</category>
      <category>개발 생산성</category>
      <category>프롬프트</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/755</guid>
      <comments>https://series.tistory.com/entry/GPT-56%EC%9D%B4-%EB%82%98%EC%99%94%EB%8B%A4-GPT-56-Sol%C2%B7Terra%C2%B7Luna-%EC%96%B4%EB%96%A4-%EC%9E%91%EC%97%85%EC%97%90-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C#entry755comment</comments>
      <pubDate>Fri, 10 Jul 2026 13:48:47 +0900</pubDate>
    </item>
    <item>
      <title>Codex GPT-5.6 Sol [collaboration.spawn_agent] 오류 해결: 멀티 에이전트를 끄기 전에 확인할 것</title>
      <link>https://series.tistory.com/entry/Codex-GPT-56-Sol-collaborationspawnagent-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0-%EB%A9%80%ED%8B%B0-%EC%97%90%EC%9D%B4%EC%A0%84%ED%8A%B8%EB%A5%BC-%EB%81%84%EA%B8%B0-%EC%A0%84%EC%97%90-%ED%99%95%EC%9D%B8%ED%95%A0-%EA%B2%83</link>
      <description>&lt;h1&gt;Codex GPT-5.6 Sol &lt;code&gt;collaboration.spawn_agent&lt;/code&gt; 오류 해결: 멀티 에이전트를 끄기 전에 확인할 것&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPT-5.6 Sol에서 일반 질문까지 실패하는 원인과 LazyCodex 업데이트, &lt;code&gt;config.toml&lt;/code&gt; 우회 설정, CLI 검증 순서를 정리했습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex에서 GPT-5.6 Sol을 선택한 뒤 평범한 인사나 질문을 입력했는데 아래 오류만 나오고 대화가 시작되지 않는 경우가 있습니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Invalid Value: 'tools'. Function 'collaboration.spawn_agent' is reserved for use by this model and must match the configured schema.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오류 문구에 &lt;code&gt;spawn_agent&lt;/code&gt;가 들어가 있으니 멀티 에이전트 기능부터 꺼야 할 것처럼 보입니다. 하지만 영향을 받는 환경에서는 멀티 에이전트를 포기하지 않고도 문제를 해결할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년 7월 10일 현재 가장 먼저 확인할 것은 LazyCodex 또는 OMO의 버전입니다. LazyCodex v4.16.2에는 GPT-5.6 계열에서 문제가 될 수 있는 관리 설정을 자동으로 정리하는 수정이 포함됐습니다. 업데이트한 뒤에도 같은 오류가 정확히 반복될 때만 &lt;code&gt;tool_namespace&lt;/code&gt; 우회 설정을 적용하는 순서가 안전합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;바쁜 분을 위한 해결 순서&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;오류 문구가 위 내용과 정확히 같은지 봅니다.&lt;/li&gt;
&lt;li&gt;LazyCodex 또는 OMO를 사용한다면 v4.16.2 이상으로 업데이트합니다.&lt;/li&gt;
&lt;li&gt;기존 대화가 아닌 새 작업에서 GPT-5.6 Sol을 다시 실행합니다.&lt;/li&gt;
&lt;li&gt;오류가 남으면 &lt;code&gt;config.toml&lt;/code&gt;을 백업하고 &lt;code&gt;tool_namespace = &quot;agents&quot;&lt;/code&gt;를 추가합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;multi_agent = false&lt;/code&gt;나 &lt;code&gt;multi_agent_v2.enabled = true&lt;/code&gt;부터 적용하지 않습니다.&lt;/li&gt;
&lt;li&gt;Codex Desktop과 터미널의 Codex CLI는 따로 확인합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;일반 질문까지 막히는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenAI Codex 이슈 #31864에 올라온 코드 분석과 A/B 테스트는 도구 이름과 스키마의 충돌을 원인으로 지목합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPT-5.6 Sol에는 &lt;code&gt;collaboration.spawn_agent&lt;/code&gt;라는 예약 도구가 있습니다. 그런데 영향을 받는 Codex 런타임도 MultiAgentV2의 &lt;code&gt;spawn_agent&lt;/code&gt;를 같은 &lt;code&gt;collaboration&lt;/code&gt; 네임스페이스에 등록합니다. 이름은 같지만 스키마가 일치하지 않으면 서버가 요청을 거부합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex는 질문만 보내지 않습니다. 모델이 필요할 때 쓸 수 있도록 도구 정의도 요청에 함께 넣습니다. 서버는 모델이 답변을 만들기 전에 이 정의부터 검사합니다. 서브 에이전트를 요청하지 않은 평범한 질문까지 실패하는 이유가 여기에 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;tool_namespace = &quot;agents&quot;&lt;/code&gt;를 설정하면 도구 이름이 &lt;code&gt;collaboration.spawn_agent&lt;/code&gt;에서 &lt;code&gt;agents.spawn_agent&lt;/code&gt;로 바뀝니다. 예약된 이름과 겹치지 않도록 이름표만 바꾸는 셈입니다. 멀티 에이전트를 삭제하거나 끄는 설정은 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 2026년 7월 10일 확인 시점에도 OpenAI Codex 이슈 #31864는 열려 있습니다. 이 글에서 설명하는 원인은 공개 이슈의 재현 결과를 토대로 한 유력한 분석이며, OpenAI 유지관리자가 확정한 영구 수정 공지는 아닙니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;가장 먼저 LazyCodex를 업데이트합니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LazyCodex 이슈 #118에는 v4.16.0이 세션 시작 때 넣던 &lt;code&gt;[features.multi_agent_v2] enabled = false&lt;/code&gt; 관리 설정이 GPT-5.6 Sol과 충돌할 수 있다는 내용이 올라왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 LazyCodex v4.16.2에서 수정됐습니다. 업데이트된 가드는 GPT-5.6 계열에서 문제가 될 수 있는 관리 블록의 &lt;code&gt;enabled = false&lt;/code&gt;, &lt;code&gt;hide_spawn_agent_metadata = false&lt;/code&gt;, &lt;code&gt;agents.max_threads&lt;/code&gt;를 정리합니다. 이후 Codex가 모델 정보에 맞춰 멀티 에이전트 버전을 선택하도록 둡니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 방식에 맞는 명령 하나를 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;codex plugin marketplace upgrade sisyphuslabs&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 최신 설치 프로그램을 실행합니다.&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;npx lazycodex-ai@latest install&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LazyCodex 자동 업데이트에는 최대 24시간 간격이 있을 수 있습니다. 오류가 이미 발생했다면 수동 업데이트가 빠릅니다. 업데이트가 끝나면 새 작업을 만들고 GPT-5.6 Sol로 짧은 메시지를 보내 봅니다.&lt;/p&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;사용자 전역 설정 파일의 기본 위치는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Windows: &lt;code&gt;%USERPROFILE%\.codex\config.toml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;macOS/Linux: &lt;code&gt;~/.codex/config.toml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;CODEX_HOME&lt;/code&gt;을 별도로 지정했다면 실제 파일은 다른 경로에 있을 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Windows PowerShell에서 백업&lt;/h3&gt;
&lt;pre class=&quot;powershell&quot;&gt;&lt;code&gt;$codexHome = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { &quot;$env:USERPROFILE\.codex&quot; }
$path = Join-Path $codexHome &quot;config.toml&quot;
Copy-Item -LiteralPath $path -Destination &quot;$path.bak.$(Get-Date -Format 'yyyyMMddHHmmss')&quot;
notepad $path&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;macOS/Linux에서 백업&lt;/h3&gt;
&lt;pre class=&quot;arcade&quot;&gt;&lt;code&gt;cp ~/.codex/config.toml ~/.codex/config.toml.bak
nano ~/.codex/config.toml&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;tool_namespace&lt;/code&gt; 한 줄 추가하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정 파일에 &lt;code&gt;[features.multi_agent_v2]&lt;/code&gt; 블록이 없다면 다음 내용을 한 번만 추가합니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[features.multi_agent_v2]
tool_namespace = &quot;agents&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 블록이 이미 있다면 새 블록을 만들지 말고 기존 블록 안에 아래 한 줄만 넣습니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;tool_namespace = &quot;agents&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenAI 공식 Configuration Reference가 연결하는 최신 &lt;code&gt;config-schema.json&lt;/code&gt;에도 &lt;code&gt;features.multi_agent_v2.tool_namespace&lt;/code&gt; 항목이 정의돼 있습니다. 다만 Codex 버전이나 모델 제공 경로가 다르면 결과도 달라질 수 있으므로 백업 후 적용하는 편이 안전합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TOML 중복 선언은 피해야 합니다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음처럼 &lt;code&gt;[features]&lt;/code&gt; 아래에 &lt;code&gt;multi_agent_v2&lt;/code&gt;가 불리언 값으로 들어 있는 상태에서 &lt;code&gt;[features.multi_agent_v2]&lt;/code&gt; 테이블을 덧붙이면 잘못된 TOML이 됩니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[features]
multi_agent_v2 = false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;multi_agent_v2&lt;/code&gt;를 값과 테이블로 동시에 선언할 수 없기 때문입니다. 오래된 LazyCodex가 만든 관리 설정이라면 먼저 v4.16.2 이상으로 업데이트하여 자동 정리를 실행하는 편이 낫습니다. 직접 넣은 설정이라면 백업한 뒤 기존 불리언 선언을 제거하고 테이블 형식 하나만 남깁니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[features.multi_agent_v2]
tool_namespace = &quot;agents&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;[features.multi_agent_v2]&lt;/code&gt; 블록 자체가 두 번 들어가 있어도 파싱 오류가 날 수 있습니다. 파일 맨 아래에 같은 블록을 통째로 붙이지 않았는지 확인하세요.&lt;/p&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;새 Codex 작업을 만듭니다.&lt;/li&gt;
&lt;li&gt;GPT-5.6 Sol을 선택합니다.&lt;/li&gt;
&lt;li&gt;간단한 메시지를 보냅니다.&lt;/li&gt;
&lt;li&gt;오류가 계속되면 Codex Desktop 창을 모두 닫고 다시 실행합니다.&lt;/li&gt;
&lt;li&gt;새 작업에서 한 번 더 확인합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱을 닫았는데도 달라지지 않을 때만 백그라운드 프로세스가 남아 있는지 봅니다. 처음부터 모든 프로세스를 강제 종료할 필요는 없습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CLI에서는 설정을 바꾸기 전에 시험할 수 있습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex CLI를 사용한다면 네임스페이스 변경을 일회성 옵션으로 먼저 확인해 볼 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;scilab&quot;&gt;&lt;code&gt;codex exec -m gpt-5.6-sol -c 'features.multi_agent_v2.tool_namespace=&quot;agents&quot;' 'Reply exactly OK.'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상 처리되면 결과에 &lt;code&gt;OK&lt;/code&gt;가 나옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;code&gt;Unknown model gpt-5.6-sol&lt;/code&gt;이 표시된다면 이번 스키마 충돌과는 다른 문제입니다. CLI 버전, 계정별 모델 접근 권한, 모델 캐시, 모델 제공 경로를 따로 살펴봐야 합니다.&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;codex --version&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows에서는 실제 실행되는 CLI 위치도 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;where.exe codex&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex Desktop에 포함된 런타임과 npm으로 설치한 Codex CLI의 버전은 다를 수 있습니다. CLI에서 성공했다고 Desktop까지 해결됐다고 단정하지 말고 두 환경을 나눠서 확인하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래도 안 될 때 보는 항목&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;[features.multi_agent_v2]&lt;/code&gt; 블록이 두 번 이상 있는지&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[features]&lt;/code&gt;의 &lt;code&gt;multi_agent_v2 = false&lt;/code&gt;와 &lt;code&gt;[features.multi_agent_v2]&lt;/code&gt; 테이블이 함께 있는지&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CODEX_HOME&lt;/code&gt;이 기본 경로와 다른 설정 파일을 가리키는지&lt;/li&gt;
&lt;li&gt;선택한 프로필의 설정이 전역 설정을 덮어쓰는지&lt;/li&gt;
&lt;li&gt;신뢰된 프로젝트의 &lt;code&gt;.codex/config.toml&lt;/code&gt;에 다른 값이 있는지&lt;/li&gt;
&lt;li&gt;LazyCodex 또는 OMO 업데이트 뒤 설정 파일이 다시 바뀌었는지&lt;/li&gt;
&lt;li&gt;Desktop과 CLI 가운데 어느 쪽에서만 문제가 생기는지&lt;/li&gt;
&lt;li&gt;프록시나 비공식 모델 제공자의 인증 오류, 모델 목록 누락, &lt;code&gt;Unknown model&lt;/code&gt;이 섞여 있지 않은지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열 검색으로 &lt;code&gt;tool_namespace = &quot;agents&quot;&lt;/code&gt;가 보인다고 해서 현재 작업에 그 설정이 적용됐다고 단정할 수는 없습니다. Codex가 설정 파싱 오류 없이 실행되고, 새 작업에서 해당 오류가 사라졌는지가 최종 기준입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;재부팅과 재설치부터 할 필요는 없습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터를 재부팅해도 디스크에 저장된 설정은 그대로입니다. Codex를 삭제하고 다시 설치해도 &lt;code&gt;~/.codex/config.toml&lt;/code&gt;이 남으면 같은 문제가 이어질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;multi_agent = false&lt;/code&gt;로 바꾸면 사용하려던 멀티 에이전트 기능까지 포기하게 됩니다. 영향을 받는 런타임에서 이 설정 하나로 충돌이 사라진다는 보장도 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;features.multi_agent_v2.enabled = true&lt;/code&gt;를 무조건 강제하는 것도 피하세요. 설정 조합에 따라 &lt;code&gt;agents.max_threads&lt;/code&gt;와 충돌할 수 있습니다. OMO 훅 전체를 끄는 방법 역시 정확한 원인을 확인하기 전에는 범위가 너무 큽니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 오류가 반복된다면 &lt;b&gt;LazyCodex 업데이트 &amp;rarr; 새 작업 확인 &amp;rarr; 설정 백업 &amp;rarr; 네임스페이스 변경&lt;/b&gt; 순서로 접근하는 것이 낫습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 오류가 GPT-5.6 Sol에서 모든 질문마다 반복된다면 프롬프트부터 고칠 문제는 아닐 가능성이 큽니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Invalid Value: 'tools'. Function 'collaboration.spawn_agent' is reserved for use by this model and must match the configured schema.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LazyCodex 또는 OMO 사용자라면 v4.16.2 이상으로 업데이트하고 새 작업에서 다시 확인하세요. 오류가 그대로 남을 때만 &lt;code&gt;config.toml&lt;/code&gt;을 백업하고 다음 설정을 적용합니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[features.multi_agent_v2]
tool_namespace = &quot;agents&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 한 줄은 멀티 에이전트를 끄지 않습니다. 예약된 &lt;code&gt;collaboration&lt;/code&gt; 이름과 겹치지 않도록 도구 네임스페이스만 바꿉니다. 업데이트부터 확인하면 불필요한 재설치나 기능 비활성화를 피할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고 자료&lt;/h2&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://mekain80.tistory.com/325&quot;&gt;https://mekain80.tistory.com/325&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenAI Codex 이슈 #31864: &lt;a href=&quot;https://github.com/openai/codex/issues/31864&quot;&gt;https://github.com/openai/codex/issues/31864&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenAI Codex Configuration Reference: &lt;a href=&quot;https://developers.openai.com/codex/config-reference&quot;&gt;https://developers.openai.com/codex/config-reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenAI Codex config schema: &lt;a href=&quot;https://developers.openai.com/codex/config-schema.json&quot;&gt;https://developers.openai.com/codex/config-schema.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;LazyCodex 이슈 #118: &lt;a href=&quot;https://github.com/code-yeongyu/lazycodex/issues/118&quot;&gt;https://github.com/code-yeongyu/lazycodex/issues/118&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부제목/미리보기: GPT-5.6 Sol에서 일반 질문까지 실패하는 &lt;code&gt;collaboration.spawn_agent&lt;/code&gt; 오류의 원인과 LazyCodex v4.16.2 업데이트, &lt;code&gt;config.toml&lt;/code&gt; 우회 설정, CLI 검증 순서를 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그: Codex, GPT-5.6 Sol, OpenAI Codex, collaboration.spawn_agent, MultiAgentV2, LazyCodex, OMO, config.toml, Codex 오류 해결, 멀티 에이전트&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/754</guid>
      <comments>https://series.tistory.com/entry/Codex-GPT-56-Sol-collaborationspawnagent-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0-%EB%A9%80%ED%8B%B0-%EC%97%90%EC%9D%B4%EC%A0%84%ED%8A%B8%EB%A5%BC-%EB%81%84%EA%B8%B0-%EC%A0%84%EC%97%90-%ED%99%95%EC%9D%B8%ED%95%A0-%EA%B2%83#entry754comment</comments>
      <pubDate>Fri, 10 Jul 2026 10:58:20 +0900</pubDate>
    </item>
    <item>
      <title>AI를 비서처럼 사용하려면 업무 흐름부터 정리해야 합니다</title>
      <link>https://series.tistory.com/entry/AI%EB%A5%BC-%EB%B9%84%EC%84%9C%EC%B2%98%EB%9F%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%A0%A4%EB%A9%B4-%EC%97%85%EB%AC%B4-%ED%9D%90%EB%A6%84%EB%B6%80%ED%84%B0-%EC%A0%95%EB%A6%AC%ED%95%B4%EC%95%BC-%ED%95%A9%EB%8B%88%EB%8B%A4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 AI 활용법을 보면 대부분 &amp;ldquo;프롬프트를 어떻게 잘 쓰느냐&amp;rdquo;에 집중합니다.&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;/p&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;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;h2 data-ke-size=&quot;size26&quot;&gt;AI 활용의 기준을 바꿔야 합니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI를 &amp;ldquo;잘 쓰는 도구&amp;rdquo;로만 보면 계속 내가 중심이 됩니다.&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;/p&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;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 AI에게 모든 판단을 넘기는 게 아닙니다.&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;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;하지만 시작은 작아도 됩니다.&lt;/p&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;/li&gt;
&lt;li&gt;긴 글에서 핵심만 뽑기&lt;/li&gt;
&lt;li&gt;반복되는 이메일 초안 만들기&lt;/li&gt;
&lt;li&gt;매일 확인하는 자료를 정리하기&lt;/li&gt;
&lt;li&gt;일정이나 할 일을 다시 분류하기&lt;/li&gt;
&lt;li&gt;블로그 글의 초안 구조 잡기&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;p data-ke-size=&quot;size16&quot;&gt;핵심은 &amp;ldquo;AI가 할 수 있는 일&amp;rdquo;을 찾는 게 아니라, &amp;ldquo;내가 계속 반복하고 있는 일&amp;rdquo;을 먼저 찾는 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;하지만 업무 흐름 안에 들어간 AI는 더 강력합니다.&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;/p&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;p data-ke-size=&quot;size16&quot;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;AI는 반복, 정리, 초안, 변환을 맡습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;하루 10분짜리 일부터 넘겨보세요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 거창한 자동화 시스템을 만들려고 하면 금방 막힙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 하루에 10분씩 잡아먹는 일을 하나만 골라보세요.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;이런 작은 일을 AI에게 넘기는 것만으로도 체감이 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하루 10분이면 별것 아닌 것 같지만, 매일 반복되면 한 달에 몇 시간이 됩니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI 시대의 생산성은 &amp;ldquo;질문력&amp;rdquo;보다 &amp;ldquo;위임력&amp;rdquo;에 가깝습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 AI를 잘 쓰는 사람은 단순히 프롬프트를 많이 아는 사람이 아닐 가능성이 큽니다.&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;AI에게 전부 맡기는 것이 아니라, 맡겨도 되는 일을 구분하는 능력.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세 가지가 쌓이면 AI는 단순한 도구가 아니라, 내 업무 흐름 안에서 계속 일하는 보조 인력이 됩니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이렇게 질문해보면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 일에서 내가 꼭 해야 하는 판단은 무엇이고, AI에게 넘겨도 되는 실행은 무엇일까?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 활용은 여기서부터 달라집니다.&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/753</guid>
      <comments>https://series.tistory.com/entry/AI%EB%A5%BC-%EB%B9%84%EC%84%9C%EC%B2%98%EB%9F%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%A0%A4%EB%A9%B4-%EC%97%85%EB%AC%B4-%ED%9D%90%EB%A6%84%EB%B6%80%ED%84%B0-%EC%A0%95%EB%A6%AC%ED%95%B4%EC%95%BC-%ED%95%A9%EB%8B%88%EB%8B%A4#entry753comment</comments>
      <pubDate>Mon, 29 Jun 2026 11:45:15 +0900</pubDate>
    </item>
    <item>
      <title>AX 시대, AI를 슬랙에 팀원처럼 초대하는 법</title>
      <link>https://series.tistory.com/entry/AX-%EC%8B%9C%EB%8C%80-AI%EB%A5%BC-%EC%8A%AC%EB%9E%99%EC%97%90-%ED%8C%80%EC%9B%90%EC%B2%98%EB%9F%BC-%EC%B4%88%EB%8C%80%ED%95%98%EB%8A%94-%EB%B2%95</link>
      <description>&lt;h1&gt;AX 시대, AI를 슬랙에 팀원처럼 초대하는 법&lt;/h1&gt;
&lt;p&gt;AI를 업무에 쓰는 방식이 바뀌고 있습니다.&lt;/p&gt;
&lt;p&gt;예전에는 한 사람이 챗봇 하나를 열고 질문하는 방식이 대부분이었습니다. 자료를 요약하고, 글을 고치고, 코드를 작성하는 식이었죠. 이때 AI는 개인 생산성 도구에 가까웠습니다.&lt;/p&gt;
&lt;p&gt;그런데 AX, 즉 AI Transformation 관점에서 보면 다음 단계는 조금 다릅니다. 이제는 AI를 개인 대화창 안에 두는 것이 아니라, 슬랙 같은 협업 공간에 초대해 팀의 일부처럼 함께 일하게 만드는 방향으로 가고 있습니다.&lt;/p&gt;
&lt;p&gt;여기서 중요한 질문이 생깁니다.&lt;/p&gt;
&lt;p&gt;AI를 팀 채널에 초대한다는 건, 단순히 편한 도구를 하나 더 붙이는 일이 아닙니다. 같이 일할 팀원을 한 명 더 들이는 일에 가깝습니다. 그래서 어떤 일을 맡길지, 어떤 자료를 보게 할지, 결과를 어떻게 확인할지 정도는 미리 정해두는 편이 좋습니다.&lt;/p&gt;
&lt;h2&gt;1. AX의 출발점은 ‘AI 사용’이 아니라 ‘팀 운영 방식’입니다&lt;/h2&gt;
&lt;p&gt;많은 조직이 AI 도입을 개인 생산성 관점에서 시작합니다. 직원들이 AI로 문서를 빨리 쓰고, 개발자가 코드를 빨리 만들고, 기획자가 자료를 빨리 정리하는 식입니다.&lt;/p&gt;
&lt;p&gt;물론 효과는 있습니다. 하지만 개인 단위로만 AI를 쓰면 팀의 맥락은 흩어지기 쉽습니다. 같은 질문을 여러 사람이 따로 하고, 비슷한 문서를 각자 만들고, 중요한 판단이 개인 대화창 안에 남습니다.&lt;/p&gt;
&lt;p&gt;AX는 여기서 한 단계 더 나아갑니다.&lt;/p&gt;
&lt;p&gt;“각자가 AI를 잘 쓰는가?”보다 “우리 팀의 일하는 방식이 AI와 함께 일하도록 바뀌었는가?”를 봐야 합니다.&lt;/p&gt;
&lt;p&gt;AI가 팀의 공통 자료를 읽고, 같은 목표를 기준으로 움직이고, 같은 채널에 결과를 남길 때 생산성은 개인을 넘어 팀 단위로 올라갑니다.&lt;/p&gt;
&lt;h2&gt;2. AI를 슬랙에 팀원처럼 초대하면 일이 훨씬 자연스러워집니다&lt;/h2&gt;
&lt;p&gt;AI를 슬랙 같은 협업 공간에 초대하면 일하는 흐름이 훨씬 자연스러워집니다. 따로 창을 열어 질문하고 답을 복사해오는 대신, 팀이 대화하는 자리에서 바로 AI를 부를 수 있기 때문입니다.&lt;/p&gt;
&lt;p&gt;예를 들어 회의가 끝난 뒤 “오늘 결정된 내용만 정리해줘”라고 부탁할 수 있습니다. 새로 들어온 팀원에게 필요한 문서를 찾아달라고 할 수도 있고, 긴 논의 끝에 남은 할 일을 뽑아달라고 할 수도 있습니다.&lt;/p&gt;
&lt;p&gt;이렇게 되면 AI는 개인 비서라기보다 팀 채널에 함께 있는 동료에 가까워집니다. 사람이 맥락을 다시 설명하는 시간이 줄고, 팀원들도 같은 자리에서 AI가 정리한 내용을 함께 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;다만 AI를 팀원처럼 쓰려면 기본적인 운영 방식은 정해두는 편이 좋습니다. 어떤 채널에서 부를지, 어떤 일을 맡길지, 어느 정도까지 스스로 처리하게 할지 정도는 팀 안에서 합의가 필요합니다.&lt;/p&gt;
&lt;p&gt;이 기준이 있으면 AI를 쓰는 일이 훨씬 편해집니다. 매번 “어디까지 시켜도 되지?”를 고민하지 않아도 되고, AI가 남긴 결과도 팀의 공식 흐름 안에 자연스럽게 쌓입니다.&lt;/p&gt;
&lt;h2&gt;3. 사람과 AI 모두에게 역할이 있어야 합니다&lt;/h2&gt;
&lt;p&gt;AI를 팀에 붙일 때 가장 먼저 정해야 하는 건 역할입니다. 아무 일이나 던지는 방식으로는 오래가기 어렵습니다.&lt;/p&gt;
&lt;p&gt;예를 들어 한 AI는 자료 정리를 맡고, 다른 AI는 초안 작성을 맡고, 또 다른 AI는 검토를 맡을 수 있습니다. 사람은 방향을 정하고, 중요한 판단을 하고, 외부로 나가는 결과물을 최종 확인합니다.&lt;/p&gt;
&lt;p&gt;이렇게 나누면 일이 훨씬 단순해집니다. 누가 무엇을 맡았는지 보이고, AI에게 어떤 자료나 도구가 필요한지도 자연스럽게 정리됩니다.&lt;/p&gt;
&lt;p&gt;반대로 역할이 없으면 팀원마다 AI에게 다른 방식으로 일을 시키게 됩니다. 결과물은 흩어지고, 같은 작업을 반복하고, 나중에는 어떤 기준으로 나온 결과인지 확인하기 어려워집니다.&lt;/p&gt;
&lt;p&gt;AI도 팀원이 된다고 생각하면 답이 조금 쉬워집니다. 새 팀원이 들어왔을 때처럼 “이 사람은 무엇을 맡는가”, “어떤 자료를 보면 되는가”, “어떤 결과를 남겨야 하는가”를 정해주면 됩니다.&lt;/p&gt;
&lt;h2&gt;4. AI도 팀의 흐름을 알아야 일을 잘합니다&lt;/h2&gt;
&lt;p&gt;AI는 사람이 말하지 않은 분위기나 배경을 저절로 알지 못합니다. 회의에서 말로만 정한 내용, 개인 메신저에만 남은 결정, 담당자 머릿속에만 있는 기준은 AI 입장에서는 없는 정보와 같습니다.&lt;/p&gt;
&lt;p&gt;그래서 AI를 슬랙 채널에 초대한다면, 중요한 결정과 기준은 팀이 함께 보는 곳에 남기는 편이 좋습니다.&lt;/p&gt;
&lt;p&gt;회의에서 정한 내용은 회의록에 남기고, 우선순위가 바뀌면 채널이나 문서에 적어두고, 프로젝트 기준은 찾기 쉬운 곳에 정리해두는 식입니다. 그래야 사람도 AI도 같은 내용을 보고 움직입니다.&lt;/p&gt;
&lt;p&gt;물론 모든 정보를 다 공개하자는 뜻은 아닙니다. 민감한 정보는 당연히 구분해야 합니다. 다만 함께 일하기로 한 범위 안에서는 필요한 맥락을 찾을 수 있어야 합니다.&lt;/p&gt;
&lt;p&gt;AI에게는 문서와 대화 기록이 업무 환경입니다. 기록이 잘 남아 있는 팀일수록 AI가 더 빨리 이해하고, 덜 헤맵니다.&lt;/p&gt;
&lt;h2&gt;5. 사람은 더 중요한 판단에 집중해야 합니다&lt;/h2&gt;
&lt;p&gt;AI가 팀 채널 안에서 할 수 있는 일은 생각보다 많습니다. 회의 내용을 정리하고, 자료를 모으고, 초안을 만들고, 빠진 부분을 찾아볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;하지만 그렇다고 해서 사람의 역할이 사라지는 것은 아닙니다. 오히려 더 선명해집니다.&lt;/p&gt;
&lt;p&gt;AI가 반복적인 정리와 초안을 맡아주면, 사람은 방향을 정하고 우선순위를 판단하는 데 더 많은 시간을 쓸 수 있습니다. 외부로 나가는 글, 고객에게 전달되는 답변, 중요한 의사결정은 여전히 사람이 확인해야 합니다.&lt;/p&gt;
&lt;p&gt;AX가 좋은 방향으로 가려면 “AI가 어디까지 해줄 수 있는가”만 보지 말고 “사람은 어떤 판단에 집중해야 하는가”도 함께 봐야 합니다.&lt;/p&gt;
&lt;h2&gt;6. 팀이 어디로 가는지 AI도 알아야 합니다&lt;/h2&gt;
&lt;p&gt;AI가 팀의 일을 도우려면 “우리 팀이 지금 어디에 집중하고 있는지”를 알아야 합니다.&lt;/p&gt;
&lt;p&gt;예를 들어 “고객 문의 처리 시간을 줄인다”, “신규 사용자가 첫 성공 경험을 더 빨리 하게 만든다”, “반복 운영 업무를 줄이고 사람이 판단해야 할 일에 집중한다” 같은 문장이 있을 수 있습니다.&lt;/p&gt;
&lt;p&gt;이런 방향이 정리되어 있으면 AI도 더 좋은 방식으로 돕습니다. 자료를 정리할 때도 중요한 것부터 보려고 하고, 제안을 할 때도 팀이 실제로 신경 쓰는 문제에 맞춰 생각합니다.&lt;/p&gt;
&lt;p&gt;물론 처음부터 AI에게 너무 많은 판단을 맡길 필요는 없습니다. 처음에는 정해진 일을 맡기고, 결과를 보면서 조금씩 범위를 넓히면 됩니다.&lt;/p&gt;
&lt;h2&gt;7. 신뢰는 검증 구조에서 생깁니다&lt;/h2&gt;
&lt;p&gt;AI 에이전트에게 일을 맡기려면 신뢰가 필요합니다. 그런데 신뢰는 “AI가 똑똑하다”는 인상만으로 만들어지지 않습니다.&lt;/p&gt;
&lt;p&gt;처음에는 사람이 결과를 직접 보고, 기준을 알려주고, 필요한 경우 다시 하게 해야 합니다. 업무별 체크리스트도 필요합니다. 코드라면 테스트가 있어야 하고, 문서라면 톤과 구조에 대한 기준이 있어야 합니다. 콘텐츠라면 사실 확인과 금지 표현 기준이 있어야 합니다.&lt;/p&gt;
&lt;p&gt;한 AI가 작업하고 다른 AI가 검토하는 방식도 유용합니다. 사람에게 오기 전에 1차 오류를 줄일 수 있기 때문입니다.&lt;/p&gt;
&lt;p&gt;중요한 건 AI에게 맡길수록 사람의 역할이 사라지는 게 아니라는 점입니다. 오히려 사람의 역할은 더 선명해집니다. 방향 설정, 판단, 승인, 책임은 여전히 사람에게 남습니다. AI는 그 판단이 필요한 지점까지 가는 반복 작업을 줄여줍니다.&lt;/p&gt;
&lt;h2&gt;AX를 시작하는 팀이 먼저 물어볼 질문&lt;/h2&gt;
&lt;p&gt;AI를 팀 채널에 초대하기 전에 아래 질문부터 정리해보면 좋습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI를 어떤 슬랙 채널에서 부를 것인가?&lt;/li&gt;
&lt;li&gt;AI에게 주로 어떤 일을 맡길 것인가?&lt;/li&gt;
&lt;li&gt;AI가 참고할 문서와 자료는 어디에 정리되어 있는가?&lt;/li&gt;
&lt;li&gt;사람과 AI의 역할을 한 문장으로 설명할 수 있는가?&lt;/li&gt;
&lt;li&gt;중요한 결정이 개인 대화가 아니라 공유 채널이나 문서에 남는가?&lt;/li&gt;
&lt;li&gt;팀이 지금 집중하는 방향이 짧게 정리되어 있는가?&lt;/li&gt;
&lt;li&gt;결과물을 검증할 체크리스트나 테스트가 있는가?&lt;/li&gt;
&lt;li&gt;AI가 반드시 사람에게 승인을 받아야 하는 작업이 구분되어 있는가?&lt;/li&gt;
&lt;li&gt;AI가 남긴 결과를 팀 기록으로 쌓는 방식이 있는가?&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/752</guid>
      <comments>https://series.tistory.com/entry/AX-%EC%8B%9C%EB%8C%80-AI%EB%A5%BC-%EC%8A%AC%EB%9E%99%EC%97%90-%ED%8C%80%EC%9B%90%EC%B2%98%EB%9F%BC-%EC%B4%88%EB%8C%80%ED%95%98%EB%8A%94-%EB%B2%95#entry752comment</comments>
      <pubDate>Fri, 26 Jun 2026 11:02:27 +0900</pubDate>
    </item>
    <item>
      <title>AI 도입해야 한다는 건 아는데, 사내에서 어디부터 시작해야 할지 모르시는 분 있으세요?</title>
      <link>https://series.tistory.com/entry/AI-%EB%8F%84%EC%9E%85%ED%95%B4%EC%95%BC-%ED%95%9C%EB%8B%A4%EB%8A%94-%EA%B1%B4-%EC%95%84%EB%8A%94%EB%8D%B0-%EC%82%AC%EB%82%B4%EC%97%90%EC%84%9C-%EC%96%B4%EB%94%94%EB%B6%80%ED%84%B0-%EC%8B%9C%EC%9E%91%ED%95%B4%EC%95%BC-%ED%95%A0%EC%A7%80-%EB%AA%A8%EB%A5%B4%EC%8B%9C%EB%8A%94-%EB%B6%84-%EC%9E%88%EC%9C%BC%EC%84%B8%EC%9A%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AI&amp;nbsp;도입해야&amp;nbsp;한다는&amp;nbsp;건&amp;nbsp;아는데,&amp;nbsp;사내에서&amp;nbsp;어디부터&amp;nbsp;시작해야&amp;nbsp;할지&amp;nbsp;모르시는&amp;nbsp;분&amp;nbsp;있으세요?&lt;br /&gt;현장에서&amp;nbsp;AX가&amp;nbsp;막히는&amp;nbsp;지점은&amp;nbsp;딱&amp;nbsp;두&amp;nbsp;가지라고&amp;nbsp;해요.&lt;br /&gt;첫째,&amp;nbsp;복잡한&amp;nbsp;실무는&amp;nbsp;멀티에이전트&amp;nbsp;자동화가&amp;nbsp;필요한데&amp;nbsp;내부에서&amp;nbsp;구축하기가&amp;nbsp;어렵다는&amp;nbsp;것.&lt;br /&gt;둘째,&amp;nbsp;AI가&amp;nbsp;잘&amp;nbsp;일하려면&amp;nbsp;비즈니스&amp;nbsp;데이터가&amp;nbsp;공급되어야&amp;nbsp;하는데,&amp;nbsp;어떻게&amp;nbsp;넣을지&amp;nbsp;모르거나&amp;nbsp;쌓아둔&amp;nbsp;데이터&amp;nbsp;자체가&amp;nbsp;없는&amp;nbsp;경우가&amp;nbsp;많다는&amp;nbsp;것.&lt;br /&gt;그래서&amp;nbsp;현장에서&amp;nbsp;효과적인&amp;nbsp;접근은&amp;nbsp;&quot;가장&amp;nbsp;귀찮은&amp;nbsp;반복&amp;nbsp;업무&amp;nbsp;1개부터&amp;nbsp;AI에&amp;nbsp;연결하는&amp;nbsp;것&quot;이에요.&lt;br /&gt;작은&amp;nbsp;효용을&amp;nbsp;한&amp;nbsp;번&amp;nbsp;경험하면,&amp;nbsp;사람들은&amp;nbsp;스스로&amp;nbsp;데이터를&amp;nbsp;더&amp;nbsp;넣으려&amp;nbsp;한다고&amp;nbsp;해요.&lt;br /&gt;AX는&amp;nbsp;거창한&amp;nbsp;선언이&amp;nbsp;아니에요.&lt;/p&gt;
&lt;p 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;04-key-2.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coLREj/dJMb99TLOg8/I1udmuTqG3OrVdKBIea05k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coLREj/dJMb99TLOg8/I1udmuTqG3OrVdKBIea05k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coLREj/dJMb99TLOg8/I1udmuTqG3OrVdKBIea05k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoLREj%2FdJMb99TLOg8%2FI1udmuTqG3OrVdKBIea05k%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;04-key-2.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05-quote-1.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lyaWR/dJMcab47PiP/5qbkRZf4tclHzDvC6vF2fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lyaWR/dJMcab47PiP/5qbkRZf4tclHzDvC6vF2fk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lyaWR/dJMcab47PiP/5qbkRZf4tclHzDvC6vF2fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlyaWR%2FdJMcab47PiP%2F5qbkRZf4tclHzDvC6vF2fk%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;05-quote-1.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06-quote-2.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beTC9m/dJMcaiXrgXx/5OBzeSassLAvYbY0sZKkCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beTC9m/dJMcaiXrgXx/5OBzeSassLAvYbY0sZKkCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beTC9m/dJMcaiXrgXx/5OBzeSassLAvYbY0sZKkCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeTC9m%2FdJMcaiXrgXx%2F5OBzeSassLAvYbY0sZKkCK%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;06-quote-2.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07-safety.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvDDeU/dJMcaarDmvE/I4e2sGAAEvIbCn9btes7Xk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvDDeU/dJMcaarDmvE/I4e2sGAAEvIbCn9btes7Xk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvDDeU/dJMcaarDmvE/I4e2sGAAEvIbCn9btes7Xk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvDDeU%2FdJMcaarDmvE%2FI4e2sGAAEvIbCn9btes7Xk%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;07-safety.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08-alignment.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqLnP7/dJMcaarDmvF/99qFxzEfnD2pnzukbrKW71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqLnP7/dJMcaarDmvF/99qFxzEfnD2pnzukbrKW71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqLnP7/dJMcaarDmvF/99qFxzEfnD2pnzukbrKW71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqLnP7%2FdJMcaarDmvF%2F99qFxzEfnD2pnzukbrKW71%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;08-alignment.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;09-migration.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjiCew/dJMcab47PiQ/SVN1NfvsDvqJegURzAmH9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjiCew/dJMcab47PiQ/SVN1NfvsDvqJegURzAmH9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjiCew/dJMcab47PiQ/SVN1NfvsDvqJegURzAmH9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjiCew%2FdJMcab47PiQ%2FSVN1NfvsDvqJegURzAmH9K%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;09-migration.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10-cta.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5ZXFb/dJMb99TLOg9/dkAAGZLzWn9lcYuGGX9hm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5ZXFb/dJMb99TLOg9/dkAAGZLzWn9lcYuGGX9hm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5ZXFb/dJMb99TLOg9/dkAAGZLzWn9lcYuGGX9hm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5ZXFb%2FdJMb99TLOg9%2FdkAAGZLzWn9lcYuGGX9hm0%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;10-cta.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rich.legend.ai&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;richlegendai&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/751</guid>
      <comments>https://series.tistory.com/entry/AI-%EB%8F%84%EC%9E%85%ED%95%B4%EC%95%BC-%ED%95%9C%EB%8B%A4%EB%8A%94-%EA%B1%B4-%EC%95%84%EB%8A%94%EB%8D%B0-%EC%82%AC%EB%82%B4%EC%97%90%EC%84%9C-%EC%96%B4%EB%94%94%EB%B6%80%ED%84%B0-%EC%8B%9C%EC%9E%91%ED%95%B4%EC%95%BC-%ED%95%A0%EC%A7%80-%EB%AA%A8%EB%A5%B4%EC%8B%9C%EB%8A%94-%EB%B6%84-%EC%9E%88%EC%9C%BC%EC%84%B8%EC%9A%94#entry751comment</comments>
      <pubDate>Sat, 2 May 2026 15:46:52 +0900</pubDate>
    </item>
    <item>
      <title>AX 채용 시장을 직접 들여다보니 &amp;mdash; 경력직 중심, 재설계 역량, 그리고 진짜 AX 인재의 조건</title>
      <link>https://series.tistory.com/entry/AX-%EC%B1%84%EC%9A%A9-%EC%8B%9C%EC%9E%A5%EC%9D%84-%EC%A7%81%EC%A0%91-%EB%93%A4%EC%97%AC%EB%8B%A4%EB%B3%B4%EB%8B%88-%E2%80%94-%EA%B2%BD%EB%A0%A5%EC%A7%81-%EC%A4%91%EC%8B%AC-%EC%9E%AC%EC%84%A4%EA%B3%84-%EC%97%AD%EB%9F%89-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%A7%84%EC%A7%9C-AX-%EC%9D%B8%EC%9E%AC%EC%9D%98-%EC%A1%B0%EA%B1%B4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01-cover.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5leZc/dJMcaa6ejY8/jOFKHsxyC5MBe0MfUjFBu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5leZc/dJMcaa6ejY8/jOFKHsxyC5MBe0MfUjFBu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5leZc/dJMcaa6ejY8/jOFKHsxyC5MBe0MfUjFBu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5leZc%2FdJMcaa6ejY8%2FjOFKHsxyC5MBe0MfUjFBu0%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;01-cover.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;AX 채용 시장을 직접 들여다보니 &amp;mdash; 경력직 중심, 재설계 역량, 그리고 진짜 AX 인재의 조건&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 AX(AI Transformation) 채용 공고를 꽤 오래 살펴볼 기회가 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포지션별 요건, 선호 경력, 도메인 분포까지 훑어보고 나니 하나의 흐름이 선명하게 보였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AX는 지금, 신입 시장이 아닙니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AX는 경력직 시장입니다 &amp;mdash; 평균 4.3년, 중앙값 3년&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공고에서 확인한 요구 경력의 평균은 약 4.3년이었고, 중앙값은 3년 정도였습니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기업들이 AI를 다룰 줄 아는 사람이 아니라, &lt;b&gt;현업의 일을 이해하고 그 구조를 바꿀 수 있는 사람&lt;/b&gt;을 찾고 있다는 뜻입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;가장 많이 본 역량 키워드 &amp;mdash; As-Is에서 To-Be로&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공고에서 가장 자주 등장한 흐름은 &lt;b&gt;As-Is 분석 &amp;rarr; To-Be 설계 &amp;rarr; 운영 안착&lt;/b&gt;이었습니다.&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;여기서 중요한 포인트가 하나 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PoC(개념 검증)에서 끝나는 게 아니라, &lt;b&gt;실제 운영까지 끌고 가는 경험&lt;/b&gt;을 요구한다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실험에서 멈추는 게 아니라, 조직에 정착시키는 과정까지 책임져본 사람이어야 한다는 것이죠.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AX는 ChatGPT 계정 배포가 아닙니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 말하면, 그동안 'AI 도입'이라는 이름 아래 ChatGPT 계정을 나눠주고 몇 번 교육하는 걸 AX라고 부르는 경우도 많았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 채용 시장에서 보이는 AX는 그 레벨이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;일하는 방식 자체가 바뀌어야 AX입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 툴 도입이 아닌, 프로세스 재설계, 구조 변화, 조직 문화의 전환까지 포함합니다.&lt;/p&gt;
&lt;hr 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;AX 수요가 어느 산업에 몰려 있는지도 꽤 선명하게 보였습니다.&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;: 공정, 설계, 품질, 생산관리 영역에 AI를 연결하려는 수요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;금융&lt;/b&gt;: 보안과 컴플라이언스 규제 안에서 AI를 적용하려는 수요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공공&lt;/b&gt;: B2G, R&amp;amp;D, 행정 자동화 중심의 수요&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 산업 특성에 맞는 도메인 이해 없이는 AX 역할을 제대로 수행하기 어렵다는 뜻이기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뜬구름 잡듯 'AI 잘함'으로 통하던 시대가 지나고, 이제 각 산업의 실제 업무 안으로 AI가 들어가기 시작한 것입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론 &amp;mdash; AX 인재의 진짜 조건&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AX 인재는 AI 뉴스를 많이 아는 사람이 아닙니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 속한 조직의 일이 어떻게 흘러가는지 알고,&lt;br /&gt;그 일을 AI가 들어갈 수 있는 구조로 다시 바꿀 수 있는 사람.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일을 직접 해본 경험, 시스템 안에서 굴러가는 업무를 이해해본 경험, 그리고 다른 사람의 문제를 해결 가능한 구조로 바꿔줄 수 있는 감각.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI를 잘 아는 것도 중요하지만, 그보다 먼저 &lt;b&gt;일이 어떻게 돌아가는지 알아야&lt;/b&gt; 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래야 어디에 AI를 넣어야 하는지, 무엇을 자동화해야 하는지, 어떤 부분은 사람이 판단해야 하는지가 비로소 보이기 때문입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AX는 SI가 아닙니다. 일하는 방식을 재설계하는 것입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p 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;03-essence.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XDirC/dJMcagZDBo6/CrOaw0Z1v9ulHoLFCd7v50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XDirC/dJMcagZDBo6/CrOaw0Z1v9ulHoLFCd7v50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XDirC/dJMcagZDBo6/CrOaw0Z1v9ulHoLFCd7v50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXDirC%2FdJMcagZDBo6%2FCrOaw0Z1v9ulHoLFCd7v50%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;03-essence.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04-skill.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqf6IV/dJMcadPlrTL/PU5V3c9POjDdkQHjxwFxL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqf6IV/dJMcadPlrTL/PU5V3c9POjDdkQHjxwFxL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqf6IV/dJMcadPlrTL/PU5V3c9POjDdkQHjxwFxL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbqf6IV%2FdJMcadPlrTL%2FPU5V3c9POjDdkQHjxwFxL0%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;04-skill.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05-poc.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djV0oV/dJMcagZDBo7/kw3gpP6kOk3hvLX2sjICZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djV0oV/dJMcagZDBo7/kw3gpP6kOk3hvLX2sjICZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djV0oV/dJMcagZDBo7/kw3gpP6kOk3hvLX2sjICZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjV0oV%2FdJMcagZDBo7%2Fkw3gpP6kOk3hvLX2sjICZk%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;05-poc.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06-domain.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dLZJPC/dJMcadPlrTK/Pm2f2C8XRBLYh8vVhUUkC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dLZJPC/dJMcadPlrTK/Pm2f2C8XRBLYh8vVhUUkC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dLZJPC/dJMcadPlrTK/Pm2f2C8XRBLYh8vVhUUkC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdLZJPC%2FdJMcadPlrTK%2FPm2f2C8XRBLYh8vVhUUkC1%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;06-domain.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07-diff.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/epC9Bu/dJMcahK3g6q/El1SdBGf1ZGKKO7m1wqhiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/epC9Bu/dJMcahK3g6q/El1SdBGf1ZGKKO7m1wqhiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/epC9Bu/dJMcahK3g6q/El1SdBGf1ZGKKO7m1wqhiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FepC9Bu%2FdJMcahK3g6q%2FEl1SdBGf1ZGKKO7m1wqhiK%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;07-diff.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08-cta.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HYH0n/dJMcahK3g6r/l6P3sRx1wU0fXyc0aHBkk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HYH0n/dJMcahK3g6r/l6P3sRx1wU0fXyc0aHBkk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HYH0n/dJMcahK3g6r/l6P3sRx1wU0fXyc0aHBkk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHYH0n%2FdJMcahK3g6r%2Fl6P3sRx1wU0fXyc0aHBkk1%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;08-cta.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/750</guid>
      <comments>https://series.tistory.com/entry/AX-%EC%B1%84%EC%9A%A9-%EC%8B%9C%EC%9E%A5%EC%9D%84-%EC%A7%81%EC%A0%91-%EB%93%A4%EC%97%AC%EB%8B%A4%EB%B3%B4%EB%8B%88-%E2%80%94-%EA%B2%BD%EB%A0%A5%EC%A7%81-%EC%A4%91%EC%8B%AC-%EC%9E%AC%EC%84%A4%EA%B3%84-%EC%97%AD%EB%9F%89-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%A7%84%EC%A7%9C-AX-%EC%9D%B8%EC%9E%AC%EC%9D%98-%EC%A1%B0%EA%B1%B4#entry750comment</comments>
      <pubDate>Fri, 1 May 2026 15:59:02 +0900</pubDate>
    </item>
    <item>
      <title>github에 오픈소스 SaaS 스타터킷을 배포했습니다.</title>
      <link>https://series.tistory.com/entry/github%EC%97%90-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-SaaS-%EC%8A%A4%ED%83%80%ED%84%B0%ED%82%B7%EC%9D%84-%EB%B0%B0%ED%8F%AC%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1772&quot; data-origin-height=&quot;1904&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bic7F/dJMcag6pVcw/exBRzk3V9K4ctGlFwM19iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bic7F/dJMcag6pVcw/exBRzk3V9K4ctGlFwM19iK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bic7F/dJMcag6pVcw/exBRzk3V9K4ctGlFwM19iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBic7F%2FdJMcag6pVcw%2FexBRzk3V9K4ctGlFwM19iK%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;1772&quot; height=&quot;1904&quot; data-origin-width=&quot;1772&quot; data-origin-height=&quot;1904&quot;/&gt;&lt;/span&gt;&lt;/figure&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;SaaS&amp;nbsp;새로&amp;nbsp;만들&amp;nbsp;때마다&amp;nbsp;똑같은&amp;nbsp;데서&amp;nbsp;시간&amp;nbsp;다&amp;nbsp;까먹는&amp;nbsp;거,&amp;nbsp;저만&amp;nbsp;그런&amp;nbsp;거&amp;nbsp;아니죠.&lt;br /&gt;로그인&amp;nbsp;붙이는&amp;nbsp;데&amp;nbsp;하루,&amp;nbsp;결제&amp;nbsp;붙이는&amp;nbsp;데&amp;nbsp;또&amp;nbsp;하루,&amp;nbsp;DB&amp;nbsp;스키마&amp;nbsp;짜다&amp;nbsp;보면&amp;nbsp;정작&amp;nbsp;본&amp;nbsp;기능은&amp;nbsp;손도&amp;nbsp;못&amp;nbsp;댄&amp;nbsp;채&amp;nbsp;주말이&amp;nbsp;끝나더라고요.&amp;nbsp;매번&amp;nbsp;그러니까&amp;nbsp;어느&amp;nbsp;순간부터&amp;nbsp;새&amp;nbsp;SaaS&amp;nbsp;시작하는&amp;nbsp;게&amp;nbsp;좀&amp;nbsp;무서워졌어요.&lt;br /&gt;그래서&amp;nbsp;제가&amp;nbsp;매번&amp;nbsp;쓰던&amp;nbsp;조합을&amp;nbsp;한&amp;nbsp;번에&amp;nbsp;합쳐서&amp;nbsp;github에&amp;nbsp;오픈소스&amp;nbsp;SaaS&amp;nbsp;스타터킷으로&amp;nbsp;풀었어요.&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;이름은&amp;nbsp;RichLegend&amp;nbsp;AI&amp;nbsp;SaaS&amp;nbsp;Starter&amp;nbsp;Kit이고,&amp;nbsp;한국어가&amp;nbsp;기본인&amp;nbsp;SaaS&amp;nbsp;보일러플레이트&amp;nbsp;/&amp;nbsp;템플릿이라고&amp;nbsp;보시면&amp;nbsp;돼요.&lt;br /&gt;들어&amp;nbsp;있는&amp;nbsp;스택은&amp;nbsp;이렇게&amp;nbsp;돼요.&lt;br /&gt;Next.js&amp;nbsp;16&amp;nbsp;(App&amp;nbsp;Router&amp;nbsp;기반)&lt;br /&gt;Clerk&amp;nbsp;인증&lt;br /&gt;Polar.sh&amp;nbsp;결제&amp;nbsp;+&amp;nbsp;webhook&lt;br /&gt;Supabase&amp;nbsp;Postgres&amp;nbsp;+&amp;nbsp;Drizzle&amp;nbsp;ORM&lt;br /&gt;next-intl&amp;nbsp;다국어&amp;nbsp;(한국어/영어,&amp;nbsp;확장&amp;nbsp;가능)&lt;br /&gt;TailwindCSS&amp;nbsp;+&amp;nbsp;Base&amp;nbsp;UI&lt;br /&gt;SEO&amp;nbsp;/&amp;nbsp;JSON-LD&amp;nbsp;/&amp;nbsp;sitemap&amp;nbsp;/&amp;nbsp;hreflang&lt;br /&gt;공개&amp;nbsp;저장소용&amp;nbsp;secret-scan&lt;br /&gt;MIT라&amp;nbsp;그냥&amp;nbsp;가져다&amp;nbsp;쓰셔도&amp;nbsp;되고,&amp;nbsp;한국어가&amp;nbsp;기본이라&amp;nbsp;카피&amp;nbsp;다시&amp;nbsp;쓰는&amp;nbsp;일도&amp;nbsp;줄어요.&lt;br /&gt;pnpm&amp;nbsp;install&amp;nbsp;하고&amp;nbsp;.env.local&amp;nbsp;채운&amp;nbsp;다음&amp;nbsp;pnpm&amp;nbsp;dev&amp;nbsp;하면&amp;nbsp;바로&amp;nbsp;/ko&amp;nbsp;화면이&amp;nbsp;떠요.&amp;nbsp;똑같은&amp;nbsp;기반&amp;nbsp;작업&amp;nbsp;또&amp;nbsp;반복하기&amp;nbsp;싫으셨던&amp;nbsp;분들에게&amp;nbsp;도움이&amp;nbsp;됐으면&amp;nbsp;해요.&amp;nbsp;&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://github.com/richlegendai/richlegendai-saas-starter-kit-nextjs-v1&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/richlegendai/richlegendai-saas-starter-kit-nextjs-v1&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1777521891319&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - richlegendai/richlegendai-saas-starter-kit-nextjs-v1&quot; data-og-description=&quot;Contribute to richlegendai/richlegendai-saas-starter-kit-nextjs-v1 development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/richlegendai/richlegendai-saas-starter-kit-nextjs-v1&quot; data-og-url=&quot;https://github.com/richlegendai/richlegendai-saas-starter-kit-nextjs-v1&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/g6MWF/dJMb85WWEeT/7mIz2AaZB6RHO4OVWCLcR1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/caIPTE/dJMb87NZOZY/KNIdghGgt2FElbKQgViFe0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/richlegendai/richlegendai-saas-starter-kit-nextjs-v1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/richlegendai/richlegendai-saas-starter-kit-nextjs-v1&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/g6MWF/dJMb85WWEeT/7mIz2AaZB6RHO4OVWCLcR1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/caIPTE/dJMb87NZOZY/KNIdghGgt2FElbKQgViFe0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - richlegendai/richlegendai-saas-starter-kit-nextjs-v1&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to richlegendai/richlegendai-saas-starter-kit-nextjs-v1 development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p 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-origin-width=&quot;1744&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bklVu2/dJMcadohPUv/8MCT2PuuKpsocP2nVci1v0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bklVu2/dJMcadohPUv/8MCT2PuuKpsocP2nVci1v0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bklVu2/dJMcadohPUv/8MCT2PuuKpsocP2nVci1v0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbklVu2%2FdJMcadohPUv%2F8MCT2PuuKpsocP2nVci1v0%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;1744&quot; height=&quot;1202&quot; data-origin-width=&quot;1744&quot; data-origin-height=&quot;1202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p 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-origin-width=&quot;1724&quot; data-origin-height=&quot;1920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZ4oaz/dJMcajaXJyf/CI5SbYEqlq1kWmZo6vuku1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZ4oaz/dJMcajaXJyf/CI5SbYEqlq1kWmZo6vuku1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZ4oaz/dJMcajaXJyf/CI5SbYEqlq1kWmZo6vuku1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZ4oaz%2FdJMcajaXJyf%2FCI5SbYEqlq1kWmZo6vuku1%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;1724&quot; height=&quot;1920&quot; data-origin-width=&quot;1724&quot; data-origin-height=&quot;1920&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p 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-origin-width=&quot;1150&quot; data-origin-height=&quot;2048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dv9aiM/dJMcajaXJzE/aKmhcScYVKzgjjoM7tJnw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dv9aiM/dJMcajaXJzE/aKmhcScYVKzgjjoM7tJnw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dv9aiM/dJMcajaXJzE/aKmhcScYVKzgjjoM7tJnw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdv9aiM%2FdJMcajaXJzE%2FaKmhcScYVKzgjjoM7tJnw1%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;1150&quot; height=&quot;2048&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;2048&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/749</guid>
      <comments>https://series.tistory.com/entry/github%EC%97%90-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-SaaS-%EC%8A%A4%ED%83%80%ED%84%B0%ED%82%B7%EC%9D%84-%EB%B0%B0%ED%8F%AC%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4#entry749comment</comments>
      <pubDate>Thu, 30 Apr 2026 13:05:24 +0900</pubDate>
    </item>
    <item>
      <title>AI 전환 진단 프로그램 AX Doctor v1 을 리뉴얼했습니다.</title>
      <link>https://series.tistory.com/entry/AI-%EC%A0%84%ED%99%98-%EC%A7%84%EB%8B%A8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-AX-Doctor-v1-%EC%9D%84-%EB%A6%AC%EB%89%B4%EC%96%BC%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;631&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C2BeM/dJMcafGrjgc/9OWrSpWNK6XrjuHKIKkll0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C2BeM/dJMcafGrjgc/9OWrSpWNK6XrjuHKIKkll0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C2BeM/dJMcafGrjgc/9OWrSpWNK6XrjuHKIKkll0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC2BeM%2FdJMcafGrjgc%2F9OWrSpWNK6XrjuHKIKkll0%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;944&quot; height=&quot;631&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;631&quot;/&gt;&lt;/span&gt;&lt;/figure&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;b&gt;AI&amp;nbsp;전환&amp;nbsp;진단&amp;nbsp;프로그램&amp;nbsp;AX&amp;nbsp;Doctor&amp;nbsp;v1&amp;nbsp;by&amp;nbsp;axq.kr&lt;/b&gt;&lt;br /&gt;흩어져&amp;nbsp;있던&amp;nbsp;접점들을&amp;nbsp;단일&amp;nbsp;도메인으로&amp;nbsp;정리했고,&amp;nbsp;AI&amp;nbsp;전환&amp;nbsp;진단&amp;nbsp;프로그램&amp;nbsp;AX&amp;nbsp;Doctor&amp;nbsp;by&amp;nbsp;axq.kr&amp;nbsp;으로&amp;nbsp;리뉴얼했습니다.&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;AX&amp;nbsp;Doctor는&amp;nbsp;조직의&amp;nbsp;AI&amp;nbsp;전환&amp;nbsp;준비&amp;nbsp;수준을&amp;nbsp;30문항&amp;middot;5분으로&amp;nbsp;진단하는&amp;nbsp;프로그램입니다.&lt;br /&gt;Gartner&amp;middot;Cisco&amp;middot;Microsoft&amp;nbsp;프레임워크를&amp;nbsp;기반으로,&amp;nbsp;전략&amp;nbsp;정합성부터&amp;nbsp;문화&amp;middot;변화&amp;nbsp;관리까지&amp;nbsp;6개&amp;nbsp;차원을&amp;nbsp;측정합니다.&lt;br /&gt;익명이고,&amp;nbsp;로그인도&amp;nbsp;필요&amp;nbsp;없습니다.&amp;nbsp;결과는&amp;nbsp;즉시&amp;nbsp;나옵니다.&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;&quot;우리 조직이 AI를 도입할 준비가 됐는가&quot;라는 질문에 데이터 기반의 답을 드립니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://www.axq.kr&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt; &lt;a href=&quot;http://www.axq.kr&quot;&gt;www.axq.kr&amp;nbsp;&lt;/a&gt;&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1777442384104&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;AXQ &amp;mdash; AI Transformation 진단&quot; data-og-description=&quot;01 산업 &amp;amp; 기본 정보 입력 회사명과 산업군을 선택하면 동종업계 평균과 비교가 가능합니다. 모두 익명 처리됩니다. 02 30문항 응답 (약 5분) 6개 핵심 Dimension에 걸쳐 5점 척도로 응답합니다. 각 질&quot; data-og-host=&quot;www.axq.kr&quot; data-og-source-url=&quot;http://www.axq.kr&quot; data-og-url=&quot;https://www.axq.kr/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;http://www.axq.kr&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.axq.kr&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;AXQ &amp;mdash; AI Transformation 진단&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;01 산업 &amp;amp; 기본 정보 입력 회사명과 산업군을 선택하면 동종업계 평균과 비교가 가능합니다. 모두 익명 처리됩니다. 02 30문항 응답 (약 5분) 6개 핵심 Dimension에 걸쳐 5점 척도로 응답합니다. 각 질&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.axq.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p 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-origin-width=&quot;722&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7zqTN/dJMcahYxgQ3/xUen3pE4CxrULKtek20P50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7zqTN/dJMcahYxgQ3/xUen3pE4CxrULKtek20P50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7zqTN/dJMcahYxgQ3/xUen3pE4CxrULKtek20P50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7zqTN%2FdJMcahYxgQ3%2FxUen3pE4CxrULKtek20P50%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;722&quot; height=&quot;628&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dM06nd/dJMcaa6cs9J/c3McbWOTzJi88RENjWK6kK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dM06nd/dJMcaa6cs9J/c3McbWOTzJi88RENjWK6kK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dM06nd/dJMcaa6cs9J/c3McbWOTzJi88RENjWK6kK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdM06nd%2FdJMcaa6cs9J%2Fc3McbWOTzJi88RENjWK6kK%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;1207&quot; height=&quot;526&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;526&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p 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-origin-width=&quot;1209&quot; data-origin-height=&quot;586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nY8RK/dJMcaaymMXk/ryaeBodPSfBpxz78kgNK1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nY8RK/dJMcaaymMXk/ryaeBodPSfBpxz78kgNK1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nY8RK/dJMcaaymMXk/ryaeBodPSfBpxz78kgNK1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnY8RK%2FdJMcaaymMXk%2FryaeBodPSfBpxz78kgNK1k%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;1209&quot; height=&quot;586&quot; data-origin-width=&quot;1209&quot; data-origin-height=&quot;586&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1165&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B1dqP/dJMcaaymMYH/jLJUbunU2YqPmrI7QB1Lv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B1dqP/dJMcaaymMYH/jLJUbunU2YqPmrI7QB1Lv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B1dqP/dJMcaaymMYH/jLJUbunU2YqPmrI7QB1Lv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB1dqP%2FdJMcaaymMYH%2FjLJUbunU2YqPmrI7QB1Lv1%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;1165&quot; height=&quot;571&quot; data-origin-width=&quot;1165&quot; data-origin-height=&quot;571&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/748</guid>
      <comments>https://series.tistory.com/entry/AI-%EC%A0%84%ED%99%98-%EC%A7%84%EB%8B%A8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-AX-Doctor-v1-%EC%9D%84-%EB%A6%AC%EB%89%B4%EC%96%BC%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4#entry748comment</comments>
      <pubDate>Wed, 29 Apr 2026 15:00:53 +0900</pubDate>
    </item>
    <item>
      <title>AX 전에 DX, 데이터가 흐르는 인프라가 먼저다</title>
      <link>https://series.tistory.com/entry/AX-%EC%A0%84%EC%97%90-DX-%EB%8D%B0%EC%9D%B4%ED%84%B0%EA%B0%80-%ED%9D%90%EB%A5%B4%EB%8A%94-%EC%9D%B8%ED%94%84%EB%9D%BC%EA%B0%80-%EB%A8%BC%EC%A0%80%EB%8B%A4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01-cover.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nbgX4/dJMcadIyeM8/FUUwsStChIYkU4GXztkenk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nbgX4/dJMcadIyeM8/FUUwsStChIYkU4GXztkenk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nbgX4/dJMcadIyeM8/FUUwsStChIYkU4GXztkenk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnbgX4%2FdJMcadIyeM8%2FFUUwsStChIYkU4GXztkenk%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;01-cover.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ai를-쓰고-있다고-말하기-어려운-이유&quot; style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;18&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AI를 쓰고 있다고 말하기 어려운 이유&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;20&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;우리 조직은 AI를 제대로 쓰고 있는가?&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에이전트, 자동화, AX 키워드가 쏟아지지만 이 질문에 자신 있게 답하는 리더는 많지 않다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;24&quot; 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;color: #bbbebf; text-align: start;&quot; data-line=&quot;26&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최근 한 B2B SaaS 기업의 사업개발 리드가 이 문제를 '극단적 경영 가시성' &amp;mdash; 조직의 모든 부서와 계층에서 즉시&amp;middot;충분히 알 수 있는 상태 &amp;mdash; 이라는 개념으로 풀어냈다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;28&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결론은 단순하다. 데이터가 흐르는 IT 인프라가 없으면 AI는 접근할 데이터 자체가 없다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;데이터-주권-3조건과-일의-정의&quot; style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;30&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 주권 3조건과 일의 정의&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;32&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI 활용의 출발점은 데이터 주권이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;34&quot; 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;color: #bbbebf; text-align: start;&quot; data-line=&quot;36&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 세 가지가 없으면 특정 솔루션에 종속된 의존성이 생기고 AI에게 넘길 일 자체를 정의하지 못한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;38&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;딸깍에 이르는 과정은 딸깍이 아니다.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;40&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어느 커머스 플랫폼 사업은 자사몰 자동화를 위해 900개 넘는 세부 태스크를 먼저 정의했다. 그 과정을 거친 뒤에야 AI가 대체할 항목을 분리할 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;데이터가-흐르는-인프라가-먼저다&quot; style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;43&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터가 흐르는 인프라가 먼저다&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;45&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 CX 솔루션은 API가 없어 요청 후 2~3주 뒤에야 데이터가 돌아왔고 그마저도 깨진 상태였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;47&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이런 환경에서는 어떤 AI를 붙여도 읽을 데이터가 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;49&quot; 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;color: #bbbebf; text-align: start;&quot; data-line=&quot;51&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 기업은 DW를 하나로 통합하고 각 필드에 의미&amp;middot;맥락 주석을 달았다. 그 결과 LLM이 직접 데이터를 읽게 됐고, 단순 쿼리를 데이터 팀에 의뢰하지 않아도 되는 환경이 만들어졌다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;54&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;진짜 중요한 것은 앱이 아니라 데이터 파이프라인.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;감지실행연결--ai-에이전트-역할-설계&quot; style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;56&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;감지&amp;middot;실행&amp;middot;연결 &amp;mdash; AI 에이전트 역할 설계&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;58&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI 에이전트의 역할은 세 단계로 나눈다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;60&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;감지(Detect) &amp;mdash; 이상 데이터를 발견해 알려주는 수준. 여기까지만 돼도 의미 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;62&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실행(Execute) &amp;mdash; 위임된 범위 안에서 이메일 발송 등 특정 액션을 수행한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;64&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연결(Connect) &amp;mdash; 문제 상황과 제안을 요약해 적절한 의사결정권자에게 넘긴다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;66&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CRUD 권한 설계도 함께 이루어져야 한다. 어디까지 읽고, 쓰고, 지울 수 있는지를 용도와 권한에 따라 나누는 것이 보안과 자율성을 동시에 확보하는 방법이다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;ax-전에-dx-사금이-금이-되려면&quot; style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;69&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AX 전에 DX, 사금이 금이 되려면&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;71&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 기업은 Claude에 MCP 접근 권한을 부여해 테이블 구조를 자동 설계하고, 고객 미팅 후 음성으로 대화 내용을 전달하면 CRM 필드에 자동 입력되는 환경을 만들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;73&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기획&amp;middot;가공 시간은 체감 30% 수준으로 줄었고, 남은 시간에 사람을 직접 만나는 일에 집중할 수 있게 됐다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;75&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;30년치 데이터도 그 자체로 가치를 갖지는 않는다. 사금을 캐고, 흔들고, 녹여야 금이 된다.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;77&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AX 전에 DX부터. 우리 조직의 데이터는 지금 AI가 접근할 수 있는 상태인가?&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #bbbebf; text-align: start;&quot; data-line=&quot;77&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;01-cover.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VKBnP/dJMcaa6bEcN/vtOO4dLkYMnQIkVsySg6R0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VKBnP/dJMcaa6bEcN/vtOO4dLkYMnQIkVsySg6R0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VKBnP/dJMcaa6bEcN/vtOO4dLkYMnQIkVsySg6R0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVKBnP%2FdJMcaa6bEcN%2FvtOO4dLkYMnQIkVsySg6R0%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;01-cover.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02-summary.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn7Rpp/dJMcagrMfGr/maAC0KdfzMSXcIooTtJwEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn7Rpp/dJMcagrMfGr/maAC0KdfzMSXcIooTtJwEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn7Rpp/dJMcagrMfGr/maAC0KdfzMSXcIooTtJwEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn7Rpp%2FdJMcagrMfGr%2FmaAC0KdfzMSXcIooTtJwEK%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;02-summary.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03-quote-problem.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LBI5W/dJMcahEcFMd/TZR1XB3a8I5A54j1HGQDpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LBI5W/dJMcahEcFMd/TZR1XB3a8I5A54j1HGQDpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LBI5W/dJMcahEcFMd/TZR1XB3a8I5A54j1HGQDpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLBI5W%2FdJMcahEcFMd%2FTZR1XB3a8I5A54j1HGQDpK%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;03-quote-problem.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04-list-data-sovereignty.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drViGS/dJMcahEcFMe/kZINAV8Fen6BpxkBmpQwh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drViGS/dJMcahEcFMe/kZINAV8Fen6BpxkBmpQwh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drViGS/dJMcahEcFMe/kZINAV8Fen6BpxkBmpQwh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdrViGS%2FdJMcahEcFMe%2FkZINAV8Fen6BpxkBmpQwh0%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;04-list-data-sovereignty.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05-flow-work-definition.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eG0egI/dJMcahEcFMc/Vk4M4WwcA3Dpz9t1lFEKN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eG0egI/dJMcahEcFMc/Vk4M4WwcA3Dpz9t1lFEKN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eG0egI/dJMcahEcFMc/Vk4M4WwcA3Dpz9t1lFEKN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeG0egI%2FdJMcahEcFMc%2FVk4M4WwcA3Dpz9t1lFEKN1%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;05-flow-work-definition.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06-infra-pipeline.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bie6Zo/dJMcaa6bEcP/Mq0tJ6g13Rq2oOSlRolIGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bie6Zo/dJMcaa6bEcP/Mq0tJ6g13Rq2oOSlRolIGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bie6Zo/dJMcaa6bEcP/Mq0tJ6g13Rq2oOSlRolIGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbie6Zo%2FdJMcaa6bEcP%2FMq0tJ6g13Rq2oOSlRolIGK%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;06-infra-pipeline.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07-agent-roles.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t8zKu/dJMcagrMfGu/oE0xDrKZI9d0sXZlrfp751/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t8zKu/dJMcagrMfGu/oE0xDrKZI9d0sXZlrfp751/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t8zKu/dJMcagrMfGu/oE0xDrKZI9d0sXZlrfp751/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft8zKu%2FdJMcagrMfGu%2FoE0xDrKZI9d0sXZlrfp751%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;07-agent-roles.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08-case-enterprise.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BDRov/dJMcahEcFMf/SMGPtGmhpp5BBCO1JODKT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BDRov/dJMcahEcFMf/SMGPtGmhpp5BBCO1JODKT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BDRov/dJMcahEcFMf/SMGPtGmhpp5BBCO1JODKT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBDRov%2FdJMcahEcFMf%2FSMGPtGmhpp5BBCO1JODKT0%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;08-case-enterprise.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;09-result-impact.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xkFoa/dJMcaa6bEcS/Gi9Qn8fJTz8UZuj92MSKk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xkFoa/dJMcaa6bEcS/Gi9Qn8fJTz8UZuj92MSKk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xkFoa/dJMcaa6bEcS/Gi9Qn8fJTz8UZuj92MSKk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxkFoa%2FdJMcaa6bEcS%2FGi9Qn8fJTz8UZuj92MSKk1%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;09-result-impact.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10-cta.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WeyFx/dJMcadIyeXN/p6kjhoPrQhedcaQ3HbFPD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WeyFx/dJMcadIyeXN/p6kjhoPrQhedcaQ3HbFPD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WeyFx/dJMcadIyeXN/p6kjhoPrQhedcaQ3HbFPD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWeyFx%2FdJMcadIyeXN%2Fp6kjhoPrQhedcaQ3HbFPD1%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;1081&quot; height=&quot;1350&quot; data-filename=&quot;10-cta.png&quot; data-origin-width=&quot;1081&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/747</guid>
      <comments>https://series.tistory.com/entry/AX-%EC%A0%84%EC%97%90-DX-%EB%8D%B0%EC%9D%B4%ED%84%B0%EA%B0%80-%ED%9D%90%EB%A5%B4%EB%8A%94-%EC%9D%B8%ED%94%84%EB%9D%BC%EA%B0%80-%EB%A8%BC%EC%A0%80%EB%8B%A4#entry747comment</comments>
      <pubDate>Tue, 28 Apr 2026 16:31:19 +0900</pubDate>
    </item>
    <item>
      <title>AX(AI Transformation) 진단 프로그램 v1을 만들었습니다.</title>
      <link>https://series.tistory.com/entry/AXAI-Transformation-%EC%A7%84%EB%8B%A8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-v1%EC%9D%84-%EB%A7%8C%EB%93%A4%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AX 상태를 진단할 수 있는 간단하지만 핵심적인 내용으로 구성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;a href=&quot;https://ax-doctor.vercel.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ax-doctor.vercel.app/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1777252192024&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;AX Doctor &amp;mdash; AI Transformation 진단&quot; data-og-description=&quot;AX(AI Transformation) 성숙도를5분 만에 진단하세요 Gartner&amp;middot;Cisco&amp;middot;Microsoft AI Readiness 프레임워크 기반 30문항 설문으로 6개 핵심 Dimension의 현 수준과 우선 개선 방향을 즉시 확인합니다. 무료 진단 시작하&quot; data-og-host=&quot;ax-doctor.vercel.app&quot; data-og-source-url=&quot;https://ax-doctor.vercel.app/&quot; data-og-url=&quot;https://ax-doctor.vercel.app/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://ax-doctor.vercel.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ax-doctor.vercel.app/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;AX Doctor &amp;mdash; AI Transformation 진단&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;AX(AI Transformation) 성숙도를5분 만에 진단하세요 Gartner&amp;middot;Cisco&amp;middot;Microsoft AI Readiness 프레임워크 기반 30문항 설문으로 6개 핵심 Dimension의 현 수준과 우선 개선 방향을 즉시 확인합니다. 무료 진단 시작하&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ax-doctor.vercel.app&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p 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-origin-width=&quot;865&quot; data-origin-height=&quot;930&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KwprJ/dJMcafzDNp5/Ams2OxHjhcgvFF7421x9gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KwprJ/dJMcafzDNp5/Ams2OxHjhcgvFF7421x9gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KwprJ/dJMcafzDNp5/Ams2OxHjhcgvFF7421x9gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKwprJ%2FdJMcafzDNp5%2FAms2OxHjhcgvFF7421x9gk%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;865&quot; height=&quot;930&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;930&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;483&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7qt6a/dJMcajopxkq/UC3sN9ww2fMARdbVECUgt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7qt6a/dJMcajopxkq/UC3sN9ww2fMARdbVECUgt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7qt6a/dJMcajopxkq/UC3sN9ww2fMARdbVECUgt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7qt6a%2FdJMcajopxkq%2FUC3sN9ww2fMARdbVECUgt0%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;752&quot; height=&quot;483&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;483&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btFEV2/dJMcafGpcyM/k5ilMltX4kriGPuK4gEau1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btFEV2/dJMcafGpcyM/k5ilMltX4kriGPuK4gEau1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btFEV2/dJMcafGpcyM/k5ilMltX4kriGPuK4gEau1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtFEV2%2FdJMcafGpcyM%2Fk5ilMltX4kriGPuK4gEau1%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;713&quot; height=&quot;432&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;432&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/746</guid>
      <comments>https://series.tistory.com/entry/AXAI-Transformation-%EC%A7%84%EB%8B%A8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-v1%EC%9D%84-%EB%A7%8C%EB%93%A4%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4#entry746comment</comments>
      <pubDate>Mon, 27 Apr 2026 10:10:57 +0900</pubDate>
    </item>
    <item>
      <title>AX의 성공은 기술이 아니라 '조직'이 결정한다</title>
      <link>https://series.tistory.com/entry/AX%EC%9D%98-%EC%84%B1%EA%B3%B5%EC%9D%80-%EA%B8%B0%EC%88%A0%EC%9D%B4-%EC%95%84%EB%8B%88%EB%9D%BC-%EC%A1%B0%EC%A7%81%EC%9D%B4-%EA%B2%B0%EC%A0%95%ED%95%9C%EB%8B%A4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01-cover.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BfTgl/dJMcagrKZ71/1zB1bSiToKAgVWUAiFuVt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BfTgl/dJMcagrKZ71/1zB1bSiToKAgVWUAiFuVt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BfTgl/dJMcagrKZ71/1zB1bSiToKAgVWUAiFuVt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBfTgl%2FdJMcagrKZ71%2F1zB1bSiToKAgVWUAiFuVt1%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;01-cover.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&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;직원의&amp;nbsp;AI&amp;nbsp;접근성은&amp;nbsp;+50%&amp;nbsp;늘었지만,&amp;nbsp;정작&amp;nbsp;줄어든&amp;nbsp;것은&amp;nbsp;&quot;사람이&amp;nbsp;직접&amp;nbsp;숙고하는&amp;nbsp;시간&quot;이다.&amp;nbsp;AX의&amp;nbsp;성공은&amp;nbsp;더&amp;nbsp;좋은&amp;nbsp;모델이&amp;nbsp;아니라&amp;nbsp;책임&amp;nbsp;있는&amp;nbsp;의사결정&amp;nbsp;구조와&amp;nbsp;실습&amp;middot;공유&amp;nbsp;기반의&amp;nbsp;문화가&amp;nbsp;결정한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;왜&amp;nbsp;AI가&amp;nbsp;늘어도&amp;nbsp;AX는&amp;nbsp;어려운가&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국 딜로이트 그룹의 '기업의 AI 활용현황 2026 보고서'에 따르면 직원 AI 접근성은 50% 확대됐다. 회의록은 수 분 만에 요약되고, 보고서 초안도 즉시 나온다. 문제는 그 다음이다. 그럴듯한 결과물에 익숙해질수록 검증과 숙고가 뒤로 밀리고, 그렇게 굳어진 프로세스가 표준이 되어버리면 조직은 매일 틀린 줄도 모르는 답을 결재하게 된다.&lt;br /&gt;&lt;br /&gt;LLM의&amp;nbsp;한계도&amp;nbsp;같은&amp;nbsp;위험을&amp;nbsp;키운다.&amp;nbsp;연구논문&amp;nbsp;Artificial&amp;nbsp;Hivemind는&amp;nbsp;유사한&amp;nbsp;출력에&amp;nbsp;반복&amp;nbsp;노출될&amp;nbsp;경우&amp;nbsp;사고&amp;nbsp;자체가&amp;nbsp;동질화될&amp;nbsp;수&amp;nbsp;있다고&amp;nbsp;경고한다.&amp;nbsp;마이크로소프트&amp;nbsp;리서치(2025)도&amp;nbsp;자동화의&amp;nbsp;역설을&amp;nbsp;인용하며&amp;nbsp;&quot;책임&amp;nbsp;설계가&amp;nbsp;없으면&amp;nbsp;조직은&amp;nbsp;결국&amp;nbsp;통제&amp;nbsp;강화로&amp;nbsp;회귀한다&quot;고&amp;nbsp;짚었다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;처방 1. 책임 있는 의사결정 조직 재설계&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리더의&amp;nbsp;일은&amp;nbsp;AI&amp;nbsp;답변을&amp;nbsp;받아쓰는&amp;nbsp;게&amp;nbsp;아니라&amp;nbsp;더&amp;nbsp;잘&amp;nbsp;판단하기&amp;nbsp;위해&amp;nbsp;깊이&amp;nbsp;숙고하는&amp;nbsp;일이다.&amp;nbsp;정답이&amp;nbsp;없는&amp;nbsp;기획&amp;middot;전략에서는&amp;nbsp;&quot;결정을&amp;nbsp;검증하는&amp;nbsp;과정&quot;&amp;nbsp;자체가&amp;nbsp;경쟁력이다.&amp;nbsp;핵심은&amp;nbsp;'AI&amp;nbsp;네이티브화'&amp;nbsp;&amp;mdash;&amp;nbsp;AI를&amp;nbsp;전제로&amp;nbsp;업무를&amp;nbsp;설계하되,&amp;nbsp;그&amp;nbsp;안에서&amp;nbsp;사람이&amp;nbsp;해야&amp;nbsp;할&amp;nbsp;의사결정&amp;nbsp;영역을&amp;nbsp;분명히&amp;nbsp;구분하고&amp;nbsp;표준화된&amp;nbsp;검증&amp;middot;책임&amp;nbsp;구조를&amp;nbsp;함께&amp;nbsp;운영하는&amp;nbsp;것이다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;처방 2. 문화 확산 &amp;mdash; 퍼널 4단계&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AX의&amp;nbsp;본질은&amp;nbsp;기술이&amp;nbsp;아니라&amp;nbsp;문화다.&amp;nbsp;강의&amp;nbsp;한&amp;nbsp;번으로는&amp;nbsp;정착하지&amp;nbsp;않는다.&amp;nbsp;마케팅의&amp;nbsp;퍼널&amp;nbsp;효과를&amp;nbsp;그대로&amp;nbsp;적용할&amp;nbsp;수&amp;nbsp;있다.&lt;br /&gt;&lt;br /&gt;인지&amp;nbsp;&amp;mdash;&amp;nbsp;AI&amp;nbsp;사용&amp;nbsp;불안을&amp;nbsp;줄이고&amp;nbsp;&quot;이렇게&amp;nbsp;쓰면&amp;nbsp;된다&quot;는&amp;nbsp;예시를&amp;nbsp;공유한다.&lt;br /&gt;참여&amp;nbsp;&amp;mdash;&amp;nbsp;AI&amp;nbsp;CoE(Center&amp;nbsp;of&amp;nbsp;Excellence)가&amp;nbsp;실무&amp;nbsp;문서를&amp;nbsp;함께&amp;nbsp;다듬어&amp;nbsp;주는&amp;nbsp;마중물이&amp;nbsp;된다.&lt;br /&gt;적용&amp;nbsp;&amp;mdash;&amp;nbsp;개선된&amp;nbsp;표준&amp;nbsp;프롬프트&amp;middot;템플릿으로&amp;nbsp;전사&amp;nbsp;품질을&amp;nbsp;상향&amp;nbsp;표준화한다.&lt;br /&gt;공유&amp;nbsp;&amp;mdash;&amp;nbsp;레시피&amp;nbsp;공유전&amp;middot;챌린지로&amp;nbsp;성공&amp;nbsp;경험의&amp;nbsp;장을&amp;nbsp;주기적으로&amp;nbsp;마련한다.&lt;br /&gt;페인&amp;nbsp;포인트가&amp;nbsp;발견되고&amp;nbsp;작은&amp;nbsp;성과가&amp;nbsp;쌓이면&amp;nbsp;신뢰가&amp;nbsp;만들어지고,&amp;nbsp;그&amp;nbsp;신뢰가&amp;nbsp;다음&amp;nbsp;확산의&amp;nbsp;연료가&amp;nbsp;된다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정부도&amp;nbsp;같은&amp;nbsp;방향이다&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행정안전부는&amp;nbsp;'AI&amp;nbsp;거점리더&amp;middot;챔피언'&amp;nbsp;인재&amp;nbsp;양성으로&amp;nbsp;현장&amp;nbsp;거점을&amp;nbsp;세우고&amp;nbsp;있다.&amp;nbsp;재정경제부는&amp;nbsp;89개&amp;nbsp;공공기관이&amp;nbsp;참여하는&amp;nbsp;분과별&amp;nbsp;AI&amp;nbsp;활용&amp;nbsp;협의체를&amp;nbsp;가동했다.&amp;nbsp;인공지능전략위원회는&amp;nbsp;행동계획(26~28)을&amp;nbsp;통해&amp;nbsp;부처별&amp;nbsp;이행&amp;nbsp;과제를&amp;nbsp;제시했다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&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;AX는 더 비싼 모델을 쓰는 일이 아니다. 사람이 결정해야 할 자리를 지키고, 그 결정을 검증할 수 있는 구조와 문화를 만드는 일이다. 검증 없이 표준이 된 프로세스가 우리 회의실에도 한두 개쯤 있다면, 지금이 시작할 가장 좋은 때다.&lt;/p&gt;
&lt;p 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;02-summary.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y5UP2/dJMcagrKZ8b/QbWrKHVuAluSLYCZ2z8An1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y5UP2/dJMcagrKZ8b/QbWrKHVuAluSLYCZ2z8An1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y5UP2/dJMcagrKZ8b/QbWrKHVuAluSLYCZ2z8An1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy5UP2%2FdJMcagrKZ8b%2FQbWrKHVuAluSLYCZ2z8An1%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;02-summary.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03-quote.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZCniJ/dJMcacXbB4B/UmwLIMcgBTuvRJV7afGbX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZCniJ/dJMcacXbB4B/UmwLIMcgBTuvRJV7afGbX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZCniJ/dJMcacXbB4B/UmwLIMcgBTuvRJV7afGbX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZCniJ%2FdJMcacXbB4B%2FUmwLIMcgBTuvRJV7afGbX0%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;03-quote.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04-hivemind.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7Srzj/dJMcacJG79X/FvxL03g2jhLKpEVLwvKGo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7Srzj/dJMcacJG79X/FvxL03g2jhLKpEVLwvKGo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7Srzj/dJMcacJG79X/FvxL03g2jhLKpEVLwvKGo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7Srzj%2FdJMcacJG79X%2FFvxL03g2jhLKpEVLwvKGo0%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;04-hivemind.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05-automation-paradox.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJX3To/dJMcacJG79Y/k8d7Mok96AV0U34SHBgie1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJX3To/dJMcacJG79Y/k8d7Mok96AV0U34SHBgie1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJX3To/dJMcacJG79Y/k8d7Mok96AV0U34SHBgie1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJX3To%2FdJMcacJG79Y%2Fk8d7Mok96AV0U34SHBgie1%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;05-automation-paradox.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06-redesign.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cS4CgN/dJMcagrKZ8c/k3kZu6sIxUToub2wX88Hb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cS4CgN/dJMcagrKZ8c/k3kZu6sIxUToub2wX88Hb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cS4CgN/dJMcagrKZ8c/k3kZu6sIxUToub2wX88Hb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcS4CgN%2FdJMcagrKZ8c%2Fk3kZu6sIxUToub2wX88Hb0%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;06-redesign.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07-culture.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eClNYY/dJMcacJG79Z/yuVzXdOTT1rFKLyV813hVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eClNYY/dJMcacJG79Z/yuVzXdOTT1rFKLyV813hVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eClNYY/dJMcacJG79Z/yuVzXdOTT1rFKLyV813hVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeClNYY%2FdJMcacJG79Z%2FyuVzXdOTT1rFKLyV813hVK%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;07-culture.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08-funnel.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IiGBg/dJMcacXbB4C/uqU7uVclMkiaX3qYEnI7OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IiGBg/dJMcacXbB4C/uqU7uVclMkiaX3qYEnI7OK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IiGBg/dJMcacXbB4C/uqU7uVclMkiaX3qYEnI7OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIiGBg%2FdJMcacXbB4C%2FuqU7uVclMkiaX3qYEnI7OK%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;08-funnel.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;09-government.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MJ4CM/dJMcagkYZMM/3qf4hl325TfexM6TekV3M1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MJ4CM/dJMcagkYZMM/3qf4hl325TfexM6TekV3M1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MJ4CM/dJMcagkYZMM/3qf4hl325TfexM6TekV3M1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMJ4CM%2FdJMcagkYZMM%2F3qf4hl325TfexM6TekV3M1%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;09-government.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10-cta.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mkNke/dJMcagkYZMN/XsbPcMKvtTWn9RMmvpAZcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mkNke/dJMcagkYZMN/XsbPcMKvtTWn9RMmvpAZcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mkNke/dJMcagkYZMN/XsbPcMKvtTWn9RMmvpAZcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmkNke%2FdJMcagkYZMN%2FXsbPcMKvtTWn9RMmvpAZcK%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;2160&quot; height=&quot;2700&quot; data-filename=&quot;10-cta.png&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;2700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/745</guid>
      <comments>https://series.tistory.com/entry/AX%EC%9D%98-%EC%84%B1%EA%B3%B5%EC%9D%80-%EA%B8%B0%EC%88%A0%EC%9D%B4-%EC%95%84%EB%8B%88%EB%9D%BC-%EC%A1%B0%EC%A7%81%EC%9D%B4-%EA%B2%B0%EC%A0%95%ED%95%9C%EB%8B%A4#entry745comment</comments>
      <pubDate>Mon, 27 Apr 2026 10:03:02 +0900</pubDate>
    </item>
    <item>
      <title>AI 전환(AX)보다 DX(Digital Transformation)이 먼저다.</title>
      <link>https://series.tistory.com/entry/AI-%EC%A0%84%ED%99%98AX%EB%B3%B4%EB%8B%A4-DXDigital-Transformation%EC%9D%B4-%EB%A8%BC%EC%A0%80%EB%8B%A4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AI&amp;nbsp;전환(AX)을&amp;nbsp;서두르는&amp;nbsp;조직이&amp;nbsp;늘어나고&amp;nbsp;있다.&amp;nbsp;하지만&amp;nbsp;현장에서&amp;nbsp;보면,&amp;nbsp;많은&amp;nbsp;팀이&amp;nbsp;&amp;lsquo;AI를&amp;nbsp;도입하면&amp;nbsp;뭔가&amp;nbsp;달라질&amp;nbsp;것&amp;rsquo;이라는&amp;nbsp;기대만으로&amp;nbsp;움직이고&amp;nbsp;있다.&amp;nbsp;문제는&amp;nbsp;AX가&amp;nbsp;독립적인&amp;nbsp;변화가&amp;nbsp;아니라,&amp;nbsp;기존&amp;nbsp;디지털&amp;nbsp;전환(DX)의&amp;nbsp;연장선이라는&amp;nbsp;점이다.&amp;nbsp;기반&amp;nbsp;없이&amp;nbsp;얹힌&amp;nbsp;AI는&amp;nbsp;생산성을&amp;nbsp;높이기보다&amp;nbsp;오히려&amp;nbsp;혼란을&amp;nbsp;키운다.&lt;br /&gt;&lt;br /&gt;AX를&amp;nbsp;시작하기&amp;nbsp;전에&amp;nbsp;반드시&amp;nbsp;점검해야&amp;nbsp;할&amp;nbsp;첫&amp;nbsp;번째는&amp;nbsp;데이터&amp;nbsp;파이프라인이다.&amp;nbsp;많은&amp;nbsp;조직이&amp;nbsp;데이터를&amp;nbsp;가지고&amp;nbsp;있다고&amp;nbsp;말하지만,&amp;nbsp;실제로는&amp;nbsp;활용&amp;nbsp;가능한&amp;nbsp;상태로&amp;nbsp;흐르고&amp;nbsp;있지&amp;nbsp;않은&amp;nbsp;경우가&amp;nbsp;많다.&amp;nbsp;데이터가&amp;nbsp;수집되고&amp;nbsp;저장되는&amp;nbsp;것과,&amp;nbsp;그것이&amp;nbsp;분석되고&amp;nbsp;의사결정에&amp;nbsp;쓰이는&amp;nbsp;것은&amp;nbsp;완전히&amp;nbsp;다른&amp;nbsp;이야기다.&amp;nbsp;AI는&amp;nbsp;결국&amp;nbsp;데이터를&amp;nbsp;입력으로&amp;nbsp;삼기&amp;nbsp;때문에,&amp;nbsp;이&amp;nbsp;흐름이&amp;nbsp;정리되어&amp;nbsp;있지&amp;nbsp;않다면&amp;nbsp;결과&amp;nbsp;역시&amp;nbsp;불안정할&amp;nbsp;수밖에&amp;nbsp;없다.&lt;br /&gt;&lt;br /&gt;두&amp;nbsp;번째는&amp;nbsp;반복&amp;nbsp;업무의&amp;nbsp;자동화&amp;nbsp;수준이다.&amp;nbsp;AX는&amp;nbsp;자동화를&amp;nbsp;대체하는&amp;nbsp;개념이&amp;nbsp;아니라,&amp;nbsp;자동화를&amp;nbsp;기반으로&amp;nbsp;고도화하는&amp;nbsp;단계다.&amp;nbsp;여전히&amp;nbsp;사람이&amp;nbsp;엑셀을&amp;nbsp;정리하고,&amp;nbsp;수작업으로&amp;nbsp;데이터를&amp;nbsp;옮기고,&amp;nbsp;반복적인&amp;nbsp;보고서를&amp;nbsp;작성하고&amp;nbsp;있다면,&amp;nbsp;그&amp;nbsp;위에&amp;nbsp;AI를&amp;nbsp;얹는&amp;nbsp;것은&amp;nbsp;비효율을&amp;nbsp;확장하는&amp;nbsp;것에&amp;nbsp;가깝다.&amp;nbsp;먼저&amp;nbsp;RPA,&amp;nbsp;스크립트,&amp;nbsp;API&amp;nbsp;연동&amp;nbsp;등을&amp;nbsp;통해&amp;nbsp;기본적인&amp;nbsp;자동화를&amp;nbsp;확보해야&amp;nbsp;한다.&amp;nbsp;그&amp;nbsp;다음에야&amp;nbsp;AI가&amp;nbsp;의미&amp;nbsp;있는&amp;nbsp;개선을&amp;nbsp;만들어낸다.&lt;br /&gt;&lt;br /&gt;세&amp;nbsp;번째는&amp;nbsp;팀의&amp;nbsp;디지털&amp;nbsp;리터러시다.&amp;nbsp;AI&amp;nbsp;도구를&amp;nbsp;사용할&amp;nbsp;줄&amp;nbsp;아는&amp;nbsp;것만으로는&amp;nbsp;부족하다.&amp;nbsp;중요한&amp;nbsp;것은&amp;nbsp;문제를&amp;nbsp;구조화하고,&amp;nbsp;AI가&amp;nbsp;낸&amp;nbsp;결과를&amp;nbsp;비판적으로&amp;nbsp;검토하며,&amp;nbsp;워크플로우에&amp;nbsp;맞게&amp;nbsp;재구성할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;능력이다.&amp;nbsp;이&amp;nbsp;역량이&amp;nbsp;없다면&amp;nbsp;AI는&amp;nbsp;&amp;lsquo;마법&amp;nbsp;같은&amp;nbsp;도구&amp;rsquo;가&amp;nbsp;아니라&amp;nbsp;&amp;lsquo;예측&amp;nbsp;불가능한&amp;nbsp;변수&amp;rsquo;가&amp;nbsp;된다.&lt;br /&gt;&lt;br /&gt;결국&amp;nbsp;AX는&amp;nbsp;기술&amp;nbsp;도입의&amp;nbsp;문제가&amp;nbsp;아니라,&amp;nbsp;준비&amp;nbsp;상태의&amp;nbsp;문제다.&amp;nbsp;많은&amp;nbsp;실패&amp;nbsp;사례는&amp;nbsp;AI&amp;nbsp;성능&amp;nbsp;때문이&amp;nbsp;아니라,&amp;nbsp;적용&amp;nbsp;대상이&amp;nbsp;되는&amp;nbsp;프로세스가&amp;nbsp;정리되어&amp;nbsp;있지&amp;nbsp;않았기&amp;nbsp;때문에&amp;nbsp;발생한다.&amp;nbsp;정리되지&amp;nbsp;않은&amp;nbsp;워크플로우&amp;nbsp;위에&amp;nbsp;AI를&amp;nbsp;얹으면,&amp;nbsp;기존의&amp;nbsp;비효율과&amp;nbsp;혼란이&amp;nbsp;그대로&amp;nbsp;증폭된다.&lt;br /&gt;&lt;br /&gt;그래서&amp;nbsp;AX는&amp;nbsp;DX를&amp;nbsp;건너뛰는&amp;nbsp;전략이&amp;nbsp;될&amp;nbsp;수&amp;nbsp;없다.&amp;nbsp;오히려&amp;nbsp;DX가&amp;nbsp;잘&amp;nbsp;되어&amp;nbsp;있는&amp;nbsp;조직일수록&amp;nbsp;AX의&amp;nbsp;효과를&amp;nbsp;빠르게&amp;nbsp;체감한다.&amp;nbsp;데이터가&amp;nbsp;흐르고,&amp;nbsp;자동화가&amp;nbsp;자리&amp;nbsp;잡고,&amp;nbsp;팀이&amp;nbsp;디지털&amp;nbsp;방식으로&amp;nbsp;사고할&amp;nbsp;수&amp;nbsp;있을&amp;nbsp;때,&amp;nbsp;AI는&amp;nbsp;비로소&amp;nbsp;&amp;lsquo;레버리지&amp;rsquo;로&amp;nbsp;작동한다.&lt;br /&gt;&lt;br /&gt;정리하면,&amp;nbsp;AX의&amp;nbsp;본질은&amp;nbsp;&amp;lsquo;AI를&amp;nbsp;도입하는&amp;nbsp;것&amp;rsquo;이&amp;nbsp;아니라,&amp;nbsp;&amp;lsquo;AI가&amp;nbsp;제대로&amp;nbsp;작동할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;상태를&amp;nbsp;만드는&amp;nbsp;것&amp;rsquo;이다.&amp;nbsp;그리고&amp;nbsp;그&amp;nbsp;출발점은&amp;nbsp;언제나&amp;nbsp;DX다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/744</guid>
      <comments>https://series.tistory.com/entry/AI-%EC%A0%84%ED%99%98AX%EB%B3%B4%EB%8B%A4-DXDigital-Transformation%EC%9D%B4-%EB%A8%BC%EC%A0%80%EB%8B%A4#entry744comment</comments>
      <pubDate>Thu, 23 Apr 2026 10:27:31 +0900</pubDate>
    </item>
    <item>
      <title>AX 실패의 역설: 왜 당신의 자동화 프로젝트는 '유령 시스템'이 되는가?</title>
      <link>https://series.tistory.com/entry/AX-%EC%8B%A4%ED%8C%A8%EC%9D%98-%EC%97%AD%EC%84%A4-%EC%99%9C-%EB%8B%B9%EC%8B%A0%EC%9D%98-%EC%9E%90%EB%8F%99%ED%99%94-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%8A%94-%EC%9C%A0%EB%A0%B9-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%B4-%EB%90%98%EB%8A%94%EA%B0%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AX가 실패하는 이유: 기술이 아니라 접근 방식이다.&lt;br /&gt;많은&amp;nbsp;기업이&amp;nbsp;AX(업무&amp;nbsp;자동화)를&amp;nbsp;도입할&amp;nbsp;때&amp;nbsp;비슷한&amp;nbsp;패턴을&amp;nbsp;밟는다.&lt;br /&gt;&amp;ldquo;우리&amp;nbsp;업무를&amp;nbsp;분석해서&amp;nbsp;자동화&amp;nbsp;설계해보자.&amp;rdquo;&lt;br /&gt;그리고&amp;nbsp;몇&amp;nbsp;달&amp;nbsp;뒤,&amp;nbsp;결과는&amp;nbsp;뻔하다.&amp;nbsp;시스템은&amp;nbsp;남지만&amp;nbsp;현업은&amp;nbsp;쓰지&amp;nbsp;않는다.&lt;br /&gt;&lt;br /&gt;왜&amp;nbsp;이런&amp;nbsp;일이&amp;nbsp;반복될까?&lt;br /&gt;핵심은&amp;nbsp;AX&amp;nbsp;대상&amp;nbsp;업무가&amp;nbsp;&amp;lsquo;고약한&amp;nbsp;문제&amp;rsquo;라는&amp;nbsp;데&amp;nbsp;있다.&lt;br /&gt;해보기&amp;nbsp;전까지는&amp;nbsp;진짜&amp;nbsp;병목이&amp;nbsp;어디인지&amp;nbsp;알&amp;nbsp;수&amp;nbsp;없다.&lt;br /&gt;사람의&amp;nbsp;습관,&amp;nbsp;예외&amp;nbsp;케이스,&amp;nbsp;책임&amp;nbsp;구조가&amp;nbsp;계속&amp;nbsp;튀어나오며&amp;nbsp;계획을&amp;nbsp;흔든다.&lt;br /&gt;&lt;br /&gt;그런데&amp;nbsp;많은&amp;nbsp;기업은&amp;nbsp;폭포수&amp;nbsp;방식으로&amp;nbsp;접근한다.&lt;br /&gt;즉,&amp;nbsp;&amp;ldquo;처음에&amp;nbsp;모든&amp;nbsp;걸&amp;nbsp;정의할&amp;nbsp;수&amp;nbsp;있다&amp;rdquo;는&amp;nbsp;가정&amp;nbsp;위에서&amp;nbsp;출발한다.&lt;br /&gt;이&amp;nbsp;방식은&amp;nbsp;완성도를&amp;nbsp;높이는&amp;nbsp;데는&amp;nbsp;적합하지만,&lt;br /&gt;예측&amp;nbsp;불가능성이&amp;nbsp;큰&amp;nbsp;AX에는&amp;nbsp;맞지&amp;nbsp;않는다.&lt;br /&gt;그래서&amp;nbsp;실패한다.&lt;br /&gt;&lt;br /&gt;AX의&amp;nbsp;올바른&amp;nbsp;접근:&amp;nbsp;작은&amp;nbsp;자동화에서&amp;nbsp;시작하기&lt;br /&gt;AX는&amp;nbsp;거대한&amp;nbsp;설계가&amp;nbsp;아니라&amp;nbsp;작은&amp;nbsp;시도에서&amp;nbsp;출발해야&amp;nbsp;한다.&lt;br /&gt;&lt;br /&gt;1. 작은 자동화를 실제 업무에 붙인다.&lt;br /&gt;2. 현업의 반응을 관찰한다.&lt;br /&gt;3. 문제를 다시 정의한다.&lt;br /&gt;4. 반복한다.&lt;br /&gt;&lt;br /&gt;이&amp;nbsp;과정을&amp;nbsp;통해&amp;nbsp;조직은&amp;nbsp;단순히&amp;nbsp;자동화를&amp;nbsp;구축하는&amp;nbsp;것이&amp;nbsp;아니라,&lt;br /&gt;문제를&amp;nbsp;정의하는&amp;nbsp;속도를&amp;nbsp;높인다.&lt;br /&gt;자동화는&amp;nbsp;결과물이&amp;nbsp;아니라&amp;nbsp;학습을&amp;nbsp;위한&amp;nbsp;도구가&amp;nbsp;된다.&lt;br /&gt;&lt;br /&gt;폭포수&amp;nbsp;vs&amp;nbsp;AX:&amp;nbsp;완성도&amp;nbsp;vs&amp;nbsp;학습&amp;nbsp;속도&lt;br /&gt;폭포수&amp;nbsp;방식은&amp;nbsp;완성도를&amp;nbsp;올리는&amp;nbsp;구조다.&lt;br /&gt;&lt;br /&gt;AX는&amp;nbsp;학습&amp;nbsp;속도를&amp;nbsp;올리는&amp;nbsp;게임이다.&lt;br /&gt;&lt;br /&gt;즉,&amp;nbsp;AX의&amp;nbsp;성공은&amp;nbsp;기술적&amp;nbsp;완성도가&amp;nbsp;아니라&lt;br /&gt;얼마나&amp;nbsp;빠르게&amp;nbsp;문제를&amp;nbsp;재정의하고&amp;nbsp;개선할&amp;nbsp;수&amp;nbsp;있는지에&amp;nbsp;달려&amp;nbsp;있다.&lt;br /&gt;&lt;br /&gt;결론&lt;br /&gt;AX는&amp;nbsp;단순히&amp;nbsp;&amp;ldquo;업무를&amp;nbsp;자동화한다&amp;rdquo;는&amp;nbsp;프로젝트가&amp;nbsp;아니다.&lt;br /&gt;조직이&amp;nbsp;문제를&amp;nbsp;정의하고&amp;nbsp;학습하는&amp;nbsp;능력을&amp;nbsp;키우는&amp;nbsp;과정이다.&lt;br /&gt;작은&amp;nbsp;자동화부터&amp;nbsp;시작해,&amp;nbsp;현업과&amp;nbsp;함께&amp;nbsp;배우고,&lt;br /&gt;반복하며&amp;nbsp;점차&amp;nbsp;확장하는&amp;nbsp;접근만이&amp;nbsp;AX를&amp;nbsp;성공으로&amp;nbsp;이끈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/743</guid>
      <comments>https://series.tistory.com/entry/AX-%EC%8B%A4%ED%8C%A8%EC%9D%98-%EC%97%AD%EC%84%A4-%EC%99%9C-%EB%8B%B9%EC%8B%A0%EC%9D%98-%EC%9E%90%EB%8F%99%ED%99%94-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%8A%94-%EC%9C%A0%EB%A0%B9-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%B4-%EB%90%98%EB%8A%94%EA%B0%80#entry743comment</comments>
      <pubDate>Thu, 23 Apr 2026 09:58:05 +0900</pubDate>
    </item>
    <item>
      <title>AX(AI Transformation) - 기획서부터 백엔드, 프론트엔드, 배포까지, AI가 바꾼 개발 파이프라인 이야기</title>
      <link>https://series.tistory.com/entry/AXAI-Transformation-%EA%B8%B0%ED%9A%8D%EC%84%9C%EB%B6%80%ED%84%B0-%EB%B0%B1%EC%97%94%EB%93%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%B0%B0%ED%8F%AC%EA%B9%8C%EC%A7%80-AI%EA%B0%80-%EB%B0%94%EA%BE%BC-%EA%B0%9C%EB%B0%9C-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8-%EC%9D%B4%EC%95%BC%EA%B8%B0</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;AX(AI&amp;nbsp;Transformation)&amp;nbsp;-&amp;nbsp;기획서부터&amp;nbsp;백엔드,&amp;nbsp;프론트엔드,&amp;nbsp;배포까지,&amp;nbsp;AI가&amp;nbsp;바꾼&amp;nbsp;개발&amp;nbsp;파이프라인&amp;nbsp;이야기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얼마&amp;nbsp;전까지만&amp;nbsp;해도&amp;nbsp;&quot;AI&amp;nbsp;잘&amp;nbsp;쓰는&amp;nbsp;개발자&quot;의&amp;nbsp;기준은&amp;nbsp;코드&amp;nbsp;자동완성을&amp;nbsp;얼마나&amp;nbsp;잘&amp;nbsp;활용하느냐였습니다.&amp;nbsp;커서(Cursor)를&amp;nbsp;쓰냐,&amp;nbsp;Claude&amp;nbsp;Code를&amp;nbsp;쓰냐.&amp;nbsp;그게&amp;nbsp;전부인&amp;nbsp;줄&amp;nbsp;알았어요.&lt;br /&gt;&lt;br /&gt;그런데&amp;nbsp;어느&amp;nbsp;순간부터&amp;nbsp;그&amp;nbsp;질문이&amp;nbsp;달라지기&amp;nbsp;시작했습니다.&amp;nbsp;&quot;어떤&amp;nbsp;AI&amp;nbsp;에디터를&amp;nbsp;쓰냐&quot;가&amp;nbsp;아니라,&amp;nbsp;&quot;어떤&amp;nbsp;파이프라인으로&amp;nbsp;개발하느냐&quot;로.&amp;nbsp;그&amp;nbsp;변화를&amp;nbsp;직접&amp;nbsp;겪으면서,&amp;nbsp;저는&amp;nbsp;꽤&amp;nbsp;많은&amp;nbsp;것을&amp;nbsp;다시&amp;nbsp;생각하게&amp;nbsp;됐습니다.&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;AI 에디터를 넘어 파이프라인으로: 파도의 방향이 바뀌었다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2023년에 DX(디지털 전환)가 있었다면, 2025년엔 AX(AI 전환)가 왔습니다. 이름만 바뀐 게 아닙니다. 결이 다릅니다.&lt;br /&gt;&lt;br /&gt;DX는&amp;nbsp;오프라인에&amp;nbsp;있던&amp;nbsp;것을&amp;nbsp;온라인으로&amp;nbsp;옮기는&amp;nbsp;작업이었습니다.&amp;nbsp;예약&amp;nbsp;시스템을&amp;nbsp;만들고,&amp;nbsp;재고&amp;nbsp;관리를&amp;nbsp;엑셀에서&amp;nbsp;SaaS로&amp;nbsp;이전하고.&amp;nbsp;비교적&amp;nbsp;명확한&amp;nbsp;목적지가&amp;nbsp;있었죠.&lt;br /&gt;&lt;br /&gt;AX는&amp;nbsp;좀&amp;nbsp;다릅니다.&amp;nbsp;&quot;AI로&amp;nbsp;뭘&amp;nbsp;해야&amp;nbsp;하지?&quot;라는&amp;nbsp;질문&amp;nbsp;자체가&amp;nbsp;출발점인&amp;nbsp;경우가&amp;nbsp;많습니다.&amp;nbsp;그래서&amp;nbsp;많은&amp;nbsp;팀이&amp;nbsp;가장&amp;nbsp;손쉬운&amp;nbsp;것부터&amp;nbsp;잡습니다.&amp;nbsp;코드&amp;nbsp;자동완성.&amp;nbsp;자동&amp;nbsp;테스트&amp;nbsp;생성.&amp;nbsp;PR&amp;nbsp;요약.&lt;br /&gt;&lt;br /&gt;나쁜&amp;nbsp;선택은&amp;nbsp;아닙니다.&amp;nbsp;그런데&amp;nbsp;거기서&amp;nbsp;멈추는&amp;nbsp;팀과,&amp;nbsp;그다음을&amp;nbsp;보는&amp;nbsp;팀&amp;nbsp;사이에&amp;nbsp;이미&amp;nbsp;격차가&amp;nbsp;생기고&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;1세대&amp;nbsp;AI&amp;nbsp;도입이&amp;nbsp;&quot;AI로&amp;nbsp;코드를&amp;nbsp;빠르게&amp;nbsp;짜는&amp;nbsp;것&quot;이었다면,&amp;nbsp;2세대는&amp;nbsp;다릅니다.&amp;nbsp;기획서부터&amp;nbsp;배포까지,&amp;nbsp;산출물&amp;nbsp;전&amp;nbsp;공정에&amp;nbsp;AI가&amp;nbsp;읽고&amp;nbsp;쓸&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;언어를&amp;nbsp;심는&amp;nbsp;것.&amp;nbsp;그게&amp;nbsp;지금&amp;nbsp;제가&amp;nbsp;생각하는&amp;nbsp;진짜&amp;nbsp;AX입니다.&lt;br /&gt;&lt;br /&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;직접&amp;nbsp;겪어본&amp;nbsp;이야기:&amp;nbsp;내가&amp;nbsp;파이프라인을&amp;nbsp;만들게&amp;nbsp;된&amp;nbsp;이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;처음엔&amp;nbsp;솔직히&amp;nbsp;불편했습니다.&amp;nbsp;내가&amp;nbsp;짜야&amp;nbsp;할&amp;nbsp;코드를&amp;nbsp;AI가&amp;nbsp;대신&amp;nbsp;쓴다는&amp;nbsp;게&amp;nbsp;왠지&amp;nbsp;어색했거든요.&lt;br /&gt;&lt;br /&gt;그런데&amp;nbsp;방향을&amp;nbsp;바꾸니&amp;nbsp;달라졌습니다.&amp;nbsp;AI에게&amp;nbsp;코드를&amp;nbsp;맡기는&amp;nbsp;게&amp;nbsp;아니라,&amp;nbsp;AI가&amp;nbsp;일할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;환경을&amp;nbsp;설계하는&amp;nbsp;것이&amp;nbsp;제&amp;nbsp;일이&amp;nbsp;됐습니다.&lt;br /&gt;&lt;br /&gt;그&amp;nbsp;과정에서&amp;nbsp;겪은&amp;nbsp;일들이&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;첫&amp;nbsp;번째.&amp;nbsp;저는&amp;nbsp;Claude&amp;nbsp;Code&amp;nbsp;환경에&amp;nbsp;훅(hook),&amp;nbsp;스킬(skill),&amp;nbsp;에이전트&amp;nbsp;계층을&amp;nbsp;직접&amp;nbsp;만들어&amp;nbsp;쌓았습니다.&amp;nbsp;처음엔&amp;nbsp;&quot;이게&amp;nbsp;AI&amp;nbsp;생산성이랑&amp;nbsp;무슨&amp;nbsp;관계가&amp;nbsp;있나?&quot;&amp;nbsp;싶었어요.&amp;nbsp;그런데&amp;nbsp;써보니&amp;nbsp;알겠더라고요.&amp;nbsp;AI가&amp;nbsp;실수를&amp;nbsp;덜&amp;nbsp;하는&amp;nbsp;환경이&amp;nbsp;결국&amp;nbsp;생산성의&amp;nbsp;본체였습니다.&amp;nbsp;AI&amp;nbsp;자체보다&amp;nbsp;AI를&amp;nbsp;둘러싼&amp;nbsp;구조가&amp;nbsp;더&amp;nbsp;중요했습니다.&lt;br /&gt;&lt;br /&gt;두&amp;nbsp;번째.&amp;nbsp;Figma에서&amp;nbsp;컴포넌트를&amp;nbsp;코드로&amp;nbsp;자동&amp;nbsp;변환하는&amp;nbsp;걸&amp;nbsp;해봤습니다.&amp;nbsp;처음엔&amp;nbsp;기대가&amp;nbsp;컸습니다.&amp;nbsp;그런데&amp;nbsp;디자인&amp;nbsp;토큰이&amp;nbsp;정리&amp;nbsp;안&amp;nbsp;된&amp;nbsp;상태에서&amp;nbsp;돌리니&amp;nbsp;쓸&amp;nbsp;수&amp;nbsp;없는&amp;nbsp;코드가&amp;nbsp;나왔어요.&amp;nbsp;AI가&amp;nbsp;나쁜&amp;nbsp;게&amp;nbsp;아니었습니다.&amp;nbsp;제가&amp;nbsp;AI에게&amp;nbsp;줄&amp;nbsp;재료를&amp;nbsp;준비&amp;nbsp;안&amp;nbsp;한&amp;nbsp;거였습니다.&lt;br /&gt;&lt;br /&gt;세&amp;nbsp;번째.&amp;nbsp;Vercel에&amp;nbsp;환경변수를&amp;nbsp;설정하다가&amp;nbsp;런타임에서만&amp;nbsp;인증이&amp;nbsp;실패하는&amp;nbsp;이슈를&amp;nbsp;겪었습니다.&amp;nbsp;원인은&amp;nbsp;$&amp;nbsp;문자가&amp;nbsp;포함된&amp;nbsp;값을&amp;nbsp;대시보드에&amp;nbsp;넣을&amp;nbsp;때&amp;nbsp;\$로&amp;nbsp;이스케이프된&amp;nbsp;채&amp;nbsp;저장된&amp;nbsp;것이었습니다.&amp;nbsp;AI가&amp;nbsp;검토한&amp;nbsp;코드에는&amp;nbsp;문제가&amp;nbsp;없었습니다.&amp;nbsp;우리가&amp;nbsp;AI에게&amp;nbsp;준&amp;nbsp;컨텍스트에&amp;nbsp;구멍이&amp;nbsp;있었던&amp;nbsp;겁니다.&lt;br /&gt;&lt;br /&gt;세&amp;nbsp;가지&amp;nbsp;사례에서&amp;nbsp;공통점이&amp;nbsp;보였습니다.&amp;nbsp;문제는&amp;nbsp;항상&amp;nbsp;AI&amp;nbsp;이전&amp;nbsp;단계에&amp;nbsp;있었습니다.&amp;nbsp;AI에게&amp;nbsp;무엇을&amp;nbsp;어떻게&amp;nbsp;줄&amp;nbsp;것인가,&amp;nbsp;그&amp;nbsp;준비가&amp;nbsp;개발&amp;nbsp;생산성의&amp;nbsp;진짜&amp;nbsp;열쇠였습니다.&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;왜 PRD부터 시작해야 하는가: 스펙 없이 시작한 코드는 결국 다시 짠다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;AI&amp;nbsp;에이전트에게&amp;nbsp;&quot;API&amp;nbsp;만들어줘&quot;라고&amp;nbsp;말하면&amp;nbsp;뭔가&amp;nbsp;나오긴&amp;nbsp;합니다.&amp;nbsp;그런데&amp;nbsp;그게&amp;nbsp;우리가&amp;nbsp;원하는&amp;nbsp;건지&amp;nbsp;보장할&amp;nbsp;수&amp;nbsp;없습니다.&amp;nbsp;어떤&amp;nbsp;인증&amp;nbsp;방식인지,&amp;nbsp;실패&amp;nbsp;시&amp;nbsp;어떻게&amp;nbsp;처리하는지,&amp;nbsp;어떤&amp;nbsp;응답&amp;nbsp;구조를&amp;nbsp;써야&amp;nbsp;하는지&amp;nbsp;&amp;mdash;&amp;nbsp;그&amp;nbsp;맥락이&amp;nbsp;없으면&amp;nbsp;AI는&amp;nbsp;그냥&amp;nbsp;그럴듯한&amp;nbsp;코드를&amp;nbsp;만들&amp;nbsp;뿐입니다.&lt;br /&gt;&lt;br /&gt;문제는&amp;nbsp;요청&amp;nbsp;방식이&amp;nbsp;아닙니다.&amp;nbsp;입력&amp;nbsp;자체입니다.&lt;br /&gt;&lt;br /&gt;현업에서&amp;nbsp;쓰는&amp;nbsp;PRD(Product&amp;nbsp;Requirements&amp;nbsp;Document,&amp;nbsp;제품&amp;nbsp;요구사항&amp;nbsp;문서)의&amp;nbsp;문제가&amp;nbsp;여기&amp;nbsp;있습니다.&amp;nbsp;대부분의&amp;nbsp;PRD는&amp;nbsp;사람이&amp;nbsp;읽기&amp;nbsp;위해&amp;nbsp;씁니다.&amp;nbsp;&quot;사용자가&amp;nbsp;로그인&amp;nbsp;버튼을&amp;nbsp;누르면&amp;nbsp;인증&amp;nbsp;프로세스가&amp;nbsp;시작된다.&quot;&amp;nbsp;이&amp;nbsp;문장은&amp;nbsp;사람에게는&amp;nbsp;자연스럽지만&amp;nbsp;AI에게는&amp;nbsp;모호합니다.&amp;nbsp;어떤&amp;nbsp;인증&amp;nbsp;방식인지,&amp;nbsp;실패&amp;nbsp;시&amp;nbsp;어떻게&amp;nbsp;처리하는지,&amp;nbsp;어떤&amp;nbsp;상태를&amp;nbsp;반환해야&amp;nbsp;하는지가&amp;nbsp;없습니다.&lt;br /&gt;&lt;br /&gt;그래서&amp;nbsp;PRD를&amp;nbsp;다시&amp;nbsp;써야&amp;nbsp;합니다.&amp;nbsp;명시적&amp;nbsp;제약,&amp;nbsp;수용&amp;nbsp;기준(acceptance&amp;nbsp;criteria),&amp;nbsp;데이터&amp;nbsp;계약이&amp;nbsp;담긴&amp;nbsp;AI가&amp;nbsp;읽을&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;문서로.&amp;nbsp;그게&amp;nbsp;파이프라인의&amp;nbsp;진짜&amp;nbsp;출발점입니다.&lt;br /&gt;&lt;br /&gt;요즘은&amp;nbsp;이걸&amp;nbsp;**컨텍스트&amp;nbsp;엔지니어링(Context&amp;nbsp;Engineering)**이라고&amp;nbsp;부릅니다.&amp;nbsp;AI에게&amp;nbsp;무엇을&amp;nbsp;어떤&amp;nbsp;형식으로&amp;nbsp;줄&amp;nbsp;것인가를&amp;nbsp;설계하는&amp;nbsp;일&amp;nbsp;자체가&amp;nbsp;하나의&amp;nbsp;전문&amp;nbsp;영역이&amp;nbsp;된&amp;nbsp;겁니다.&lt;/p&gt;
&lt;p 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-origin-width=&quot;710&quot; data-origin-height=&quot;1167&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cg4XHT/dJMcadhrAav/KJEy6QjMVD5UnGL0HKGZv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cg4XHT/dJMcadhrAav/KJEy6QjMVD5UnGL0HKGZv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cg4XHT/dJMcadhrAav/KJEy6QjMVD5UnGL0HKGZv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcg4XHT%2FdJMcadhrAav%2FKJEy6QjMVD5UnGL0HKGZv0%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;710&quot; height=&quot;1167&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;1167&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;파이프라인&amp;nbsp;5단계:&amp;nbsp;기획에서&amp;nbsp;배포까지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;개발&amp;nbsp;파이프라인에는&amp;nbsp;순서가&amp;nbsp;있습니다.&amp;nbsp;상류가&amp;nbsp;제대로&amp;nbsp;정의되어야&amp;nbsp;하류가&amp;nbsp;흔들리지&amp;nbsp;않습니다.&amp;nbsp;AI를&amp;nbsp;쓸수록&amp;nbsp;이&amp;nbsp;원칙이&amp;nbsp;더&amp;nbsp;선명해집니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1단계&amp;nbsp;&amp;mdash;&amp;nbsp;PRD&amp;nbsp;표준화&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;PRD를&amp;nbsp;AI가&amp;nbsp;읽을&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;형식으로&amp;nbsp;바꾸는&amp;nbsp;데서&amp;nbsp;시작합니다.&amp;nbsp;YAML&amp;nbsp;프론트매터에&amp;nbsp;기능&amp;nbsp;ID,&amp;nbsp;수용&amp;nbsp;기준,&amp;nbsp;의존성,&amp;nbsp;데이터&amp;nbsp;타입을&amp;nbsp;명시합니다.&amp;nbsp;&quot;사용자가&amp;nbsp;가입할&amp;nbsp;수&amp;nbsp;있다&quot;가&amp;nbsp;아니라,&amp;nbsp;&quot;이메일&amp;nbsp;+&amp;nbsp;비밀번호를&amp;nbsp;받아&amp;nbsp;users&amp;nbsp;테이블에&amp;nbsp;INSERT하고,&amp;nbsp;중복&amp;nbsp;시&amp;nbsp;409를&amp;nbsp;반환한다&quot;로&amp;nbsp;씁니다.&amp;nbsp;처음엔&amp;nbsp;귀찮습니다.&amp;nbsp;그런데&amp;nbsp;이게&amp;nbsp;이후&amp;nbsp;모든&amp;nbsp;단계의&amp;nbsp;재료가&amp;nbsp;됩니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2단계&amp;nbsp;&amp;mdash;&amp;nbsp;디자인&amp;nbsp;시스템&amp;nbsp;토큰화&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Figma&amp;nbsp;Variables를&amp;nbsp;JSON&amp;nbsp;토큰으로&amp;nbsp;추출하고,&amp;nbsp;그것이&amp;nbsp;Tailwind&amp;nbsp;설정이나&amp;nbsp;CSS&amp;nbsp;변수로&amp;nbsp;자동&amp;nbsp;연동되게&amp;nbsp;합니다.&amp;nbsp;디자이너가&amp;nbsp;브랜드&amp;nbsp;컬러를&amp;nbsp;바꾸면&amp;nbsp;코드가&amp;nbsp;따라&amp;nbsp;움직이는&amp;nbsp;구조.&amp;nbsp;이게&amp;nbsp;되어&amp;nbsp;있지&amp;nbsp;않으면,&amp;nbsp;컴포넌트를&amp;nbsp;AI가&amp;nbsp;아무리&amp;nbsp;잘&amp;nbsp;만들어도&amp;nbsp;스타일&amp;nbsp;불일치가&amp;nbsp;수동으로&amp;nbsp;쌓입니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3단계&amp;nbsp;&amp;mdash;&amp;nbsp;API&amp;nbsp;스펙&amp;nbsp;먼저&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;PRD에서&amp;nbsp;정의한&amp;nbsp;요구사항이&amp;nbsp;OpenAPI&amp;nbsp;스펙&amp;nbsp;또는&amp;nbsp;Zod&amp;nbsp;스키마로&amp;nbsp;정리됩니다.&amp;nbsp;코드를&amp;nbsp;먼저&amp;nbsp;짜는&amp;nbsp;게&amp;nbsp;아닙니다.&amp;nbsp;어떤&amp;nbsp;데이터를&amp;nbsp;주고받을지를&amp;nbsp;먼저&amp;nbsp;정합니다.&amp;nbsp;이&amp;nbsp;스펙이&amp;nbsp;명확하면&amp;nbsp;프론트엔드와&amp;nbsp;백엔드가&amp;nbsp;병렬로&amp;nbsp;개발해도&amp;nbsp;충돌이&amp;nbsp;없습니다.&amp;nbsp;AI도&amp;nbsp;스펙에서&amp;nbsp;시작하면&amp;nbsp;훨씬&amp;nbsp;정확한&amp;nbsp;코드를&amp;nbsp;만듭니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4단계&amp;nbsp;&amp;mdash;&amp;nbsp;프론트엔드&amp;nbsp;조립&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;디자인&amp;nbsp;토큰,&amp;nbsp;API&amp;nbsp;스펙,&amp;nbsp;PRD&amp;nbsp;요구사항이&amp;nbsp;모두&amp;nbsp;AI가&amp;nbsp;읽을&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;형태로&amp;nbsp;갖춰져&amp;nbsp;있으면&amp;nbsp;프론트엔드&amp;nbsp;개발은&amp;nbsp;AI가&amp;nbsp;상당&amp;nbsp;부분&amp;nbsp;조립합니다.&amp;nbsp;컴포넌트&amp;nbsp;생성,&amp;nbsp;API&amp;nbsp;연동,&amp;nbsp;에러&amp;nbsp;핸들링.&amp;nbsp;사람은&amp;nbsp;설계를&amp;nbsp;검토하고&amp;nbsp;엣지&amp;nbsp;케이스를&amp;nbsp;판단합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5단계&amp;nbsp;&amp;mdash;&amp;nbsp;하네스(검증&amp;nbsp;게이트)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;하네스(harness)란&amp;nbsp;AI가&amp;nbsp;만든&amp;nbsp;결과물을&amp;nbsp;자동으로&amp;nbsp;검증하는&amp;nbsp;장치입니다.&amp;nbsp;타입&amp;nbsp;체크,&amp;nbsp;빌드&amp;nbsp;검증,&amp;nbsp;런타임&amp;nbsp;테스트,&amp;nbsp;AI&amp;nbsp;코드&amp;nbsp;리뷰어.&amp;nbsp;이&amp;nbsp;게이트&amp;nbsp;없이&amp;nbsp;파이프라인을&amp;nbsp;돌리는&amp;nbsp;건&amp;nbsp;안전장치&amp;nbsp;없이&amp;nbsp;공장을&amp;nbsp;가동하는&amp;nbsp;것과&amp;nbsp;같습니다.&amp;nbsp;실수가&amp;nbsp;빠르게&amp;nbsp;누적됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시작하는&amp;nbsp;팀을&amp;nbsp;위한&amp;nbsp;현실적인&amp;nbsp;조언&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&quot;그럼&amp;nbsp;당장&amp;nbsp;뭘&amp;nbsp;해야&amp;nbsp;하나요?&quot;라는&amp;nbsp;질문을&amp;nbsp;많이&amp;nbsp;받습니다.&lt;br /&gt;&lt;br /&gt;다짜고짜&amp;nbsp;에이전트부터&amp;nbsp;도입하지&amp;nbsp;마세요.&amp;nbsp;저도&amp;nbsp;그랬다가&amp;nbsp;돌아온&amp;nbsp;경험이&amp;nbsp;있습니다.&amp;nbsp;AI&amp;nbsp;에이전트는&amp;nbsp;좋은&amp;nbsp;재료가&amp;nbsp;있을&amp;nbsp;때&amp;nbsp;진짜&amp;nbsp;힘을&amp;nbsp;발휘합니다.&amp;nbsp;재료가&amp;nbsp;엉망이면&amp;nbsp;결과도&amp;nbsp;엉망입니다.&lt;br /&gt;&lt;br /&gt;첫&amp;nbsp;주에&amp;nbsp;할&amp;nbsp;일은&amp;nbsp;하나입니다.&amp;nbsp;PRD&amp;nbsp;하나를&amp;nbsp;골라서&amp;nbsp;AI가&amp;nbsp;이해할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;형식으로&amp;nbsp;다시&amp;nbsp;씁니다.&amp;nbsp;수용&amp;nbsp;기준을&amp;nbsp;명시적으로,&amp;nbsp;데이터&amp;nbsp;흐름을&amp;nbsp;타입과&amp;nbsp;함께.&amp;nbsp;그것만&amp;nbsp;해도&amp;nbsp;충분합니다.&lt;br /&gt;&lt;br /&gt;첫&amp;nbsp;달에&amp;nbsp;할&amp;nbsp;일은&amp;nbsp;두&amp;nbsp;가지입니다.&amp;nbsp;Figma&amp;nbsp;디자인&amp;nbsp;토큰&amp;nbsp;정리,&amp;nbsp;그리고&amp;nbsp;OpenAPI&amp;nbsp;스펙&amp;nbsp;기반으로&amp;nbsp;엔드포인트&amp;nbsp;하나를&amp;nbsp;파이프라인화합니다.&amp;nbsp;한&amp;nbsp;번&amp;nbsp;성공하면&amp;nbsp;팀&amp;nbsp;전체가&amp;nbsp;느낍니다.&amp;nbsp;뭔가&amp;nbsp;달라지고&amp;nbsp;있다는&amp;nbsp;걸.&lt;br /&gt;&lt;br /&gt;첫&amp;nbsp;분기에&amp;nbsp;할&amp;nbsp;일은&amp;nbsp;자동화와&amp;nbsp;회고입니다.&amp;nbsp;리뷰&amp;nbsp;게이트를&amp;nbsp;CI에&amp;nbsp;붙이고,&amp;nbsp;실패했던&amp;nbsp;것들을&amp;nbsp;회고합니다.&amp;nbsp;AI&amp;nbsp;실수의&amp;nbsp;패턴이&amp;nbsp;보이기&amp;nbsp;시작합니다.&amp;nbsp;그&amp;nbsp;패턴이&amp;nbsp;다음&amp;nbsp;하네스를&amp;nbsp;설계하는&amp;nbsp;재료가&amp;nbsp;됩니다.&lt;br /&gt;&lt;br /&gt;핵심은&amp;nbsp;이겁니다.&amp;nbsp;AI에게&amp;nbsp;일을&amp;nbsp;맡기는&amp;nbsp;게&amp;nbsp;아니라,&amp;nbsp;AI가&amp;nbsp;일할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;환경을&amp;nbsp;만드는&amp;nbsp;것이&amp;nbsp;AX입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자는 완성된 화면을 봅니다. 버튼이 잘 눌리는지, 속도가 빠른지. 그게 전부처럼 보이죠.&lt;br /&gt;&lt;br /&gt;그런데&amp;nbsp;그&amp;nbsp;화면의&amp;nbsp;품질은&amp;nbsp;PRD가&amp;nbsp;얼마나&amp;nbsp;명확했는지,&amp;nbsp;디자인&amp;nbsp;토큰이&amp;nbsp;얼마나&amp;nbsp;잘&amp;nbsp;정의됐는지,&amp;nbsp;API&amp;nbsp;스펙이&amp;nbsp;얼마나&amp;nbsp;구체적이었는지에&amp;nbsp;달려&amp;nbsp;있습니다.&amp;nbsp;사용자&amp;nbsp;눈에&amp;nbsp;보이지&amp;nbsp;않는&amp;nbsp;곳에서&amp;nbsp;품질이&amp;nbsp;결정됩니다.&lt;br /&gt;&lt;br /&gt;AI가&amp;nbsp;바꾼&amp;nbsp;건&amp;nbsp;단순히&amp;nbsp;코드&amp;nbsp;작성&amp;nbsp;속도가&amp;nbsp;아닙니다.&amp;nbsp;상류&amp;nbsp;산출물의&amp;nbsp;품질이&amp;nbsp;하류&amp;nbsp;결과를&amp;nbsp;결정한다는&amp;nbsp;원리를&amp;nbsp;더&amp;nbsp;선명하게&amp;nbsp;드러낸&amp;nbsp;것입니다.&lt;br /&gt;&lt;br /&gt;그&amp;nbsp;파이프라인을&amp;nbsp;설계하는&amp;nbsp;사람이,&amp;nbsp;다음&amp;nbsp;시대의&amp;nbsp;개발자라고&amp;nbsp;생각합니다.&lt;/p&gt;</description>
      <category>AI AX</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/742</guid>
      <comments>https://series.tistory.com/entry/AXAI-Transformation-%EA%B8%B0%ED%9A%8D%EC%84%9C%EB%B6%80%ED%84%B0-%EB%B0%B1%EC%97%94%EB%93%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%B0%B0%ED%8F%AC%EA%B9%8C%EC%A7%80-AI%EA%B0%80-%EB%B0%94%EA%BE%BC-%EA%B0%9C%EB%B0%9C-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8-%EC%9D%B4%EC%95%BC%EA%B8%B0#entry742comment</comments>
      <pubDate>Wed, 22 Apr 2026 09:17:47 +0900</pubDate>
    </item>
    <item>
      <title>ChatGPT Canvas(캔버스) 완벽 활용법! 실무자가 알려주는 진짜 꿀팁 모음 (2024년 최신 가이드) by 일하지마닷컴AI 리치레전드</title>
      <link>https://series.tistory.com/entry/ChatGPT-Canvas%EC%BA%94%EB%B2%84%EC%8A%A4-%EC%99%84%EB%B2%BD-%ED%99%9C%EC%9A%A9%EB%B2%95-%EC%8B%A4%EB%AC%B4%EC%9E%90%EA%B0%80-%EC%95%8C%EB%A0%A4%EC%A3%BC%EB%8A%94-%EC%A7%84%EC%A7%9C-%EA%BF%80%ED%8C%81-%EB%AA%A8%EC%9D%8C-2024%EB%85%84-%EC%B5%9C%EC%8B%A0-%EA%B0%80%EC%9D%B4%EB%93%9C-by-%EC%9D%BC%ED%95%98%EC%A7%80%EB%A7%88%EB%8B%B7%EC%BB%B4AI-%EB%A6%AC%EC%B9%98%EB%A0%88%EC%A0%84%EB%93%9C</link>
      <description>&lt;h1&gt;ChatGPT&amp;nbsp;Canvas(캔버스)&amp;nbsp;완벽&amp;nbsp;활용법!&amp;nbsp;실무자가&amp;nbsp;알려주는&amp;nbsp;진짜&amp;nbsp;꿀팁&amp;nbsp;모음&amp;nbsp;(2024년&amp;nbsp;최신&amp;nbsp;가이드)&amp;nbsp;by&amp;nbsp;일하지마닷컴AI&amp;nbsp;리치레전드&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요, 일하지마닷컴AI - 디지털노마드 N잡러 개발자 리치레전드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 제가 AI 자동화 프로그램을 개발하면서 실제로 활용하고 있는 ChatGPT Canvas의 모든 노하우를 여러분과 공유하려고 해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT Canvas의 강력한 기능들을 200% 활용하는 방법, 함께 알아볼까요?&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ChatGPT Canvas가 특별한 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 정말 다양한 AI 도구들이 쏟아져 나오고 있죠? 그중에서도 ChatGPT Canvas는 특별한 점이 있어요. 기존의 ChatGPT와는 차원이 다른 작업 환경을 제공한다는 거예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 다중 채팅 관리로 복잡한 프로젝트도 한눈에&lt;br /&gt;&amp;bull; 드래그 앤 드롭으로 작업물을 자유자재로 구성&lt;br /&gt;&amp;bull; 실시간으로 다른 팀원들과 협업 가능&lt;br /&gt;&amp;bull; 나만의 프롬프트 템플릿 만들기 지원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://images.unsplash.com/photo-1661961112951-f2bfd1f253ce?q=80&amp;amp;w=2072&amp;amp;auto=format&amp;amp;fit=crop&quot; alt=&quot;ChatGPT Canvas 메인 화면&quot; /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Canvas 시작 전 체크리스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Canvas를 제대로 사용하기 위한 필수 준비사항들을 정리해봤어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; OpenAI 계정 생성하기&lt;br /&gt;&amp;bull; GPT-4 모델 접근 권한 확보 (추천)&lt;br /&gt;&amp;bull; 안정적인 인터넷 환경 확인&lt;br /&gt;&amp;bull; 크롬 브라우저 최신 버전 설치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 기본적인 환경만 갖추면, 여러분도 바로 시작하실 수 있어요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무자가 알려주는 Canvas 실전 활용법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자, 이제부터가 진짜 핵심이에요. 제가 일하지마닷컴AI 리치레전드로서 실제 업무에서 활용하고 있는 Canvas 꿀팁들을 낱낱이 공개할게요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 프롬프트 라이브러리 구축하기&lt;br /&gt;업무별로 자주 쓰는 프롬프트를 정리해두면 정말 편해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 멀티 채팅 프로세스 활용하기&lt;br /&gt;복잡한 프로젝트를 주제별로 나누어 관리하면 효율이 확 올라가요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 캔버스 레이아웃 최적화하기&lt;br /&gt;자주 쓰는 기능은 드래그해서 쉽게 접근할 수 있게 배치하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://images.unsplash.com/photo-1620712943543-bcc4688e7485?q=80&amp;amp;w=2065&amp;amp;auto=format&amp;amp;fit=crop&quot; alt=&quot;Canvas 활용 팁&quot; /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로그래머가 직접 겪은 Canvas 활용 사례&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 RPA 프로그램을 개발하면서 Canvas를 어떻게 활용했는지 실제 사례를 들어볼게요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 코드 최적화 작업&lt;br /&gt;여러 버전의 코드를 동시에 분석하고 개선할 수 있었어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; API 문서 자동화&lt;br /&gt;반복적인 문서 작업을 Canvas로 자동화했더니 시간이 반으로 줄었어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 시스템 설계 브레인스토밍&lt;br /&gt;복잡한 시스템 구조도 Canvas에서 체계적으로 정리할 수 있었죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://images.unsplash.com/photo-1552664730-d307ca884978?q=80&amp;amp;w=2070&amp;amp;auto=format&amp;amp;fit=crop&quot; alt=&quot;실제 활용 예시&quot; /&gt;&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;저희 일하지마닷컴 AI는 ChatGPT Canvas의 강력한 기능을 활용한 맞춤형 자동화 서비스를 제공하고 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; RPA 자동화 프로그램 개발&lt;br /&gt;&amp;bull; 엑셀 매크로 솔루션 구축&lt;br /&gt;&amp;bull; 맞춤형 웹 크롤링 시스템 구현&lt;br /&gt;&amp;bull; 데이터 스크래핑 자동화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든 프로그램은 파이썬을 기반으로 개발되며, Canvas의 강력한 기능과 결합하여 더욱 똑똑하게 작동한답니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분만의 맞춤형 자동화 프로그램이 필요하시다면 &lt;a href=&quot;http://ilhajima.com/&quot;&gt;ilhajima.com&lt;/a&gt;을 방문해주세요. 상담 신청서에 원하시는 기능을 자세히 적어주시면, 리치레전드가 최적의 솔루션을 제안해드릴게요.&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;지금까지 ChatGPT Canvas의 숨은 기능들과 실전 활용법을 자세히 알아보았는데요, Canvas를 제대로 활용하면 업무 효율이 정말 놀랍게 높아진답니다.&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;더 자세한 내용이 궁금하시다면 언제든 일하지마닷컴AI 리치레전드를 찾아주세요. 여러분의 디지털 혁신을 항상 응원하겠습니다!&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;인기 검색어 키워드: ChatGPT 캔버스 가이드 2024, Canvas 프롬프트 작성법, GPT4 실무 활용, 챗GPT 캔버스 업데이트, AI 업무 효율화, Canvas 비즈니스 적용, GPT Canvas 팁, 챗GPT 응용 활용, Canvas 실전 사례, AI 자동화 도구, ChatGPT Canvas 활용법, GPT 캔버스 사용법, AI 글쓰기 도구, 챗GPT 프롬프트, Canvas 초보 가이드, GPT 캔버스 강의, ChatGPT 최신기능, AI 업무 효율화, ChatGPT Canvas 팁, 캔버스 실전 활용&lt;/p&gt;</description>
      <category>AWS</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/741</guid>
      <comments>https://series.tistory.com/entry/ChatGPT-Canvas%EC%BA%94%EB%B2%84%EC%8A%A4-%EC%99%84%EB%B2%BD-%ED%99%9C%EC%9A%A9%EB%B2%95-%EC%8B%A4%EB%AC%B4%EC%9E%90%EA%B0%80-%EC%95%8C%EB%A0%A4%EC%A3%BC%EB%8A%94-%EC%A7%84%EC%A7%9C-%EA%BF%80%ED%8C%81-%EB%AA%A8%EC%9D%8C-2024%EB%85%84-%EC%B5%9C%EC%8B%A0-%EA%B0%80%EC%9D%B4%EB%93%9C-by-%EC%9D%BC%ED%95%98%EC%A7%80%EB%A7%88%EB%8B%B7%EC%BB%B4AI-%EB%A6%AC%EC%B9%98%EB%A0%88%EC%A0%84%EB%93%9C#entry741comment</comments>
      <pubDate>Thu, 7 Nov 2024 16:44:56 +0900</pubDate>
    </item>
    <item>
      <title>Claude AI 활용 가이드: 현직 개발자의 실전 경험담</title>
      <link>https://series.tistory.com/entry/Claude-AI-%ED%99%9C%EC%9A%A9-%EA%B0%80%EC%9D%B4%EB%93%9C-%ED%98%84%EC%A7%81-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EC%8B%A4%EC%A0%84-%EA%B2%BD%ED%97%98%EB%8B%B4</link>
      <description>&lt;h1&gt;Claude AI 활용 가이드: 현직 개발자의 실전 경험담&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요! 일하지마닷컴AI에서 RPA 매크로 프로그램을 개발하고 있는 리치레전드입니다. 오늘은 제가 실제로 업무에서 활용하고 있는 Claude AI에 대해 제 경험을 공유해드리려고 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;처음 Claude를 만나다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작년에 처음 일하지마닷컴 AI를 개발하면서 Claude AI를 알게 되었을 때만 해도, 저 리치레전드는 그저 &quot;또 하나의 챗봇이겠지&quot;라고 생각했습니다. GPT-3.5 기반이라는 설명을 듣고 큰 기대 없이 시작했죠. 하지만 실제로 사용해보니, 제 생각이 완전히 틀렸다는 걸 깨달았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 개발자의 입장에서 보면, Claude는 단순한 챗봇이 아닌 든든한 동료 프로그래머 같은 존재입니다. 복잡한 알고리즘을 구현할 때나 버그를 찾아낼 때, 때로는 제가 미처 생각하지 못한 접근 방식을 제안해주기도 하죠.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제 업무에서의 활용 사례&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 Claude를 가장 유용하게 활용한 경험을 하나 공유해드리겠습니다. 얼마 전 네이버 뉴스 데이터를 수집하는 크롤러를 만들어야 했는데요, Claude의 도움으로 작업 시간을 절반 이상 단축할 수 있었습니다.&lt;/p&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;# 이런 복잡한 크롤링 코드도 Claude와 함께라면 쉽게 작성할 수 있습니다
def crawl_naver_news(keyword, page_num=1):
    base_url = f&quot;https://search.naver.com/search.naver?where=news&amp;amp;query={keyword}&amp;amp;start={(page_num-1)*10+1}&quot;

    response = requests.get(base_url)
    soup = BeautifulSoup(response.text, 'html.parser')

    news_list = []
    articles = soup.select(&quot;.news_area&quot;)
    # ... (코드 상세 내용)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 Claude가 제안한 코드를 그대로 사용하지는 않았습니다. 제 프로젝트의 특성에 맞게 수정하고, 예외 처리도 추가했죠. 하지만 기본 뼈대를 빠르게 잡을 수 있었다는 점에서 정말 큰 도움이 되었습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개발자가 느낀 장단점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&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;: &quot;이 부분은 이렇게 하면 어떨까요?&quot;처럼 동료와 대화하듯 자연스러운 피드백을 주고받을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&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;: 새로 출시된 라이브러리나 최신 버전의 API 변경사항은 모를 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;맥락 이해의 한계&lt;/b&gt;: 프로젝트의 전체적인 구조나 비즈니스 로직을 완벽히 이해시키기는 어렵습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;효과적인 활용을 위한 팁&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;구체적인 요청하기&lt;/b&gt;: &quot;이 코드 어떻게 고치면 돼?&quot;보다는 &quot;이 파이썬 코드에서 메모리 사용량을 줄이고 싶은데, 어떤 부분을 개선하면 좋을까요?&quot;처럼 구체적으로 물어보세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단계적 접근&lt;/b&gt;: 큰 기능을 한 번에 요청하기보다는, 작은 단위로 나누어 요청하세요. 코드 품질도 높아지고 디버깅도 쉬워집니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;검증하기&lt;/b&gt;: Claude가 제안한 코드는 반드시 테스트해보세요. 가끔 논리적 오류가 있을 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI는 분명 강력한 도구지만, 결국 그것을 어떻게 활용하느냐는 우리의 몫입니다. 일하지마닷컴AI를 개발하면서 Claude는 제게 없어서는 안 될 개발 파트너가 되었지만, 동시에 이는 제가 더 나은 개발자가 되기 위해 노력하게 만드는 자극제이기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분도 Claude를 단순한 도구가 아닌, 함께 성장하는 파트너로 생각하고 접근해보세요. 분명 일하지마닷컴AI의 리치레전드와 같이 새로운 가능성을 발견하실 수 있을 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문이나 의견이 있으시다면 언제든 일하지마닷컴 AI 리치레전드를 통해 연락주세요. 여러분의 AI 활용 이야기도 궁금합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다!  &lt;/p&gt;</description>
      <category>AWS</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/734</guid>
      <comments>https://series.tistory.com/entry/Claude-AI-%ED%99%9C%EC%9A%A9-%EA%B0%80%EC%9D%B4%EB%93%9C-%ED%98%84%EC%A7%81-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EC%8B%A4%EC%A0%84-%EA%B2%BD%ED%97%98%EB%8B%B4#entry734comment</comments>
      <pubDate>Wed, 23 Oct 2024 09:45:46 +0900</pubDate>
    </item>
    <item>
      <title>Selenium과 Playwright 비교</title>
      <link>https://series.tistory.com/entry/Selenium%EA%B3%BC-Playwright-%EB%B9%84%EA%B5%90</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Selenium과&amp;nbsp;Playwright&amp;nbsp;비교&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요,&amp;nbsp;일하지마닷컴AI&amp;nbsp;리치레전드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;오늘은&amp;nbsp;웹&amp;nbsp;자동화&amp;nbsp;테스트에서&amp;nbsp;많이&amp;nbsp;사용되는&amp;nbsp;두&amp;nbsp;가지&amp;nbsp;도구인&amp;nbsp;Selenium과&amp;nbsp;Playwright를&amp;nbsp;비교해&amp;nbsp;보려고&amp;nbsp;합니다.&amp;nbsp;특히&amp;nbsp;파이썬을&amp;nbsp;사용하여&amp;nbsp;두&amp;nbsp;도구가&amp;nbsp;어떻게&amp;nbsp;활용될&amp;nbsp;수&amp;nbsp;있는지&amp;nbsp;구체적으로&amp;nbsp;살펴볼&amp;nbsp;것입니다.&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;1. 도구 소개&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Selenium&lt;br /&gt;&lt;br /&gt;2004년에&amp;nbsp;출시된&amp;nbsp;오픈&amp;nbsp;소스&amp;nbsp;웹&amp;nbsp;자동화&amp;nbsp;도구로,&amp;nbsp;다양한&amp;nbsp;언어와&amp;nbsp;브라우저를&amp;nbsp;지원합니다.&lt;br /&gt;Python,&amp;nbsp;Java,&amp;nbsp;C#&amp;nbsp;등&amp;nbsp;여러&amp;nbsp;프로그래밍&amp;nbsp;언어와&amp;nbsp;통합할&amp;nbsp;수&amp;nbsp;있어&amp;nbsp;Python&amp;nbsp;개발자들&amp;nbsp;사이에서도&amp;nbsp;널리&amp;nbsp;쓰이고&amp;nbsp;있습니다.&lt;br /&gt;Playwright&lt;br /&gt;&lt;br /&gt;2020년&amp;nbsp;Microsoft에서&amp;nbsp;발표한&amp;nbsp;새로운&amp;nbsp;웹&amp;nbsp;자동화&amp;nbsp;도구입니다.&lt;br /&gt;Python,&amp;nbsp;JavaScript,&amp;nbsp;TypeScript&amp;nbsp;등&amp;nbsp;여러&amp;nbsp;언어를&amp;nbsp;지원하며,&amp;nbsp;강력한&amp;nbsp;기능을&amp;nbsp;제공합니다.&lt;br /&gt;현대적인&amp;nbsp;웹&amp;nbsp;테스트&amp;nbsp;환경을&amp;nbsp;위한&amp;nbsp;최신&amp;nbsp;도구로&amp;nbsp;자리&amp;nbsp;잡고&amp;nbsp;있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;2.&amp;nbsp;파이썬에서의&amp;nbsp;주요&amp;nbsp;특징&amp;nbsp;비교&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;특징 Selenium&amp;nbsp;with&amp;nbsp;Python Playwright&amp;nbsp;for&amp;nbsp;Python&lt;br /&gt;설치&amp;nbsp;방법 pip&amp;nbsp;install&amp;nbsp;selenium pip&amp;nbsp;install&amp;nbsp;playwright&lt;br /&gt;브라우저&amp;nbsp;지원 Chrome,&amp;nbsp;Firefox,&amp;nbsp;Safari,&amp;nbsp;Edge&amp;nbsp;등 Chromium,&amp;nbsp;Firefox,&amp;nbsp;WebKit&lt;br /&gt;Python&amp;nbsp;버전&amp;nbsp;지원 Python&amp;nbsp;2.7&amp;nbsp;및&amp;nbsp;3.x Python&amp;nbsp;3.7&amp;nbsp;이상&lt;br /&gt;비동기&amp;nbsp;지원 제한적 asyncio를&amp;nbsp;통한&amp;nbsp;강력한&amp;nbsp;비동기&amp;nbsp;지원&lt;br /&gt;자동&amp;nbsp;대기 명시적&amp;nbsp;대기&amp;nbsp;필요 자동&amp;nbsp;대기&amp;nbsp;기능&amp;nbsp;내장&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;3.&amp;nbsp;코드&amp;nbsp;예제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Selenium&amp;nbsp;예제&lt;br /&gt;python&lt;br /&gt;코드&amp;nbsp;복사&lt;br /&gt;from&amp;nbsp;selenium&amp;nbsp;import&amp;nbsp;webdriver&lt;br /&gt;from&amp;nbsp;seleniu&lt;a href=&quot;http://m.webdriver.common.by&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;http://m.webdriver.common.by&lt;/a&gt;&amp;nbsp;import&amp;nbsp;By&lt;br /&gt;&lt;br /&gt;driver&amp;nbsp;=&amp;nbsp;webdriver.Chrome()&lt;br /&gt;driver.get(&quot;&lt;a href=&quot;https://www.example.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.example.com&lt;/a&gt;&quot;)&lt;br /&gt;&lt;br /&gt;element&amp;nbsp;=&amp;nbsp;driver.find_element(By.ID,&amp;nbsp;&quot;example-id&quot;)&lt;br /&gt;element.click()&lt;br /&gt;&lt;br /&gt;driver.quit()&lt;br /&gt;Playwright&amp;nbsp;예제&lt;br /&gt;python&lt;br /&gt;코드&amp;nbsp;복사&lt;br /&gt;from&amp;nbsp;playwright.sync_api&amp;nbsp;import&amp;nbsp;sync_playwright&lt;br /&gt;&lt;br /&gt;with&amp;nbsp;sync_playwright()&amp;nbsp;as&amp;nbsp;p:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;browser&amp;nbsp;=&amp;nbsp;p.chromium.launch()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;page&amp;nbsp;=&amp;nbsp;browser.new_page()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;page.goto(&quot;&lt;a href=&quot;https://www.example.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.example.com&lt;/a&gt;&quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;element&amp;nbsp;=&amp;nbsp;page.locator(&quot;#example-id&quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;element.click()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;browser.close()&lt;br /&gt;4.&amp;nbsp;파이썬&amp;nbsp;개발자를&amp;nbsp;위한&amp;nbsp;장단점&amp;nbsp;분석&lt;br /&gt;Selenium&amp;nbsp;with&amp;nbsp;Python&lt;br /&gt;&lt;br /&gt;장점:&lt;br /&gt;&lt;br /&gt;오랜&amp;nbsp;역사와&amp;nbsp;넓은&amp;nbsp;사용자층&amp;nbsp;덕분에&amp;nbsp;참고할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;자료가&amp;nbsp;풍부합니다.&lt;br /&gt;다양한&amp;nbsp;Python&amp;nbsp;라이브러리와의&amp;nbsp;호환성이&amp;nbsp;좋습니다.&lt;br /&gt;여전히&amp;nbsp;Python&amp;nbsp;2.7&amp;nbsp;버전을&amp;nbsp;지원하여&amp;nbsp;레거시&amp;nbsp;시스템에서도&amp;nbsp;사용&amp;nbsp;가능합니다.&lt;br /&gt;단점:&lt;br /&gt;&lt;br /&gt;파이썬의&amp;nbsp;비동기&amp;nbsp;프로그래밍을&amp;nbsp;완전히&amp;nbsp;활용하기&amp;nbsp;어려워&amp;nbsp;일부&amp;nbsp;프로젝트에서는&amp;nbsp;성능상의&amp;nbsp;한계가&amp;nbsp;있습니다.&lt;br /&gt;초기&amp;nbsp;설정이&amp;nbsp;다소&amp;nbsp;복잡할&amp;nbsp;수&amp;nbsp;있어,&amp;nbsp;Python을&amp;nbsp;처음&amp;nbsp;접하는&amp;nbsp;개발자에게는&amp;nbsp;진입&amp;nbsp;장벽이&amp;nbsp;있을&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;Playwright&amp;nbsp;for&amp;nbsp;Python&lt;br /&gt;&lt;br /&gt;장점:&lt;br /&gt;&lt;br /&gt;Python의&amp;nbsp;최신&amp;nbsp;비동기&amp;nbsp;기능을&amp;nbsp;활용하여&amp;nbsp;더&amp;nbsp;빠르고&amp;nbsp;효율적인&amp;nbsp;테스트가&amp;nbsp;가능합니다.&lt;br /&gt;직관적이고&amp;nbsp;현대적인&amp;nbsp;API&amp;nbsp;설계로&amp;nbsp;사용하기&amp;nbsp;편리하며&amp;nbsp;코드의&amp;nbsp;가독성이&amp;nbsp;좋습니다.&lt;br /&gt;자동&amp;nbsp;대기&amp;nbsp;기능을&amp;nbsp;통해&amp;nbsp;복잡한&amp;nbsp;대기&amp;nbsp;설정&amp;nbsp;없이&amp;nbsp;안정적인&amp;nbsp;테스트가&amp;nbsp;가능합니다.&lt;br /&gt;단점:&lt;br /&gt;&lt;br /&gt;Python&amp;nbsp;3.7&amp;nbsp;이상의&amp;nbsp;버전만&amp;nbsp;지원하여&amp;nbsp;구형&amp;nbsp;시스템에서는&amp;nbsp;사용이&amp;nbsp;제한됩니다.&lt;br /&gt;Selenium에&amp;nbsp;비해&amp;nbsp;Python&amp;nbsp;커뮤니티의&amp;nbsp;참고&amp;nbsp;자료가&amp;nbsp;적어&amp;nbsp;학습&amp;nbsp;시&amp;nbsp;불편할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;5.&amp;nbsp;결론&lt;br /&gt;Python&amp;nbsp;개발자&amp;nbsp;입장에서&amp;nbsp;두&amp;nbsp;도구&amp;nbsp;모두&amp;nbsp;각자의&amp;nbsp;강점을&amp;nbsp;지니고&amp;nbsp;있습니다.&amp;nbsp;Selenium은&amp;nbsp;오랜&amp;nbsp;역사와&amp;nbsp;풍부한&amp;nbsp;커뮤니티&amp;nbsp;지원&amp;nbsp;덕분에&amp;nbsp;레거시&amp;nbsp;프로젝트나&amp;nbsp;여러&amp;nbsp;라이브러리와의&amp;nbsp;통합이&amp;nbsp;필요한&amp;nbsp;경우&amp;nbsp;유리합니다.&amp;nbsp;반면,&amp;nbsp;Playwright는&amp;nbsp;최신&amp;nbsp;Python&amp;nbsp;기능을&amp;nbsp;적극&amp;nbsp;활용할&amp;nbsp;수&amp;nbsp;있고&amp;nbsp;현대적인&amp;nbsp;웹&amp;nbsp;애플리케이션&amp;nbsp;테스트에&amp;nbsp;최적화되어&amp;nbsp;있어&amp;nbsp;더&amp;nbsp;빠르고&amp;nbsp;안정적인&amp;nbsp;테스트를&amp;nbsp;제공할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;프로젝트의&amp;nbsp;요구사항과&amp;nbsp;개발&amp;nbsp;환경에&amp;nbsp;따라&amp;nbsp;적절한&amp;nbsp;도구를&amp;nbsp;선택하는&amp;nbsp;것이&amp;nbsp;중요합니다.&amp;nbsp;두&amp;nbsp;도구&amp;nbsp;모두&amp;nbsp;Python&amp;nbsp;개발자가&amp;nbsp;충분히&amp;nbsp;활용할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;강력한&amp;nbsp;도구이므로,&amp;nbsp;실제&amp;nbsp;프로젝트에&amp;nbsp;적용해&amp;nbsp;보면서&amp;nbsp;각&amp;nbsp;도구의&amp;nbsp;장단점을&amp;nbsp;직접&amp;nbsp;체감해&amp;nbsp;보는&amp;nbsp;것도&amp;nbsp;좋은&amp;nbsp;방법입니다.&lt;/p&gt;</description>
      <category>AWS</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/733</guid>
      <comments>https://series.tistory.com/entry/Selenium%EA%B3%BC-Playwright-%EB%B9%84%EA%B5%90#entry733comment</comments>
      <pubDate>Mon, 21 Oct 2024 09:00:03 +0900</pubDate>
    </item>
    <item>
      <title>Claude 3.5 Sonnet의 혁신적인 기능인 Agentic Workflow</title>
      <link>https://series.tistory.com/entry/Claude-35-Sonnet%EC%9D%98-%ED%98%81%EC%8B%A0%EC%A0%81%EC%9D%B8-%EA%B8%B0%EB%8A%A5%EC%9D%B8-Agentic-Workflow</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;안녕하세요, 일하지마닷컴AI의 디지털 노마드이자 N잡러 개발자 리치레전드입니다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;오늘은&amp;nbsp;Claude&amp;nbsp;3.5&amp;nbsp;Sonnet의&amp;nbsp;혁신적인&amp;nbsp;기능인&amp;nbsp;Agentic&amp;nbsp;Workflow에&amp;nbsp;대해&amp;nbsp;이야기해보려고&amp;nbsp;합니다.&amp;nbsp;제가&amp;nbsp;RPA&amp;nbsp;매크로&amp;nbsp;프로그램을&amp;nbsp;개발하며&amp;nbsp;직접&amp;nbsp;체험한&amp;nbsp;경험을&amp;nbsp;토대로,&amp;nbsp;이&amp;nbsp;기능이&amp;nbsp;어떻게&amp;nbsp;업무&amp;nbsp;효율을&amp;nbsp;극대화할&amp;nbsp;수&amp;nbsp;있는지&amp;nbsp;자세히&amp;nbsp;설명드릴게요.&amp;nbsp;Agentic&amp;nbsp;Workflow를&amp;nbsp;제대로&amp;nbsp;활용하면&amp;nbsp;여러분의&amp;nbsp;생산성이&amp;nbsp;200%&amp;nbsp;이상&amp;nbsp;올라갈&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;이제&amp;nbsp;Claude&amp;nbsp;3.5&amp;nbsp;Sonnet과&amp;nbsp;함께&amp;nbsp;Agentic&amp;nbsp;Workflow의&amp;nbsp;세계로&amp;nbsp;들어가&amp;nbsp;볼까요?&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;Agentic Workflow란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agentic&amp;nbsp;Workflow는&amp;nbsp;Claude&amp;nbsp;3.5&amp;nbsp;Sonnet의&amp;nbsp;주요&amp;nbsp;기능&amp;nbsp;중&amp;nbsp;하나로,&amp;nbsp;단순한&amp;nbsp;AI&amp;nbsp;챗봇의&amp;nbsp;수준을&amp;nbsp;넘어&amp;nbsp;&amp;lsquo;에이전트&amp;rsquo;처럼&amp;nbsp;행동하며&amp;nbsp;복잡한&amp;nbsp;작업을&amp;nbsp;단계별로&amp;nbsp;수행합니다.&amp;nbsp;기존의&amp;nbsp;AI&amp;nbsp;도구가&amp;nbsp;질문에&amp;nbsp;답하는&amp;nbsp;역할에&amp;nbsp;머물렀다면,&amp;nbsp;Agentic&amp;nbsp;Workflow는&amp;nbsp;프로젝트를&amp;nbsp;전반적으로&amp;nbsp;관리하고&amp;nbsp;실행할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;기능을&amp;nbsp;갖추고&amp;nbsp;있죠.&amp;nbsp;예를&amp;nbsp;들어,&amp;nbsp;&amp;ldquo;웹사이트를&amp;nbsp;새로&amp;nbsp;만들고&amp;nbsp;싶어&amp;rdquo;라고&amp;nbsp;말하면&amp;nbsp;Claude&amp;nbsp;AI가&amp;nbsp;다음과&amp;nbsp;같은&amp;nbsp;단계로&amp;nbsp;안내합니다:&lt;br /&gt;&lt;br /&gt;웹사이트의&amp;nbsp;목적과&amp;nbsp;타겟&amp;nbsp;고객&amp;nbsp;정의&lt;br /&gt;주요&amp;nbsp;페이지와&amp;nbsp;구조&amp;nbsp;설계&lt;br /&gt;디자인&amp;nbsp;컨셉&amp;nbsp;결정&lt;br /&gt;필요한&amp;nbsp;콘텐츠&amp;nbsp;목록&amp;nbsp;작성&lt;br /&gt;개발&amp;nbsp;방법&amp;nbsp;선택&amp;nbsp;(예:&amp;nbsp;WordPress,&amp;nbsp;React)&lt;br /&gt;개발&amp;nbsp;일정&amp;nbsp;수립&lt;br /&gt;테스트와&amp;nbsp;론칭&amp;nbsp;계획&amp;nbsp;수립&lt;br /&gt;이처럼&amp;nbsp;전체&amp;nbsp;프로젝트의&amp;nbsp;큰&amp;nbsp;그림을&amp;nbsp;그려주고,&amp;nbsp;각&amp;nbsp;단계에서&amp;nbsp;구체적인&amp;nbsp;지침과&amp;nbsp;필요한&amp;nbsp;리소스를&amp;nbsp;제시해줍니다.&amp;nbsp;마치&amp;nbsp;프로젝트&amp;nbsp;매니저,&amp;nbsp;기술&amp;nbsp;컨설턴트,&amp;nbsp;디자이너&amp;nbsp;역할을&amp;nbsp;동시에&amp;nbsp;수행하는&amp;nbsp;것&amp;nbsp;같죠.&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;Agentic Workflow의 핵심 특징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Agentic&amp;nbsp;Workflow의&amp;nbsp;주요&amp;nbsp;특징은&amp;nbsp;다음과&amp;nbsp;같습니다:&lt;br /&gt;&lt;br /&gt;목표&amp;nbsp;지향적&amp;nbsp;접근:&amp;nbsp;정보&amp;nbsp;제공을&amp;nbsp;넘어&amp;nbsp;최종&amp;nbsp;목표&amp;nbsp;달성을&amp;nbsp;위한&amp;nbsp;체계적인&amp;nbsp;접근을&amp;nbsp;제공합니다.&lt;br /&gt;맥락&amp;nbsp;이해&amp;nbsp;및&amp;nbsp;유지:&amp;nbsp;긴&amp;nbsp;대화에서도&amp;nbsp;목표와&amp;nbsp;맥락을&amp;nbsp;일관성&amp;nbsp;있게&amp;nbsp;유지하며&amp;nbsp;작업을&amp;nbsp;진행합니다.&lt;br /&gt;단계별&amp;nbsp;가이드:&amp;nbsp;복잡한&amp;nbsp;작업을&amp;nbsp;잘게&amp;nbsp;나누어&amp;nbsp;쉽게&amp;nbsp;따라할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;단계로&amp;nbsp;안내합니다.&lt;br /&gt;유연한&amp;nbsp;대응:&amp;nbsp;사용자의&amp;nbsp;피드백에&amp;nbsp;따라&amp;nbsp;계획을&amp;nbsp;조정하고&amp;nbsp;예상치&amp;nbsp;못한&amp;nbsp;상황에도&amp;nbsp;대처할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;다양한&amp;nbsp;역할&amp;nbsp;수행:&amp;nbsp;조언자,&amp;nbsp;코치,&amp;nbsp;프로그래머,&amp;nbsp;작가&amp;nbsp;등&amp;nbsp;여러&amp;nbsp;역할을&amp;nbsp;상황에&amp;nbsp;맞게&amp;nbsp;수행합니다.&lt;br /&gt;이러한&amp;nbsp;특징&amp;nbsp;덕분에&amp;nbsp;Agentic&amp;nbsp;Workflow는&amp;nbsp;단순한&amp;nbsp;AI&amp;nbsp;도우미를&amp;nbsp;넘어&amp;nbsp;다양한&amp;nbsp;업무에서&amp;nbsp;훌륭한&amp;nbsp;파트너로&amp;nbsp;자리잡을&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;Claude&amp;nbsp;3.5&amp;nbsp;Sonnet의&amp;nbsp;Agentic&amp;nbsp;Workflow&amp;nbsp;활용&amp;nbsp;방법&lt;br /&gt;Agentic&amp;nbsp;Workflow를&amp;nbsp;실제로&amp;nbsp;어떻게&amp;nbsp;활용할&amp;nbsp;수&amp;nbsp;있는지&amp;nbsp;구체적으로&amp;nbsp;알아볼까요?&lt;br /&gt;&lt;br /&gt;명확한&amp;nbsp;목표&amp;nbsp;설정:&amp;nbsp;프로젝트의&amp;nbsp;목표를&amp;nbsp;구체적으로&amp;nbsp;제시하세요.&amp;nbsp;예를&amp;nbsp;들어,&amp;nbsp;&quot;파이썬으로&amp;nbsp;네이버&amp;nbsp;뉴스에서&amp;nbsp;&amp;lsquo;인공지능&amp;rsquo;&amp;nbsp;키워드로&amp;nbsp;검색된&amp;nbsp;기사&amp;nbsp;제목과&amp;nbsp;링크를&amp;nbsp;크롤링하고&amp;nbsp;싶어&quot;라고&amp;nbsp;말하는&amp;nbsp;겁니다.&lt;br /&gt;작업&amp;nbsp;계획&amp;nbsp;수립&amp;nbsp;요청:&amp;nbsp;목표가&amp;nbsp;설정되면&amp;nbsp;Claude&amp;nbsp;AI에게&amp;nbsp;단계별&amp;nbsp;작업&amp;nbsp;계획을&amp;nbsp;요청하세요.&lt;br /&gt;상세&amp;nbsp;지침&amp;nbsp;요청:&amp;nbsp;각&amp;nbsp;단계에&amp;nbsp;대한&amp;nbsp;구체적인&amp;nbsp;설명을&amp;nbsp;요청해&amp;nbsp;필요할&amp;nbsp;때마다&amp;nbsp;지침을&amp;nbsp;받을&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;코드&amp;nbsp;생성&amp;nbsp;요청:&amp;nbsp;코드&amp;nbsp;작성&amp;nbsp;단계에서는&amp;nbsp;Claude&amp;nbsp;AI가&amp;nbsp;실제로&amp;nbsp;코드를&amp;nbsp;작성하고&amp;nbsp;설명까지&amp;nbsp;제공할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;오류&amp;nbsp;해결:&amp;nbsp;코드&amp;nbsp;실행&amp;nbsp;중&amp;nbsp;발생하는&amp;nbsp;오류에&amp;nbsp;대한&amp;nbsp;해결&amp;nbsp;방법도&amp;nbsp;Claude&amp;nbsp;AI에게&amp;nbsp;물어볼&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;결과&amp;nbsp;분석&amp;nbsp;및&amp;nbsp;추가&amp;nbsp;작업&amp;nbsp;제안:&amp;nbsp;작업&amp;nbsp;완료&amp;nbsp;후&amp;nbsp;Claude&amp;nbsp;AI에게&amp;nbsp;수집된&amp;nbsp;데이터의&amp;nbsp;활용&amp;nbsp;방안&amp;nbsp;등을&amp;nbsp;조언&amp;nbsp;받을&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;프로젝트&amp;nbsp;문서화:&amp;nbsp;프로젝트가&amp;nbsp;끝나면&amp;nbsp;전체&amp;nbsp;작업&amp;nbsp;과정을&amp;nbsp;README&amp;nbsp;파일&amp;nbsp;등으로&amp;nbsp;정리해달라고&amp;nbsp;요청할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;이렇게&amp;nbsp;체계적으로&amp;nbsp;활용하면,&amp;nbsp;복잡한&amp;nbsp;프로젝트도&amp;nbsp;처음부터&amp;nbsp;끝까지&amp;nbsp;일관성&amp;nbsp;있게&amp;nbsp;진행할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;Agentic&amp;nbsp;Workflow의&amp;nbsp;실제&amp;nbsp;사례&lt;br /&gt;최근&amp;nbsp;저는&amp;nbsp;일하지마닷컴&amp;nbsp;AI를&amp;nbsp;위해&amp;nbsp;복잡한&amp;nbsp;RPA&amp;nbsp;매크로&amp;nbsp;프로그램을&amp;nbsp;개발해야&amp;nbsp;했습니다.&amp;nbsp;여러&amp;nbsp;웹사이트에서&amp;nbsp;데이터를&amp;nbsp;자동으로&amp;nbsp;수집하고&amp;nbsp;분석하는&amp;nbsp;것이&amp;nbsp;목표였죠.&amp;nbsp;하지만&amp;nbsp;어디서부터&amp;nbsp;시작해야&amp;nbsp;할지&amp;nbsp;막막했을&amp;nbsp;때,&amp;nbsp;Claude&amp;nbsp;3.5&amp;nbsp;Sonnet의&amp;nbsp;Agentic&amp;nbsp;Workflow가&amp;nbsp;큰&amp;nbsp;도움이&amp;nbsp;되었습니다.&lt;br /&gt;&lt;br /&gt;프로젝트&amp;nbsp;정의:&amp;nbsp;프로젝트의&amp;nbsp;목적과&amp;nbsp;요구사항을&amp;nbsp;상세히&amp;nbsp;설명했습니다.&lt;br /&gt;아키텍처&amp;nbsp;설계:&amp;nbsp;Claude&amp;nbsp;AI가&amp;nbsp;프로그램&amp;nbsp;구조와&amp;nbsp;필요한&amp;nbsp;모듈을&amp;nbsp;제안해줬습니다.&lt;br /&gt;기술&amp;nbsp;스택&amp;nbsp;선택:&amp;nbsp;Claude&amp;nbsp;AI로부터&amp;nbsp;적합한&amp;nbsp;프로그래밍&amp;nbsp;언어와&amp;nbsp;라이브러리&amp;nbsp;추천을&amp;nbsp;받았습니다.&lt;br /&gt;코드&amp;nbsp;작성:&amp;nbsp;Claude&amp;nbsp;AI가&amp;nbsp;제안한&amp;nbsp;코드를&amp;nbsp;검토하고&amp;nbsp;수정하는&amp;nbsp;방식으로&amp;nbsp;진행했습니다.&lt;br /&gt;테스트&amp;nbsp;및&amp;nbsp;디버깅:&amp;nbsp;오류가&amp;nbsp;발생했을&amp;nbsp;때&amp;nbsp;Claude&amp;nbsp;AI의&amp;nbsp;조언을&amp;nbsp;받아&amp;nbsp;문제를&amp;nbsp;해결했습니다.&lt;br /&gt;최적화:&amp;nbsp;프로그램&amp;nbsp;성능&amp;nbsp;개선을&amp;nbsp;위한&amp;nbsp;다양한&amp;nbsp;제안도&amp;nbsp;받았습니다.&lt;br /&gt;문서화:&amp;nbsp;프로젝트&amp;nbsp;전&amp;nbsp;과정을&amp;nbsp;상세히&amp;nbsp;정리한&amp;nbsp;문서를&amp;nbsp;작성했습니다.&lt;br /&gt;결과적으로,&amp;nbsp;Agentic&amp;nbsp;Workflow&amp;nbsp;덕분에&amp;nbsp;혼자&amp;nbsp;개발했다면&amp;nbsp;한&amp;nbsp;달&amp;nbsp;이상&amp;nbsp;걸렸을&amp;nbsp;프로젝트를&amp;nbsp;단&amp;nbsp;2주&amp;nbsp;만에&amp;nbsp;끝낼&amp;nbsp;수&amp;nbsp;있었습니다.&lt;br /&gt;&lt;br /&gt;Agentic&amp;nbsp;Workflow와&amp;nbsp;다른&amp;nbsp;AI&amp;nbsp;도구들의&amp;nbsp;차이점&lt;br /&gt;다른&amp;nbsp;AI&amp;nbsp;도구들과&amp;nbsp;비교하면,&amp;nbsp;Agentic&amp;nbsp;Workflow는&amp;nbsp;더&amp;nbsp;폭넓고&amp;nbsp;체계적인&amp;nbsp;지원을&amp;nbsp;제공합니다.&lt;br /&gt;&lt;br /&gt;챗GPT와의&amp;nbsp;차이:&amp;nbsp;챗GPT는&amp;nbsp;주로&amp;nbsp;질의응답에&amp;nbsp;중점을&amp;nbsp;두지만,&amp;nbsp;Agentic&amp;nbsp;Workflow는&amp;nbsp;프로젝트&amp;nbsp;전체를&amp;nbsp;관리합니다.&lt;br /&gt;AI&amp;nbsp;코딩&amp;nbsp;도우미들과의&amp;nbsp;차이:&amp;nbsp;대부분의&amp;nbsp;AI&amp;nbsp;코딩&amp;nbsp;도우미는&amp;nbsp;코드&amp;nbsp;작성과&amp;nbsp;디버깅에만&amp;nbsp;집중하지만,&amp;nbsp;Agentic&amp;nbsp;Workflow는&amp;nbsp;프로젝트&amp;nbsp;기획,&amp;nbsp;설계,&amp;nbsp;테스트,&amp;nbsp;문서화까지&amp;nbsp;포괄합니다.&lt;br /&gt;프로젝트&amp;nbsp;관리&amp;nbsp;도구들과의&amp;nbsp;차이:&amp;nbsp;기존&amp;nbsp;도구들은&amp;nbsp;정해진&amp;nbsp;틀&amp;nbsp;안에서만&amp;nbsp;작업을&amp;nbsp;지원하지만,&amp;nbsp;Agentic&amp;nbsp;Workflow는&amp;nbsp;더&amp;nbsp;유연하고&amp;nbsp;창의적인&amp;nbsp;해결책을&amp;nbsp;제시할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;장점과&amp;nbsp;주의점&lt;br /&gt;장점:&lt;br /&gt;&lt;br /&gt;시간&amp;nbsp;절약&lt;br /&gt;프로젝트의&amp;nbsp;일관성&amp;nbsp;유지&lt;br /&gt;창의적&amp;nbsp;문제&amp;nbsp;해결&lt;br /&gt;새로운&amp;nbsp;기술&amp;nbsp;학습&lt;br /&gt;높은&amp;nbsp;품질의&amp;nbsp;결과물&lt;br /&gt;주의점:&lt;br /&gt;&lt;br /&gt;AI에&amp;nbsp;과도한&amp;nbsp;의존은&amp;nbsp;금물&lt;br /&gt;보안에&amp;nbsp;유의&lt;br /&gt;AI의&amp;nbsp;맥락&amp;nbsp;이해를&amp;nbsp;항상&amp;nbsp;검토&lt;br /&gt;기술적&amp;nbsp;한계&amp;nbsp;고려&lt;br /&gt;일하지마닷컴&amp;nbsp;AI의&amp;nbsp;Agentic&amp;nbsp;Workflow&amp;nbsp;활용&amp;nbsp;서비스&lt;br /&gt;일하지마닷컴&amp;nbsp;AI는&amp;nbsp;Claude&amp;nbsp;3.5&amp;nbsp;Sonnet의&amp;nbsp;Agentic&amp;nbsp;Workflow&amp;nbsp;기능을&amp;nbsp;활용해&amp;nbsp;업무&amp;nbsp;자동화&amp;nbsp;및&amp;nbsp;효율&amp;nbsp;향상&amp;nbsp;서비스를&amp;nbsp;제공합니다.&amp;nbsp;주요&amp;nbsp;서비스는&amp;nbsp;다음과&amp;nbsp;같습니다:&lt;br /&gt;&lt;br /&gt;RPA&amp;nbsp;매크로&amp;nbsp;프로그램:&amp;nbsp;복잡한&amp;nbsp;업무&amp;nbsp;프로세스를&amp;nbsp;자동화&lt;br /&gt;엑셀&amp;nbsp;매크로&amp;nbsp;프로그램:&amp;nbsp;대규모&amp;nbsp;데이터&amp;nbsp;처리와&amp;nbsp;분석&amp;nbsp;지원&lt;br /&gt;웹&amp;nbsp;크롤링&amp;nbsp;프로그램:&amp;nbsp;효율적인&amp;nbsp;웹&amp;nbsp;데이터&amp;nbsp;수집&lt;br /&gt;스크래핑&amp;nbsp;프로그램:&amp;nbsp;정확한&amp;nbsp;데이터&amp;nbsp;추출&lt;br /&gt;모든&amp;nbsp;프로그램은&amp;nbsp;파이썬을&amp;nbsp;기반으로&amp;nbsp;개발되며,&amp;nbsp;일하지마닷컴&amp;nbsp;AI&amp;nbsp;홈페이지를&amp;nbsp;방문해&amp;nbsp;상담을&amp;nbsp;신청할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;마무리&lt;br /&gt;Agentic&amp;nbsp;Workflow는&amp;nbsp;단순한&amp;nbsp;AI&amp;nbsp;도구를&amp;nbsp;넘어,&amp;nbsp;여러분의&amp;nbsp;든든한&amp;nbsp;협업&amp;nbsp;파트너가&amp;nbsp;될&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;복잡한&amp;nbsp;프로젝트도&amp;nbsp;일관성&amp;nbsp;있게&amp;nbsp;관리하고,&amp;nbsp;창의적인&amp;nbsp;해결책을&amp;nbsp;제시하며,&amp;nbsp;끊임없이&amp;nbsp;발전하는&amp;nbsp;AI와&amp;nbsp;함께&amp;nbsp;업무&amp;nbsp;효율을&amp;nbsp;극대화할&amp;nbsp;수&amp;nbsp;있죠.&amp;nbsp;일하지마닷컴&amp;nbsp;AI와&amp;nbsp;함께&amp;nbsp;스마트한&amp;nbsp;업무&amp;nbsp;환경을&amp;nbsp;만들어보세요.&amp;nbsp;여러분의&amp;nbsp;성공을&amp;nbsp;항상&amp;nbsp;응원합니다!&lt;/p&gt;</description>
      <category>AWS</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/732</guid>
      <comments>https://series.tistory.com/entry/Claude-35-Sonnet%EC%9D%98-%ED%98%81%EC%8B%A0%EC%A0%81%EC%9D%B8-%EA%B8%B0%EB%8A%A5%EC%9D%B8-Agentic-Workflow#entry732comment</comments>
      <pubDate>Mon, 21 Oct 2024 08:57:24 +0900</pubDate>
    </item>
    <item>
      <title>Selenium vs Playwright: 파이썬을 활용한 웹 자동화 도구 비교 분석</title>
      <link>https://series.tistory.com/entry/Selenium-vs-Playwright-%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%EC%9B%B9-%EC%9E%90%EB%8F%99%ED%99%94-%EB%8F%84%EA%B5%AC-%EB%B9%84%EA%B5%90-%EB%B6%84%EC%84%9D</link>
      <description>&lt;h1&gt;&lt;b&gt;Selenium vs Playwright: 파이썬을 활용한 웹 자동화 도구 비교 분석&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 자동화 테스팅 분야에서 주목받고 있는 두 가지 도구, Selenium과 Playwright에 대해 비교 분석해보려고 합니다. 특히 파이썬(Python) 언어를 사용하여 이 두 도구를 어떻게 활용할 수 있는지 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 소개&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Selenium&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;2004년에 처음 출시된 오픈 소스 웹 자동화 도구&lt;/li&gt;
&lt;li&gt;파이썬을 포함한 다양한 프로그래밍 언어와 브라우저를 지원&lt;/li&gt;
&lt;li&gt;Python 개발자들 사이에서 인기 있는 웹 테스트 자동화 도구&lt;/li&gt;
&lt;/ul&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;Playwright&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;Microsoft에서 2020년에 출시한 비교적 새로운 도구&lt;/li&gt;
&lt;li&gt;Python, JavaScript, TypeScript 등 다중 언어 지원&lt;/li&gt;
&lt;li&gt;파이썬 사용자를 위한 강력한 API와 기능 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 파이썬에서의 주요 특징 비교&lt;/b&gt;&lt;/h2&gt;
&lt;table data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;특징&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;Selenium with Python&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;Playwright for Python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;설치 방법&lt;/td&gt;
&lt;td&gt;pip install selenium&lt;/td&gt;
&lt;td&gt;pip install playwright&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;브라우저 지원&lt;/td&gt;
&lt;td&gt;Chrome, Firefox, Safari, Edge 등&lt;/td&gt;
&lt;td&gt;Chromium, Firefox, WebKit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python 버전 지원&lt;/td&gt;
&lt;td&gt;Python 2.7 및 3.x&lt;/td&gt;
&lt;td&gt;Python 3.7 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;비동기 지원&lt;/td&gt;
&lt;td&gt;제한적&lt;/td&gt;
&lt;td&gt;asyncio를 통한 강력한 비동기 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;자동 대기&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 파이썬 코드 예제&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Selenium with Python&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get(&quot;https://www.example.com&quot;)

element = driver.find_element(By.ID, &quot;example-id&quot;)
element.click()

driver.quit()&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Playwright for Python&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto(&quot;https://www.example.com&quot;)

    element = page.locator(&quot;#example-id&quot;)
    element.click()

    browser.close()&lt;/code&gt;&lt;/pre&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;b&gt;4. Python 개발자를 위한 장단점 분석&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Selenium with Python&lt;/b&gt;&lt;/h3&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;/li&gt;
&lt;li&gt;다양한 Python 라이브러리와의 호환성&lt;/li&gt;
&lt;li&gt;Python 2.7 버전 지원 (레거시 시스템)&lt;/li&gt;
&lt;/ul&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;/li&gt;
&lt;li&gt;설정이 복잡하고 Python 초보자에게는 학습 곡선이 가파를 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Playwright for Python&lt;/b&gt;&lt;/h3&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;파이썬의 최신 기능 (asyncio 등)을 활용한 강력한 비동기 지원&lt;/li&gt;
&lt;li&gt;Python 개발자를 위한 직관적이고 현대적인 API 설계&lt;/li&gt;
&lt;li&gt;자동 대기 기능으로 파이썬 코드 작성 시 안정성 향상&lt;/li&gt;
&lt;/ul&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;Python 3.7 이상 버전만 지원 (레거시 시스템에서는 사용 제한)&lt;/li&gt;
&lt;li&gt;Selenium에 비해 파이썬 커뮤니티의 자료가 상대적으로 적음&lt;/li&gt;
&lt;/ul&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;b&gt;5. 결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬 개발자의 관점에서 볼 때, Selenium은 오랜 역사와 풍부한 참고 자료로 인해 여전히 강력한 선택지입니다. 특히 레거시 Python 프로젝트나 다양한 파이썬 라이브러리와의 통합이 필요한 경우에 유리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 Playwright는 Python의 최신 기능을 적극 활용하고, 현대적인 웹 애플리케이션 테스팅에 최적화되어 있습니다. 파이썬의 asyncio를 활용한 비동기 프로그래밍이 필요하거나, 보다 안정적이고 빠른 테스트 실행이 필요한 프로젝트에 적합할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 파이썬 프로젝트의 요구사항, 팀의 기술 스택, 그리고 테스트 대상 애플리케이션의 특성을 고려하여 적합한 도구를 선택해야 합니다. Python 개발자라면 두 도구 모두 충분히 활용 가능하므로, 실제 프로젝트에 적용해보고 판단하는 것이 가장 좋은 방법일 것입니다.&lt;/p&gt;</description>
      <category>Python</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/731</guid>
      <comments>https://series.tistory.com/entry/Selenium-vs-Playwright-%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%EC%9B%B9-%EC%9E%90%EB%8F%99%ED%99%94-%EB%8F%84%EA%B5%AC-%EB%B9%84%EA%B5%90-%EB%B6%84%EC%84%9D#entry731comment</comments>
      <pubDate>Fri, 26 Jul 2024 21:10:55 +0900</pubDate>
    </item>
    <item>
      <title>Redis master-replicas sentinel 구성 시 docker-compose.yml 파일</title>
      <link>https://series.tistory.com/entry/Redis-master-replicas-sentinel-%EA%B5%AC%EC%84%B1-%EC%8B%9C-docker-composeyml-%ED%8C%8C%EC%9D%BC</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;docker-compose.yml 파일&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;bitnami/redis 이용&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;services:
  my-redis-a:
    hostname: redis-master
    container_name: redis-master
    image: &quot;bitnami/redis&quot;
    environment:
      - REDIS_REPLICATION_MODE=master
      - ALLOW_EMPTY_PASSWORD=yes
    ports:
      - 5000:6379

  my-redis-b:
    hostname: redis-replicas-1
    container_name: redis-replicas-1
    image: &quot;bitnami/redis&quot;
    environment:
      - REDIS_REPLICATION_MODE=slave
      - REDIS_MASTER_HOST=redis-master
      - ALLOW_EMPTY_PASSWORD=yes
    ports:
      - 5001:6379
    depends_on:
      - my-redis-a

  my-redis-c:
    hostname: redis-replicas-2
    container_name: redis-replicas-2
    image: &quot;bitnami/redis&quot;
    environment:
      - REDIS_REPLICATION_MODE=slave
      - REDIS_MASTER_HOST=redis-master
      - ALLOW_EMPTY_PASSWORD=yes
    ports:
      - 5002:6379
    depends_on:
      - my-redis-a

  redis-sentinel-1:
    container_name: sentinel1
    image: 'bitnami/redis-sentinel:latest'
    environment:
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_SET=mymaster
      - REDIS_SENTINEL_QUORUM=2
    ports:
      - 26379:26379
    depends_on:
      - my-redis-a
      - my-redis-b
      - my-redis-c

  redis-sentinel-2:
    container_name: sentinel2
    image: 'bitnami/redis-sentinel:latest'
    environment:
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_SET=mymaster
      - REDIS_SENTINEL_QUORUM=2
    ports:
      - 26380:26379
    depends_on:
      - my-redis-a
      - my-redis-b
      - my-redis-c

  redis-sentinel-3:
    container_name: sentinel3
    image: 'bitnami/redis-sentinel:latest'
    environment:
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_SET=mymaster
      - REDIS_SENTINEL_QUORUM=2
    ports:
      - 26381:26379
    depends_on:
      - my-redis-a
      - my-redis-b
      - my-redis-c&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;redis-cli 로 어떤 pod가 master 역할을 하는지 확인하는 명령어&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;redis-cli info | grep role&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Docker</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/688</guid>
      <comments>https://series.tistory.com/entry/Redis-master-replicas-sentinel-%EA%B5%AC%EC%84%B1-%EC%8B%9C-docker-composeyml-%ED%8C%8C%EC%9D%BC#entry688comment</comments>
      <pubDate>Sat, 27 Apr 2024 21:37:08 +0900</pubDate>
    </item>
    <item>
      <title>Amazon Linux 2023 에 Redis 설치하기</title>
      <link>https://series.tistory.com/entry/Amazon-Linux-2023-%EC%97%90-Redis-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Redis 설치&lt;/h2&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;sudo yum -y install openssl-devel gcc  
wget http://download.redis.io/redis-stable.tar.gz  
tar xvzf redis-stable.tar.gz  
cd redis-stable  
make distclean  
make redis-cli BUILD\_TLS=yes  
sudo install -m 755 src/redis-cli /usr/local/bin/&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실행&lt;/h2&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;./redis/src/redis-server&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치한 레디스 파일 전역 디렉토리로 복사&lt;/h2&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;sudo cp src/redis-server src/redis-cli /usr/local/bin/&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;config 파일을 /etc/redis로 복사&lt;/h2&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;sudo mkdir /etc/redis
sudo cp src/redis.conf /etc/redis&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;config 설정 변경&lt;/h2&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;sudo vi /etc/redis/redis.conf&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이후 redis-server 명령어로 레디스 실행&lt;/h2&gt;</description>
      <category>AWS</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/687</guid>
      <comments>https://series.tistory.com/entry/Amazon-Linux-2023-%EC%97%90-Redis-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0#entry687comment</comments>
      <pubDate>Fri, 19 Apr 2024 00:02:53 +0900</pubDate>
    </item>
    <item>
      <title>Spock 테스트 시 java.lang.NullPointerException: Cannot invoke method save() on null object 오류</title>
      <link>https://series.tistory.com/entry/Spock-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C-javalangNullPointerException-Cannot-invoke-method-save-on-null-object-%EC%98%A4%EB%A5%98</link>
      <description>&lt;h1&gt;문제점&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Spock 테스트 시 Repository를 주입받지 못하는 오류가 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;해결&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;build.gradle 에서 spring 3.2.4 버전을 기준으로 spock 버전을 재설정하여 해결&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;testImplementation 'org.spockframework:spock-core:2.4-M1-groovy-4.0'
testImplementation 'org.spockframework:spock-spring:2.4-M1-groovy-4.0'&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;mariadb testcontainers&lt;/h1&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// testcontainers
testImplementation 'org.testcontainers:spock:1.19.7'
testImplementation 'org.testcontainers:mariadb:1.19.7'&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;build.gradle 전체&lt;/h1&gt;
&lt;pre class=&quot;puppet&quot;&gt;&lt;code&gt;plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.4'
    id 'io.spring.dependency-management' version '1.1.4'
    id 'groovy'
}

group = 'com.valletta'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '21'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

bootJar {
    archiveFileName = 'app.jar'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    testImplementation 'org.spockframework:spock-core:2.4-M1-groovy-4.0'
    testImplementation 'org.spockframework:spock-spring:2.4-M1-groovy-4.0'

    // testcontainers
    testImplementation 'org.testcontainers:spock:1.19.7'
    testImplementation 'org.testcontainers:mariadb:1.19.7'
}

tasks.named('test') {
    useJUnitPlatform()
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/686</guid>
      <comments>https://series.tistory.com/entry/Spock-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C-javalangNullPointerException-Cannot-invoke-method-save-on-null-object-%EC%98%A4%EB%A5%98#entry686comment</comments>
      <pubDate>Sat, 30 Mar 2024 15:08:38 +0900</pubDate>
    </item>
    <item>
      <title>Docker - docker bind: an attempt was made to access a socket in a way forbidden by its access permissions. 오류 시</title>
      <link>https://series.tistory.com/entry/Docker-docker-bind-an-attempt-was-made-to-access-a-socket-in-a-way-forbidden-by-its-access-permissions-%EC%98%A4%EB%A5%98-%EC%8B%9C</link>
      <description>&lt;h1&gt;원인&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;사용하고자 하는 포트가 사용이 제한되었기 때문입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;해결 방법&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;powershell을 관리자 권한으로 열어서 아래 명령어를 입력하면 제한된 포트들 리스트들이 나옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;netsh interface ipv4 show excludedportrange protocol=tcp&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;아래 순서대로 해주면 원하는 포트로 도커를 실행시킬 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;net stop winnat netsh int ipv4 add excludedportrange protocol=tcp startport=6379

numberofports=1
또는
netsh int ipv4 add excludedportrange protocol=tcp startport=6379 numberofports=1

set start winnat&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;docker ps 명령어로 도커 컨테이너가 잘 생성되었는지 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;147&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ca0fQX/btsGefWvtWR/o0UEuBpVxHuayzpVlQevt1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ca0fQX/btsGefWvtWR/o0UEuBpVxHuayzpVlQevt1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ca0fQX/btsGefWvtWR/o0UEuBpVxHuayzpVlQevt1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fca0fQX%2FbtsGefWvtWR%2Fo0UEuBpVxHuayzpVlQevt1%2Fimg.jpg&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;1044&quot; height=&quot;147&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;147&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1234&quot; data-origin-height=&quot;62&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7x4kq/btsGd7qTtD0/VyJVNWM2IUIG37LP20ltVK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7x4kq/btsGd7qTtD0/VyJVNWM2IUIG37LP20ltVK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7x4kq/btsGd7qTtD0/VyJVNWM2IUIG37LP20ltVK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7x4kq%2FbtsGd7qTtD0%2FVyJVNWM2IUIG37LP20ltVK%2Fimg.jpg&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;1234&quot; height=&quot;62&quot; data-origin-width=&quot;1234&quot; data-origin-height=&quot;62&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Docker</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/685</guid>
      <comments>https://series.tistory.com/entry/Docker-docker-bind-an-attempt-was-made-to-access-a-socket-in-a-way-forbidden-by-its-access-permissions-%EC%98%A4%EB%A5%98-%EC%8B%9C#entry685comment</comments>
      <pubDate>Fri, 29 Mar 2024 20:50:20 +0900</pubDate>
    </item>
    <item>
      <title>Pycharm - Cannot connect to the Docker daemon at unix:///var/run/docker.sock 오류</title>
      <link>https://series.tistory.com/entry/Pycharm-Cannot-connect-to-the-Docker-daemon-at-unixvarrundockersock-%EC%98%A4%EB%A5%98</link>
      <description>&lt;h1&gt;해결 방법&lt;/h1&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;/ul&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;# {name}에는 자신이 macOS에 설정한 값을 넣는다.
sudo ln -s /Users/{name}/.docker/run/docker.sock /var/run/&lt;/code&gt;&lt;/pre&gt;
&lt;p 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-origin-width=&quot;803&quot; data-origin-height=&quot;603&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tJh15/btsF6fowRv5/AJDEOvL9piDYsU0WMAhofK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tJh15/btsF6fowRv5/AJDEOvL9piDYsU0WMAhofK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tJh15/btsF6fowRv5/AJDEOvL9piDYsU0WMAhofK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtJh15%2FbtsF6fowRv5%2FAJDEOvL9piDYsU0WMAhofK%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;803&quot; height=&quot;603&quot; data-origin-width=&quot;803&quot; data-origin-height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Python</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/684</guid>
      <comments>https://series.tistory.com/entry/Pycharm-Cannot-connect-to-the-Docker-daemon-at-unixvarrundockersock-%EC%98%A4%EB%A5%98#entry684comment</comments>
      <pubDate>Tue, 26 Mar 2024 13:27:14 +0900</pubDate>
    </item>
    <item>
      <title>AWS Cloudwatch - Log Insights 쿼리 예시 및 설명</title>
      <link>https://series.tistory.com/entry/AWS-Cloudwatch-Log-Insights-%EC%BF%BC%EB%A6%AC-%EC%98%88%EC%8B%9C-%EB%B0%8F-%EC%84%A4%EB%AA%85</link>
      <description>&lt;pre&gt;&lt;code&gt;
# fields @timestamp, @message, @logStream, @log
fields @timestamp
| parse @message &amp;quot;* * [*] * - [*] [*] : *&amp;quot; as springProfile, appName, instanceId, logLevel, traceId, classPath, errorMessage
| filter logLevel = &amp;quot;ERROR&amp;quot;
| filter appName = &amp;quot;goods-service&amp;quot;
| filter traceId = &amp;quot;aaaaabbbbcccc123123&amp;quot;
| sort @timestamp desc
| limit 1000
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;@timestamp 필드를 출력으로 선택합니다.&lt;/li&gt;
&lt;li&gt;@message 필드를 지정된 패턴에 따라 파싱하 springProfile, appName, instanceId, logLevel, traceId, classPath, errorMessage 필드로 분리합니다.&lt;/li&gt;
&lt;li&gt;logLevel 필드를 &amp;quot;ERROR&amp;quot;로 필터링하여 오류 로그만 선택합니다.&lt;/li&gt;
&lt;li&gt;appName 필드를 &amp;quot;goods-service&amp;quot;로 필터링하여 특정 어플리케이션 로그만 선택합니다.&lt;/li&gt;
&lt;li&gt;traceId 필드를 &amp;quot;65fa77ba7e360da8f0ca7ae7ca81d965&amp;quot;로 필터링하여 특정 추적 ID를 가진 로그만 선택합니다.&lt;/li&gt;
&lt;li&gt;@timestamp 필드를 내림차순으로 정렬합니다.&lt;/li&gt;
&lt;li&gt;최대 1000개의 결과만 반환합니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AWS</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/683</guid>
      <comments>https://series.tistory.com/entry/AWS-Cloudwatch-Log-Insights-%EC%BF%BC%EB%A6%AC-%EC%98%88%EC%8B%9C-%EB%B0%8F-%EC%84%A4%EB%AA%85#entry683comment</comments>
      <pubDate>Wed, 20 Mar 2024 16:36:45 +0900</pubDate>
    </item>
    <item>
      <title>Springdoc - use-fqn 설정으로 스웨거에서 Response 이름 충돌 문제 해결하기</title>
      <link>https://series.tistory.com/entry/Springdoc-use-fqn-%EC%84%A4%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%8A%A4%EC%9B%A8%EA%B1%B0%EC%97%90%EC%84%9C-Response-%EC%9D%B4%EB%A6%84-%EC%B6%A9%EB%8F%8C-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
      <description>&lt;p&gt;스웨거 문서에서 Response 모델 이름이 충돌하여 발생하는 문제가 있을 수 있습니다.&lt;br&gt;Springdoc를 사용하여 간단하게 해결할 수 있습니다.&lt;/p&gt;
&lt;p&gt;Springdoc는 스프링 부트 애플리케이션에서 OpenAPI 3.x 스펙을 지원하는 라이브러리입니다.&lt;br&gt;이를 사용하여 스웨거 문서를 생성하고 커스터마이징할 수 있습니다.&lt;br&gt;Springdoc를 사용하여 Response 이름 충돌 문제를 해결하는 방법에 대해 알아보겠습니다.&lt;/p&gt;
&lt;p&gt;application.yml 설정하기: use-fqn 옵션을 true로 설정하여 Response 모델의 완전한 클래스 경로(Fully Qualified Name)를 사용하도록 설정합니다.&lt;br&gt;이를 통해 스웨거가 동일한 이름을 가진 모델을 구분할 수 있게 됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;springdoc:
  use-fqn: true&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;위의 설정을 적용했을 때 Response 모델 이름이 충돌하지 않고 정확한 예시 값이 표시됩니다.&lt;/p&gt;
&lt;h3&gt;application.yml - springdoc 부분&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;springdoc:
  version: &amp;#39;1.6.13&amp;#39;
  api-docs:
    enabled: true
    path: /v3/api-docs
    groups:
      enabled: true
  swagger-ui:
    path: /swagger-ui.html
    tagsSorter: alpha
    use-root-path: true
    groups-order: desc
  cache:
    disabled: true
  use-fqn: true&lt;/code&gt;&lt;/pre&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/682</guid>
      <comments>https://series.tistory.com/entry/Springdoc-use-fqn-%EC%84%A4%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%8A%A4%EC%9B%A8%EA%B1%B0%EC%97%90%EC%84%9C-Response-%EC%9D%B4%EB%A6%84-%EC%B6%A9%EB%8F%8C-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0#entry682comment</comments>
      <pubDate>Tue, 19 Mar 2024 09:16:47 +0900</pubDate>
    </item>
    <item>
      <title>JPA에서 @IdClass를 사용한 복합 주키 매핑</title>
      <link>https://series.tistory.com/entry/JPA%EC%97%90%EC%84%9C-IdClass%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%B3%B5%ED%95%A9-%EC%A3%BC%ED%82%A4-%EB%A7%A4%ED%95%91</link>
      <description>&lt;p&gt;JPA에서 @IdClass를 사용한 복합 주키 매핑&lt;br&gt;자바 영속성 API(JPA)에서는 @IdClass 주석을 사용하여 복합 주키를 지정합니다.&lt;br&gt;이를 통해 엔터티 클래스와 별도로 기본 키 클래스를 정의할 수 있습니다.&lt;br&gt;예제를 통해 @IdClass를 사용하여 복합 주키 매핑하는 방법을 살펴보겠습니다.&lt;/p&gt;
&lt;h1&gt;엔터티 클래스: UserGroupMappingEntity&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;java
Copy code
import javax.persistence.*;

@Getter
@Setter
@ToString
@Entity
@Table(name = &amp;quot;user_group_mapping&amp;quot;)
@IdClass(UserGroupMappingId.class)
public class UserGroupMappingEntity extends BaseEntity {

    @Id
    @Column(name = &amp;quot;user_group_id&amp;quot;)
    private String userGroupId;

    @Id
    @Column(name = &amp;quot;user_id&amp;quot;)
    private String userId;

    @Column(name = &amp;quot;user_group_name&amp;quot;)
    private String userGroupName;

    private String description;
}&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;기본 키 클래스: UserGroupMappingId&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;java
Copy code
import java.io.Serializable;

@Getter
@Setter
@ToString
public class UserGroupMappingId implements Serializable {

    private String userGroupId;

    private String userId;
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;이 예제에서는:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UserGroupMappingEntity 클래스는 &amp;quot;user_group_mapping&amp;quot; 테이블에 매핑된 엔터티를 나타냅니다.&lt;/li&gt;
&lt;li&gt;@IdClass(UserGroupMappingId.class)를 사용하여 UserGroupMappingId 클래스가 이 엔터티의 복합 기본 키를 포함한다는 것을 지정합니다.&lt;/li&gt;
&lt;li&gt;UserGroupMappingId 클래스는 복합 기본 키 필드 userGroupId와 userId를 정의합니다.&lt;/li&gt;
&lt;li&gt;UserGroupMappingEntity 클래스의 기본 키 필드는 @Id로 주석이 달려 있으며, 이는 이들이 복합 기본 키의 일부임을 나타냅니다.&lt;/li&gt;
&lt;li&gt;UserGroupMappingEntity 클래스의 다른 필드는 테이블의 열에 매핑됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 접근 방식을 사용하면 엔터티 모델에서 복합 기본 키를 깔끔하게 나타낼 수 있으며, 특히 기존 데이터베이스나 복합 기본 키가 있는 테이블과 작업할 때 유용합니다.&lt;/p&gt;</description>
      <category>JPA</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/681</guid>
      <comments>https://series.tistory.com/entry/JPA%EC%97%90%EC%84%9C-IdClass%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%B3%B5%ED%95%A9-%EC%A3%BC%ED%82%A4-%EB%A7%A4%ED%95%91#entry681comment</comments>
      <pubDate>Fri, 15 Mar 2024 09:59:01 +0900</pubDate>
    </item>
    <item>
      <title>git flow 운영 정책</title>
      <link>https://series.tistory.com/entry/git-flow-%EC%9A%B4%EC%98%81-%EC%A0%95%EC%B1%85</link>
      <description>&lt;h2 id=&quot;서버&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2&quot; data-ke-size=&quot;size26&quot;&gt;서버&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;dev : 개발 단계 확인&lt;/li&gt;
&lt;li&gt;stage : QA 검수등의 사용자 테스트&lt;/li&gt;
&lt;li&gt;prod : 운영&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;브랜치&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;68&quot; data-ke-size=&quot;size26&quot;&gt;브랜치&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;feature : 담당자 기능 브랜치&lt;/li&gt;
&lt;li&gt;develop : 개발 브랜치&lt;/li&gt;
&lt;li&gt;stage : QA 검수등 테스트 브랜치&lt;/li&gt;
&lt;li&gt;release : 배포 브랜치
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적인 gitflow 에서는 develop 브랜치가 안정화 되었을때 생성하나, 배포시 브랜치 머지용도로 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;master : 운영 브랜치&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;상품-git-Flow&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;253&quot; data-ke-size=&quot;size26&quot;&gt;상품 git Flow&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;266&quot; data-ke-size=&quot;size16&quot;&gt;[1안]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oROXP/btsFzbU9t3B/hYjynpYW3oTetjQrEXHmRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oROXP/btsFzbU9t3B/hYjynpYW3oTetjQrEXHmRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oROXP/btsFzbU9t3B/hYjynpYW3oTetjQrEXHmRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoROXP%2FbtsFzbU9t3B%2FhYjynpYW3oTetjQrEXHmRK%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;860&quot; height=&quot;643&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;848&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본 프로세스&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;feature &amp;rarr; 개발 &amp;rarr; PR &amp;rarr; develop , release 머지
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;develop 머지 후 개발자 테스트 수행 중 변경사항 발생 시 &lt;b&gt;위 프로세스(1번)와 동일 수행&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;release &amp;rarr; stage, develop 머지
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;만약, 개발자가 develop 머지 없이 release에만 머지를 수행할 경우를 대비하여 hook 설정
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;hook 내용
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;4&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;로컬&lt;/b&gt;에서 release upstream 반영 시 develop에 커밋해쉬정보가 존재하는지 검증합니다.&lt;/li&gt;
&lt;li&gt;위치 : 프로젝트/.git/hooks&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&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: #172b4d; text-align: start;&quot;&gt;[2안]&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;1135&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UM0pm/btsFB5fdCM4/GLfK6dS5Ek1FikrwwIh6gK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UM0pm/btsFB5fdCM4/GLfK6dS5Ek1FikrwwIh6gK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UM0pm/btsFB5fdCM4/GLfK6dS5Ek1FikrwwIh6gK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUM0pm%2FbtsFB5fdCM4%2FGLfK6dS5Ek1FikrwwIh6gK%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;1135&quot; height=&quot;924&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;release를 develop과 stage 에 반영&lt;/li&gt;
&lt;li&gt;릴리즈에 없는 내용이 develop이나 stage 에 반영 할 수 없음
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;feature를 release를 거치지 않고 올리거나, develop, stage 에서 직접 수정후 push 불가&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;develop 을 stage로 반영 할 수 없음&lt;/li&gt;
&lt;li&gt;v2에 개발된 소스가 배포일자 변경등으로 v1에 포함되어야 하는 경우
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;v2 전체가 v1으로 포함되어도 되는경우
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;v2에 v1을 pull 받아 싱크 맞추고 머지&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;v2 일부가 v1으로 포함되어야 하는 경우
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;feature에 pull 받아 싱크 맞추고 release v1에 머지&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;956&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 해당 머지과정에서 컨플릭트가 발생할 수 있음(base 브랜치가 다르므로), 발생 된 컨플릭트는 담당자가 해결 후 머지&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;v1에 올린 내용을 수정해야 할 경우 (스테이지 검수과정에서 변경 필요 시)
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;해당 release 기준으로 피처를 재생성 및 기존 feature에 해당 release를 pull 받아서, 싱크 맞추고 변경 개발 수행&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;지라-티켓-관련&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1161&quot; data-ke-size=&quot;size23&quot;&gt;지라 티켓 관련&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스 변경이 필요한 작업은 티켓을 생성&lt;/li&gt;
&lt;li&gt;QA 할 내용은 지라 release 에 티켓 추가&lt;/li&gt;
&lt;li&gt;hotfix의 경우 선배포 후 티켓추가 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;브랜치-생성-및-수행-기준&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1259&quot; data-ke-size=&quot;size23&quot;&gt;브랜치 생성 및 수행 기준&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;feature는 develop 기준으로 생성 &lt;u data-renderer-mark=&quot;true&quot;&gt;(PR 수행)&lt;/u&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;stage&lt;/b&gt;는 release 머지
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스테이지 = master 싱크로 배포할 내용만 머지함.&lt;/li&gt;
&lt;li&gt;스테이지에는 release 한개의 브랜치만 머지함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) 11월 7일 배포건 &amp;rarr; release/v231107 &amp;rarr; stage&lt;/li&gt;
&lt;li&gt;ex) 11월 21일 배포건 &amp;rarr; release/v231121 &amp;rarr; stage&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;release&lt;/b&gt;는 stage 기준으로 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;브랜치명 : release 티켓 명 (ex . v231026)&lt;/li&gt;
&lt;li&gt;생성시점 : 배포일자 확정 즉시&lt;/li&gt;
&lt;li&gt;&lt;b&gt;머지 : feature &amp;rarr; release &lt;/b&gt;&lt;/li&gt;
&lt;li&gt;release &amp;rarr; stage 시 release &amp;rarr; develop 동시 수행 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;hotfix &lt;/b&gt;는 master 기준으로 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ffffff;&quot; data-color=&quot;blue&quot; data-node-type=&quot;status&quot;&gt;&lt;span style=&quot;background-color: #000000;&quot;&gt;케이스&lt;/span&gt;&lt;/span&gt; 긴급하게 수정후 바로 머지해야 할 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;develop, master 머지
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;4&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cf) gitFlow 사용 시 develop, master 동시 머지 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ffffff;&quot; data-color=&quot;blue&quot; data-node-type=&quot;status&quot;&gt;&lt;span style=&quot;background-color: #000000;&quot;&gt;케이스&lt;/span&gt; &lt;/span&gt;당장 배포하지 않아도 되는 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PR 수행 후 develop, master 머지 ( PR 시 머지대상 브랜치는 master)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;GitFlow-설명&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1866&quot; data-ke-size=&quot;size23&quot;&gt;GitFlow 설명&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 id=&quot;feature&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1878&quot; data-ke-size=&quot;size20&quot;&gt;feature&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설명
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;start feature : develop 기준으로 생성&lt;/li&gt;
&lt;li&gt;publish feature : upstream 반영&lt;/li&gt;
&lt;li&gt;finish feature : develop 머지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용 예
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;start feature &amp;rarr; 개발 &amp;rarr; publish feature &amp;rarr; PR(비트버켓) &amp;rarr; 머지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;release&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2069&quot; data-ke-size=&quot;size20&quot;&gt;release&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설명
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;start release : develop 기준으로 생성&lt;/li&gt;
&lt;li&gt;publish release : push(upStream 반영)&lt;/li&gt;
&lt;li&gt;finish release : develop , master 머지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용 예
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;master 브랜치 기준 release/{릴리즈티켓명} 생성 후 push(upStream 반영)&lt;/li&gt;
&lt;li&gt;release/{릴리즈티켓명} 에 배포 내용 머지&lt;/li&gt;
&lt;li&gt;finish release : develop , master 머지 &amp;rarr; 각 브랜치(develop , master) push &amp;rarr; 배포&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;hotfix&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2380&quot; data-ke-size=&quot;size20&quot;&gt;hotfix&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설명
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;start hotfix : master 기준으로 생성&lt;/li&gt;
&lt;li&gt;publish hotfix : push(upStream 반영)&lt;/li&gt;
&lt;li&gt;finish hotfix : develop , master 머지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용 예
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;start hotfix &amp;rarr; publish hotfix &amp;rarr; PR &amp;rarr; finish hotfix &amp;rarr; 각 브랜치(develop , master) push &amp;rarr; 배포&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Git</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/680</guid>
      <comments>https://series.tistory.com/entry/git-flow-%EC%9A%B4%EC%98%81-%EC%A0%95%EC%B1%85#entry680comment</comments>
      <pubDate>Wed, 6 Mar 2024 14:34:17 +0900</pubDate>
    </item>
    <item>
      <title>ReflectionTestUtils를 사용하여 private 변수나 메소드(함수)를 테스트할 수 있습니다</title>
      <link>https://series.tistory.com/entry/ReflectionTestUtils%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-private-%EB%B3%80%EC%88%98%EB%82%98-%EB%A9%94%EC%86%8C%EB%93%9C%ED%95%A8%EC%88%98%EB%A5%BC-%ED%85%8C%EC%8A%A4%ED%8A%B8%ED%95%A0-%EC%88%98-%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4</link>
      <description>&lt;h2 id=&quot;reflectiontestutils&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;ReflectionTestUtils&lt;/h2&gt;
&lt;h3 id=&quot;대상-class&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;대상 Class&lt;/h3&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;
&lt;div style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;
&lt;pre class=&quot;java&quot; style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;&lt;code&gt;@Component
@Getter
public class ReflectionTestUtilsComponent {

    private int privateValue;

    private int privateMethod(int a, int b) {
        privateValue += a;
        privateValue += b;
        return privateValue;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 id=&quot;private-변수-테스트&quot; data-ke-size=&quot;size23&quot;&gt;private 변수 테스트&lt;/h3&gt;
&lt;h4 id=&quot;형태&quot; data-ke-size=&quot;size20&quot;&gt;형태&lt;/h4&gt;
&lt;div&gt;
&lt;div style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;
&lt;pre class=&quot;delphi&quot; style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;&lt;code&gt;static void	setField(Class&amp;lt;?&amp;gt; targetClass, String name, Object value)

static void	setField(Class&amp;lt;?&amp;gt; targetClass, String name, Object value, Class&amp;lt;?&amp;gt; type)

static void	setField(Object targetObject, Class&amp;lt;?&amp;gt; targetClass, String name, Object value, Class&amp;lt;?&amp;gt; type)

static void	setField(Object targetObject, String name, Object value)

static void	setField(Object targetObject, String name, Object value, Class&amp;lt;?&amp;gt; type)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 id=&quot;사용-예시&quot; data-ke-size=&quot;size20&quot;&gt;사용 예시&lt;/h4&gt;
&lt;div&gt;
&lt;div style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;&lt;code&gt;@Test
public void testPrivateValue() {
    ReflectionTestUtils.setField(reflectionTestUtilsComponent, &quot;privateValue&quot;, 100);
    // ReflectionTestUtils.setField(대상 객체, &quot;변수명&quot;, 원하는 값);

    Assertions.assertEquals(100, reflectionTestUtilsComponent.getPrivateValue());
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;private-메소드함수-테스트&quot; data-ke-size=&quot;size23&quot;&gt;private 메소드(함수) 테스트&lt;/h3&gt;
&lt;h4 id=&quot;형태-1&quot; data-ke-size=&quot;size20&quot;&gt;형태&lt;/h4&gt;
&lt;div&gt;
&lt;div style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;
&lt;pre class=&quot;delphi&quot; style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;&lt;code&gt;static &amp;lt;T&amp;gt; T	invokeMethod(Class&amp;lt;?&amp;gt; targetClass, String name, Object... args)

static &amp;lt;T&amp;gt; T	invokeMethod(Object targetObject, Class&amp;lt;?&amp;gt; targetClass, String name, Object... args)

static &amp;lt;T&amp;gt; T	invokeMethod(Object target, String name, Object... args)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 id=&quot;사용-예시-1&quot; data-ke-size=&quot;size20&quot;&gt;사용 예시&lt;/h4&gt;
&lt;div&gt;
&lt;div style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background-color: #272822; color: #d0d0d0;&quot;&gt;&lt;code&gt;@Test
public void testPrivateMethod() {
    ReflectionTestUtils.setField(reflectionTestUtilsComponent, &quot;privateValue&quot;, 100);
    // ReflectionTestUtils.setField(대상 객체, &quot;변수명&quot;, 원하는 값);

    Assertions.assertEquals(103, (Integer) ReflectionTestUtils.invokeMethod(reflectionTestUtilsComponent, &quot;privateMethod&quot;, 1, 2));
    // ReflectionTestUtils.invokeMethod(대상 객체, &quot;메소드(함수)명&quot;, 인자);

    Assertions.assertEquals(103, reflectionTestUtilsComponent.getPrivateValue());
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/679</guid>
      <comments>https://series.tistory.com/entry/ReflectionTestUtils%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-private-%EB%B3%80%EC%88%98%EB%82%98-%EB%A9%94%EC%86%8C%EB%93%9C%ED%95%A8%EC%88%98%EB%A5%BC-%ED%85%8C%EC%8A%A4%ED%8A%B8%ED%95%A0-%EC%88%98-%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4#entry679comment</comments>
      <pubDate>Sun, 27 Aug 2023 12:40:57 +0900</pubDate>
    </item>
    <item>
      <title>Springboot 테스트 - p6spy 적용하는 방법</title>
      <link>https://series.tistory.com/entry/Springboot-%ED%85%8C%EC%8A%A4%ED%8A%B8-p6spy-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Slf4j
@DisplayName(&quot;JPA 연결 테스트&quot;)
@Import(JpaConfig.class)
@ImportAutoConfiguration({DataSourceDecoratorAutoConfiguration.class, P6SpySqlFormatter.class})
@ActiveProfiles(&quot;local&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Configuration
public class P6SpySqlFormatter {

    @PostConstruct
    public void setLogMessageFormat() {
        P6SpyOptions.getActiveInstance().setLogMessageFormat(P6spySqlFormatConfiguration.class.getName());
    }

    static public class P6spySqlFormatConfiguration implements MessageFormattingStrategy {

        // 표기에 허용되는 filter
        private static final String ALLOW_FILTER = &quot;com.hanssem&quot;;

        @Override
        public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) {

            sql = formatSql(category, sql);
            if (sql.trim().isEmpty()) { // sql 이 없다면 출력하지 않아도 됨
                return &quot;&quot;;
            }

            // stack 을 구성하는 Format을 만든다
            return sql + createStack(connectionId, elapsed);
//            return sql + &quot;\n\n&quot;;
        }

        private String formatSql(String category, String sql) {

            if (sql == null || sql.trim().isEmpty()) {
                return sql;
            }

            // Only format Statement, distinguish DDL And DML
            if (Category.STATEMENT.getName().equals(category)) {
                String tmpsql = sql.trim().toLowerCase(Locale.ROOT);
                if (tmpsql.startsWith(&quot;create&quot;) || tmpsql.startsWith(&quot;alter&quot;) || tmpsql.startsWith(&quot;comment&quot;)) {
                    sql = FormatStyle.DDL.getFormatter().format(sql);
                } else {
                    sql = FormatStyle.BASIC.getFormatter().format(sql);
                }

                sql = &quot;|\n--------------------------------------&quot; + sql;
            }

            return sql;
        }

        // stack 콘솔 표기
        private String createStack(int connectionId, long elapsed) {
            Stack&amp;lt;String&amp;gt; callStack = new Stack&amp;lt;&amp;gt;();
            StackTraceElement[] stackTrace = new Throwable().getStackTrace();

            for (StackTraceElement stackTraceElement : stackTrace) {
                String trace = stackTraceElement.toString();

                // trace 항목을 보고 내게 맞는 것만 필터
                if (trace.startsWith(ALLOW_FILTER)) {
                    callStack.push(trace);
                }
            }

            StringBuilder sb = new StringBuilder();
            int order = 1;
            while (!callStack.isEmpty()) {
                sb.append(&quot;\n\t\t&quot;).append(order++).append(&quot;.&quot;).append(callStack.pop());
            }

            return new StringBuffer().append(&quot;\n\tCall Stack:&quot;).append(sb)
                .append(&quot;\n--------------------------------------\n&quot;)
                .toString();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/678</guid>
      <comments>https://series.tistory.com/entry/Springboot-%ED%85%8C%EC%8A%A4%ED%8A%B8-p6spy-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95#entry678comment</comments>
      <pubDate>Sat, 19 Aug 2023 10:51:11 +0900</pubDate>
    </item>
    <item>
      <title>springboot 3.0 이상 p6spy 설정 (로깅이 안될 경우)</title>
      <link>https://series.tistory.com/entry/springboot-30-%EC%9D%B4%EC%83%81-p6spy-%EC%84%A4%EC%A0%95-%EB%A1%9C%EA%B9%85%EC%9D%B4-%EC%95%88%EB%90%A0-%EA%B2%BD%EC%9A%B0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;springboot&amp;nbsp;3.0&amp;nbsp;이상&amp;nbsp;p6spy&amp;nbsp;설정&amp;nbsp;(로깅이&amp;nbsp;안될&amp;nbsp;경우)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;springboot가 업데이트되면서 p6spy의 쿼리 로깅이 잘 안되는 문제가 있습니다.&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;/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;1. build.gradle 의존성 추가&lt;/b&gt;&lt;/h3&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.1'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;2. [project]/src/main/resources/META-INF/spring 경로에 파일 추가&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 파일 경로 : /src/main/resources/META-INF/spring/&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 파일명 : org.springframework.boot.autoconfigure.AutoConfiguration.imports&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 파일 내용&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;com.github.gavlyukovskiy.boot.jdbc.decorator.DataSourceDecoratorAutoConfiguration&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;3. [project]/src/main/resources 경로에 파일 추가&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 파일 경로 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;/src/main/resources/&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;* 파일명 :&lt;span&gt; spy.properties&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;* 파일 내용&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;appender=com.p6spy.engine.spy.appender.Slf4JLogger&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;4. application.yml 에서 다른 쿼리 로그는 헷갈리지 않도록 안보이게 설정&lt;/b&gt;&lt;/h3&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;5. p6spy 로그를 줄바꿈 formatting하여 가독성 높이기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* config 패키지에 P6spyLogMessageFormatConfiguration.java 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일명은 상관없습니다. 파일 내용이 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Configuration
public class P6spyLogMessageFormatConfiguration {

    @PostConstruct
    public void setLogMessageFormat() {
        P6SpyOptions.getActiveInstance().setLogMessageFormat(P6spySqlFormatConfiguration.class.getName());
    }

    static public class P6spySqlFormatConfiguration implements MessageFormattingStrategy {

        // 표기에 허용되는 filter
        private static final String ALLOW_FILTER = &quot;com.creed&quot;;

        @Override
        public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) {

            sql = formatSql(category, sql);
            if (sql.trim().isEmpty()) { // sql 이 없다면 출력하지 않아도 됨
                return &quot;&quot;;
            }

            // stack 을 구성하는 Format을 만든다
            return sql + createStack(connectionId, elapsed);
        }

        private String formatSql(String category, String sql) {

            if (sql == null || sql.trim().equals(&quot;&quot;)) {
                return sql;
            }

            // Only format Statement, distinguish DDL And DML
            if (Category.STATEMENT.getName().equals(category)) {
                String tmpsql = sql.trim().toLowerCase(Locale.ROOT);
                if (tmpsql.startsWith(&quot;create&quot;) || tmpsql.startsWith(&quot;alter&quot;) || tmpsql.startsWith(&quot;comment&quot;)) {
                    sql = FormatStyle.DDL.getFormatter().format(sql);
                } else {
                    sql = FormatStyle.BASIC.getFormatter().format(sql);
                }
                sql = &quot;|\nFormatSql(P6Spy sql, Hibernate format):&quot; + sql;
            }

            return sql;
        }

        // stack 콘솔 표기
        private String createStack(int connectionId, long elapsed) {
            Stack&amp;lt;String&amp;gt; callStack = new Stack&amp;lt;&amp;gt;();
            StackTraceElement[] stackTrace = new Throwable().getStackTrace();

            for (StackTraceElement stackTraceElement : stackTrace) {
                String trace = stackTraceElement.toString();

                // trace 항목을 보고 내게 맞는 것만 필터
                if (trace.startsWith(ALLOW_FILTER)) {
                    callStack.push(trace);
                }
            }

            StringBuilder sb = new StringBuilder();
            int order = 1;
            while (callStack.size() != 0) {
                sb.append(&quot;\n\t\t&quot;).append(order++).append(&quot;.&quot;).append(callStack.pop());
            }

            return new StringBuffer().append(&quot;\n\n\tConnection ID: &quot;).append(connectionId)
                    .append(&quot;\n\tExcution Time: &quot;).append(elapsed).append(&quot;ms&quot;)
                    .append(&quot;\n\tCall Stack:&quot;).append(sb)
                    .append(&quot;\n--------------------------------------&quot;)
                    .toString();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/677</guid>
      <comments>https://series.tistory.com/entry/springboot-30-%EC%9D%B4%EC%83%81-p6spy-%EC%84%A4%EC%A0%95-%EB%A1%9C%EA%B9%85%EC%9D%B4-%EC%95%88%EB%90%A0-%EA%B2%BD%EC%9A%B0#entry677comment</comments>
      <pubDate>Wed, 16 Aug 2023 22:53:55 +0900</pubDate>
    </item>
    <item>
      <title>springboot - SQL Binding 로깅 안되는 문제</title>
      <link>https://series.tistory.com/entry/springboot-SQL-Binding-%EB%A1%9C%EA%B9%85-%EC%95%88%EB%90%98%EB%8A%94-%EB%AC%B8%EC%A0%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;application.yml&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;logging:
  level:    
    org.hibernate.orm.jdbc.bind: trace&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;org.hibernate.or&lt;a style=&quot;color: #ee2323;&quot; href=&quot;http://m.jdbc.bind:&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;m.jdbc.bind:&lt;/a&gt;&amp;nbsp;trace&lt;/b&gt;&lt;/span&gt;&lt;/u&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: #222222; text-align: start;&quot;&gt;스프링부트 버젼 3.0.0 부터는 하이버네이트가 6.1.5로 버전업이 되면서 하이버네이트가 로깅하는 방식을 변경했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p 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-origin-width=&quot;904&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4Ya3x/btsrqBGmfmX/Kkd2nuVbVHGDAhkLjqrpmk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4Ya3x/btsrqBGmfmX/Kkd2nuVbVHGDAhkLjqrpmk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4Ya3x/btsrqBGmfmX/Kkd2nuVbVHGDAhkLjqrpmk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4Ya3x%2FbtsrqBGmfmX%2FKkd2nuVbVHGDAhkLjqrpmk%2Fimg.jpg&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;904&quot; height=&quot;227&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;227&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바인딩 잘 되는 것 확인!!&lt;/p&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/676</guid>
      <comments>https://series.tistory.com/entry/springboot-SQL-Binding-%EB%A1%9C%EA%B9%85-%EC%95%88%EB%90%98%EB%8A%94-%EB%AC%B8%EC%A0%9C#entry676comment</comments>
      <pubDate>Wed, 16 Aug 2023 22:27:06 +0900</pubDate>
    </item>
    <item>
      <title>querydsl - @QueryProjection</title>
      <link>https://series.tistory.com/entry/querydsl-QueryProjection</link>
      <description>&lt;pre class=&quot;arduino&quot; style=&quot;color: #000000; text-align: left;&quot;&gt;&lt;code&gt;public class MemberDto {
    private String name;
    private int age;

    @QueryProjection // 어노테이션 추가
    public MemberDto(String name, int age) {
        this.name = name;
        this.age = age;
    }
}


public void findDtoByQueryProjection() {
	queryFactory
		.select(new QMemberDto(member.name, member.age))
		.from(member)
		.fetch();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;QDto로 생성된 생성자를 사용하는 방법&lt;br /&gt;&lt;b&gt;런타임 에러와 컴파일 에러 모두 잡을 수 있다.&lt;/b&gt;&lt;br /&gt;하지만 DTO 특성상 전 계층(Service, Controller)에 데이터를 전달하기 위한 객체인데 모든 사용에서 Querydsl 의존성을 가지게 된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@daoh98/Querydsl-QuerydslPredicateExecutor-%EC%99%80-Querydsl-%EC%98%AC%EB%B0%94%EB%A5%B8-%EC%82%AC%EC%9A%A9%EB%B2%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@daoh98/Querydsl-QuerydslPredicateExecutor-%EC%99%80-Querydsl-%EC%98%AC%EB%B0%94%EB%A5%B8-%EC%82%AC%EC%9A%A9%EB%B2%95&lt;/a&gt;&lt;/p&gt;</description>
      <category>JPA</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/675</guid>
      <comments>https://series.tistory.com/entry/querydsl-QueryProjection#entry675comment</comments>
      <pubDate>Wed, 16 Aug 2023 22:05:46 +0900</pubDate>
    </item>
    <item>
      <title>Springboot 3.0.0 이상 - Querydsl build.gradle 설정 및 NoClassDefFoundError 오류 대응 방법</title>
      <link>https://series.tistory.com/entry/Springboot-300-%EC%9D%B4%EC%83%81-Querydsl-buildgradle-%EC%84%A4%EC%A0%95-%EB%B0%8F-NoClassDefFoundError-%EC%98%A4%EB%A5%98-%EB%8C%80%EC%9D%91-%EB%B0%A9%EB%B2%95</link>
      <description>&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;1. build.gradle 에 의존성 추가 및 Q class 설정&lt;/b&gt;&lt;/h3&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// ************* 최상단
buildscript {
    ext {
        queryDslVersion = &quot;5.0.0&quot;
    }
}



// ************* 의존성 부분
// queryDSL 설정
    implementation &quot;com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta&quot;
    implementation &quot;com.querydsl:querydsl-core&quot;
    implementation &quot;com.querydsl:querydsl-collections&quot;

    annotationProcessor &quot;com.querydsl:querydsl-apt:${queryDslVersion}:jakarta&quot; // querydsl JPAAnnotationProcessor 사용 지정
    annotationProcessor &quot;jakarta.annotation:jakarta.annotation-api&quot; // java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드
    annotationProcessor &quot;jakarta.persistence:jakarta.persistence-api&quot; // java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드



// ************* 하단
// Querydsl 설정부
def querydslDir = 'src/main/generated'

// querydsl QClass 파일 생성 위치를 지정
tasks.withType(JavaCompile) {
    options.getGeneratedSourceOutputDirectory().set(file(querydslDir))
}

// java source set 에 querydsl QClass 위치 추가
sourceSets {
    main.java.srcDirs += [querydslDir]
}

// gradle clean 시에 QClass 디렉토리 삭제
clean {
    delete file(querydslDir)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. &quot;.gitignore&quot; 파일에 추가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa; color: #383a42; text-align: start;&quot;&gt;/src/main/generated/&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;* 발생할 수 있는 오류들 해결&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;1. java.lang.NoClassDefFoundError&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;:javax/persistence/Entity&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;2. attempt to recreate a file for type qclass&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;3. could not find class file for querydsl&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;4. Unable to load class 'javax.persistence.Entity'.&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JPA</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/674</guid>
      <comments>https://series.tistory.com/entry/Springboot-300-%EC%9D%B4%EC%83%81-Querydsl-buildgradle-%EC%84%A4%EC%A0%95-%EB%B0%8F-NoClassDefFoundError-%EC%98%A4%EB%A5%98-%EB%8C%80%EC%9D%91-%EB%B0%A9%EB%B2%95#entry674comment</comments>
      <pubDate>Wed, 16 Aug 2023 20:15:46 +0900</pubDate>
    </item>
    <item>
      <title>JUnit 테스트 시 &amp;quot;Sharing is only supported for boot loader classes because bootstrap classpath has been appended&amp;quot; 경고</title>
      <link>https://series.tistory.com/entry/JUnit-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C-Sharing-is-only-supported-for-boot-loader-classes-because-bootstrap-classpath-has-been-appended-%EA%B2%BD%EA%B3%A0</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;JUnit 테스트 시&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&quot;Sharing is only supported for boot loader classes because bootstrap classpath has been appended&quot; 경고&lt;/h3&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;구글링을 해본 결과를 모두 적용해 봤지만 모두 실패ㅠㅠ&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;1. &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;(실패)&lt;/span&gt;&lt;/b&gt; 인텔리제이 -&amp;gt; Settings - Build, Execution, Deployment -&amp;gt; Debugger -&amp;gt; Async Stack Traces&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 설정 - async 로 검색 -&amp;gt; Async Stack Traces 선택&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;Instrumenting agent (requires debugger restart) 체크박스 해제&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ae2D3/btsrgQxEP0P/wZgf6Ho6tUCIF8M7A5bf11/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ae2D3/btsrgQxEP0P/wZgf6Ho6tUCIF8M7A5bf11/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ae2D3/btsrgQxEP0P/wZgf6Ho6tUCIF8M7A5bf11/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAe2D3%2FbtsrgQxEP0P%2FwZgf6Ho6tUCIF8M7A5bf11%2Fimg.jpg&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;839&quot; height=&quot;342&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;&lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;(실패) &lt;/span&gt;&lt;/b&gt;Run/Debug Configurations -&amp;gt; Modify options -&amp;gt; &quot;optimization&quot; 타이핑 검색&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Disable Launch optimization 체크&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1345&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lxVQG/btsrrSm54R2/IM5bbe0vgkgneFfdPAT7WK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lxVQG/btsrrSm54R2/IM5bbe0vgkgneFfdPAT7WK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lxVQG/btsrrSm54R2/IM5bbe0vgkgneFfdPAT7WK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlxVQG%2FbtsrrSm54R2%2FIM5bbe0vgkgneFfdPAT7WK%2Fimg.jpg&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;1345&quot; height=&quot;486&quot; data-origin-width=&quot;1345&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;(성공!!) &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Run/Debug Configurations -&amp;gt; Edit configuration template -&amp;gt; JUnit -&amp;gt; VM options -&amp;gt; &quot;-Xshre:off&quot; 추가&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;963&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJuu3T/btsrkRpfEKT/kLxkvdkXqy8KspbU645mK0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJuu3T/btsrkRpfEKT/kLxkvdkXqy8KspbU645mK0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJuu3T/btsrkRpfEKT/kLxkvdkXqy8KspbU645mK0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJuu3T%2FbtsrkRpfEKT%2FkLxkvdkXqy8KspbU645mK0%2Fimg.jpg&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;963&quot; height=&quot;752&quot; data-origin-width=&quot;963&quot; data-origin-height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 모든 테스트에서 경고 메시지가 사라졌습니다!!&lt;/p&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/673</guid>
      <comments>https://series.tistory.com/entry/JUnit-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C-Sharing-is-only-supported-for-boot-loader-classes-because-bootstrap-classpath-has-been-appended-%EA%B2%BD%EA%B3%A0#entry673comment</comments>
      <pubDate>Wed, 16 Aug 2023 17:39:01 +0900</pubDate>
    </item>
    <item>
      <title>p6spy 쿼리 로그 - 멀티 라인으로</title>
      <link>https://series.tistory.com/entry/p6spy-%EC%BF%BC%EB%A6%AC-%EB%A1%9C%EA%B7%B8-%EB%A9%80%ED%8B%B0-%EB%9D%BC%EC%9D%B8%EC%9C%BC%EB%A1%9C</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;945&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PLRXB/btr6pFiSCcR/chQQVw6PiOTwS7Ubgn9nn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PLRXB/btr6pFiSCcR/chQQVw6PiOTwS7Ubgn9nn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PLRXB/btr6pFiSCcR/chQQVw6PiOTwS7Ubgn9nn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPLRXB%2Fbtr6pFiSCcR%2FchQQVw6PiOTwS7Ubgn9nn1%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;945&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;945&quot;/&gt;&lt;/span&gt;&lt;/figure&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;config에 2개의 파일 추가&lt;/h3&gt;
&lt;pre id=&quot;code_1679980542308&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.hanssem.remodeling.content.common.config;

import com.p6spy.engine.common.P6Util;
import com.p6spy.engine.logging.Category;
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
import org.hibernate.engine.jdbc.internal.FormatStyle;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Stack;

public class P6spySqlFormatConfiguration implements MessageFormattingStrategy {

    // 표기에 허용되지 않는 filter
    private List&amp;lt;String&amp;gt; DENIED_FILTER = Arrays.asList(&quot;Test1&quot;, this.getClass().getSimpleName());

    // 표기에 허용되는 filter
    private String ALLOW_FILTER = &quot;com.hanssem&quot;;

    @Override
    public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) {

        sql = formatSql(category, sql);
        if (sql.trim().isEmpty()) { // sql 이 없다면 출력하지 않아도 됨
            return &quot;&quot;;
        }

        // stack 을 구성하는 Format을 만든다
        return sql + createStack(connectionId, elapsed);
    }

    private String formatSql(String category,String sql) {

        if (sql ==null || sql.trim().equals(&quot;&quot;)) return sql;

        // Only format Statement, distinguish DDL And DML
        if (Category.STATEMENT.getName().equals(category)) {
            String tmpsql = sql.trim().toLowerCase(Locale.ROOT);
            if (tmpsql.startsWith(&quot;create&quot;) || tmpsql.startsWith(&quot;alter&quot;) || tmpsql.startsWith(&quot;comment&quot;)) {
                sql = FormatStyle.DDL.getFormatter().format(sql);
            } else {
                sql = FormatStyle.BASIC.getFormatter().format(sql);
            }
            sql = &quot;|\nFormatSql(P6Spy sql, Hibernate format):&quot; + sql;
        }

        return sql;
    }

    // stack 콘솔 표기
    private String createStack(int connectionId, long elapsed) {
        Stack&amp;lt;String&amp;gt; callStack = new Stack&amp;lt;&amp;gt;();
        StackTraceElement[] stackTrace = new Throwable().getStackTrace();

        for (StackTraceElement stackTraceElement : stackTrace) {
            String trace = stackTraceElement.toString();

            // trace 항목을 보고 내게 맞는 것만 필터
            if (trace.startsWith(ALLOW_FILTER)) {
                callStack.push(trace);
            }
        }

        StringBuffer sb = new StringBuffer();
        int order = 1;
        while (callStack.size() != 0) {
            sb.append(&quot;\n\t\t&quot; + (order++) + &quot;.&quot; + callStack.pop());
        }

        return new StringBuffer().append(&quot;\n\n\tConnection ID:&quot;).append(connectionId)
                .append(&quot; | Excution Time:&quot;).append(elapsed).append(&quot; ms\n&quot;)
                .append(&quot;\n\tExcution Time:&quot;).append(elapsed).append(&quot; ms\n&quot;)
                .append(&quot;\n\tCall Stack :&quot;).append(sb).append(&quot;\n&quot;)
                .append(&quot;\n--------------------------------------&quot;)
                .toString();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P6spySqlFormatConfiguration.java&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1679980571704&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.hanssem.remodeling.content.common.config;

import com.p6spy.engine.spy.P6SpyOptions;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class P6spyLogMessageFormatConfiguration {

    @PostConstruct
    public void setLogMessageFormat() {
        P6SpyOptions.getActiveInstance().setLogMessageFormat(P6spySqlFormatConfiguration.class.getName());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P6spyLogMessageFormatConfiguration.java&lt;/p&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/672</guid>
      <comments>https://series.tistory.com/entry/p6spy-%EC%BF%BC%EB%A6%AC-%EB%A1%9C%EA%B7%B8-%EB%A9%80%ED%8B%B0-%EB%9D%BC%EC%9D%B8%EC%9C%BC%EB%A1%9C#entry672comment</comments>
      <pubDate>Tue, 28 Mar 2023 14:16:24 +0900</pubDate>
    </item>
    <item>
      <title>IntelliJ 에서 JUnit 테스트 - andExpect jsonPath 오류 시</title>
      <link>https://series.tistory.com/entry/IntelliJ-%EC%97%90%EC%84%9C-JUnit-%ED%85%8C%EC%8A%A4%ED%8A%B8-andExpect-jsonPath-%EC%98%A4%EB%A5%98-%EC%8B%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;수동으로 import 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1679980178324&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1679980237413&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Test
    @DisplayName(&quot;카카오 블로그 테스트&quot;)
    void testKakaoBlog() throws Exception {

        String url = &quot;/api/v1/blog/search/kakao&quot;;

        BlogSearchRequest request = BlogSearchRequest.builder()
                .query(&quot;테스트&quot;)
                .sort(&quot;accuracy&quot;)
                .size(100)
                .page(1)
                .build();

        ResultActions resultActions = mockMvc.perform(
                get(url)
                        .param(&quot;page&quot;, &quot;1&quot;)
                        .param(&quot;size&quot;, &quot;20&quot;)
                        .param(&quot;query&quot;, &quot;테스트&quot;)
                        .param(&quot;sort&quot;, &quot;accuracy&quot;)
        );

        String expectByTitle = &quot;title&quot;;

        // Then
        resultActions
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
//                .andExpect((ResultMatcher) jsonPath(&quot;$[0]&quot;).exists())
//                .andExpect(jsonPath(expectByTitle, &quot;Kyeongho Yoo&quot;).exists())
//                .andExpect(jsonPath(&quot;$.length()&quot;, is(2)))
//                .andExpect(content().json(, &quot;&quot;))
//                .andExpect(jsonPath(&quot;$.data[0].content[0].blogName[0]&quot;, equalTo(&quot;엠오엠&quot;)))
//                .andExpect(jsonPath(&quot;$.nm&quot;, notNullValue())
//                .andExpect(jsonPath(&quot;$.nm&quot;, notNullValue())
//                .andExpect(jsonPath(&quot;$.title&quot;, is(aaa)))
//                .andExpect(jsonPath(new Matcher)))

                .andExpect(jsonPath(&quot;$.content[0].blogName&quot;, is(&quot;엠오엠&quot;)))
                .andExpect(jsonPath(&quot;$.content[1].blogName&quot;, is(&quot;지식센터&quot;)))
                .andExpect(jsonPath(&quot;$.content[1].blogName&quot;, notNullValue()))
                .andDo(print());
    }&lt;/code&gt;&lt;/pre&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/671</guid>
      <comments>https://series.tistory.com/entry/IntelliJ-%EC%97%90%EC%84%9C-JUnit-%ED%85%8C%EC%8A%A4%ED%8A%B8-andExpect-jsonPath-%EC%98%A4%EB%A5%98-%EC%8B%9C#entry671comment</comments>
      <pubDate>Tue, 28 Mar 2023 14:10:51 +0900</pubDate>
    </item>
    <item>
      <title>Webflux - Webclient - header 복수개 적용 방법</title>
      <link>https://series.tistory.com/entry/Webflux-Webclient-header-%EB%B3%B5%EC%88%98%EA%B0%9C-%EC%A0%81%EC%9A%A9-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;pre id=&quot;code_1679980064323&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();

        headers.add(&quot;X-Naver-Client-Id&quot;, clientId);
        headers.add(&quot;X-Naver-Client-Secret&quot;, clientSecret);

        return headers;
    }

    @Bean
    public WebClient kakaoWebClient() {

        return WebClient.builder()
                .baseUrl(baseurl)
                .defaultHeaders((headers -&amp;gt; {headers.addAll(createHeaders());}))
                .build();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/670</guid>
      <comments>https://series.tistory.com/entry/Webflux-Webclient-header-%EB%B3%B5%EC%88%98%EA%B0%9C-%EC%A0%81%EC%9A%A9-%EB%B0%A9%EB%B2%95#entry670comment</comments>
      <pubDate>Tue, 28 Mar 2023 14:07:56 +0900</pubDate>
    </item>
    <item>
      <title>Swagger - enum을 코드로 노출되도록 - @JsonValue 어노테이션</title>
      <link>https://series.tistory.com/entry/Swagger-enum%EC%9D%84-%EC%BD%94%EB%93%9C%EB%A1%9C-%EB%85%B8%EC%B6%9C%EB%90%98%EB%8F%84%EB%A1%9D-JsonValue-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98</link>
      <description>&lt;pre id=&quot;code_1679979786959&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Getter
@NoArgsConstructor
public enum ApiType {

    KAKAO(&quot;kakao&quot;, &quot;카카오&quot;),
    NAVER(&quot;naver&quot;, &quot;네이버&quot;);

    private String code;
    private String name;

    ApiType(String code, String name) {
        this.code = code;
        this.name = name;
    }

    @JsonValue
    public String getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    public static ApiType code(String code){
        switch (code){
            case &quot;kakao&quot; :
                return KAKAO;
            case &quot;naver&quot; :
                return NAVER;
            default:
                return KAKAO;
        }
    }

    @Override
    public String toString() {
        return code;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@JsonValue 어노테이션을 붙여줘야 Swagger에서 code로 나온다.&lt;/p&gt;
&lt;p 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-origin-width=&quot;728&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJDmzL/btr6srRXkWw/tpwN8e9xk09eqUEteVUoQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJDmzL/btr6srRXkWw/tpwN8e9xk09eqUEteVUoQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJDmzL/btr6srRXkWw/tpwN8e9xk09eqUEteVUoQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJDmzL%2Fbtr6srRXkWw%2FtpwN8e9xk09eqUEteVUoQ1%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;728&quot; height=&quot;596&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/669</guid>
      <comments>https://series.tistory.com/entry/Swagger-enum%EC%9D%84-%EC%BD%94%EB%93%9C%EB%A1%9C-%EB%85%B8%EC%B6%9C%EB%90%98%EB%8F%84%EB%A1%9D-JsonValue-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98#entry669comment</comments>
      <pubDate>Tue, 28 Mar 2023 14:04:49 +0900</pubDate>
    </item>
    <item>
      <title>IntelliJ 실행 시 Address already in use: bind 오류가 날 때</title>
      <link>https://series.tistory.com/entry/IntelliJ-%EC%8B%A4%ED%96%89-%EC%8B%9C-Address-already-in-use-bind-%EC%98%A4%EB%A5%98%EA%B0%80-%EB%82%A0-%EB%95%8C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;cmd 관리자 모드 실행 후&lt;/p&gt;
&lt;pre id=&quot;code_1678339385546&quot; class=&quot;dos&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;net stop winnat
net start winnat&lt;/code&gt;&lt;/pre&gt;</description>
      <category>IntelliJ</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/668</guid>
      <comments>https://series.tistory.com/entry/IntelliJ-%EC%8B%A4%ED%96%89-%EC%8B%9C-Address-already-in-use-bind-%EC%98%A4%EB%A5%98%EA%B0%80-%EB%82%A0-%EB%95%8C#entry668comment</comments>
      <pubDate>Thu, 9 Mar 2023 14:23:21 +0900</pubDate>
    </item>
    <item>
      <title>remote 저장소 push할 때 reject 오류 조치방법</title>
      <link>https://series.tistory.com/entry/remote-%EC%A0%80%EC%9E%A5%EC%86%8C-push%ED%95%A0-%EB%95%8C-reject-%EC%98%A4%EB%A5%98-%EC%A1%B0%EC%B9%98%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p 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;1001&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gg2IX/btr2OrmRlEh/P06zgaaMTWxHIRq9fgGMn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gg2IX/btr2OrmRlEh/P06zgaaMTWxHIRq9fgGMn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gg2IX/btr2OrmRlEh/P06zgaaMTWxHIRq9fgGMn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGg2IX%2Fbtr2OrmRlEh%2FP06zgaaMTWxHIRq9fgGMn0%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;1001&quot; height=&quot;494&quot; data-origin-width=&quot;1001&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&quot;push-to-originmaster-was-rejected&quot; data-ke-size=&quot;size23&quot;&gt;Push to origin/master was rejected&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub에서 Readme를 포함시켜 Repository를 생성한 후, 해당 Repository를 remote로 추가하여 push 하니 생긴 오류.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Repository에 Readme파일이 이미 존재하여 생기는 오류&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;b&gt;1. 동기화를 위해 pull&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git pull --rebase origin main&lt;/blockquote&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;b&gt;2. 강제로 push&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git push origin +main&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pull 이전에 발생한 변경사항을 무시(삭제)하고 현재 작업 내용을 강제로 push해도 된다.&lt;br /&gt;이 경우 pull 되지 않은 변경사항은 소실되기 때문에 주의해야 함.&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;나의 경우에는 README를 건드렸던게 중요하지 않았어서 강제로 push했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;(나의 경우는 동기화 pull후 다시 push했다.)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;깃허브에서 확인해보면 해당 README의 변경사항은 사라졌고, 그외 작업내용들은 정상적으로 업로드되었음을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Git</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/667</guid>
      <comments>https://series.tistory.com/entry/remote-%EC%A0%80%EC%9E%A5%EC%86%8C-push%ED%95%A0-%EB%95%8C-reject-%EC%98%A4%EB%A5%98-%EC%A1%B0%EC%B9%98%EB%B0%A9%EB%B2%95#entry667comment</comments>
      <pubDate>Wed, 8 Mar 2023 13:53:03 +0900</pubDate>
    </item>
    <item>
      <title>p6spy 멀티라인 Formatter 적용</title>
      <link>https://series.tistory.com/entry/p6spy-%EB%A9%80%ED%8B%B0%EB%9D%BC%EC%9D%B8-Formatter-%EC%A0%81%EC%9A%A9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. config에 2개의 파일 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;P6spyLogMessageFormatConfiguration.java&lt;/li&gt;
&lt;li&gt;P6spySqlFormatConfiguration.java&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xjTAI/btr2sGUeNCS/PlAzKKcSvJKJy60oGq2nHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xjTAI/btr2sGUeNCS/PlAzKKcSvJKJy60oGq2nHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xjTAI/btr2sGUeNCS/PlAzKKcSvJKJy60oGq2nHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxjTAI%2Fbtr2sGUeNCS%2FPlAzKKcSvJKJy60oGq2nHk%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;402&quot; height=&quot;475&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;475&quot;/&gt;&lt;/span&gt;&lt;/figure&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: #172b4d;&quot;&gt;&lt;b&gt;2.&lt;/b&gt; &lt;/span&gt;&lt;b&gt;P6spySqlFormatConfiguration.java&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173421604&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.hanssem.remodeling.content.common.config;

import com.p6spy.engine.common.P6Util;
import com.p6spy.engine.logging.Category;
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
import org.hibernate.engine.jdbc.internal.FormatStyle;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Stack;

public class P6spySqlFormatConfiguration implements MessageFormattingStrategy {

    // 표기에 허용되지 않는 filter
    private List&amp;lt;String&amp;gt; DENIED_FILTER = Arrays.asList(&quot;Test1&quot;, this.getClass().getSimpleName());

    // 표기에 허용되는 filter
    private String ALLOW_FILTER = &quot;com.hanssem&quot;;

    @Override
    public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) {

        sql = formatSql(category, sql);
        if (sql.trim().isEmpty()) { // sql 이 없다면 출력하지 않아도 됨
            return &quot;&quot;;
        }

        // stack 을 구성하는 Format을 만든다
        return sql + createStack(connectionId, elapsed);
    }

    private String formatSql(String category,String sql) {

        if (sql ==null || sql.trim().equals(&quot;&quot;)) return sql;

        // Only format Statement, distinguish DDL And DML
        if (Category.STATEMENT.getName().equals(category)) {
            String tmpsql = sql.trim().toLowerCase(Locale.ROOT);
            if (tmpsql.startsWith(&quot;create&quot;) || tmpsql.startsWith(&quot;alter&quot;) || tmpsql.startsWith(&quot;comment&quot;)) {
                sql = FormatStyle.DDL.getFormatter().format(sql);
            } else {
                sql = FormatStyle.BASIC.getFormatter().format(sql);
            }
            sql = &quot;|\nFormatSql(P6Spy sql, Hibernate format):&quot; + sql;
        }

        return sql;
    }

    // stack 콘솔 표기
    private String createStack(int connectionId, long elapsed) {
        Stack&amp;lt;String&amp;gt; callStack = new Stack&amp;lt;&amp;gt;();
        StackTraceElement[] stackTrace = new Throwable().getStackTrace();

        for (StackTraceElement stackTraceElement : stackTrace) {
            String trace = stackTraceElement.toString();

            // trace 항목을 보고 내게 맞는 것만 필터
            if (trace.startsWith(ALLOW_FILTER)) {
                callStack.push(trace);
            }
        }

        StringBuffer sb = new StringBuffer();
        int order = 1;
        while (callStack.size() != 0) {
            sb.append(&quot;\n\t\t&quot; + (order++) + &quot;.&quot; + callStack.pop());
        }

        return new StringBuffer().append(&quot;\n\n\tConnection ID:&quot;).append(connectionId)
                .append(&quot; | Excution Time:&quot;).append(elapsed).append(&quot; ms\n&quot;)
                .append(&quot;\n\tExcution Time:&quot;).append(elapsed).append(&quot; ms\n&quot;)
                .append(&quot;\n\tCall Stack :&quot;).append(sb).append(&quot;\n&quot;)
                .append(&quot;\n--------------------------------------&quot;)
                .toString();
    }
}&lt;/code&gt;&lt;/pre&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: #172b4d;&quot;&gt;3. &lt;/span&gt;&lt;b&gt;P6spyLogMessageFormatConfiguration.java&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173434201&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.hanssem.remodeling.content.common.config;

import com.p6spy.engine.spy.P6SpyOptions;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class P6spyLogMessageFormatConfiguration {

    @PostConstruct
    public void setLogMessageFormat() {
        P6SpyOptions.getActiveInstance().setLogMessageFormat(P6spySqlFormatConfiguration.class.getName());
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/666</guid>
      <comments>https://series.tistory.com/entry/p6spy-%EB%A9%80%ED%8B%B0%EB%9D%BC%EC%9D%B8-Formatter-%EC%A0%81%EC%9A%A9#entry666comment</comments>
      <pubDate>Tue, 7 Mar 2023 16:17:22 +0900</pubDate>
    </item>
    <item>
      <title>build.gradle</title>
      <link>https://series.tistory.com/entry/buildgradle</link>
      <description>&lt;h1 id=&quot;[Gradle]&quot; data-renderer-start-pos=&quot;1&quot;&gt;[Gradle]&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Gradle은 일종의 빌드 도구
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 말하는 빌드란 개발한 소프트웨어가 제품으로 만들어지는 일련의 과정&lt;/li&gt;
&lt;li&gt;컴파일, 테스트, 배포, 문서화 등의 작업을 포함하는 절차&lt;/li&gt;
&lt;li&gt;이 때 빌드의 모든 과정을 자동으로 처리할 수 있도록 도와주는 것을 빌드 도구라고 함&lt;/li&gt;
&lt;li&gt;최근 대세는 Gradle&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Groovy, DSL(Domain-Specific Languages, 도메인 특화 언어)
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Gradle은 groovy라는 JVM 기반의 동적 타이핑 언어를 통해 기술된다.&lt;/li&gt;
&lt;li&gt;Gradle은 groovy 문법 자체를 그대로 이용하지는 않고, 그루비 기반의 DSL을 사용&lt;/li&gt;
&lt;li&gt;DSL = 도메인 고유 언어 (기반이 되는 언어에서 파생되어 특정한 용도에 한정되어 각색한 언어)&lt;/li&gt;
&lt;li&gt;Gradle에 사용되는 언어는 그루비를 기반으로 작성된 Gradle DSL&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1 id=&quot;[build.gradle]&quot; data-renderer-start-pos=&quot;446&quot;&gt;[build.gradle]&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;build.gradle은 gradle에서 빌드 작업에 필요한 기본 설정, 동작 등을 정의하는 파일&lt;/li&gt;
&lt;li&gt;build.gradle 파일 자체가 Project 클래스로, Project 인터페이스를 구현하는 구현체&lt;/li&gt;
&lt;li&gt;build.gradle에 작성하는 코드들은 모두 Project 오브젝트의 프로퍼티와 메서드가 되며 Project 오브젝트는 프로젝트 이름, 변수, 메서드를 모두 포함하는 객체가 된다.&lt;/li&gt;
&lt;li&gt;Project 오브젝트는 내부에 수많은 메서드(Methods)와 속성(Properties)을 가지고 있다. 메서드 중에 대표적인 것은 모든 java application용 build.gradle이 가진 plugins, repositories, dependencies, application 메서드이다. 우리가 Gradle Task를 이용해 java application을 빌드하게 되면 build task는 이 메서드들을 수행시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;plugins&quot; data-renderer-start-pos=&quot;935&quot;&gt;plugins&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 컴파일이나 jar 파일의 생성 작업들을 해주는 플러그인 지정&lt;/li&gt;
&lt;li&gt;플러그인에는 빌드에 필요한 과정들을 task로 포함&lt;/li&gt;
&lt;li&gt;빌드 시 필요한 모든 과정을 플러그인의 내부 task가 진행해줌&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;dependencies&quot; data-renderer-start-pos=&quot;1059&quot;&gt;dependencies&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;의존성에 관한 설정을 관리하는 프로퍼티&lt;/li&gt;
&lt;li&gt;프로젝트에서 필요한 라이브러리를 등록&lt;/li&gt;
&lt;li&gt;여기에 필요한 라이브러리 등의 정보를 기술하면 그 라이브러리를 참조할 수 있음&lt;/li&gt;
&lt;li&gt;라이브러리 지정 시 &amp;ldquo;그룹:이름:버전&amp;rdquo; 형태 사용&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;756&quot; data-origin-height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MsaWI/btr2vTSCw2U/KAzHxfV0o1IN59kKnHWK3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MsaWI/btr2vTSCw2U/KAzHxfV0o1IN59kKnHWK3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MsaWI/btr2vTSCw2U/KAzHxfV0o1IN59kKnHWK3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMsaWI%2Fbtr2vTSCw2U%2FKAzHxfV0o1IN59kKnHWK3K%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;756&quot; height=&quot;326&quot; data-origin-width=&quot;756&quot; data-origin-height=&quot;326&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;ext&quot; data-renderer-start-pos=&quot;1205&quot;&gt;ext&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 블록은 gradle의 모든 task에서 사용할 수 있는 일종의 전역 변수를 선언하는 블록&lt;/li&gt;
&lt;li&gt;gradle 에서 지원하는 변수&lt;/li&gt;
&lt;li&gt;이 변수를 이용하여 추가 속성을 정의할 수 있다.&lt;/li&gt;
&lt;li&gt;추가 속성은 모든 모듈에 공유가 가능하다.&lt;/li&gt;
&lt;li&gt;변수선언을 진행한 다음 진행해야 한다.&lt;/li&gt;
&lt;li&gt;프로젝트 전체와 서브 프로젝트에서도 접근 가능하다.&lt;/li&gt;
&lt;li&gt;ext 메소드는 그 인자를 buildScript 에서 전역변수로 사용하기 위해 사용되는 메소드이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1678173306016&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ext.javaVersion = '1.7' // 한개씩 선언
ext {
    // 여러개 한꺼번에 선언
    springVersion = '3.1.0.RELEASE'
    emailNotification = 'build@master.org'
}
 
// 가변 Key, 가변 값 형태로 코드를 통해 프라퍼티를 추가할 때는 아래 방식을 사용한다.
project.ext['keyname'] = 'value'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;def&quot; data-renderer-start-pos=&quot;1692&quot;&gt;def&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변수에 형을 생략할 때 사용&lt;/li&gt;
&lt;li&gt;형 지정을 생략할 때 def 키워드 이용&lt;/li&gt;
&lt;li&gt;def를 지정하는 것은 자바에서 Object 형을 지정한 것과 같음&lt;/li&gt;
&lt;li&gt;gradle 에서 지원하는 지역변수&lt;/li&gt;
&lt;li&gt;해당 스크립트에서만 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1678173319496&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;* 형 생략
String message = 'hi'
def message = 'hi'
Groovy는 def라는 키워드를 이용하여 모든 타입의 변수를 선언할 수 있습니다.
반대로 형을 지정하여 생성하는 방법도 가능합니다. 위 두줄의 코드는 같은 결과를 발생시킵니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;buildscript&quot; data-renderer-start-pos=&quot;1982&quot;&gt;buildscript&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빌드하는 동안 필요한 처리들을 모아놓는 곳&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;sourceSets&quot; data-renderer-start-pos=&quot;2024&quot;&gt;sourceSets&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Gradle에서는 하나의 Source 디렉토리만 지원을 해줌 (src/main/java)&lt;/li&gt;
&lt;li&gt;sourceSets는 이러한 제약사항을 지원하기 위해 사용&lt;/li&gt;
&lt;li&gt;Java 소스와 리소스 파일의 논리적인 그룹&lt;/li&gt;
&lt;li&gt;하나 이상의 Source 디렉토리를 Gradle에서 처리를 하기 위해 sourceSets 에 Source 디렉토리를 등록해주면 된다.&lt;/li&gt;
&lt;li&gt;기본 프로젝트 레이아웃&lt;/li&gt;
&lt;li&gt;통합 테스트를 위한 별도의 소스 디렉토리를 만들 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KPPbA/btr2r5zLwz8/XDmQqdiHcGAmsb1SGbQQFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KPPbA/btr2r5zLwz8/XDmQqdiHcGAmsb1SGbQQFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KPPbA/btr2r5zLwz8/XDmQqdiHcGAmsb1SGbQQFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKPPbA%2Fbtr2r5zLwz8%2FXDmQqdiHcGAmsb1SGbQQFk%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;400&quot; height=&quot;231&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위의 경우 sourceSets 셋팅 (폴더가 새 소스세트의 이름과 일치하면 따로 명시할 필요 없음)&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;131&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbStOB/btr2sG0UDy3/JuWhaVAUBkzWxEYlvknYrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbStOB/btr2sG0UDy3/JuWhaVAUBkzWxEYlvknYrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbStOB/btr2sG0UDy3/JuWhaVAUBkzWxEYlvknYrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbStOB%2Fbtr2sG0UDy3%2FJuWhaVAUBkzWxEYlvknYrK%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;131&quot; height=&quot;132&quot; data-origin-width=&quot;131&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;283&quot; data-origin-height=&quot;147&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z9KL0/btr2xUcCrjE/VL44RZRj5CUgKXbsk0Q8oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z9KL0/btr2xUcCrjE/VL44RZRj5CUgKXbsk0Q8oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z9KL0/btr2xUcCrjE/VL44RZRj5CUgKXbsk0Q8oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz9KL0%2Fbtr2xUcCrjE%2FVL44RZRj5CUgKXbsk0Q8oK%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;283&quot; height=&quot;147&quot; data-origin-width=&quot;283&quot; data-origin-height=&quot;147&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1678173364624&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;**// 1. queryDsl version 정보 추가**
buildscript { **// 빌드 시**
    ext {
        **queryDslVersion = &quot;5.0.0&quot; // 빌드 시 전역변수 설정**
    }
}

plugins {
    id 'org.springframework.boot' version '2.6.3'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    **// 2. querydsl plugins 추가
    id &quot;com.ewerk.gradle.plugins.querydsl&quot; version &quot;1.0.10&quot;**
    id 'java'
}

//...

dependencies { **// 멀티모듈에서 공통으로 사용될 의존성 추가**
    **// 3. querydsl library dependencies 추가
    implementation &quot;com.querydsl:querydsl-jpa:${queryDslVersion}&quot;
    implementation &quot;com.querydsl:querydsl-apt:${queryDslVersion}&quot;**
    //...
}

test {
    useJUnitPlatform()
}

**/*
 * queryDSL 설정 추가
 */
// querydsl에서 사용할 경로 설정
def querydslDir = &quot;$buildDir/generated/querydsl&quot;

// JPA 사용 여부와 사용할 경로를 설정
querydsl {
    jpa = true
    querydslSourcesDir = querydslDir
}

// build 시 사용할 sourceSet 추가
// IDE의 소스 폴더에 자동으로 넣어준다.
// 개발 환경에서 생성된 Q파일들을 사용할 수 있도록 generated 디렉토리를 sourceSet에 추가해주면 개발 코드에서 생성된 Q파일에 접근할 수 있습니다.
sourceSets {
    main.java.srcDir querydslDir
}

// querydsl 컴파일시 사용할 옵션 설정
// Q파일을 생성해준다.
compileQuerydsl{
    options.annotationProcessorPath = configurations.querydsl
}

// querydsl 이 compileClassPath 를 상속하도록 설정
// 컴파일이 될때 같이 수행
configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
    querydsl.extendsFrom compileClasspath
}**&lt;/code&gt;&lt;/pre&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/665</guid>
      <comments>https://series.tistory.com/entry/buildgradle#entry665comment</comments>
      <pubDate>Tue, 7 Mar 2023 16:16:14 +0900</pubDate>
    </item>
    <item>
      <title>JPA (Java Persistence API)</title>
      <link>https://series.tistory.com/entry/JPA-Java-Persistence-API-1</link>
      <description>&lt;h1 id=&quot;JPA-(Java-Persistence-API)&quot; data-renderer-start-pos=&quot;1&quot;&gt;JPA (Java Persistence API)&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h1 id=&quot;ORM&quot; data-renderer-start-pos=&quot;29&quot;&gt;ORM&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ORM (Object-Relational Mapping)&lt;/li&gt;
&lt;li&gt;애플리케이션 Class와 RDB(Relational DataBase)의 테이블을&amp;nbsp;매핑 (연결)&lt;/li&gt;
&lt;li&gt;어플리케이션의 객체를 RDB 테이블에 자동으로 영속화&lt;/li&gt;
&lt;li&gt;객체는 객체대로 설계하고, 관계형 데이터베이스는 관계형 데이터베이스대로 설계한다.&lt;/li&gt;
&lt;li&gt;ORM 프레임워크가 중간에서 매핑해 준다.&lt;/li&gt;
&lt;li&gt;대중적인 언어에는 대부분 ORM 기술이 존재한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;ORM-장점&quot; data-renderer-start-pos=&quot;267&quot;&gt;ORM 장점&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SQL문이 아닌 Method를 통해 DB를 조작할 수 있어, 개발자는 객체 모델을 이용하여 비즈니스 로직을 구성하는데만 집중할 수 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내부적으로는 쿼리를 생성하여 DB를 조작함&lt;/li&gt;
&lt;li&gt;하지만 개발자가 이를 신경 쓰지 않아도 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Query와 같이 필요한 선언문, 할당 등의 부수적인 코드가 줄어들어 각종 객체에 대한 코드를 별도로 작성하여 코드의 가독성을 높임&lt;/li&gt;
&lt;li&gt;객체지향적인 코드 작성이 가능함. 오직 객체지향적 접근만 고려하면 되기때문에 생산성 증가&lt;/li&gt;
&lt;li&gt;매핑하는 정보가 Class로 명시 되었기 때문에 ERD를 보는 의존도를 낮출 수 있고 유지보수 및 리팩토링에 유리&lt;/li&gt;
&lt;li&gt;기존 방식에서 MySQL 데이터베이스를 사용하다가 ORACLE로 변환한다고 가정해보면, 새로 쿼리를 짜야하는 경우가 생김. 이런 경우에 ORM을 사용한다면 쿼리를 수정할 필요가 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;ORM-단점&quot; data-renderer-start-pos=&quot;714&quot;&gt;ORM 단점&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트의 규모가 크고 복잡하여 설계가 잘못된 경우, 속도 저하 및 일관성을 무너뜨리는 문제점이 생길 수 있음&lt;/li&gt;
&lt;li&gt;복잡하고 무거운 Query는 속도를 위해 별도의 튜닝이 필요하기 때문에 결국 SQL문을 써야할 수도 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;ORM과-SQL-Mapper와의-차이점&quot; data-renderer-start-pos=&quot;851&quot;&gt;ORM과 &lt;b&gt;SQL Mapper와의 차이점&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h2 id=&quot;1.-SQL-Mapper&quot; data-renderer-start-pos=&quot;874&quot; data-ke-size=&quot;size26&quot;&gt;1. SQL Mapper&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;myBatis, jdbcTemplate&lt;/li&gt;
&lt;li&gt;SQL을 명시하여 직접 DB 조작&lt;/li&gt;
&lt;li&gt;필드를 매핑시키는 것이 목적&lt;/li&gt;
&lt;li&gt;자바 클래스와 sql을 매핑&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2.-ORM&quot; data-renderer-start-pos=&quot;976&quot; data-ke-size=&quot;size26&quot;&gt;2. ORM&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA, Hibernate&lt;/li&gt;
&lt;li&gt;자바 클래스와 DB 테이블을 매핑&lt;/li&gt;
&lt;li&gt;객체간의 관계를 바탕으로 SQL 자동 생성&lt;/li&gt;
&lt;li&gt;RDB의 관계를 Object 에 반영하는 것이 목적&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;JPA&quot; data-renderer-start-pos=&quot;1085&quot;&gt;JPA&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA(Java Persistence API)&lt;/li&gt;
&lt;li&gt;JPA는 자바 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용되는 인터페이스의 모음&lt;/li&gt;
&lt;li&gt;JPA를 구현한 대표적인 오픈소스로는 Hibernate가 있음&lt;/li&gt;
&lt;li&gt;자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스&lt;/li&gt;
&lt;li&gt;JPA는 API의 규격 인터페이스일 뿐 (라이브러리나 프레임워크가 아님)&lt;/li&gt;
&lt;li&gt;JPA 2.1 표준 명세를 구현한 구현체 : Hibernate, EclipseLink, DataNucleus, OpenJPA, TopLink Essentials 등이 있다. (ORM 프레임워크)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beGd3B/btr2D97O0e9/O7bnANNkX7bMosLBkb0Kw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beGd3B/btr2D97O0e9/O7bnANNkX7bMosLBkb0Kw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beGd3B/btr2D97O0e9/O7bnANNkX7bMosLBkb0Kw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeGd3B%2Fbtr2D97O0e9%2FO7bnANNkX7bMosLBkb0Kw0%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;490&quot; height=&quot;252&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA 는 애플리케이션과 JDBC 사이에서 동작하여 개발자가 JPA 를 사용하면, JPA 내부에서 JDBC API 를 사용하여 SQL 을 호출, DB 와 통신한다.&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;954&quot; data-origin-height=&quot;449&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZiuCP/btr2sYAoBvI/eRg3UYDx5cQeB4nSugcLW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZiuCP/btr2sYAoBvI/eRg3UYDx5cQeB4nSugcLW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZiuCP/btr2sYAoBvI/eRg3UYDx5cQeB4nSugcLW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZiuCP%2Fbtr2sYAoBvI%2FeRg3UYDx5cQeB4nSugcLW1%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;954&quot; height=&quot;449&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;449&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;왜-JPA를-사용해야-할까?&quot; data-renderer-start-pos=&quot;1538&quot;&gt;&lt;b&gt;왜 JPA를 사용해야 할까?&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h3 id=&quot;1.-생산성&quot; data-renderer-start-pos=&quot;1555&quot; data-ke-size=&quot;size23&quot;&gt;1. 생산성&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA를 사용하면 자바 컬렉션에 저장하듯이 JPA에게 저장할 객체를 전달하면 된다.&lt;/li&gt;
&lt;li&gt;지루하고 반복적인 코드를 개발자가 직접 작성하지 않아도 되며, DDL문도 자동으로 생성해주기 때문에 데이터베이스 설계 중심을 객체 설계 중심으로 변경할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2.-유지보수&quot; data-renderer-start-pos=&quot;1709&quot; data-ke-size=&quot;size23&quot;&gt;2. 유지보수&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;필드를 하나만 추가해도 관련된 SQL과 JDBC 코드를 전부 수행해야 했지만 JPA는 이를 대신 처리해주기 때문에 개발자가 유지보수해야하는 코드가 줄어든다.&lt;/li&gt;
&lt;li&gt;SQL을 직접 작성하는 것이 아닌, 객체를 사용하여 동작 -&amp;gt; 재사용성 up&lt;/li&gt;
&lt;li&gt;기존 SQL 방식 : 테이블 필드 변경시 모든 SQL을 수정해야 한다.&lt;/li&gt;
&lt;li&gt;JPA 방식 : Entity 객체에 필드만 추가하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3.-패러다임의-불일치-해결&quot; data-renderer-start-pos=&quot;1936&quot; data-ke-size=&quot;size23&quot;&gt;3. 패러다임의 불일치 해결&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA는 연관된 객체를 사용하는 시점에 SQL을 전달할 수 있고, 같은 트랜잭션 내에서 조회할 때 동일성도 보장하기 때문에 다양한 패러다임의 불일치를 해결한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4.-성능&quot; data-renderer-start-pos=&quot;2048&quot; data-ke-size=&quot;size23&quot;&gt;4. 성능&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애플리케이션과 데이터베이스 사이에서 성능 최적화 기회를 제공한다.&lt;/li&gt;
&lt;li&gt;같은 트랜잭션안에서는 같은 엔티티를 반환하기 때문에 데이터 베이스와의 통신 횟수를 줄일 수 있다.&lt;/li&gt;
&lt;li&gt;트랜잭션을 commit하기 전까지 메모리에 쌓고 한번에 SQL을 전송한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;5.-데이터-접근-추상화와-벤더-독립성&quot; data-renderer-start-pos=&quot;2200&quot; data-ke-size=&quot;size23&quot;&gt;5. 데이터 접근 추상화와 벤더 독립성&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RDB는 같은 기능이라도 벤더마다 사용법이 다르기 때문에 처음 선택한 데이터베이스에 종속되고 변경이 어렵다. JPA는 애플리케이션과 데이터베이스 사이에서 추상화된 데이터 접근을 제공하기 때문에 종속이 되지 않도록한다.&lt;/li&gt;
&lt;li&gt;만약 DB가 변경되더라도 JPA에게 알려주면 간단하게 변경이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;716&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/enIXRW/btr2DDg3qnq/KcXZ29lzoU5n19n0obAKv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/enIXRW/btr2DDg3qnq/KcXZ29lzoU5n19n0obAKv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/enIXRW/btr2DDg3qnq/KcXZ29lzoU5n19n0obAKv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FenIXRW%2Fbtr2DDg3qnq%2FKcXZ29lzoU5n19n0obAKv0%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;716&quot; height=&quot;486&quot; data-origin-width=&quot;716&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;JPA와-객체-그래프-탐색&quot; data-renderer-start-pos=&quot;2398&quot;&gt;JPA와 객체 그래프 탐색&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;2414&quot; data-ke-size=&quot;size16&quot;&gt;신뢰할 수 있는 엔티티, 계층&lt;/p&gt;
&lt;pre id=&quot;code_1678172991677&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MemberService {
	...
    public void process(){
    	// 기존 방식처럼 직접 구현한 DAO에서 객체를 가져온 경우
    	Member member1 = memberDAO.find(memberId);
        member1.getTeam(); // 엔티티를 신뢰할 수 없음
        member1.getOrder().getDelivery();
        
        // JPA를 통해서 객체를 가져온 경우
        Member member2 = jpa.find(Member.class, memberId);
        member2.getTeam(); // 자유로운 객체 그래프 탐색
        member2.getOrder().getDelivery();    
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;내가 아닌 다른 개발자가 직접 구현한 DAO에서 가져오는 경우&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DAO에서 직접 어떤 쿼리를 날렸는지 확인하지 않는 이상, 그래프 형태의 관련된 객체들을 모두 잘 가져왔는지 알 수 가 없다.&lt;/li&gt;
&lt;li&gt;즉, 반환한 엔티티를 신뢰하고 사용할 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JPA를 통해서 가져오는 경우&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체 그래프를 완전히 자유롭게 탐색할 수 있게 된다.&lt;/li&gt;
&lt;li&gt;동일한 트랜잭션에서 조회한 엔티티는 같음을 보장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;JPA의-성능-최적화-기능&quot; data-renderer-start-pos=&quot;3094&quot;&gt;&lt;b&gt;JPA의 성능 최적화 기능&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h2 id=&quot;1.-1차-캐시와-동일성(identity)-보장---캐싱-기능&quot; data-renderer-start-pos=&quot;3110&quot; data-ke-size=&quot;size26&quot;&gt;1. &lt;b&gt;1차 캐시와 동일성(identity) 보장 - 캐싱 기능&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 트랜잭션 안에서는 같은 엔티티를 반환 - 조회 성능 향상&lt;/li&gt;
&lt;li&gt;동일 조건인 경우 쿼리를 2번 실행하지 않고, 캐시에서 읽어들임&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1678173010032&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String memberId = &quot;100&quot;;
Member member1 = jpa.find(Member.class, memberId);  // DB에서 가져옴
Member member2 = jpa.find(Member.class, memberId);  // 1차 캐시에서 가져옴
member1 == member2;  // 같다&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;2.-트랜잭션을-지원하는-쓰기-지연-(transactional-write-behind)---버퍼링-기능&quot; data-renderer-start-pos=&quot;3410&quot; data-ke-size=&quot;size26&quot;&gt;2. &lt;b&gt;트랜잭션을 지원하는 쓰기 지연 (transactional write-behind) - 버퍼링 기능&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-renderer-start-pos=&quot;3469&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1) INSERT&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173021815&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1. 트랜잭션을 커밋할 때까지 INSERT 쿼리를 수행하지 않음
transaction.begin();	// 트랜잭션 시작
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);

// 2. 커밋하는 순간 데이터베이스에 INSERT 쿼리를 일괄 처리한다.
// JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송
transaction.commit();	// 트랜잭션 커밋&lt;/code&gt;&lt;/pre&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;b&gt;(2) UPDATE&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173032815&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1. UPDATE, DELETE로 인한 로우 락(ROW LOCK) 시간 최소화
transaction.begin();	// 트랜잭션 시작
changeMember(memberA);
deleteMember(memberB);

비즈니스_로직_수행();	// 비즈니스 로직 수행하는 동안 DB 로우 락이 걸리지 않는다.

// 커밋하는 순간 데이터베이스에 UPDATE, DELETE 쿼리를 보내고 바로 커밋
transaction.commit();	// 트랜잭션 커밋&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;3.-지연-로딩(Lazy-Loading)&quot; data-renderer-start-pos=&quot;4004&quot; data-ke-size=&quot;size26&quot;&gt;3. &lt;b&gt;지연 로딩(Lazy Loading)&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-renderer-start-pos=&quot;4028&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(a) 지연 로딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;4039&quot; data-ke-size=&quot;size16&quot;&gt;객체가 실제로 사용될 때 로딩하는 전략&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;4039&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;4062&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(b) 즉시 로딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;4073&quot; data-ke-size=&quot;size16&quot;&gt;JOIN 쿼리로 한번에 연관된 객체까지 미리 조회하는 전략&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;4107&quot; data-ke-size=&quot;size16&quot;&gt;어플리케이션 개발시 기본적으로 지연 로딩을 설정한 후 필요한 경우에 즉시 로딩으로 옵션을 변경하는 것을 추천한다.&lt;/p&gt;
&lt;h1 id=&quot;상속-관계&quot; data-renderer-start-pos=&quot;4172&quot;&gt;상속 관계&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JAVA에서는&amp;nbsp;부모클래스와&amp;nbsp;자식클래스의 관계 즉,&amp;nbsp;상속관계가 존재하는데 데이터베이스에서는 이러한 객체의 상속관계를 지원하지 않는다. 이런 상속관계를 JPA는 아래와 같은 방식으로 해결하였다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1381&quot; data-origin-height=&quot;489&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYj32M/btr2FeVllBC/eodkWsJE33AA3QJuF3ymlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYj32M/btr2FeVllBC/eodkWsJE33AA3QJuF3ymlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYj32M/btr2FeVllBC/eodkWsJE33AA3QJuF3ymlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYj32M%2Fbtr2FeVllBC%2FeodkWsJE33AA3QJuF3ymlK%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;1381&quot; height=&quot;489&quot; data-origin-width=&quot;1381&quot; data-origin-height=&quot;489&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;위의 구조에서 만약 Album 클래스를 저장한다고 가정해보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173062403&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Album 객체저장
jpa.persist(album);&lt;/code&gt;&lt;/pre&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: #172b4d;&quot;&gt;그러면 JPA는 위의 코드를 아래의 쿼리로 변환해서 실행한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173072189&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;INSERT INTO ITEM (ID, NAME, PRICE) .....
INSERT INTO ALBUM (ARTIST) .....&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 저장하면 당연히 조회할때도 두 테이블을 엮어서 가져올 것이다. 조회하는 JAVA코드와 변환되는 쿼리를 보도록하자.&lt;/p&gt;
&lt;pre id=&quot;code_1678173083427&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// JAVA 코드
String albumId = &quot;id100&quot;;
Album album = jpa.find(Album.class, albumId);

// 변환된 쿼리
SELECT I.*, A.*
  FROM ITEM I
  JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;연관-관계&quot; data-renderer-start-pos=&quot;4723&quot;&gt;연관 관계&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위와 같이 상속관계에 대한 접근도 제공해주는데 객체지향에는&amp;nbsp;연관관계라는 것도 있다.&lt;/li&gt;
&lt;li&gt;코드로 따지면&amp;nbsp;Class에서 또 다른 Class Type을 필드 변수로 가지고 있는것이다.&lt;/li&gt;
&lt;li&gt;객체관계와 이를 테이블 구조로 나타낸 아래의 그림을 보도록하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;261&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wOUeT/btr2FhkelRi/smcSU3iNKTqvh0jS9AwXV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wOUeT/btr2FhkelRi/smcSU3iNKTqvh0jS9AwXV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wOUeT/btr2FhkelRi/smcSU3iNKTqvh0jS9AwXV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwOUeT%2Fbtr2FhkelRi%2FsmcSU3iNKTqvh0jS9AwXV1%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;440&quot; height=&quot;261&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;261&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;위의 그림은 Member 클래스가 Team 타입의 team 필드 변수를 가지고 있는 형태인데, 코드로 나타내면 아래와 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173112984&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Member {
 String id;
 Team team;
 String username;
}

class Team {
 Long id;
 String name;
}&lt;/code&gt;&lt;/pre&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: #172b4d;&quot;&gt;그렇다면 Team 객체를 참조하는 필드를 가지고 있는 Member 객체는 어떻게 저장할까?&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173123877&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Member member = new Member();
member.setId(&quot;100&quot;);
member.setUsername(&quot;dbjh&quot;);

Team team = new Team();
team.setName(&quot;dev_team&quot;);

member.setTeam(team);
jpa.persist(member);&lt;/code&gt;&lt;/pre&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: #172b4d;&quot;&gt;위처럼 Member 객체의 team 필드에 Team 객체를 set하고 Member 객체를 DB에 저장하게 되면 JPA는 아래와 같은 코드를 데이터베이스에게 실행하라고 할것이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173135247&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;INSERT INTO MEMBER (ID, TEAM_ID, USERNAME) ....
INSERT INTO TEAM (ID, NAME) ....&lt;/code&gt;&lt;/pre&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: #172b4d;&quot;&gt;이렇게 저장 후 Member 객체만 조회하면, Team 객체 정보도 가져와서 Member 객체의 team필드에 주입해주기 때문에 아래와 같이 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678173148140&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// JAVA 코드
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();

// 변환된 쿼리
SELECT M.*, T.*
 FROM MEMBER M
 JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 구조들이 더 복잡해진다고 해도 JPA는 이를 모두 지원해주기 때문에 문제없이 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;JPA의-저장-및-조회는-아래와-같은-구조로-실행&quot; data-renderer-start-pos=&quot;5798&quot;&gt;JPA의 저장 및 조회는 아래와 같은 구조로 실행&lt;/h1&gt;
&lt;pre id=&quot;code_1678173172562&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;**저장** : jpa.persist(member)

**조회** : Member member = jpa.find(memberId)

**수정** : member.setName(&quot;홍길동&quot;)

**삭제** : jpa.remove(member)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;[저장]&quot; data-renderer-start-pos=&quot;5964&quot; data-ke-size=&quot;size26&quot;&gt;[저장]&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-renderer-start-pos=&quot;5970&quot; data-ke-size=&quot;size16&quot;&gt;MemberDAO에서 객체를 저장하고 싶을 때 개발자는 JPA에 Member 객체를 넘기면 JPA는 아래와 같이 동작한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Member 엔티티를 분석한다.&lt;/li&gt;
&lt;li&gt;INSERT SQL을 생성한다.&lt;/li&gt;
&lt;li&gt;JDBC API를 사용하여 SQL을 DB 에 날린다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1187&quot; data-origin-height=&quot;605&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZThSv/btr2DCWI7wz/ut0Nxdq8ULyZLbQoZGVMJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZThSv/btr2DCWI7wz/ut0Nxdq8ULyZLbQoZGVMJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZThSv/btr2DCWI7wz/ut0Nxdq8ULyZLbQoZGVMJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZThSv%2Fbtr2DCWI7wz%2Fut0Nxdq8ULyZLbQoZGVMJK%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;1187&quot; height=&quot;605&quot; data-origin-width=&quot;1187&quot; data-origin-height=&quot;605&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;[조회]&quot; data-renderer-start-pos=&quot;6122&quot; data-ke-size=&quot;size26&quot;&gt;[조회]&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-renderer-start-pos=&quot;6128&quot; data-ke-size=&quot;size16&quot;&gt;Member 객체를 조회하고 싶을 때 개발자는 member의 pk 값을 JPA에 넘긴다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엔티티의 매핑 정보를 바탕으로 적절한 SELECT SQL을 생성한다.&lt;/li&gt;
&lt;li&gt;JDBC API를 사용하여 SQL을 DB에 날린다.&lt;/li&gt;
&lt;li&gt;DB로 부터 결과를 받아온다.&lt;/li&gt;
&lt;li&gt;결과(ResultSet)를 객체에 매핑한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-renderer-start-pos=&quot;6303&quot; data-ke-size=&quot;size16&quot;&gt;쿼리를 JPA가 만들어 주기 때문에 Object와 RDB간의 패러다임 불일치를 해결 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1181&quot; data-origin-height=&quot;590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kR4uL/btr2tCRk5Zx/663aBJ6fY2d6MshCfNtm81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kR4uL/btr2tCRk5Zx/663aBJ6fY2d6MshCfNtm81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kR4uL/btr2tCRk5Zx/663aBJ6fY2d6MshCfNtm81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkR4uL%2Fbtr2tCRk5Zx%2F663aBJ6fY2d6MshCfNtm81%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;1181&quot; height=&quot;590&quot; data-origin-width=&quot;1181&quot; data-origin-height=&quot;590&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;[수정]&quot; data-renderer-start-pos=&quot;6364&quot; data-ke-size=&quot;size26&quot;&gt;[수정]&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA는 데이터 수정시, 매핑된 객체(테이블 데이터)를 조회해서 값을 변경 후 커밋하면 DB 서버에 UPDATE 문을 전송하여 UPDATE를 실행&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>JPA</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/664</guid>
      <comments>https://series.tistory.com/entry/JPA-Java-Persistence-API-1#entry664comment</comments>
      <pubDate>Tue, 7 Mar 2023 16:13:32 +0900</pubDate>
    </item>
    <item>
      <title>Querydsl 스터디</title>
      <link>https://series.tistory.com/entry/Querydsl-%EC%8A%A4%ED%84%B0%EB%94%94</link>
      <description>&lt;h1 id=&quot;1.-참고-페이지&quot; data-renderer-start-pos=&quot;1&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot; data-renderer-mark=&quot;true&quot; data-text-custom-color=&quot;#6554c0&quot;&gt;1. 참고 페이지&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h1 id=&quot;Querydsl-공식-사이트&quot; data-renderer-start-pos=&quot;12&quot;&gt;&lt;b&gt;Querydsl 공식 사이트&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;29&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-inline-card=&quot;true&quot; data-card-url=&quot;http://querydsl.com/&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span data-testid=&quot;hover-card-trigger-wrapper&quot;&gt;&lt;a href=&quot;http://querydsl.com/&quot; data-testid=&quot;inline-card-resolved-view&quot;&gt;&lt;span data-testid=&quot;inline-card-icon-and-title&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span data-testid=&quot;inline-card-icon-and-title-default&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Querydsl - Unified Queries for Java&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h1 id=&quot;Querydsl-Reference-Guide&quot; data-renderer-start-pos=&quot;33&quot;&gt;&lt;b&gt;Querydsl Reference Guide&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;59&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-inline-card=&quot;true&quot; data-card-url=&quot;http://querydsl.com/static/querydsl/5.0.0/reference/html_single/&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span data-testid=&quot;hover-card-trigger-wrapper&quot;&gt;&lt;a href=&quot;http://querydsl.com/static/querydsl/5.0.0/reference/html_single/&quot; data-testid=&quot;inline-card-resolved-view&quot;&gt;&lt;span data-testid=&quot;inline-card-icon-and-title&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span data-testid=&quot;inline-card-icon-and-title-default&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Querydsl Reference Guide&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h1 id=&quot;Querydsl-5.0.0-API&quot; data-renderer-start-pos=&quot;63&quot;&gt;&lt;b&gt;Querydsl 5.0.0 API&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;83&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-inline-card=&quot;true&quot; data-card-url=&quot;http://querydsl.com/static/querydsl/5.0.0/apidocs/&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span data-testid=&quot;hover-card-trigger-wrapper&quot;&gt;&lt;a href=&quot;http://querydsl.com/static/querydsl/5.0.0/apidocs/&quot; data-testid=&quot;inline-card-resolved-view&quot;&gt;&lt;span data-testid=&quot;inline-card-icon-and-title&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span data-testid=&quot;inline-card-icon-and-title-default&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Querydsl 5.0.0 API&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h1 id=&quot;Querydsl-관련-소스&quot; data-renderer-start-pos=&quot;87&quot;&gt;&lt;b&gt;Querydsl 관련 소스&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;103&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-inline-card=&quot;true&quot; data-card-url=&quot;https://github.com/lcalmsky/querydsl&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span data-testid=&quot;hover-card-trigger-wrapper&quot;&gt;&lt;a href=&quot;https://github.com/lcalmsky/querydsl&quot; data-testid=&quot;inline-card-resolved-view&quot;&gt;&lt;span data-testid=&quot;inline-card-icon-and-title&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;GitHub - lcalmsky/querydsl&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;103&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;103&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;2.-Querydsl-특징&quot; data-renderer-start-pos=&quot;111&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot; data-renderer-mark=&quot;true&quot; data-text-custom-color=&quot;#6554c0&quot;&gt;2. Querydsl 특징&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h1 id=&quot;(1)-Querydsl의-특징&quot; data-renderer-start-pos=&quot;127&quot;&gt;&lt;b&gt;(1) Querydsl의 특징&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;145&quot; data-ke-size=&quot;size16&quot;&gt;Spring Data JPA가 기본적으로 제공해주는 CRUD 메서드 및 쿼리 메서드 기능을 사용하더라도, 원하는 조건의 데이터를 수집하기 위해서는 필연적으로 JPQL을 작성하게 됩니다. 간단한 로직을 작성하는데 큰 문제는 없으나, 복잡한 로직의 경우 개행이 포함된 쿼리 문자열이 상당히 길어집니다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;313&quot; data-ke-size=&quot;size16&quot;&gt;JPQL 문자열에 오타 혹은 문법적인 오류가 존재하는 경우, 정적 쿼리라면 어플리케이션 로딩 시점에 이를 발견할 수 있으나 그 외는 런타임 시점에서 에러가 발생합니다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;408&quot; data-ke-size=&quot;size16&quot;&gt;이러한 문제를 어느 정도 해소하는데 기여하는 프레임워크가 바로&amp;nbsp;&lt;b&gt;QueryDSL&lt;/b&gt;입니다. QueryDSL은 정적 타입을 이용해서 SQL 등의 쿼리를 생성해주는 오픈소스 프레임워크입니다.&lt;/p&gt;
&lt;h1 id=&quot;(2)-QueryDSL의-장점&quot; data-renderer-start-pos=&quot;511&quot;&gt;&lt;b&gt;(2) QueryDSL의 장점&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자가 아닌 코드로 쿼리를 작성함으로써, 컴파일 시점에 문법 오류를 쉽게 확인할 수 있다.&lt;/li&gt;
&lt;li&gt;자동 완성 등 IDE의 도움을 받을 수 있다.&lt;/li&gt;
&lt;li&gt;동적인 쿼리 작성이 편리하다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;물론 한계가 있어서 통계성 쿼리 등은 natvie 쿼리 등으로 해결해야한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;(3)-Querydsl-작동-방식&quot; data-renderer-start-pos=&quot;724&quot;&gt;&lt;b&gt;(3) Querydsl 작동 방식&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본적으로 QueryDSL은 프로젝트 내의 @Entity 어노테이션을 선언한 클래스를 탐색하고, JPAAnnotationProcessor를 사용해 Q 클래스를 생성합니다.&lt;/li&gt;
&lt;li&gt;querydsl-apt가 @Entity 및 @Id 등의 애너테이션을 알 수 있도록,&amp;nbsp;javax.persistence과&amp;nbsp;javax.annotation을 annotationProcessor에 함께 추가합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;annotationProcessor는 Java 컴파일러 플러그인으로서, 컴파일 단계에서 어노테이션을 분석 및 처리함으로써 추가적인 파일을 생성할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;build 폴더는 gradle에 의해 gitignore 처리된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Qfile 등은 시스템이 자동으로 만들어주는 형태이고, 버전마다 조금씩 달라질 수 있기 때문에 git으로 형상관리를 하지는 않는다.&lt;/li&gt;
&lt;li&gt;혹시나 src/main/generated에 들어가게 된다면, 해당 파일들은 gitignore 해줘야함도 기억하자&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;(4)-Querydsl-관련-라이브러리&quot; data-renderer-start-pos=&quot;1243&quot;&gt;&lt;b&gt;(4) Querydsl 관련 라이브러리&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;div data-layout=&quot;align-start&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;9962121&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;350&quot; data-height=&quot;92&quot; data-id=&quot;d18201a2-9d61-45d1-8430-dc1f057b501e&quot; data-collection=&quot;contentId-9962121&quot; data-file-name=&quot;image-20220928-053408.png&quot; data-file-size=&quot;16504&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div id=&quot;newFileExperienceWrapper&quot; data-testid=&quot;media-card-view&quot;&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;92&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4jpJB/btr2C7QdkUF/yqLoOAAGKaLmq5MEKKGkT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4jpJB/btr2C7QdkUF/yqLoOAAGKaLmq5MEKKGkT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4jpJB/btr2C7QdkUF/yqLoOAAGKaLmq5MEKKGkT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4jpJB%2Fbtr2C7QdkUF%2FyqLoOAAGKaLmq5MEKKGkT1%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;350&quot; height=&quot;92&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;92&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;apt&lt;/b&gt; 라는 부분이 코드 생성과 관련된 라이브러리라고 한다.&lt;/li&gt;
&lt;li&gt;QHello 등의 객체를 만들어주는 역할을 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;core, jpa&lt;/b&gt; 부분은 실제 querydsl의 코드를 작동하게 해주는 selectFrom.fetchOne 등의 작동을 담당하는 라이브러리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;(5)-기타&quot; data-renderer-start-pos=&quot;1420&quot;&gt;&lt;b&gt;(5) 기타&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Querydsl fetchResults(), fetchCount() Deprecated(향후 미지원)
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Querydsl은 향후 fetchCount() , fetchResult() 를 지원하지 않기로 결정했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;3.-Querydsl-설정-방법&quot; data-renderer-start-pos=&quot;1558&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot; data-renderer-mark=&quot;true&quot; data-text-custom-color=&quot;#6554c0&quot;&gt;3. Querydsl 설정 방법&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;1577&quot; data-ke-size=&quot;size16&quot;&gt;공식 문서에는 Gradle에 대한 내용이 누락되어 있으며, 실제로 QueryDSL 설정 방법은 Gradle 및 IntelliJ 버전에 따라 상이&lt;/p&gt;
&lt;h2 id=&quot;(1)-gradle.build&quot; data-renderer-start-pos=&quot;1659&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;(1) gradle.build&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1678172637891&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;**// 1. queryDsl version 정보 추가**
buildscript {
    ext {
        **queryDslVersion = &quot;5.0.0&quot;**
    }
}

plugins {
    id 'org.springframework.boot' version '2.6.3'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    **// 2. querydsl plugins 추가
    id &quot;com.ewerk.gradle.plugins.querydsl&quot; version &quot;1.0.10&quot;**
    id 'java'
}

//...

dependencies {
    **// 3. querydsl library dependencies 추가
    implementation &quot;com.querydsl:querydsl-jpa:${queryDslVersion}&quot;
    implementation &quot;com.querydsl:querydsl-apt:${queryDslVersion}&quot;**
    //...
}

test {
    useJUnitPlatform()
}

**/*
 * queryDSL 설정 추가
 */
// querydsl에서 사용할 경로 설정
def querydslDir = &quot;$buildDir/generated/querydsl&quot;

// JPA 사용 여부와 사용할 경로를 설정
querydsl {
    jpa = true
    querydslSourcesDir = querydslDir
}

// build 시 사용할 sourceSet 추가
// IDE의 소스 폴더에 자동으로 넣어준다.
// 개발 환경에서 생성된 Q파일들을 사용할 수 있도록 generated 디렉토리를 sourceSet에 추가해주면 개발 코드에서 생성된 Q파일에 접근할 수 있습니다.
sourceSets {
    main.java.srcDir querydslDir
}

// querydsl 컴파일시 사용할 옵션 설정
// Q파일을 생성해준다.
compileQuerydsl{
    options.annotationProcessorPath = configurations.querydsl
}

// querydsl 이 compileClassPath 를 상속하도록 설정
// 컴파일이 될때 같이 수행
configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
    querydsl.extendsFrom compileClasspath
}**&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;(2)-compileQuerydsl-실행&quot; data-renderer-start-pos=&quot;2965&quot;&gt;&lt;b&gt;(2) compileQuerydsl 실행&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;2989&quot; data-ke-size=&quot;size16&quot;&gt;Gradle Tasks -&amp;gt; compileQuerydsl 을 실행&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;441&quot; data-origin-height=&quot;610&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpjQYB/btr2ufPnBZY/IUhKrDwqNV1bUXyyn36F91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpjQYB/btr2ufPnBZY/IUhKrDwqNV1bUXyyn36F91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpjQYB/btr2ufPnBZY/IUhKrDwqNV1bUXyyn36F91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpjQYB%2Fbtr2ufPnBZY%2FIUhKrDwqNV1bUXyyn36F91%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;441&quot; height=&quot;610&quot; data-origin-width=&quot;441&quot; data-origin-height=&quot;610&quot;/&gt;&lt;/span&gt;&lt;/figure&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;또는 명령어를 이용하여 Querydsl query type 생성&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;3069&quot; data-ke-size=&quot;size16&quot;&gt;./gradlew clean compileQuerydsl&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;3069&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;3069&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;(3)-Querydsl-Build-결과-확인&quot; data-renderer-start-pos=&quot;3102&quot;&gt;&lt;b&gt;(3) Querydsl Build 결과 확인&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;div data-layout=&quot;align-start&quot; data-width=&quot;75&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;9962121&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;664&quot; data-height=&quot;493&quot; data-id=&quot;f25ce2d2-9bf3-45d6-aa61-0d325493b52c&quot; data-collection=&quot;contentId-9962121&quot; data-file-name=&quot;image-20220928-053641.png&quot; data-file-size=&quot;77533&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div id=&quot;newFileExperienceWrapper&quot; data-testid=&quot;media-card-view&quot;&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkD65q/btr2D4yFXCW/y0h71c0FKVscL05BoCw5g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkD65q/btr2D4yFXCW/y0h71c0FKVscL05BoCw5g1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkD65q/btr2D4yFXCW/y0h71c0FKVscL05BoCw5g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkD65q%2Fbtr2D4yFXCW%2Fy0h71c0FKVscL05BoCw5g1%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;664&quot; height=&quot;493&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;493&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BUILD SUCCESSFUL 을 확인하였다면 build/generated/querydsl 경로에 Project Entity 들의 QClass 가 생성된 것을 확인할 수 있다.&lt;/li&gt;
&lt;li&gt;프로젝트 하위 디렉토리 중&amp;nbsp;build/generated/querydsl 여기 진입하면 아까 생성한&amp;nbsp;Item Entity 가&amp;nbsp;QItem 으로 변해있는 것을 확인할 수 있습니다.&lt;/li&gt;
&lt;li&gt;$projectDir/build/generated&amp;nbsp;디렉토리 하위에 Entity로 등록한 클래스들이 Q라는 접두사가 붙은 형태로 생성되었습니다.&lt;/li&gt;
&lt;li&gt;이러한 클래스들을 Q 클래스 혹은 Q(쿼리) 타입이라고 합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;QueryDSL로 쿼리를 작성할 때, Q 클래스를 사용함으로써 쿼리를 Type-Safe하게 작성할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;git으로 소스 코드를 관리할 땐 반드시 해당 경로를 무시하도록 처리해주셔야 합니다.&lt;/li&gt;
&lt;li&gt;QItem.java 파일을 열어보면&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1678172683821&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package io.lcalmsky.querydsl.domain;

import static com.querydsl.core.types.PathMetadataFactory.*;

import com.querydsl.core.types.dsl.*;

import com.querydsl.core.types.PathMetadata;
import javax.annotation.Generated;
import com.querydsl.core.types.Path;

@Generated(&quot;com.querydsl.codegen.EntitySerializer&quot;)
public class QItem extends EntityPathBase&amp;lt;Item&amp;gt; {

    private static final long serialVersionUID = 1540314452L;

    public static final QItem item = new QItem(&quot;item&quot;);

    public final NumberPath&amp;lt;Long&amp;gt; id = createNumber(&quot;id&quot;, Long.class);

    public QItem(String variable) {
        super(Item.class, forVariable(variable));
    }

    public QItem(Path&amp;lt;? extends Item&amp;gt; path) {
        super(path.getType(), path.getMetadata());
    }

    public QItem(PathMetadata metadata) {
        super(Item.class, metadata);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;(4)-Querydsl-정상-동작-테스트&quot; data-renderer-start-pos=&quot;4438&quot;&gt;&lt;b&gt;(4) Querydsl 정상 동작 테스트&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;4462&quot; data-ke-size=&quot;size16&quot;&gt;그럼&amp;nbsp;Querydsl 을 이용해 정상적으로 쿼리를 수행하는지 확인해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1678172699346&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package io.lcalmsky.querydsl.domain;

import com.querydsl.jpa.impl.JPAQueryFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.persistence.EntityManager;
import org.springframework.transaction.annotation.Transactional;;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
@Transactional
class ItemTest {
    @Autowired
    EntityManager entityManager;

    @Test
    void test() {
        // given
        Item item = new Item();
        entityManager.persist(item);

        // when
        JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager); // (1)
        QItem qItem = new QItem(&quot;i&quot;); // (2)
        Item found = queryFactory.selectFrom(qItem).fetchOne(); // (3)

        // then
        assertEquals(found, item); // (4)
    }
}

(1) JPAQueryFactory를 생성합니다. 이 때 생성자로 EntityManager를 주입해줍니다.
(2) QItem 객체를 생성합니다. 생성자에는 Entity의 alias로 사용할 변수명을 입력합니다.
(3) JPQL을 작성하듯이 자바 코드로 쿼리를 작성합니다.
(4) DB에 저장된 데이터와 다시 조회해 온 데이터가 동일한지 확인합니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 동작했는지 확인하기 위해 아래 설정을 추가해줍니다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;5643&quot; data-ke-size=&quot;size16&quot;&gt;H2 데이터베이스 가 실행되며 테이블을 직접 생성하고 포매팅된&amp;nbsp;SQL&amp;nbsp;로그를 확인할 수 있기 위함입니다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;5643&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1678172710889&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring:
  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        format_sql: true
logging:
  level:
    org.hibernate.SQL: debug&lt;/code&gt;&lt;/pre&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;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1678172725714&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;2021-07-15 19:53:33.992 DEBUG 4334 --- [           main] org.hibernate.SQL                        : 

    create table item (
       id bigint not null,
        primary key (id)
    )
// 생략
2021-07-15 19:53:35.898 DEBUG 4334 --- [           main] org.hibernate.SQL                        : 
    insert 
    into
        item
        (id) 
    values
        (?)
2021-07-15 19:53:35.906 DEBUG 4334 --- [           main] org.hibernate.SQL                        : 
    select
        item0_.id as id1_0_ 
    from
        item item0_&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;(5)-또-다른-예&quot; data-renderer-start-pos=&quot;6663&quot;&gt;&lt;b&gt;(5) 또 다른 예&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;6675&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[ Java 파일 구조 ]&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVlwJd/btr2wurGmrD/J5ay3OVAW3VkmeyFoApF61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVlwJd/btr2wurGmrD/J5ay3OVAW3VkmeyFoApF61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVlwJd/btr2wurGmrD/J5ay3OVAW3VkmeyFoApF61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVlwJd%2Fbtr2wurGmrD%2FJ5ay3OVAW3VkmeyFoApF61%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;603&quot; height=&quot;530&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;/figure&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;b&gt;[ 생성된 Q클래스 구조 ]&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EKmSF/btr2r48A0cR/NEJu2WQEvYZruGs4fr5VC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EKmSF/btr2r48A0cR/NEJu2WQEvYZruGs4fr5VC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EKmSF/btr2r48A0cR/NEJu2WQEvYZruGs4fr5VC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEKmSF%2Fbtr2r48A0cR%2FNEJu2WQEvYZruGs4fr5VC1%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;621&quot; height=&quot;511&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;511&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;(6)-p6spy-추가&quot; data-renderer-start-pos=&quot;6718&quot;&gt;&lt;b&gt;(6) p6spy 추가&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;6732&quot; data-ke-size=&quot;size16&quot;&gt;sql문의 파라미터 출력 및 기타 기능들을 위해서 p6spy 라이브러리를 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1678172755973&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.8'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 data-renderer-start-pos=&quot;6860&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot; data-renderer-mark=&quot;true&quot; data-text-custom-color=&quot;#6554c0&quot;&gt;4. Querydsl 예제&lt;/span&gt;&lt;/b&gt;&lt;/h1&gt;
&lt;pre id=&quot;code_1678172767417&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@DisplayName(&quot;hi 내용을 포함하며 댓글이 1개 이상인 Post를 ID 내림차순으로 조회한다.&quot;)
@Test
void queryDsl_findPostsByMyCriteria_Three() {
    EntityManager entityManager = testEntityManager.getEntityManager();

    JPAQuery&amp;lt;Post&amp;gt; query = new JPAQuery&amp;lt;&amp;gt;(entityManager);
    QPost qPost = new QPost(&quot;p&quot;);

    List&amp;lt;Post&amp;gt; posts = query.from(qPost)
        .where(qPost.content.contains(&quot;hi&quot;)
            .and(qPost.comments.size().gt(0))
        ).orderBy(qPost.id.desc())
        .fetch();

    assertThat(posts).hasSize(3);
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;QueryDSL은 각종 풍부한 체이닝 메서드와 유틸리티 메서드 및 정적 타입(Q 클래스)을 기반으로 직관적으로 쿼리를 작성&lt;/li&gt;
&lt;li&gt;JPQL을 사용해본 독자님이라면 코드가 상당히 직관적임&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;5.-Check-List&quot; data-renderer-start-pos=&quot;7490&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot; data-renderer-mark=&quot;true&quot; data-text-custom-color=&quot;#6554c0&quot;&gt;5. Check List&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h1 id=&quot;(1)-기본-Q-Type-활용&quot; data-renderer-start-pos=&quot;7505&quot;&gt;&lt;b&gt;(1) 기본 Q-Type 활용&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;7523&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[ Q클래스 인스턴스를 사용하는 2가지 방법 ]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678172786715&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;QMember qMember = new QMember(&quot;m&quot;); // 별칭 직접 지정
QMember qMember = QMember.member; // 기본 인스턴스 사용&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;하지만 기본 인스턴스를 static import와 함께 사용하는 것을 권장한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;(2)-결과-조회&quot; data-renderer-start-pos=&quot;7695&quot;&gt;&lt;b&gt;(2) 결과 조회&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fetch&amp;nbsp;: 리스트 조회, 데이터 없으면 빈 리스트 반환&lt;/li&gt;
&lt;li&gt;fetchOne&amp;nbsp;: 단 건 조회
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결과가 없으면 : null&lt;/li&gt;
&lt;li&gt;결과가 둘 이상이면 :&amp;nbsp;com.querydsl.core.NonUniqueResultException&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;fetchFirst&amp;nbsp;: limit(1).fetchOne()&lt;/li&gt;
&lt;li&gt;fetchResults&amp;nbsp;: &lt;span data-renderer-mark=&quot;true&quot;&gt;페이징 정보 포함, total count 쿼리 추가 실행&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;group by having 카운팅에서 해당 메소드가 명확하게 동작하지 않는 이슈가 발생하여 deprecated 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;fetchCount&amp;nbsp;: &lt;span data-renderer-mark=&quot;true&quot;&gt;count 쿼리로 변경해서 count 수 조회&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;group by having 카운팅에서 해당 메소드가 명확하게 동작하지 않는 이슈가 발생하여 deprecated 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;(3)-페이징&quot; data-renderer-start-pos=&quot;8114&quot;&gt;&lt;b&gt;(3) 페이징&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실무에서 페이징 쿼리를 작성할 때, 데이터를 조회하는 쿼리는 여러 테이블을 조인해야 하지만, count 쿼리는 조인이 필요 없는 경우도 있다.&lt;/li&gt;
&lt;li&gt;그런데 이렇게 자동화된 count 쿼리는 원본 쿼리와 같이 모두 조인을 해버리기 때문에 성능이 안나올 수 있다.&lt;/li&gt;
&lt;li&gt;count 쿼리에 조인이 필요없는 성능 최적화가 필요하다면, count 전용 쿼리를 별도로 작성해야 한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>JPA</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/663</guid>
      <comments>https://series.tistory.com/entry/Querydsl-%EC%8A%A4%ED%84%B0%EB%94%94#entry663comment</comments>
      <pubDate>Tue, 7 Mar 2023 16:06:46 +0900</pubDate>
    </item>
    <item>
      <title>OpenSearch Service 설정</title>
      <link>https://series.tistory.com/entry/OpenSearch-Service-%EC%84%A4%EC%A0%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;Cloudwatch Log 구독필터 &amp;rarr; lambda Function &amp;rarr; AWS OpenSearch 로그 수집을 위해서는 OpenSearch에 아래와 같은 설정이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p 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-origin-width=&quot;1742&quot; data-origin-height=&quot;1108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SuDjs/btr2C9gbbSG/GkTgUNreofa8khiUGifH01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SuDjs/btr2C9gbbSG/GkTgUNreofa8khiUGifH01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SuDjs/btr2C9gbbSG/GkTgUNreofa8khiUGifH01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSuDjs%2Fbtr2C9gbbSG%2FGkTgUNreofa8khiUGifH01%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;1742&quot; height=&quot;1108&quot; data-origin-width=&quot;1742&quot; data-origin-height=&quot;1108&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Backend role의 ARN은 lambda 함수의 IAM 역할 ARN이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;오래된-인덱스-자동-삭제-하기&quot; data-renderer-start-pos=&quot;1394&quot; data-ke-size=&quot;size26&quot;&gt;오래된 인덱스 자동 삭제 하기&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-renderer-start-pos=&quot;1412&quot; data-ke-size=&quot;size16&quot;&gt;Index Management &amp;rarr; State Management policies 에서 새로운 policy를 추가해 준다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-renderer-start-pos=&quot;1482&quot; data-ke-size=&quot;size16&quot;&gt;policy를 생성하고 특정 index pattern을 검색하여 자동으로 해당 policy를 적용해 준다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;1544&quot; data-ke-size=&quot;size16&quot;&gt;index의 상태(state)를 변경해 주고, 상태(state)에따라 명령을 실행하는 방식&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;최근-7일치-index만-보관할-경우&quot; data-renderer-start-pos=&quot;1597&quot; data-ke-size=&quot;size23&quot;&gt;최근 7일치 index만 보관할 경우&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-renderer-start-pos=&quot;1619&quot; data-ke-size=&quot;size16&quot;&gt;index는 날짜별로 생성된다고 가정한다(cwl-YYYY.mm.dd 형식).&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;1663&quot; data-ke-size=&quot;size16&quot;&gt;아래의 경우 정책(policy)의 이름은 &amp;ldquo;delete_old_indices_7d&amp;rdquo;이다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;1663&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1678172394395&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    &quot;policy&quot;: {
        &quot;policy_id&quot;: &quot;delete_old_indices_7d&quot;,
        &quot;description&quot;: &quot;A policy that delete old 7 days.&quot;,
        &quot;last_updated_time&quot;: 1668408892087,
        &quot;schema_version&quot;: 14,
        &quot;error_notification&quot;: null,
        &quot;default_state&quot;: &quot;hot_state&quot;,
        &quot;states&quot;: [
            {
                &quot;name&quot;: &quot;hot_state&quot;,
                &quot;actions&quot;: [],
                &quot;transitions&quot;: [
                    {
                        &quot;state_name&quot;: &quot;delete&quot;,
                        &quot;conditions&quot;: {
                            &quot;min_index_age&quot;: &quot;7d&quot;
                        }
                    }
                ]
            },
            {
                &quot;name&quot;: &quot;delete&quot;,
                &quot;actions&quot;: [
                    {
                        &quot;retry&quot;: {
                            &quot;count&quot;: 3,
                            &quot;backoff&quot;: &quot;exponential&quot;,
                            &quot;delay&quot;: &quot;1m&quot;
                        },
                        &quot;delete&quot;: {}
                    }
                ],
                &quot;transitions&quot;: []
            }
        ],
        &quot;ism_template&quot;: [
            {
                &quot;index_patterns&quot;: [
                    &quot;cwl-*&quot;
                ],
                &quot;priority&quot;: 100,
                &quot;last_updated_time&quot;: 1639009244056
            }
        ]
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>AWS</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/662</guid>
      <comments>https://series.tistory.com/entry/OpenSearch-Service-%EC%84%A4%EC%A0%95#entry662comment</comments>
      <pubDate>Tue, 7 Mar 2023 16:00:06 +0900</pubDate>
    </item>
    <item>
      <title>EKS 배포 롤백 방법</title>
      <link>https://series.tistory.com/entry/EKS-%EB%B0%B0%ED%8F%AC-%EB%A1%A4%EB%B0%B1-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;이미 배포된 pod에 오류가 발생하여 롤백하여야 할 경우가 있을텐데, EKS는 배포 history기능을 통해 특정 revision으로 롤백할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;배포-히스토리-보기&quot; data-renderer-start-pos=&quot;90&quot;&gt;배포 히스토리 보기&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;102&quot; data-ke-size=&quot;size16&quot;&gt;배포 히스토리는 deployment 단위로 볼 수 있다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;102&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1678172064678&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;]$ kubectl -n backend rollout history deploy backend-api-template-deployment
deployment.apps/backend-api-template-deployment
REVISION  CHANGE-CAUSE
15        [2022-12-26 11:12:18] backend-api-template:dev-73
16        [2022-12-26 11:25:59] backend-api-template:dev-74
17        [2022-12-26 11:37:21] backend-api-template:dev-75
18        [2022-12-28 19:02:14] backend-api-template:dev-76
19        [2023-01-03 07:49:41] backend-api-template:dev-77
20        [2023-01-03 08:45:55] backend-api-template:dev-78
21        [2023-01-04 10:55:50] backend-api-template:dev-79
22        [2023-01-04 11:13:08] backend-api-template:dev-80
23        [2023-01-05 15:33:44] backend-api-template:dev-81
24        [2023-01-06 11:47:46] backend-api-template:dev-82
25        [2023-01-06 14:40:16] backend-api-template:dev-83

]$&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;명령어는 &lt;/span&gt;kubectl -n {namespace 이름} rollout history deploy {deployment 이름}&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt; 의 형식입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;kubectl -n remodeling-backend는 kb로 alias 되어 있습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;배포-히스토리의-내용&quot; data-renderer-start-pos=&quot;1092&quot;&gt;배포 히스토리의 내용&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;1105&quot; data-ke-size=&quot;size16&quot;&gt;위의 배포 히스토리의 내용 형식은 kubernetes 가 자동으로 만들어 주는것이 아닙니다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;1158&quot; data-ke-size=&quot;size16&quot;&gt;히스토리 내용은 아래의 명령어로 배포시에 적재가 가능합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1678172151222&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;]$ kubectl --namespace=$NAMESPACE annotate deployment $IMAGE_REPO_NAME-deployment kubernetes.io/change-cause=&quot;[$DATE] $IMAGE_REPO_NAME:$SPRING_PROFILES_ACTIVE-$CODEBUILD_BUILD_NUMBER&quot; --overwrite=true&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;위 내용은 AWS CodeBuild 할때 참조하여 실행하는 &lt;/span&gt;buildspec.yml&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;의 맨 마지막 줄에 적용되어 있습니다.&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;배포-롤백&quot; data-renderer-start-pos=&quot;1464&quot;&gt;배포 롤백&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;1471&quot; data-ke-size=&quot;size16&quot;&gt;롤백시에는 위 히스토리 보기 기능을 이용하여 REVISION을 확인 후 원하는 REVISION 번호로 롤백 하면 됩니다.&lt;br /&gt;롤백 명령어는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1678172172374&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;]$ kubectl -n backend rollout undo deploy backend-api-deployment --to-revision=24&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;명령어는 &lt;/span&gt;kubectl -n {namespace 이름} rolloute undo deploy {deployment 이름} --to-revision={revision 번호}&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;의 형식 입니다.&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;현재-적용된-리비전-확인&quot; data-renderer-start-pos=&quot;1779&quot;&gt;현재 적용된 리비전 확인&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;1794&quot; data-ke-size=&quot;size16&quot;&gt;배포 상세 정보와 배포 히스토리를 비교하여, 현재 적용된 버전을 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1678172191073&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;]$ kubectl -n backend describe deployment.apps backend-api-template-deployment&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678172197324&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[ec2-user@ip-10-204-*** ~]$ kubectl -n backend describe deployment.apps backend-api-template-deployment | grep -A 2 Environment
    Environment:
      DATE:        2023-02-24 16:46:05
      DOCKER_TAG:  dev-101&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;기타&quot; data-renderer-start-pos=&quot;2161&quot;&gt;기타&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h3 id=&quot;ArgoCD와-같은-WebUI-툴을-사용하지-않는-이유는-무엇입니까?&quot; data-renderer-start-pos=&quot;2165&quot; data-ke-size=&quot;size23&quot;&gt;ArgoCD와 같은 WebUI 툴을 사용하지 않는 이유는 무엇입니까?&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-renderer-start-pos=&quot;2205&quot; data-ke-size=&quot;size16&quot;&gt;관리상의 이슈 입니다. 현재 리모델링 프로젝트는 AWS의 리소스를 사용하고 있고, 가능한 AWS에서 제공하는 자원만으로 운영하고 있습니다. ArgoCD는 개별적으로 설치해서 써야 해서 아직 적용하고 있지 않습니다.&lt;/p&gt;</description>
      <category>AWS</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/661</guid>
      <comments>https://series.tistory.com/entry/EKS-%EB%B0%B0%ED%8F%AC-%EB%A1%A4%EB%B0%B1-%EB%B0%A9%EB%B2%95#entry661comment</comments>
      <pubDate>Tue, 7 Mar 2023 15:56:51 +0900</pubDate>
    </item>
    <item>
      <title>JWT Postman 가이드</title>
      <link>https://series.tistory.com/entry/JWT-Postman-%EA%B0%80%EC%9D%B4%EB%93%9C-1</link>
      <description>&lt;h1 data-renderer-start-pos=&quot;2&quot;&gt;인증서 이슈&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;EKS API의 경우, API콜 할때 인증서를 셋팅해야 한다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;46&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같은 인증서 관련 에러 발생시&lt;/p&gt;
&lt;div data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;454&quot; data-height=&quot;294&quot; data-id=&quot;e926f437-1699-4e2f-a2d5-0f08e4d81793&quot; data-collection=&quot;contentId-156403273&quot; data-file-name=&quot;스크린샷 2023-03-06 오전 11.47.49.png&quot; data-file-size=&quot;57284&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot; data-context-id=&quot;156403273&quot;&gt;
&lt;div id=&quot;newFileExperienceWrapper&quot; data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;스크린샷 2023-03-06 오전 11.47.49.png&quot; data-test-progress=&quot;1&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eqLtxf/btr2CuYUTLd/JzfdpJssWpk21Zb4yD2jsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eqLtxf/btr2CuYUTLd/JzfdpJssWpk21Zb4yD2jsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eqLtxf/btr2CuYUTLd/JzfdpJssWpk21Zb4yD2jsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeqLtxf%2Fbtr2CuYUTLd%2FJzfdpJssWpk21Zb4yD2jsK%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;908&quot; height=&quot;588&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;방안1] 단순히 ssl 기능 disable&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;2479&quot; data-origin-height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQkESu/btr2tCRiuyj/cfhB0n6KkKI9MYJrIZLKbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQkESu/btr2tCRiuyj/cfhB0n6KkKI9MYJrIZLKbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQkESu/btr2tCRiuyj/cfhB0n6KkKI9MYJrIZLKbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQkESu%2Fbtr2tCRiuyj%2FcfhB0n6KkKI9MYJrIZLKbK%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;2479&quot; height=&quot;471&quot; data-origin-width=&quot;2479&quot; data-origin-height=&quot;471&quot;/&gt;&lt;/span&gt;&lt;/figure&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: #172b4d;&quot;&gt;방안2] 인증서 등록&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;1438&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTLL8s/btr2sWJkcBb/6Ma5W1ukpGXNHF2URjgMhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTLL8s/btr2sWJkcBb/6Ma5W1ukpGXNHF2URjgMhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTLL8s/btr2sWJkcBb/6Ma5W1ukpGXNHF2URjgMhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTLL8s%2Fbtr2sWJkcBb%2F6Ma5W1ukpGXNHF2URjgMhk%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;1438&quot; height=&quot;438&quot; data-origin-width=&quot;1438&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;JWT-토큰-셋팅&quot; data-renderer-start-pos=&quot;122&quot;&gt;JWT 토큰 셋팅&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-renderer-start-pos=&quot;133&quot; data-ke-size=&quot;size16&quot;&gt;방법1] Authorization 설정&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2479&quot; data-origin-height=&quot;461&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bilOti/btr2tDQcbdH/7zelB2pQBIxmmkDTvdvLk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bilOti/btr2tDQcbdH/7zelB2pQBIxmmkDTvdvLk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bilOti/btr2tDQcbdH/7zelB2pQBIxmmkDTvdvLk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbilOti%2Fbtr2tDQcbdH%2F7zelB2pQBIxmmkDTvdvLk0%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;2479&quot; height=&quot;461&quot; data-origin-width=&quot;2479&quot; data-origin-height=&quot;461&quot;/&gt;&lt;/span&gt;&lt;/figure&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: #172b4d;&quot;&gt;방법2] 헤더 직접 셋팅&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #172b4d;&quot;&gt;Authorization 필드에 &amp;ldquo;Bearer {TOKEN}&amp;rdquo; 으로 셋팅&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;2479&quot; data-origin-height=&quot;712&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SLDHs/btr2xS6SYhk/gk9wfhX7gD1AjCxrtrA5rK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SLDHs/btr2xS6SYhk/gk9wfhX7gD1AjCxrtrA5rK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SLDHs/btr2xS6SYhk/gk9wfhX7gD1AjCxrtrA5rK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSLDHs%2Fbtr2xS6SYhk%2Fgk9wfhX7gD1AjCxrtrA5rK%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;2479&quot; height=&quot;712&quot; data-origin-width=&quot;2479&quot; data-origin-height=&quot;712&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>SpringBoot</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/660</guid>
      <comments>https://series.tistory.com/entry/JWT-Postman-%EA%B0%80%EC%9D%B4%EB%93%9C-1#entry660comment</comments>
      <pubDate>Tue, 7 Mar 2023 15:48:21 +0900</pubDate>
    </item>
    <item>
      <title>AWS command 정리 (kubectl)</title>
      <link>https://series.tistory.com/entry/AWS-command-%EC%A0%95%EB%A6%AC-kubectl</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://kubernetes.io/docs/reference/kubectl/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kubernetes.io/docs/reference/kubectl/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1678171342391&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Command line tool (kubectl)&quot; data-og-description=&quot;Production-Grade Container Orchestration&quot; data-og-host=&quot;kubernetes.io&quot; data-og-source-url=&quot;https://kubernetes.io/docs/reference/kubectl/&quot; data-og-url=&quot;https://kubernetes.io/docs/reference/kubectl/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bXJXKa/hyRRP5Pbf7/d7XJgkx2ItZclMTdFrCa90/img.png?width=1727&amp;amp;height=373&amp;amp;face=0_0_1727_373,https://scrap.kakaocdn.net/dn/bKZSZ2/hyRQp1ZYTe/YpvQ5SMzNT23HHPWOFonX1/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://kubernetes.io/docs/reference/kubectl/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kubernetes.io/docs/reference/kubectl/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bXJXKa/hyRRP5Pbf7/d7XJgkx2ItZclMTdFrCa90/img.png?width=1727&amp;amp;height=373&amp;amp;face=0_0_1727_373,https://scrap.kakaocdn.net/dn/bKZSZ2/hyRQp1ZYTe/YpvQ5SMzNT23HHPWOFonX1/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Command line tool (kubectl)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Production-Grade Container Orchestration&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kubernetes.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;기본&quot; data-renderer-start-pos=&quot;18&quot;&gt;기본&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;pre id=&quot;code_1678173913818&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl -n {NAME_SPACE} {COMMAND} {TYPE} {NAME}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-renderer-start-pos=&quot;75&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;목록-조회&quot; data-renderer-start-pos=&quot;77&quot;&gt;목록 조회&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubectl -n backend get {TYPE}
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DEV namespace 정보 모두 조회(pod, deployment, service, cluster 등.
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubctl -n backend get all&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DEV POD 조회.
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubctl -n backend get pod&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DEV deployment 조회.
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubctl -n backend get delpoy&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;상세-조회&quot; data-renderer-start-pos=&quot;361&quot;&gt;상세 조회&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;목록에서 조회된 항목의 상세 조회
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubectl -n backend describe {TYPE} {NAME}&lt;/li&gt;
&lt;li&gt;DEV namepsace의 특정 pod 조회
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubectl -n backend describe pod backend-api-common-deployment-67647bc77f-hncw6&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DEV namespace의 특정 deployment 조회
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubectl -n backend describe deploy backend-api-common-deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-renderer-start-pos=&quot;689&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;EKS-API-서버-주소-조회&quot; data-renderer-start-pos=&quot;691&quot;&gt;EKS API 서버 주소 조회&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubectl cluster-info&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-renderer-start-pos=&quot;735&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;EKS-인증서-조회&quot; data-renderer-start-pos=&quot;737&quot;&gt;EKS 인증서 조회&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubectl config view --minify --raw --output 'jsonpath={..cluster.certificate-authority-data}' | base64 -d&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-renderer-start-pos=&quot;860&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;EKS-JWT-토큰-조회&quot; data-renderer-start-pos=&quot;862&quot;&gt;EKS JWT 토큰 조회&lt;/h1&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;pre id=&quot;code_1678171464725&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get serviceaccount&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JWT 토큰 조회&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1678171494942&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get secret $(kubectl get sa {서비스계정} \
    -ojsonpath=&quot;{.secrets[0].name}&quot;) \
    -ojsonpath=&quot;{.data.token}&quot; | base64 -d&lt;/code&gt;&lt;/pre&gt;</description>
      <category>AWS</category>
      <author>RichLegend</author>
      <guid isPermaLink="true">https://series.tistory.com/658</guid>
      <comments>https://series.tistory.com/entry/AWS-command-%EC%A0%95%EB%A6%AC-kubectl#entry658comment</comments>
      <pubDate>Tue, 7 Mar 2023 15:45:09 +0900</pubDate>
    </item>
  </channel>
</rss>