LIGHT
IT 2026. 6. 12. 21:39

티스토리 블로그 꽃단장 가이드 및 이슈 노트(w/ Claude Design)

Tistory 커스텀 스킨 제작 가이드

— 디자인 시안부터 실서비스 적용까지, 삽질 기록과 해결법

대상 독자: HTML/CSS/JS 기본기가 있는 1~3년차 개발자.
이 문서는 실제로 블로그(hyos.blog) 스킨을 디자인 시안부터 만들어 Tistory에 적용하면서
겪은 이슈와 해결 과정을 정리한 것입니다.


0. 전체 흐름 요약

1) HTML/CSS로 디자인 시안 제작 (홈 + 상세 2종)
2) 시안을 Tistory 스킨(skin.html) 구조로 변환
3) 치환자(템플릿 변수) 적용 → 업로드 → 깨지는 부분 디버깅 (대부분의 시간이 여기)
4) JS 폴백/정규화 레이어 추가로 마무리

핵심 교훈을 먼저 말하면:

  • Tistory 치환자는 문서대로 동작하지 않는 경우가 많다. 변수가 빈값으로 치환되거나, 아예 치환되지 않고 텍스트가 그대로 남기도 한다.
  • 그래서 최종 구조는 "치환자 우선 + JS 폴백"의 2중 구조가 됐다. 서버가 제대로 렌더하면 그대로 쓰고, 실패하면 JS가 DOM/RSS/모바일 페이지에서 데이터를 긁어와 채운다.
  • Tistory가 주입하는 기본 스타일과 싸우려면 !important가 생각보다 자주 필요하다.

1. 스킨 파일 구조

Tistory 스킨은 최소 두 파일이다.

파일 역할
skin.html 페이지 전체 구조. 치환자 포함
style.css 스타일 (skin.html 안에 <style>로 넣어도 동작함)

우리는 관리 편의상 skin.html 하나에 CSS/JS를 전부 인라인으로 넣었다.
업로드는 블로그 관리 → 꾸미기 → 스킨 편집 → html 편집에서 한다.

페이지 1장으로 모든 화면을 처리한다

Tistory는 홈/카테고리/태그/검색/글상세가 전부 같은 skin.html로 렌더링된다.
<s_list>(목록)와 <s_article_rep>(글)을 같은 파일에 두고, 현재 페이지 타입에 따라
Tistory가 알아서 한쪽만 채워준다. 우리는 여기에 더해 JS로 상세/목록 레이아웃을 토글했다.


2. 치환자(템플릿 변수) 기초

치환자는 형태이고, 반복/조건 블록은 <s_블록명>...</s_블록명> 태그다.

<s_list>                          <!-- 목록 페이지에서만 렌더 -->
  <s_list_rep>                    <!-- 글 개수만큼 반복 -->
    <a href=""></a>
  </s_list_rep>
</s_list>

중요한 규칙: 변수는 지정된 블록 안에서만 치환된다.
블록 밖에 변수를 쓰면 치환되지 않고 raw 텍스트가 그대로 노출된다. (아래 이슈 4 참고)


3. 겪은 이슈와 해결법

이슈 1 — 홈 목록에서 글 전문이 다 보임

증상: 홈 화면 카드에 미리보기 2줄이 아니라 본문 전체가 출력됨.

원인: 목록에서 본문 변수를 그대로 쓰면 전문이 들어온다.

해결: CSS line-clamp로 강제 제한. Tistory가 어떤 HTML을 넣어주든 2줄로 자른다.

.preview{
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
}
/* 본문 안의 어떤 태그가 와도 스타일 통일 */
.preview *{
  font-size:14px !important;
  margin:0 !important;
  background:none !important;
}

포인트: 미리보기 안에는 <p>, <h2>, <figure> 등 무엇이든 들어올 수 있으므로
* 셀렉터 + !important로 전부 평탄화해야 한다.

이슈 2 — 상세 페이지와 목록 페이지 구분

증상: "마지막 페이지에 글이 1개만 있으면 상세 페이지로 보임."

원인(우리 실수): 처음에 "카드가 1개면 상세"라는 휴리스틱으로 판별했다.
목록 페이지의 마지막 페이지에 글이 1개 남자 상세로 오인.

해결: Tistory 공식 변수 tt-body-index를 사용한다.

<body id="b" class="tt-body-index">

렌더되면 tt-body-index(홈), tt-body-page(글 상세), tt-body-category,
tt-body-tag, tt-body-search 같은 클래스가 붙는다.

var bodyCls = document.body.className || '';
var isDetail;
if (/tt-body-/.test(bodyCls)) {
  isDetail = /tt-body-page(\s|$)/.test(bodyCls);   // 정식 판별
} else {
  isDetail = cards.length === 1;                    // 변수 미처리 시 폴백
}

교훈: 휴리스틱을 쓰더라도 항상 "정식 방법 우선, 휴리스틱은 폴백"으로 겹쳐라.

이슈 3 — 다크모드 토글이 페이지 판별을 깨뜨림

증상: 다크모드를 켜면 상세 페이지 레이아웃이 풀림.

원인: 토글 코드가 body.className = 'dk'로 클래스를 통째로 덮어써서
tt-body-page 클래스가 날아갔다.

해결: classList.toggle 사용.

// BAD
document.body.className = dk ? 'dk' : '';
// GOOD
document.body.classList.toggle('dk', dk);

사소해 보이지만 실제로 한참 헤맨 버그. 남의 플랫폼 위에서는 body/root 요소의
클래스를 절대 통째로 덮어쓰지 말 것.

이슈 4 — 태그가 절대 안 나옴 (최대 난관)

증상: 글 하단 태그 영역이 항상 빈값. , 등
어떤 변수를 써도 안 나옴.

원인이 3겹이었다:

  1. 블록 누락: 태그 변수는 반드시 <s_tag_label> 블록 안에 있어야 치환된다.

    <s_tag_label>
      <div class="atags"></div>
    </s_tag_label>

    블록 없이 변수만 쓰면 영원히 빈값/raw 텍스트.

  2. 길이 필터에 걸림: JS 정리 로직에서 "50자 넘는 태그는 쓰레기값"으로 버렸는데,
    실제로는 사용자가 태그 입력란에 NLP #자연어처리 #프롬프트엔지니어링 #...처럼
    #로 이어 적은 80자짜리 태그 1개가 등록되어 있었다. 통째로 필터에 걸려 0개가 됨.

  3. 입력 방식 자체의 문제: Tistory 에디터 하단 태그 입력란에서는
    태그 하나 입력 후 엔터로 구분해야 개별 태그가 된다.
    #로 이어 적으면 전부 한 덩어리 태그로 저장되고, /tag/ 검색도 덩어리째로만 잡힌다.

해결:

// '#'로 이어 적은 멀티 태그를 분리해서 개별 칩으로 표시
var add = function (t) {
  t = (t || '').trim();
  if (!t) return;
  if (t.indexOf('#') > 0 || /^#.+#/.test(t)) {
    t.split('#').forEach(function (p) {
      p = p.trim();
      if (p && !seen[p] && p.length <= 80) { seen[p] = 1; tagSet.push(p); }
    });
    return;
  }
  t = t.replace(/^#/, '');
  if (!t || seen[t] || t.length > 80) return;
  seen[t] = 1; tagSet.push(t);
};

교훈:

  • 변수가 안 나오면 먼저 해당 변수의 필수 블록(<s_...>)을 확인하라.
  • "데이터가 안 온다"고 단정하기 전에 내 필터 로직이 데이터를 버리고 있는지 의심하라.
  • 디버깅할 땐 기존(잘 동작하는) 스킨의 렌더 결과 HTML을 직접 까보는 게 가장 빠르다.
    개발자도구에서 동작하는 스킨의 태그 영역 HTML을 복사해 비교하면서 원인을 찾았다.

이슈 5 — 사이드바 태그 클라우드의 반복 단위

증상: <s_random_tags>로 감싼 TAGS 섹션이 뜨긴 뜨는데 구조가 깨지거나,
섹션 제목까지 태그 개수만큼 복제됨.

원인: <s_random_tags>는 반복 블록이다. 섹션 전체를 감싸면 섹션이 통째로 반복된다.

<!-- BAD: 섹션 전체가 태그 수만큼 반복됨 -->
<s_random_tags>
  <div class="ss">
    <h3>TAGS</h3>
    <div class="tc"><a href=""></a></div>
  </div>
</s_random_tags>

<!-- GOOD: 반복시킬 <a> 하나만 감싼다 -->
<div class="ss">
  <h3>TAGS</h3>
  <div class="tc">
    <s_random_tags><a href=""></a></s_random_tags>
  </div>
</div>

교훈: <s_..._rep> 류 블록을 만나면 "이 블록의 반복 단위가 무엇인가"를 먼저 정하라.

이슈 6 — 페이지네이션 링크가 href= 로 깨짐

증상: 페이지 번호를 누르면 https://blog.com/href= 같은 이상한 URL로 이동.

원인: 는 URL이 아니라 href="..." 속성 전체를 출력하는
변수다. href="[##_...]"처럼 감싸면 href="href=..."로 깨진다.

<!-- BAD -->
<a href=""></a>
<!-- GOOD -->
<a ></a>

교훈: 치환자마다 출력 형식(URL만 vs 속성 전체)이 다르다. 깨지면
렌더된 HTML을 개발자도구로 열어 변수가 뭘 뱉었는지 확인하는 게 정답.

이슈 7 — ‹ › 버튼이 없는 페이지로 이동

증상: 이전/다음 화살표를 누르면 "없는 페이지" 에러.

해결: 서버 변수에 의존하지 않고 JS로 페이지네이션을 재구성했다.

  1. 서버가 렌더한 번호 링크에서 현재 페이지(href 없는 번호), 전체 페이지 수, URL 패턴을 수집
  2. ‹ 1 … 4 5 6 … 23 › 형태로 다시 그림 (현재 ±2 윈도우 + 첫/끝 + 줄임표)
  3. 첫 페이지의 ‹, 마지막 페이지의 ›는 pointer-events:none + 흐림 처리
var win = 2, lo = Math.max(1, cur - win), hi = Math.min(total, cur + win);
var pages = [1];
if (lo > 2) pages.push('…');
for (var i = lo; i <= hi; i++) { if (i > 1 && i < total) pages.push(i); }
if (hi < total - 1) pages.push('…');
if (total > 1) pages.push(total);

이슈 8 — 댓글 수가 항상 0

증상: 목록 카드의 댓글 카운트 변수가 4종
(rp_cnt, comment_count, comment_cnt, reply_cnt) 전부 빈값/0.

해결: RSS 폴백. Tistory RSS(/rss)의 각 <item>에는 댓글 수가 들어있다.

fetch('/rss').then(r => r.text()).then(xml => {
  var doc = new DOMParser().parseFromString(xml, 'text/xml');
  doc.querySelectorAll('item').forEach(it => {
    var link = it.querySelector('link').textContent;
    var slash = it.getElementsByTagNameNS(
      'http://purl.org/rss/1.0/modules/slash/', 'comments')[0];
    var cnt = slash ? parseInt(slash.textContent, 10) : 0;
    // link의 pathname으로 카드와 매칭해서 카운트 표시
  });
});

같은 도메인이라 CORS 문제 없음. 단, RSS 공개 설정(블로그 관리 → 콘텐츠)이 켜져 있어야 하고
RSS에 노출되는 글 수 제한이 있다는 점은 감안할 것.

이슈 9 — 신형 댓글/프로필은 React 마운트 방식

증상: 댓글 영역이 아예 비어 있음. 직접 <form>을 그려도 동작 안 함.

원인: 최신 Tistory는 댓글·프로필 카드를 React 앱으로 클라이언트에서 마운트한다.
스킨은 마운트 포인트만 제공해야 한다.

<div data-tistory-react-app="Comment"></div>

이 div를 두면 Tistory 스크립트가 댓글 목록+입력창을 통째로 렌더해준다.
디자인 통일은 마운트된 DOM을 CSS로 덮는 방식으로 처리:

#hyos-cmt [class*="tt_"] { font-family:'Noto Sans KR',sans-serif !important; }

주의: React가 비동기로 마운트되므로, 관련 DOM을 읽는 JS는
setTimeout 재시도(예: 0ms / 800ms / 2500ms)를 걸어야 한다.

이슈 10 — 첨부파일 영역 깨짐 + 확장자 아이콘

증상: <s_attachment> 영역이 Tistory 기본 스타일과 충돌해 깨짐.

해결:

  1. 파일명에서 확장자를 JS로 파싱해 data-ext 속성 부여
  2. 확장자별 색상 칩(PDF=빨강, HWP=파랑, XLS=초록...)을 CSS로 표시
  3. Tistory가 background를 덮어써서 칩 색상에 !important 필수였다
.file-ext-ico[data-ext="pdf"]{ background:#c0392b !important; color:#fff !important; }
.file-ext-ico[data-ext="hwp"]{ background:#2e6ab0 !important; color:#fff !important; }

이슈 11 — 본문 표(table)가 안 보임

증상: 에디터에서 만든 표가 본문에서 투명/무스타일로 렌더됨.

원인: 에디터는 <table data-ke-align="..."> 형태로 저장하는데, 스킨 CSS에
table 스타일이 전혀 없었고 리셋 CSS가 보더를 다 지워버렸다.

해결: 본문 영역(.pe) 한정으로 table 스타일을 명시.

.pe table{border-collapse:collapse;width:100%;margin:20px 0;}
.pe th,.pe td{border:1px solid var(--bd);padding:10px 14px;text-align:left;}
.pe thead th{background:var(--tb);font-weight:600;}

교훈: 본문에는 에디터가 생성하는 모든 마크업(표, 인용, 코드, 이미지 캡션...)이
들어올 수 있다. 스킨 만들 때 에디터로 온갖 요소를 넣은 테스트 글을 하나 만들어두면
디버깅이 훨씬 빨라진다.


4. 최종 아키텍처: "치환자 우선 + JS 폴백"

여러 이슈를 거치며 정착한 패턴. 모든 동적 데이터에 동일하게 적용했다.

┌─ 1순위: Tistory 치환자가 정상 렌더 → 그대로 사용
├─ 2순위: DOM에 남은 흔적(미처리 변수, 링크 등)을 JS로 정규화
├─ 3순위: 다른 소스에서 페치 (RSS, 모바일 페이지 /m/...)
└─ 실패: 해당 섹션을 깔끔하게 숨김 (빈 껍데기 노출 금지)

체크 코드 패턴:

var raw = el.innerHTML || '';
if (/\[##_/.test(raw)) {
  // 치환자가 처리되지 않음 → 폴백 또는 숨김
}

[##_ 문자열이 남아있으면 변수 미처리라는 뜻이다. 이 체크 하나로
"raw 변수 텍스트가 사용자에게 노출되는" 최악의 상황을 방지할 수 있다.


5. 디버깅 워크플로우 (시간 아끼는 법)

  1. 개발자도구 → Elements가 진실이다. 스킨 코드가 아니라 렌더된 결과를 봐라.
    변수가 뭘로 치환됐는지, 빈값인지, raw로 남았는지 바로 보인다.
  2. console.log를 스킨 JS에 심어라. 우리는 [hyos] 접두사로 통일해서
    [hyos] 태그 추출 결과: [] 처럼 각 폴백 단계의 결과를 찍었다.
  3. 잘 동작하는 다른 스킨과 비교하라. 같은 블로그에 기본 스킨을 잠깐 적용해보고
    해당 영역의 렌더 HTML을 복사해두면, 내 스킨에서 뭐가 다른지 즉시 비교된다.
  4. 테스트용 글을 만들어라. 표, 코드블록, 이미지, 첨부파일, 태그 여러 개,
    댓글 있는 글 — 전부 들어간 글 하나면 회귀 테스트가 된다.
  5. 스킨 저장 후 강력 새로고침(Ctrl+Shift+R). Tistory는 캐시가 꽤 끈질기다.

6. 치환자 빠른 참조 (이번에 실제로 쓴 것들)

치환자 / 블록 용도 함정
tt-body-index 페이지 타입 (tt-body-page 등) body class에 넣고 classList로만 조작
<s_list> / <s_list_rep> 글 목록 / 반복 반복 단위에 주의
<s_article_rep> 글 상세
<s_tag_label> + 글 태그 블록 필수. 변수 단독으론 절대 안 나옴
<s_random_tags> + 사이드바 태그 클라우드 반복 블록임 — <a> 하나만 감싸기
페이지 링크 href= 포함 속성 전체 출력. href="..."로 감싸면 깨짐
<s_attachment> 첨부파일 Tistory 기본 스타일과 충돌 → !important
data-tistory-react-app="Comment" 댓글 (신형) React 비동기 마운트. JS 재시도 필요
/rss 댓글 수 폴백 slash:comments 네임스페이스 파싱
/m/{글번호} 모바일 렌더 페이지 태그 등 데이터 폴백 소스로 활용 가능

7. 마지막 조언

  • 처음부터 Tistory 구조에 맞춰 디자인하지 마라. 순수 HTML 시안을 먼저 완성하고
    (디자인 의사결정이 자유로움), 그 다음 스킨으로 이식하는 편이 결과물이 훨씬 좋다.
  • 이식은 한 섹션씩. 헤더 → 목록 → 상세 → 사이드바 → 댓글 순으로 하나씩 옮기고
    매번 업로드해서 확인해라. 한 번에 다 옮기면 어디서 깨졌는지 못 찾는다.
  • 플랫폼과 싸우지 말고 폴백을 쌓아라. 치환자가 안 먹는 건 흔한 일이다.
    "정식 방법 → 정규화 → 대체 소스 → 숨김"의 사다리를 만들면 어떤 상황에도 깨지지 않는다.

행운을 빕니다. 🛠

h

hyos

IT · 스타트업 · 개인기록. 만들고, 실패하고, 기록합니다.

공부/AI-POT 2026. 6. 12. 18:09

AI-POT 2급 자격증 공부(AI자연어처리_NLP_프롬프트구조화_패턴)

AI는 "배가 고파요"를 어떻게 알아들을까? NLP 4단계와 프롬프트 패턴 완전 정리

"불 좀 꺼줘"라고 하면 AI는 어떻게 '전등을 끄라'는 뜻으로 알아들을까요? 반대로 "배가 고파요"의 '배'를 엉뚱하게 '선박'으로 이해하는 실수는 왜 생길까요? 그 비밀은 AI가 인간의 말을 처리하는 NLP(자연어 처리) 에 있습니다. 이 글에서는 NLP 4단계부터 효과적인 프롬프트 구조화 기법, 그리고 꼭 알아야 할 프롬프트 패턴과 안티패턴까지 한 번에 정리합니다.


AI가 사람 말을 알아듣는 4단계 — NLP

AI는 우리의 문장을 한 번에 '느낌'으로 이해하지 않습니다. 네 단계를 차근차근 거쳐요. 이게 바로 NLP(Natural Language Processing, 자연어 처리) 이고, 시험에서도 단골입니다.

형태소 분석 → 구문 분석 → 의미 분석 → 화용 분석

단계 하는 일 비유
① 형태소 분석 문장을 명사·조사·형용사로 쪼갬 레고를 조각으로 분해
② 구문 분석 쪼갠 조각을 주어·목적어로 분류 문장의 뼈대 세우기
③ 의미 분석 단어가 문맥상 무슨 뜻인지 해석 '배'가 신체? 과일? 선박?
④ 화용 분석 의미를 합쳐 숨겨진 의도 파악 "불 꺼줘" → 전등 끄기

이 4단계를 알면 AI의 '실수'도 어디서 났는지 보입니다.

🧐 "배가 고파요"의 '배'를 선박으로 이해한 오류 → ③ 의미 분석 실패
🟢 "불 좀 꺼줘"를 듣고 전등을 끄는 행동 → ④ 화용 분석이 제대로 작동한 사례

🔑 핵심 구분: 의미 분석 = 단어 뜻 / 화용 분석 = 문장 속 숨은 의도


같은 부탁도 다르게 — 프롬프트 구조화 기법

NLP를 이해했다면, 이제 AI가 헷갈리지 않게 잘 묻는 방법이 보입니다. '벚꽃 축제 보고서 써줘' 같은 밋밋한 프롬프트도 다음 기법들로 확 달라져요.

기법 내용
순차적 지시 한 프롬프트에 1번·2번… 여러 단계를 한 번에 입력
제약 조건 명시 날짜·장소·분량·형식을 구체적으로 → AI가 딴 길로 새는 것 방지
문맥 제공 배경·목적·추가 자료를 줘서 이해를 도움
예시 활용 제로샷·원샷처럼 예시를 곁들임
형식 최적화 마크다운·JSON·템플릿으로 형식 지정

💡 답변 분량을 단어 수·문단 수로 제한하고 싶다면? 가장 효과적인 건 제약 조건 명시입니다.
💡 그리고 프롬프트에 샵(#) 기호가 보인다면, 그건 마크다운(Markdown) 형식이에요.


잘 쓰는 법 — 프롬프트 4대 패턴

효과적인 프롬프트에는 정형화된 '패턴'이 있습니다. 네 가지만 기억하세요.

패턴 핵심 예시
페르소나 설정 AI에게 역할·인격 부여 "넌 이솝 우화 속 현명한 거북이야"
CoT (생각의 사슬) 여러 단계로 차근차근 사고 "단계별로 생각해서…"
Few-shot 예시를 들어줌 답변 샘플 2~3개 제공
Zero-shot 예시 없이 자체 판단 바로 질문만

🔑 "예시를 전혀 주지 않고 AI가 알아서 판단하게 하는 기법"이라면? 정답은 제로샷(Zero-shot).


이렇게 쓰면 망한다 — 안티패턴

반대로, AI를 헷갈리게 하거나 위험하게 만드는 '나쁜 습관'도 있습니다. 이걸 안티패턴이라고 해요.

안티패턴 무엇이 문제인가
모호한 지시 여러 요청을 뒤섞어 알아듣기 어려움
과도한 복잡성 너무 복잡해 AI가 혼란
비현실적 기대 AI가 못 하는 걸 요구
프롬프트 주입 악의적 명령을 몰래 삽입
토큰 낭비 쓸데없는 말로 한도 초과
컨텍스트 창 오버플로 답이 너무 길어 중간에 끊김
맥락 부재 회사·목적 없이 "자기소개서 써줘"
윤리적 경계 위반 부적절·불법 요청

⚠️ 기출 포인트: "웹사이트 보안을 우회하는 방법을 알려줘" → 명백한 윤리적 경계 위반.
⚠️ 여러 요청을 섞고 배경도 없는 대화 → 모호한 지시 + 맥락 부재.


한 걸음 더 — 1급 고급 패턴

복잡한 과제일수록 프롬프트를 더 정교하게 짜야 합니다. 1급에서 다루는 고급 기법들이에요.

① 트리약 분해 프롬프트 — 복잡한 사고를 여러 단계로 쪼개 해결시킵니다.

과제 → 조사 → 통찰 → 분석 → 결론

예를 들어 여행 가이드를 만들 때 *"각 관광지별 소요 시간·혼잡도·이동 거리를 고려한 최적의 방문 순서를 분석하라"* 는 요청은 이 중 분석 단계에 해당합니다.

② 전문가 역할 패턴 — AI에게 특정 분야 전문가를 맡깁니다.

패턴 핵심
엘리트 패턴 "넌 이 분야 최고 전문가야" + 프레임워크·관점 지정
청중 설정 패턴 "초보자에게 설명하듯 논리적 흐름으로"
코더 패턴 시니어 코드 리뷰어 역할 + 3관점(버그·엣지케이스·성능 최적화) 분석

💡 결국 프롬프트 엔지니어링은 AI와의 협업 설계도입니다. 의도가 명확한지, 맥락이 충분한지, 제약 조건이 잘 작동하는지 점검하는 게 핵심이에요.


마치며

오늘 내용을 한 문장으로 정리하면 이렇습니다.

AI는 우리 말을 형태소→구문→의미→화용 4단계로 분석한다. 이 과정을 이해하면, 좋은 패턴은 살리고 안티패턴은 피하는 '잘 묻는 법'이 보인다.

AI가 어떻게 듣는지를 알면, 어떻게 말해야 할지도 자연스럽게 따라옵니다. NLP 4단계부터 머릿속에 그려두세요.


📇 핵심만 빠르게 — 한 줄 암기 카드

  • NLP 4단계: 형태소 → 구문 → 의미 → 화용
  • '배'를 선박으로 오해 → 의미 분석 실패 / "불 꺼줘"→전등 → 화용 분석
  • 분량·범위 제한 → 제약 조건 명시 / 샵(#) → 마크다운
  • 패턴: 페르소나(역할)·CoT(단계 사고)·Few-shot(예시O)·Zero-shot(예시X)
  • 안티패턴: 모호·복잡·비현실·주입·토큰낭비·오버플로·맥락부재·윤리위반
  • "보안 우회 방법 알려줘" → 윤리적 경계 위반
  • 1급: 트리약(과제·조사·통찰·분석·결론) / 코더=시니어 리뷰어+3관점

이 글이 도움이 되셨다면 공감과 댓글 부탁드려요. AI 개념 정리 시리즈, 다음 편에서 계속됩니다! 🙌

h

hyos

IT · 스타트업 · 개인기록. 만들고, 실패하고, 기록합니다.

공부/AI-POT 2026. 6. 12. 17:16

AI-POT 2급 자격증 공부(프롬프트엔지니어링_개념_구성요소_역사)

같은 AI인데 왜 결과가 다를까? 프롬프트 엔지니어링 개념·구성요소·역사 완전 정리

똑같은 ChatGPT에 누군가는 두루뭉술한 답을 받고, 누군가는 곧바로 써먹을 결과물을 뽑아냅니다. 차이는 AI가 아니라 '질문하는 법' 에 있어요. 이것을 체계화한 기술이 바로 프롬프트 엔지니어링입니다. 이 글에서는 프롬프트 엔지니어링의 정의부터 시험 단골인 5대 구성요소, 좋은 프롬프트의 조건, 그리고 CoT·제로샷·퓨샷이라는 핵심 기법까지 한 번에 정리합니다.


프롬프트 엔지니어링이 뭔가요?

거창해 보이지만 핵심은 단순합니다.

프롬프트 엔지니어링 = AI와 효과적으로 소통하기 위해 입력(프롬프트)을 최적화하는 기술이자, 원하는 출력을 얻기 위한 체계적인 설계 방법

한마디로 자연어(우리가 쓰는 말)로 AI의 성능을 최대한 끌어내는 기법이에요. 코딩으로 AI를 뜯어고치는 게 아니라, '어떻게 말을 거느냐'로 결과를 바꾸는 거죠. 그래서 이걸 잘하는 사람을 프롬프트 엔지니어라고 부르고, 이들은 질문과 지시문을 체계적으로 설계하고 테스트합니다.


시험 단골 — 프롬프트 5대 구성요소

이 부분은 출제 확률이 매우 높습니다. 좋은 프롬프트 하나에는 다음 다섯 가지가 담겨 있어요.

구성 요소 무엇인가 예시
지시(Instruction) AI에게 시키려는 일 "설명해라", "요약해라"
맥락(Context) AI가 알아야 할 배경 정보 상황·목적 설명
입력(Input) 추가로 첨부하는 자료 코드, 텍스트, 엑셀 시트
제약 조건(Constraints) 결과물에서 반드시 지킬 규칙 글자 수, 형식, 문체
출력 형식(Output Format) 원하는 결과의 구조·형태 표, 목록, JSON 등

🔑 통째로 외우세요: 지시 · 맥락 · 입력 · 제약 조건 · 출력 형식

이 다섯 개를 챙겨서 쓰면 AI는 헷갈릴 일이 줄고, 우리는 불필요한 재질문 없이 원하는 결과에 한 번에 가까워집니다. 실제로 프롬프트 엔지니어링의 효과가 바로 이거예요 — 활용 효율 극대화, 정확도·품질 향상, 반복 감소, 리소스 절약.

💡 실무에서 가장 중요한 건? 명확한 지시 + 구체적인 제약 조건입니다.


좋은 프롬프트의 조건 — 그리고 흔한 함정

좋은 프롬프트에는 네 가지 특성이 있습니다.

명확성 · 구조화 · 맥락성 · 목적성

분명하게(명확성), 짜임새 있게(구조화), 배경을 충분히(맥락성), 목표가 또렷하게(목적성). 그런데 여기서 사람들이 자주 틀리는 함정이 있어요.

⚠️ '복잡성'은 좋은 프롬프트의 특징이 아닙니다. 프롬프트가 복잡할수록 좋은 게 아니라, 오히려 AI를 혼란스럽게 만듭니다.

하나 더. 프롬프트 엔지니어링의 목표를 묻는 문제에서 "AI 내부 작동 메커니즘을 직접 수정한다" 는 보기가 나오면 함정입니다. 그건 개발자의 영역이지 프롬프트 엔지니어링이 아니에요.


어디서 시작됐나 — CoT·제로샷·퓨샷

생성형 AI의 역사가 짧다 보니 프롬프트 엔지니어링의 역사도 짧습니다. '기초 확립기'에 등장한 세 가지 핵심 기법만 알면 됩니다.

기법 핵심 한 줄 설명
생각의 사슬(CoT) 단계별 사고 AI가 생각을 사슬처럼 엮어 차근차근 풀게 유도
제로샷(Zero-shot) 예시 0개 예시 없이 AI 자체 성능으로 답하게 함
퓨샷(Few-shot) 예시 2개+ 여러 예시를 줘서 그 특징·자료를 따라 결과를 만들게 함

특히 CoT(Chain of Thought) 는 단골 출제 포인트예요.

📌 2022년 구글 연구진이 논문으로 발표한, 단계별 사고로 정확도를 높이는 기법 = CoT(생각의 사슬)


한 걸음 더 — 1급에서 보는 패러다임과 역량

조금 더 깊이 들어가면, 프롬프트는 단순한 질문이 아니라 인간과 AI가 협업하는 '설계도' 로 봅니다. 이 관점에서 핵심 패러다임은 세 가지예요.

의도 명확화 · 맥락 제공 · 제약 균형화

그리고 한때 '미래 기술'로 불렸지만 이제는 현실이 된 것들 — 프롬프트 자동 최적화, 다중 에이전트 프롬프팅, 개인화 프롬프트 템플릿도 알아두면 좋습니다.

마지막으로 프롬프트 엔지니어에게 요구되는 5대 핵심 역량입니다.

역량 의미
전략적 사고 큰 그림 설계
분석적 평가 결과 분석·판단
효과적 실행 실제 적용
역할적 이해 AI 역할 부여 이해
언어적 명확성 모호함 제거 + 의도를 분명히 전달

🔑 "모호함을 제거하고 의도를 명확히 전달하는 역량"을 묻는다면? 정답은 언어적 명확성.


마치며

정리하면 이렇습니다.

프롬프트 엔지니어링은 AI를 고치는 기술이 아니라, '잘 묻는' 기술이다. 지시·맥락·입력·제약조건·출력형식을 명확하게 설계할수록 AI는 더 정확한 답을 돌려준다.

AI 시대에 진짜 경쟁력은 '얼마나 좋은 도구를 쓰느냐'보다 '그 도구에게 얼마나 잘 질문하느냐' 에 가깝습니다. 오늘 배운 5대 구성요소부터 한번 적용해보세요. 결과물의 질이 달라질 거예요.


📇 핵심만 빠르게 — 한 줄 암기 카드

  • 자연어로 AI 성능 극대화하는 체계적 설계 → 프롬프트 엔지니어링
  • 질문·지시문 체계적 설계·테스트 → 프롬프트 엔지니어
  • 5대 구성요소: 지시·맥락·입력·제약조건·출력형식 (빈출!)
  • 좋은 프롬프트: 명확성·구조화·맥락성·목적성 / 함정은 복잡성
  • 목표 아님: AI 내부 메커니즘 직접 수정(=개발자 영역)
  • 단계별 사고·2022 구글 → CoT / 예시 없이 → 제로샷 / 예시 2개+ → 퓨샷
  • 모호함 제거·의도 전달 → 언어적 명확성

이 글이 도움이 되셨다면 공감과 댓글 부탁드려요. AI 개념 정리 시리즈, 다음 편에서 계속됩니다! 🙌

 

프롬프트엔지니어링 #프롬프트 #CoT #제로샷 #퓨샷 #생성형AI #ChatGPT #AI자격증 #AIPOT #프롬프트활용능력

h

hyos

IT · 스타트업 · 개인기록. 만들고, 실패하고, 기록합니다.

공부/AI-POT 2026. 6. 12. 16:50

AI-POT 2급 자격증 공부(ChatGPT_구조_프롬프트처리_RLHF)

ChatGPT는 어떻게 내 질문에 답할까? 구조·처리 과정·RLHF 완전 정리

ChatGPT에 한 줄 입력하면 마치 사람처럼 술술 문장이 흘러나옵니다. 그런데 이 'GPT'가 정확히 뭘 줄인 말인지, 내 질문이 안에서 어떤 단계를 거쳐 답으로 바뀌는지 아시나요? 이 글에서는 ChatGPT의 구조와 특징부터, 프롬프트가 응답으로 변환되는 5단계, 그리고 ChatGPT를 '사람처럼' 만들어준 핵심 기술 RLHF까지 한 번에 정리합니다.


ChatGPT, 이름부터 뜯어보자 — GPT의 정체

ChatGPT는 OpenAI가 개발한 대화형 인공지능 언어 모델이자 대표적인 생성형 AI입니다. 그런데 이 'GPT'라는 세 글자에 ChatGPT의 정체가 다 들어 있어요.

GPT = Generative(생성) · Pre-trained(사전 훈련된) · Transformer(트랜스포머)

시험이든 면접이든 단골로 나오는 부분입니다. 세 단어 중 'Generative(생성)' 와 'Transformer' 는 비교적 쉽게 외워지는데, 진짜 함정은 가운데 있어요.

📌 헷갈리기 쉬운 포인트: 가운데 'Pre-trained(사전 훈련된)' 에 집중하세요. 여기서 한 번씩 막힙니다.

발전 흐름도 간단히 짚고 갈게요.

시점 모델 내용
2021.12.30 ChatGPT 3.5 모델 출시
2023.03 GPT-4 성능 대폭 향상

버전마다 다르다 — 멀티모달은 GPT-4부터

ChatGPT의 기본기는 대화 맥락을 기억하면서 질문 답변·창작·번역·요약 같은 텍스트 작업을 해내는 것입니다. 그런데 버전이 올라가면서 결정적인 변화가 생겼어요. 바로 멀티모달(Multimodal) 입니다.

멀티모달 = 텍스트뿐 아니라 이미지·음성까지 다루는 능력. GPT-4부터 적용됩니다.

버전 특징
GPT-3.5 기본 대화 + 텍스트 작업 (멀티모달 ❌)
GPT-4 향상된 처리 능력 + 멀티모달(이미지 생성·음성 처리·실시간 웹 검색)
GPT-4 옴니(Omni) 더 복잡한 작업 + 한층 높은 정확도

📌 시험 포인트: GPT-3.5는 멀티모달로 보기 어렵고, 멀티모달은 GPT-4 모델부터입니다. 이거 한 줄이 종종 정답을 가릅니다.

참고로 ChatGPT 같은 생성형 AI는 UI/UX가 2~4주마다 빠르게 바뀌기 때문에, 교재 스크린샷과 실제 화면이 다른 건 자연스러운 일이에요. 또 예전 시험과 달리 이제는 웹 검색 기능이 추가돼서, 출제 범위에 따라 답이 달라질 수 있다는 점도 알아두면 좋습니다.


내 질문은 어떻게 답이 될까? — 프롬프트 처리 5단계

여기가 이번 글의 핵심입니다. 내가 입력창에 글을 쓰고 엔터를 누르는 순간, ChatGPT 내부에서는 5단계가 차례로 돌아갑니다.

입력 → 전처리 → 토큰화 → 모델 처리 → 후처리

순서 단계 안에서 벌어지는 일
1 입력 사용자가 텍스트를 입력
2 전처리 이전 대화 기록까지 포함해 컴퓨터가 이해할 컨텍스트를 만듦
3 토큰화 컨텍스트를 컴퓨터가 이해하는 조각(토큰) 으로 나누고 의미 부여
4 모델 처리 토큰을 받아 계산 → 이때 트랜스포머의 셀프 어텐션이 작동
5 후처리 모델이 만든 토큰 ID를 다시 텍스트로 변환 → 최종 응답 완성

흐름을 잡는 팁은 이렇습니다. 사람의 말(입력) 이 들어와서, 컴퓨터가 알아들을 형태(전처리·토큰화) 로 바뀌고, 모델이 계산(모델 처리) 한 뒤, 다시 사람의 말(후처리) 로 돌아 나오는 거죠.

🔑 순서 통째 암기: 입력 · 전처리 · 토큰화 · 모델 처리 · 후처리


한 글자씩 예측한다 — 자기 회귀적 생성

그럼 4단계 '모델 처리'에서 답은 정확히 어떻게 만들어질까요? ChatGPT는 완성된 문장을 한 번에 뱉어내지 않습니다. 한 글자(토큰)씩, 차례대로 예측하며 문장을 쌓아 올려요. 이걸 자기 회귀적 생성(Autoregressive) 이라고 부릅니다.

자기 회귀 = 이전에 생성한 토큰들을 근거로, 그다음 올 토큰을 순차적으로 예측하는 방식

예를 들어 "한국의 수도는"이라는 입력이 들어오면,

한국의 수도는 → 서울 → 입니다

이렇게 앞 내용을 보고 다음 단어를 한 칸씩 예측해 나갑니다. ChatGPT가 답을 한 글자씩 타이핑하듯 보여주는 것도 바로 이 원리 때문이에요.


ChatGPT를 '사람처럼' 만든 비밀 — RLHF

기술적으로 답을 생성할 수 있다고 해서, 그게 곧 '사람이 만족하는 답'은 아닙니다. ChatGPT가 유독 자연스럽고 인간적인 이유, 그 핵심에 RLHF가 있습니다.

RLHF (Reinforcement Learning from Human Feedback) = 인간 피드백을 통한 강화 학습

원리는 의외로 직관적입니다. AI가 여러 답변을 내놓으면, 사람이 "이게 더 좋다"고 평가하고, AI는 사람이 좋다고 한 답변을 더 많이 내놓도록 훈련됩니다. 기본 모델이 인간 평가를 받아 강화 학습되는 3단계 구조예요.

여기서 가장 중요한 키워드는 단 하나입니다.

🔑 인간의 피드백(Human Feedback) — "인간 평가자들의 평가로 작동하는 AI 훈련 방법론"이라면 정답은 무조건 RLHF.


모든 토큰을 동시에 본다 — 멀티헤드 어텐션

마지막으로, 모델 처리 단계에서 작동하는 멀티헤드 어텐션(Multi-Head Attention) 을 짚고 갑니다. GPT가 문맥을 이해하는 핵심 메커니즘이에요.

기존 방식이 문장을 앞에서 뒤로 순서대로 읽었다면, 트랜스포머는 모든 토큰 간의 관계를 동시에, 전(全) 방향으로 계산합니다. 작동 순서는 이렇습니다.

  1. 프롬프트를 여러 토큰으로 분리
  2. 각 토큰이 다른 토큰과 어떻게 연결되는지 관계를 파악
  3. 중요도에 따라 점수를 부여
  4. 수집한 정보를 종합해 응답을 생성

🎼 비유: 멀티헤드 어텐션은 오케스트라 지휘자와 같습니다. 모든 악기(단어)의 관계를 동시에, 병렬적으로 파악해 하나의 연주(응답)로 엮어내죠.


마치며

오늘 내용을 한 문장으로 정리하면 이렇습니다.

ChatGPT는 내 질문을 5단계(입력→전처리→토큰화→모델 처리→후처리)로 가공해, 한 토큰씩 자기회귀적으로 답을 생성하고, RLHF로 그 답을 '사람이 좋아하는 방향'으로 다듬는다.

작동 원리를 알면 프롬프트를 쓰는 손끝도 달라집니다. AI가 어떻게 생각하는지 이해한 사람이, 결국 더 좋은 질문을 던지니까요.


📇 핵심만 빠르게 — 한 줄 암기 카드

  • OpenAI 대화형 언어 모델 = 생성형 AI
  • GPT = Generative(생성)·Pre-trained(사전훈련)·Transformer(트랜스포머)
  • 멀티모달(이미지·음성·웹검색) = GPT-4부터 (3.5 ❌)
  • 처리 5단계: 입력 → 전처리 → 토큰화 → 모델 처리 → 후처리
  • 모델 처리 단계에서 셀프 어텐션 작동, 후처리 = 토큰 ID → 텍스트
  • 한 토큰씩 순차 예측 → 자기 회귀적 생성 ("한국의 수도는 서울입니다")
  • 인간 피드백 강화 학습 → RLHF (사람처럼 대화하는 핵심)
  • 모든 토큰 관계 동시·병렬 계산 → 멀티헤드 어텐션 (오케스트라 지휘자)

이 글이 도움이 되셨다면 공감과 댓글 부탁드려요. AI 개념 정리 시리즈, 다음 편에서 계속됩니다! 🙌

 

h

hyos

IT · 스타트업 · 개인기록. 만들고, 실패하고, 기록합니다.

공부/AI-POT 2026. 6. 12. 01:50

AI-POT 2급 자격증 공부(트랜스포머_사전학습_토크나이저_임베딩)

LLM은 어떻게 학습할까? 트랜스포머·토크나이저·임베딩 한 번에 이해하기

ChatGPT 같은 거대 언어 모델(LLM)은 도대체 어떻게 사람 말을 배우는 걸까요? 그 비밀은 트랜스포머라는 두뇌 구조, 그리고 문장을 잘게 쪼개 숫자로 바꾸는 토크나이저·임베딩 과정에 있습니다. 이번 글에서는 LLM이 학습하는 전 과정을 처음부터 끝까지 따라가 봅니다.


1. 모든 것의 시작, 트랜스포머 아키텍처

2017년, AI 역사를 바꾼 논문 한 편이 나옵니다. 제목부터 강렬한 'Attention Is All You Need(필요한 건 어텐션뿐)'. 여기서 제안된 트랜스포머(Transformer) 는 기존 RNN의 한계를 깨부수며, 오늘날 GPT와 BERT의 공통 뿌리가 되었습니다.

두 개의 심장: 인코더와 디코더

트랜스포머는 크게 두 부분으로 나뉩니다.

  • 인코더(Encoder): 입력된 문장(프롬프트)을 이해하고 변환하는 부분
  • 디코더(Decoder): 그 이해를 바탕으로 결과물을 생성하는 부분

트랜스포머가 강력한 두 가지 이유

  1. 병렬 처리: 단어를 하나씩 읽던 RNN과 달리, 모든 단어를 동시에 처리합니다. → 압도적으로 빠름
  2. 장거리 의존성 해결: 문장이 아무리 길어도 전체 맥락을 기억합니다. → "앞에서 뭐라고 했더라?" 문제 해결

트랜스포머를 움직이는 3대 부품

부품 역할 쉽게 말하면
셀프 어텐션 단어들의 관련성을 동시에 계산 "이 단어가 어떤 단어와 연결되지?"
멀티헤드 어텐션 셀프 어텐션을 여러 개 묶음 여러 관점에서 동시에 분석
포지셔널 인코딩 단어의 순서(위치) 정보 제공 "이게 몇 번째 단어더라?"

여기서 재밌는 점. 트랜스포머는 모든 단어를 동시에 보다 보니 순서 감각이 없습니다. "나는 너를 좋아해"와 "너는 나를 좋아해"를 구분하려면 위치 정보가 필요하죠. 그래서 포지셔널 인코딩이 "몇 번째 단어인지"를 따로 알려주는 겁니다.

💡 (심화) 셀프 어텐션은 내부적으로 Query(질문)·Key(키)·Value(밸류) 세 요소로 단어 간 관련성을 계산합니다. 도서관에서 검색어(Query)로 책 제목(Key)을 찾아 내용(Value)을 얻는 것과 비슷해요.


2. AI의 교육 과정 — 사전 학습과 파인튜닝

사람이 초등학교부터 대학 전공까지 단계별로 배우듯, AI도 두 단계로 학습합니다.

📚 1단계: 사전 학습 (Pre-training) — 기초 교육

대규모 데이터셋으로 언어의 기본기를 닦는 과정입니다. 방식은 모델마다 다릅니다.

방식 사용 모델 학습법
마스킹 기반 BERT 문장의 단어를 가린 뒤 빈칸 맞히기
자기회귀 기반 GPT 다음에 올 단어 예측하기

🎯 2단계: 파인튜닝 (Fine-tuning) — 전공 교육

기초를 닦은 모델을 특정 용도에 맞게 미세 조정하는 단계입니다. 예를 들어 의료 상담용, 법률 검토용처럼 전문 분야에 특화시키는 거죠. 기초 교육을 받은 학생에게 전공을 가르치는 것과 같습니다.

💡 (심화) 두 가지 학습 개념

  • 자기지도 학습: 모델이 스스로 문제와 답을 만들어 학습 (정답 라벨이 따로 없어도 됨)
  • 전이 학습: 이미 배운 기존 지식을 활용해 새로운 분야를 빠르게 익힘


3. 문장을 숫자로 — 토크나이저와 임베딩

컴퓨터는 글자를 모릅니다. 오직 숫자만 이해하죠. 그래서 우리 문장을 AI에게 먹이려면 두 단계 변환이 필요합니다.

✂️ 토크나이저 — 문장 자르기

문장을 작은 조각, 즉 토큰(token) 으로 나누는 과정입니다. 자르는 단위에 따라 세 종류가 있어요.

방식 자르는 단위 장점 단점
문자 단위 글자 하나하나 (ㄱ,ㅏ...) 단순함 의미 파악이 어려움
단어 단위 완성된 단어 의미가 명확 처음 보는 단어에 취약
서브워드 단위 🏆 의미 있는 조각 두 방식의 장점만 결합 —

오늘날 주류는 서브워드 단위입니다. 자주 쓰는 단어는 통째로 두고, 드문 단어만 의미 있는 조각으로 쪼개죠. 예를 들어 "끝없이"라는 단어를 "끝" + "없이"로 나누면, 처음 보는 단어라도 의미를 추측할 수 있습니다.

🔢 임베딩 — 숫자로 바꾸기

쪼갠 토큰을 컴퓨터가 이해하는 숫자 벡터로 변환하는 단계입니다. 이렇게 숫자로 바뀌어야 비로소 AI 모델에 입력되어 학습이 진행돼요.

🔑 전체 흐름: 문장 → [토크나이저] 토큰으로 분리 → [임베딩] 숫자 벡터로 변환 → AI 모델 입력 → 학습

토크나이저와 임베딩은 떼려야 뗄 수 없는 짝꿍입니다. 자르지 않으면 숫자로 바꿀 수도 없으니까요.


마치며

LLM의 학습 과정을 한 문장으로 요약하면 이렇습니다.

트랜스포머라는 두뇌로, 문장을 토큰으로 쪼개 숫자(임베딩)로 바꾼 뒤, 대규모 사전학습으로 기초를 닦고 파인튜닝으로 전문성을 갖춘다.

복잡해 보이지만, 결국 "사람 말을 컴퓨터가 알아들을 숫자로 바꾸고, 단계별로 가르친다" 는 단순한 원리입니다. 이 흐름만 잡아두면 어떤 LLM을 만나도 구조가 보이기 시작할 거예요.


📇 핵심만 빠르게 — 한 줄 암기 카드

  • 2017·RNN극복·GPT/BERT 기반 → 트랜스포머 (Attention Is All You Need)
  • 입력 이해 → 인코더 / 결과 생성 → 디코더
  • 단어 관련성 동시 계산 → 셀프 어텐션 / 여러 묶음 → 멀티헤드 / 순서 정보 → 포지셔널 인코딩
  • 셀프 어텐션 3요소 → Query·Key·Value
  • 대규모 기초 교육 → 사전 학습 (마스킹=BERT / 자기회귀=GPT)
  • 특정 용도 미세 조정 → 파인튜닝
  • 스스로 문제·답 생성 → 자기지도 학습 / 기존 지식 활용 → 전이 학습
  • 문장→토큰 분리 → 토크나이저 (문자/단어/서브워드)
  • 토큰→숫자 벡터 → 임베딩

이 글이 도움이 되셨다면 공감과 댓글 부탁드려요. AI 개념 정리 시리즈, 다음 편에서 계속됩니다! 🙌

#LLM #트랜스포머 #토크나이저 #임베딩 #파인튜닝 #사전학습 #셀프어텐션 #AI자격증 #AIPOT

h

hyos

IT · 스타트업 · 개인기록. 만들고, 실패하고, 기록합니다.

COMMENTS