LIGHT
IT 2026. 10. 11. 21:30

AI로 업무 효율 늘리기(MCP-Claude)

회의가 끝나면 브라우저를 열지 않는다, 팀 업무 도구에 MCP를 붙이고 달라진 것

왜 만들었나

혼자 쓰는 도구가 아니라, 같이 일하는 도구가 필요했다

일을 하다 보면 기록은 늘 흩어진다. 회의 내용은 누군가의 노트에, 결정사항은 메신저 어딘가에, 할 일은 각자의 메모장에 남는다. 회의 때 분명히 정한 일인데 일주일 뒤에 "그거 누가 하기로 했었지?"라는 말이 나온다. 혼자 정리를 잘한다고 해결되는 문제가 아니었다. 팀이 같은 기록을 보고, 같은 할 일 목록을 기준으로 움직여야 했다.

그래서 팀이 함께 쓰는 업무 서비스를 직접 만들었다. 회의록을 올리면 요약, 결정사항, 할 일이 정리되고, 그 할 일이 담당자의 「오늘」 화면, 일정, 마일스톤, 주간보고로 이어진다. 회의록 하나에서 팀 전체의 일정과 할 일이 만들어지는 구조다. 팀원들은 같은 워크스페이스에서 같은 기록을 보고, 권한에 따라 직접 고칠 수도 있다.

그런데 정작 나는 터미널에 있었다

문제는 나 자신이었다. 하루 대부분을 이 서비스가 아니라 터미널에서 보낸다. 회사 PC에서 Claude Code를 켜두고 개발도 하고 문서도 쓴다. 그러다 "이번 주에 뭐 하기로 했더라" 싶으면 하던 일을 멈추고 브라우저를 열고, 로그인하고, 할 일 화면을 찾아 들어가야 했다. 한 번이면 별일 아니지만, 하루에 몇 번씩 반복되니 흐름이 계속 끊겼다.

회의가 끝나면 정리가 또 하나의 일이었다

팀이 함께 보는 기록이 되려면 누군가는 회의를 정리해서 올려야 한다. 녹음을 듣고, 요약을 쓰고, 결정사항과 할 일을 뽑아서 하나씩 옮긴다. 회의보다 정리가 더 귀찮을 때도 있었다. 정리가 늦어지면 팀원들은 그만큼 늦게 할 일을 받는다.

그래서 바라는 모습은 두 가지였다.

  1. 터미널에서 "이번 주 내 할 일 보여줘"라고 물으면 팀 서비스에 쌓인 데이터로 답이 온다.
  2. "오늘 회의록 올려줘" 한마디로 녹음 정리부터 등록까지 끝나고, 팀원들이 바로 볼 수 있다.

이걸 가능하게 해주는 연결 방식이 MCP(Model Context Protocol)다.


어떤 구조로 되어 있나

한 줄 요약: AI가 쓸 수 있는 도구 상자를 서비스가 직접 내준다

MCP는 AI 도구(여기서는 Claude Code)와 다른 서비스를 잇는 표준 연결 방식이다. 서비스가 "나는 이런 기능들을 갖고 있고, 각 기능은 이런 정보를 받는다"는 목록을 내주면, Claude Code는 연결하는 순간 그 목록을 받아 필요한 기능을 알아서 골라 쓴다.

사용자 입장에서 중요한 건 이 점이다. 사용 설명서를 따로 써줄 필요가 없다. 설명은 서비스 서버 안에 들어 있고, 기능이 바뀌어도 서버만 고치면 된다. 팀원마다 설정 문서를 따로 챙길 필요도 없다.

연결은 명령 한 줄

서비스 설정 화면의 「외부 접근」 카드에서 토큰을 발급하면, Claude Code 등록 명령이 토큰까지 채워진 채로 나온다. [명령 복사]를 눌러 터미널에 붙이면 연결이 끝난다.

claude mcp add --transport http team-tool https://<주소>/api/mcp \
  --header "Authorization: Bearer <토큰>" --scope user

토큰 원문은 발급 직후 한 번만 보여주고, 그 뒤에는 끝 4자리만 남는다.

토큰마다 볼 수 있는 범위와 할 수 있는 일이 정해진다

팀이 함께 쓰는 서비스라 권한 구분이 특히 중요했다. 토큰을 발급할 때 두 가지를 정한다.

  • 어느 워크스페이스인가. 토큰 하나는 워크스페이스 하나만 볼 수 있다. 회사 PC에서 토큰이 유출되더라도 다른 팀의 공간은 열리지 않는다.
  • 읽기만 할 것인가, 쓰기도 할 것인가. 처음엔 읽기 전용으로 시작하고, 쓰기가 필요해지면 그때 따로 발급하면 된다.

읽기 전용 토큰으로 연결하면 쓰기 기능은 목록에 아예 나타나지 않는다. 막혀 있는 게 아니라 처음부터 없는 것이다. MCP로 연결해도 팀 안에서 정한 권한은 그대로 적용된다. 보기 전용 권한인 팀원에게는 회의록 원문 자체가 응답에 들어가지 않고, 가계부는 관리자 이상만 읽을 수 있다.

쓸 수 있는 기능 19개

구분 도구 하는 일
확인 get_workspace 지금 연결된 공간, 내 권한, 토큰 권한
읽기 list_items, list_meetings, get_meeting, search 외 할 일, 회의록, 마일스톤, 프로젝트, 전체 검색 등
쓰기 preview_changes 바꿀 내용을 미리 보여주기만 함 (실제 데이터는 그대로)
쓰기 apply_changes 실제로 적용. 삭제는 한 번 더 확인해야 통과
쓰기 undo_changes 방금 적용한 묶음을 통째로 롤백

읽기 16개, 쓰기 3개다. 쓰기는 미리보기 → 적용 → 롤백 세 단계가 한 세트다. AI가 바로 데이터를 바꾸지 않고, 무엇을 바꿀지 먼저 보여준 뒤 내가 확인하면 적용한다.

AI가 바꾼 기록은 팀이 보는 화면에 남는다

서비스 웹 화면의 어시스턴트에는 「채팅 / MCP」 탭이 있다. MCP 탭에는 Claude Code가 어떤 토큰으로, 언제, 무엇을, 몇 건 바꿨는지가 쌓이고, 마음에 안 드는 변경은 거기서 [롤백]으로 취소한다. AI가 팀 데이터를 바꾼 기록이 팀 모두가 볼 수 있는 곳에 남는 셈이다.

회의 정리는 MCP 두 개를 잇는다

회의 녹음은 Tiro로 한다. Tiro도 MCP를 제공하기 때문에, Claude Code 스킬 하나가 Tiro와 서비스를 이어준다.

  1. 회의를 Tiro로 녹음한다.
  2. Claude Code에서 "오늘 회의록 올려줘"라고 입력한다.
  3. Claude Code가 Tiro에서 전사본을 읽고, 정해둔 템플릿(정기 회의, 외부 미팅, 결정 회의)으로 요약, 결정사항, 할 일을 정리한다.
  4. 정리안을 보여주고, 내가 확인하면 서비스에 올린다.
  5. 결정사항과 할 일을 방금 만든 회의록에 연결한다. 이때부터 팀원들도 같은 회의록과 할 일을 본다.

반대 방향의 연결도 있다. 팀원이 서비스에 새 회의록을 올리면 내 Claude Code 세션에 한 줄 알림이 뜬다. PC를 꺼둔 사이에 올라온 회의록도 다음에 켤 때 알려준다.


이걸 하면 뭐가 좋은가

1. 팀의 기록이 한곳에 모인다

회의록, 결정사항, 할 일이 각자의 메모장이 아니라 팀이 함께 보는 서비스에 쌓인다. 정리하는 수고가 줄어 기록이 밀리지 않고, 덕분에 팀원들이 같은 정보를 같은 시점에 본다. "그거 누가 하기로 했었지?"를 물을 일이 줄었다.

2. 일하던 자리를 떠나지 않는다

할 일 확인, 회의록 검색, 마일스톤 확인을 터미널에서 묻고 바로 답을 받는다. 브라우저를 열고 로그인하고 메뉴를 찾아 들어가는 몇 단계가 질문 한 줄로 줄었다. 작은 차이 같지만, 하루에 몇 번씩 끊기던 흐름이 이어진다.

3. 회의 뒤처리가 대화 한 번으로 끝난다

녹음을 다시 듣고, 요약을 쓰고, 할 일을 하나씩 옮기던 일이 "오늘 회의록 올려줘"로 바뀌었다. 나는 AI가 만든 정리안을 읽고 확인만 하면 된다. 템플릿이 정해져 있어서 누가 정리해도 회의록 형식이 같고, 팀원들이 읽기도 편하다.

4. 비용이 따로 들지 않는다

원래 웹 화면의 [요약 생성] 버튼은 서버에서 Claude API를 호출해서 쓸 때마다 비용이 들었다. 이 흐름은 내가 이미 쓰고 있는 Claude Code 구독 안에서 끝난다.

5. AI에게 맡겨도 불안하지 않다

팀이 함께 쓰는 데이터를 AI가 직접 바꾼다고 하면 걱정이 먼저 든다. 그래서 안전장치를 겹겹이 뒀다.

  • 쓰기 전에 공간부터 확인한다. Claude Code는 쓰기 전에 get_workspace로 지금 연결된 공간이 어디인지 확인한다. 엉뚱한 팀의 공간에 회의록을 올리는 실수를 막기 위해서다.
  • 바꾸기 전에 미리보기로 보여준다. 삭제는 한 번 거절된 뒤 다시 확인해야 통과한다.
  • 적용한 뒤에도 롤백할 수 있다. 터미널에서 AI가 한 일을 브라우저에서 검토하고 취소할 수 있다는 게 생각보다 든든하다.
  • 토큰은 공간 하나, 권한 하나로 묶인다. 팀 안에서 정한 권한도 그대로 적용된다.

솔직히 롤백이 없었다면 쓰기 토큰은 발급하지 않고 읽기 전용에서 멈췄을 것이다.

6. 팀원이 올린 회의록을 놓치지 않는다

새 회의록이 올라오면 내가 일하는 터미널로 알림이 온다. 새 회의록이 있는지 서비스에 들어가 확인할 필요가 없다. 내가 올리면 팀원이 보고, 팀원이 올리면 내가 바로 안다.


마무리

처음 목표는 혼자 정리를 잘하는 게 아니라, 팀이 같은 기록을 보며 함께 일하는 것이었다. 그래서 팀 업무 서비스를 만들었고, 거기에 MCP를 붙이면서 가장 큰 걸림돌이었던 "기록을 올리는 수고"를 덜었다. 지금은 회의가 끝나도 브라우저를 열지 않는다. 녹음은 Tiro가, 정리는 Claude Code가, 기록과 공유는 서비스가 맡고, 나는 확인만 한다.

팀과 함께 쓰는 업무 도구가 있고, 하루 대부분을 AI 도구 안에서 보내고 있다면, MCP로 둘을 이어 보는 것도 방법이다. 도구를 오가는 시간이 생각보다 많았다는 걸 알게 된다.

h

hyos

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

IT 2026. 9. 27. 22:51

MCP 란 무엇인가?

MCP

MCP 두 편 · 1 설명

회사 PC 의 Claude Code 에서 내 업무 도구를 쓰고 싶어서 MCP 서버를 하나 만들었다. 시작하기 전에 찾아본 설명은 대부분 「AI 의 USB-C」라는 비유에서 끝났고, 그걸로는 뭘 만들어야 하는지 감이 오지 않았다. 다 만들고 나서 보니 프로토콜은 생각보다 단순했고, 시간은 엉뚱하게 권한 쪽에서 다 썼다. 그 순서대로 적어 본다.

2026년 9월 · 읽는 데 약 7분 · foronelab Phase 30 기록

1한 줄로 말하면

AI 앱이 바깥의 데이터나 도구에 닿는 방법을 규격 하나로 정해 둔 것. 이름은 Model Context Protocol 이고, 2024년 11월 25일 앤트로픽의 David Soria Parra 와 Justin Spahr-Summers 가 공개했다.

USB-C 비유가 왜 붙었는지는 그 전 상황을 보면 이해가 된다.

2그 전에는 어떻게 했나

회사 DB 를 ChatGPT 에 붙이려면 ChatGPT 용 연동을 만들고, Claude 에 붙이려면 Claude 용을 또 만들었다. Cursor, Copilot, 사내 챗봇까지 치면 같은 데이터 하나에 연동이 다섯 벌이다.

거꾸로 봐도 마찬가지다. Claude 하나에 노션, 슬랙, 깃허브, DB 를 붙이면 또 네 벌.

AI 앱이 N 개, 데이터 소스가 M 개면 연동은 N×M 개가 된다. 흔히 N×M 문제라고 부른다. MCP 는 그 사이에 규격을 하나 끼워 넣어서 이걸 N+M 으로 바꾼다. 데이터 쪽은 MCP 서버 하나, AI 앱 쪽은 MCP 클라이언트 하나만 만들면 서로 붙는다.

MCP 없이 연동 20개, MCP 로 연동 9개
앱 5개와 데이터 4개. 왼쪽은 짝마다 연동을 따로 만들고, 오른쪽은 각자 규격 하나만 맞춘다.

기기마다 따로 굴러다니던 충전기가 USB-C 하나로 정리된 것과 모양이 같다. 비유는 여기서 나왔다.

3구조는 셋으로 나뉜다

이름 무엇인가 예
호스트 사람이 직접 쓰는 AI 앱. 모델과 대화 창을 쥐고 있다 Claude Code, Claude 데스크톱, ChatGPT, Cursor
클라이언트 호스트 안에서 서버 하나와의 연결을 맡는 부분 서버 1개당 클라이언트 1개
서버 도구와 데이터를 내놓는 쪽 내 DB, 깃허브, 파일시스템
호스트 안의 클라이언트 3개가 서버 3개와 각각 연결된다
서버 하나에 클라이언트 하나. 호스트와 클라이언트는 Claude Code 에 이미 있고, 내가 만든 건 보라색 한 칸이다.

내가 만든 건 서버다. 호스트와 클라이언트는 Claude Code 안에 이미 있어서 건드릴 일이 없었다. 처음엔 이 구분을 몰라서 클라이언트도 만들어야 하나 한참 찾아봤다.

4서버가 내놓을 수 있는 것 세 가지

실제로 코드를 쓰는 건 여기부터다. 서버가 내놓을 수 있는 건 세 종류이고, 스펙은 이걸 누가 쓰기로 정하느냐로 나눈다.

종류 누가 정하나 성격
도구 (Tools) 모델 (model-controlled) 함수 호출. 「이번 주 할 일 보여줘」라고 하면 모델이 알아서 list_items 를 부른다
리소스 (Resources) 앱 (application-driven) 읽을거리. 파일, 문서, 레코드를 컨텍스트에 넣는다
프롬프트 (Prompts) 사용자 (user-controlled) 서버가 준비해 둔 프롬프트 템플릿. 사용자가 메뉴에서 고른다

나는 도구만 만들었다. 읽기 도구 다섯, 쓰기 도구 셋. 리소스나 프롬프트가 하나도 없어도 잘 돈다. 셋을 다 채워야 하는 줄 알았는데 아니어서, 처음 만들 때 제일 반가웠던 부분이다.

도구 하나는 대략 이렇게 생겼다. 이름, 설명, 입력 스키마, 실행 함수.

server.registerTool("list_items", {
  title: "할 일 목록",
  description: "할 일을 조회한다. when: today(오늘) · week(7일) · late(지연) · all(전체)…",
  inputSchema: {
    when: z.enum(["today", "week", "late", "all"]).default("today"),
    limit: z.number().int().min(1).max(100).default(50),
    // status · projectId · owner 는 생략
  },
}, async ({ when, limit }) => {
  // 기존 조회 함수를 그대로 부른다
  return { content: [{ type: "text", text: JSON.stringify(payload) }] };
});

여기서 description 이 사실상 문서 역할을 한다. 모델은 이 글을 읽고 언제, 어떤 인자로 부를지 정한다. REST API 로 붙였다면 CLAUDE.md 같은 데 엔드포인트 목록을 따로 적어 두고 관리해야 했을 거다. MCP 에서는 그 설명이 코드 옆에 붙어 있어서, 코드를 고치는 커밋에서 설명도 같이 고치게 된다. REST 대신 MCP 를 고른 이유가 사실 이거 하나였다.

클라이언트 쪽이 서버에 내주는 기능도 있다. 루트(Roots — 서버에게 작업할 디렉터리 범위를 알려 준다), 샘플링(Sampling — 서버가 클라이언트 쪽 모델을 빌려 쓴다), 일리시테이션(Elicitation — 서버가 작업 도중 사용자에게 추가 정보를 묻는다). 그런데 2026-07-28 개정에서 루트와 샘플링, 그리고 서버 쪽 기능인 로깅이 폐기 예고(deprecated)됐다. 당장 사라지는 건 아니고 최소 12개월의 이행 기간이 있다. 지금 새로 만든다면 이 셋에는 기대지 않는 게 낫겠다.

5붙이는 방법은 둘

전송 방식 어디서 성격
stdio 내 PC 안 호스트가 서버를 자식 프로세스로 띄우고 표준 입출력으로 주고받는다. 로컬 파일이나 DB 를 붙일 때
Streamable HTTP 원격 HTTP 로 JSON-RPC 를 주고받는다. 이미 배포된 웹 서비스에 붙일 때

내 서비스는 Vercel 에 올라가 있어서 HTTP 쪽이었다. 등록은 명령 한 줄로 끝난다.

claude mcp add --transport http foronelab https://<주소>/api/mcp \
  --header "Authorization: Bearer <토큰>" --scope user

HTTP+SSE 라는 방식도 있었는데 2025-03-26 개정에서 Streamable HTTP 로 대체됐다. 검색하면 아직 그 방식 예제가 꽤 나오니 글 날짜를 보고 거르는 게 좋다.

6표준은 1년 8개월 사이 네 번 개정됐다

버전 시점 비고
2024-11-05 최초 공개 공개 발표는 2024-11-25. 버전 이름과 날짜가 다르다
2025-03-26 Streamable HTTP 도입. OpenAI 채택(2025-03), Google DeepMind(2025-04)
2025-06-18
2025-11-25 2025-12 앤트로픽이 MCP 를 리눅스 재단 산하 Agentic AI Foundation 에 기부. 재단은 앤트로픽·Block·OpenAI 공동 설립
2026-07-28 최신 하위 호환이 깨지는 변경. 무상태 전환

2026-07-28 의 큰 변화는 무상태(stateless) 전환이다. 그 전까지 MCP 는 initialize 로 세션을 열고 Mcp-Session-Id 헤더로 그 세션을 이어 가는 방식이었다. 이번 개정에서 이 두 가지가 빠졌고, 요청마다 프로토콜 버전과 기능 정보를 직접 싣는다. 세션을 들고 있을 필요가 없으니, 공유 저장소 없이 평범한 라운드로빈 로드밸런서 뒤에 서버를 여러 대 둘 수 있다.

다른 변경도 대체로 같은 쪽을 본다. 게이트웨이가 JSON 본문을 열어 보지 않고 헤더(Mcp-Method, Mcp-Name)만으로 라우팅할 수 있게 했고, 목록 응답에는 캐시 수명(ttlMs)을 붙였다. OAuth 인가 과정에는 RFC 9207 의 발급자(iss) 검증이 들어갔다. 실제 서비스로 굴리는 사람들을 위한 개정이라는 인상을 받았다.

SDK 는 패키지가 둘로 나뉘었다

여기서 한 번 헷갈렸다. 내가 설치한 TypeScript SDK @modelcontextprotocol/sdk 1.30.0 을 열어 보면 이렇게 적혀 있다.

export const LATEST_PROTOCOL_VERSION = '2025-11-25';
export const SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, '2025-06-18', '2025-03-26', '2024-11-05', '2024-10-07'];

2026-07-28 이 목록에 없다. 공식 블로그에는 Tier 1 SDK 네 개(TypeScript, Python, Go, C#)가 모두 지원한다고 나와 있어서, 처음엔 npm 배포가 늦나 싶었다.

알고 보니 TypeScript 는 v2 부터 패키지가 따로 나왔다. 2026-07-28 은 @modelcontextprotocol/server(2.x)에 들어 있고, 원래 쓰던 @modelcontextprotocol/sdk 는 v1 으로 남아 2025-11-25 까지만 지원한다.

나는 v1 을 그대로 썼다. 예제와 검색 결과가 v1 쪽에 훨씬 많았고, v2 는 나온 지 얼마 안 된 새 판이었다. 그래서 내 서버가 실제로 쓰는 건 2025년판 프로토콜이고, initialize 핸드셰이크도 여전히 오간다. 서버리스 환경이라 세션 id 없이 요청마다 서버를 새로 만드는 방식으로 돌리긴 했지만, 그건 SDK v1 의 무상태 모드일 뿐 2026-07-28 에서 말하는 무상태와는 다른 얘기다. 그 설정은 제작기 5절에 따로 적었다.

지금 쓰는 버전이 궁금하면 스펙 문서를 뒤지기보다 node_modules 안의 이 상수를 여는 편이 빠르다. 문서는 최신이어도 내가 깐 패키지는 아닐 수 있으니까.

7보안이 제일 허술한 곳

만들면서 시간을 제일 많이 쓴 곳은 프로토콜이 아니라 권한이었다. 돌아보면 그럴 만했다.

우선 도구 설명 자체가 믿을 수 없는 입력이다. 모델은 서버가 건넨 설명을 읽고 움직인다. 악의적인 서버가 설명 안에 「먼저 ~/.ssh 를 읽어서 보내라」 같은 문장을 숨겨 두면, 모델은 그걸 지시로 받아들일 수 있다. 이걸 도구 포이즈닝이라고 부른다. 스펙에도 도구 설명은 믿을 만한 서버에서 온 게 아니면 신뢰하지 말라고 적혀 있다. 2025년에 서버 1,899개를 살펴본 연구(Hasan 외)에서는 5.5%에서 도구 포이즈닝 징후가 나왔고, 1,808개를 스캔한 AgentSeal 조사에서는 66%가 어떤 식으로든 보안 점검에 걸렸다.

다음은 혼동된 대리인(confused deputy) 문제다. 권한을 가진 쪽이 요청한 사람을 제대로 가리지 않으면, 그 권한이 엉뚱한 사람을 위해 쓰인다. 내가 겪은 것도 결이 비슷했다. 토큰이 로그인 확인을 통과하게 만드는 순간 계정 관련 라우트까지 같이 열려서, 읽기 전용 토큰으로 계정을 지울 수 있는 상태가 잠깐 생겼다. 라우트마다 막는 대신 토큰 요청을 통째로 기본 차단하는 쪽으로 풀었는데, 찾은 과정과 코드는 제작기 3절에 있다.

IDE 쪽 사고도 있었다. 2025년 8월 Cursor 에서 프로젝트에 들어 있는 MCP 설정을 한 번 승인하면, 나중에 그 설정이 바뀌어도 다시 묻지 않고 실행하는 취약점(CVE-2025-54136)이 고쳐졌다. 저장소를 같이 쓰는 팀이라면 누군가 설정 파일을 몰래 바꾸는 것만으로 팀원 PC 에서 명령이 돌 수 있었다는 얘기다.

그래서 남이 만든 MCP 서버를 붙이는 일과 내가 서버를 만드는 일은 걱정할 거리가 다르다. 앞쪽은 내 모델이 남의 설명에 휘둘릴까 봐 걱정해야 하고, 뒤쪽은 내 권한 경계가 어디서 새는지 봐야 한다. OWASP 에 MCP 보안 치트시트가 따로 있는데, 만들기 전에 한 번 훑어볼 만하다.

8지금 해볼 수 있는 것

만들지 않고 써 보기만 해도 감은 온다. 파일시스템, 깃허브, 포스트그레스, 슬랙, 노션 같은 서버는 이미 공개돼 있다. 2025년 12월 재단 이관을 발표할 때 이미 활성 서버가 1만 개, SDK 다운로드가 월 9,700만 회를 넘었다고 했다.

직접 만든다면 나는 이 순서가 편했다.

  1. 도구 하나만 먼저 만든다. 리소스나 프롬프트는 나중 일이다.
  2. 이미 있는 조회 함수를 그대로 부른다. 나는 조회 쪽 코드를 한 줄도 고치지 않았다.
  3. DB 행을 통째로 넘기지 말고 필요한 필드만 골라 담는다. 모델이 읽을 분량이 줄고, 나중에 컬럼이 늘어도 응답이 모르는 새 불어나지 않는다.
  4. 쓰기는 기존 쓰기 경로를 다시 쓴다. 따로 만들면 변경 이력과 되돌리기가 두 군데로 갈라진다.
  5. 권한은 기본 차단에 허용 목록. 제일 귀찮은 일인데, 이걸 빼먹으면 앞의 네 개가 다 소용없어진다.

마치며

MCP 는 AI 앱과 데이터 사이에 규격 하나를 둔 것이고, 서버를 만드는 입장에서는 도구 몇 개만으로도 충분히 쓸모가 있다. 표준은 빠르게 바뀌는 중이라, 글이나 예제를 볼 때는 어느 버전 얘기인지부터 확인하는 게 좋다. TypeScript 라면 설치한 패키지 이름부터 보면 된다.

프로토콜을 붙이는 데는 오래 걸리지 않았다. 시간 대부분은 누가 무엇을 할 수 있는지 정하는 데 들어갔는데, 다시 해도 그렇게 쓸 것 같다.

참고

h

hyos

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

IT 2026. 9. 13. 21:40

??? : 2개월 동안 토큰 71억개 쓰셨습니다.

영수증을 열어봤다

클로드 코드로 두 달쯤 일했다. 개발도 하고 사업 문서도 쓰고 리서치도 시켰다. 그러다 문득 궁금해졌다. 나는 토큰을 도대체 얼마나 쓴 걸까.

찾아보니 기록이 다 남아 있었다. ~/.claude/projects/ 아래에 세션마다 파일이 하나씩 있고, 그 안에 응답 한 번당 토큰을 몇 개 썼는지가 그대로 적혀 있다. 추정할 필요가 없다. 영수증이 있는 셈이다.

전부 긁어모아 합산했다. 세션 28개, 7월 9일부터 9월 13일까지.

총 71억 5,000만 토큰

숫자만 보면 무섭다. 그런데 뜯어보니 이 71억의 정체가 내 생각과 달랐다.


토큰은 한 종류가 아니다

토큰은 네 가지로 나뉘고, 종류마다 가격이 다르다.

종류 두 달 합계 비중 무슨 뜻인가
캐시 읽기 68억 8,000만 96.2% 이미 나눈 대화를 다시 읽는 것
캐시 저장 2억 4,600만 3.4% 새로 오간 대화를 다음 질문에 대비해 저장
출력 2,250만 0.3% AI가 실제로 써낸 글자
캐시 안 걸린 입력 7만 4,000 0.001% 캐시에 없어서 그대로 읽은 입력

AI가 실제로 써낸 글은 전체의 0.3%다. 나머지는 읽는 데 들어갔다.

AI는 매번 처음부터 다시 읽는다

왜 이렇게 되나. AI에게 기억이 없기 때문이다.

대화가 이어지는 것처럼 보이지만, 실제로는 질문 하나에 답할 때마다 그 세션의 대화를 처음부터 끝까지 다시 읽는다. 100번째 질문에 답하려면 앞의 99번을 읽어야 한다. 200번째면 199번을 읽는다.

그래서 대화가 길어지면 한 마디 주고받는 비용이 계속 올라간다. 질문이 어려워져서가 아니라 읽어야 할 앞부분이 길어져서다.

캐시는 이걸 싸게 만들어주는 장치다. 같은 내용을 다시 읽을 때는 정가의 10%만 받는다. 그래서 개수로는 96%를 차지해도 실제 비용은 그만큼 나오지 않는다. 반대로 출력은 입력의 5배로 비싸다. 0.3%밖에 안 되는 출력이 비용에서는 꽤 큰 자리를 차지하는 이유다.

아래부터는 종류별 가격 차이를 반영해서 환산한 값으로 비교했다. 그래야 같은 기준으로 놓고 볼 수 있다.

긴 대화는 9배 비싸다

세션을 길이별로 묶어서 질문 한 번 던지는 데 얼마가 드는지 계산했다.

세션 길이 질문 1회당 비용(환산)
대화 200번 미만 11만 9,000
500~900번 67만 1,000
1,500번 이상 110만

똑같이 "이거 고쳐줘" 한 줄을 쳐도 긴 대화 끝에서 치면 9배가 든다.

제일 긴 세션은 대화가 2,495번까지 갔다. 이 세션은 질문 한 번에 720만 토큰을 썼다. 짧게 끝낸 세션들은 30만 토큰 언저리였다. 같은 일을 시켜도 어디서 시키느냐에 따라 20배가 갈린다.

대화가 길어지면 느려진다는 건 알고 있었다. 느려지는 게 아니라 비싸지고 있었다.

세션을 쪼개 쓰고 있었다

나는 몇 달 전부터 작업을 좀 이상하게 하고 있다. 세션 하나를 관제탑으로 정해두고 실제 작업은 다른 세션들에 맡긴다. 관제탑은 지시를 내리고 결과를 기록 파일에 한 줄씩 적는다. 개발은 개발 세션에서, 문서는 문서 세션에서 한다.

원래는 맥락이 섞이지 않게 하려고 만든 방식이다. 코드 얘기하다 사업 문서 얘기를 꺼내면 둘 다 흐려지니까.

이번에 집계하면서 다른 게 하나 눈에 들어왔다.

세션 수 질문 수 질문 1회당 비용 질문당 도구 사용
관제탑 10개 852회 52만 5,000 3.9회
실행 세션 4개 284회 100만 9.0회

관제탑이 딱 절반이다.

그런데 이걸 관제가 효율적이라는 뜻으로 읽으면 안 된다. 맨 오른쪽 칸을 보자. 관제탑은 질문 하나에 도구를 3.9번 쓰고 실행 세션은 9번 쓴다. 관제탑이 하는 일은 파일 위치를 알려주고 기록에 한 줄 적는 거라 원래 가볍다. 실행 세션은 코드를 읽고 고치고 테스트를 돌리니 무거울 수밖에 없다. 하는 일이 다른 둘을 비용으로만 비교한 셈이다.

진짜 이유는 다른 데 있다.

일을 여러 세션으로 쪼개면 각 세션이 짧게 유지된다.

한 세션에 전부 밀어넣으면 뒤로 갈수록 질문 한 줄이 계속 비싸진다. 나눠서 맡기면 모든 세션이 앞쪽 구간, 그러니까 싼 구간에 머문다. 관제탑도 결과 요약만 받으니 살이 안 찐다.

돈을 아끼려고 만든 방식이 아니었는데 그렇게 굴러가고 있었다.

그래서 뭘 바꿨나

세 가지를 바꿨다.

일이 끝나면 세션을 끊는다. 아깝다고 붙잡고 있으면 다음 질문부터 비싸진다. 맥락이 필요하면 결과를 파일로 남기고 새로 시작하는 편이 싸다.

무거운 일과 가벼운 일을 섞지 않는다. 코드를 한참 읽힌 세션에서 문장 하나 다듬어달라고 하면, 그 한 문장을 위해 앞의 코드를 전부 다시 읽는다.

요약을 파일로 남긴다. 대화를 통째로 이고 다니는 것보다 결론만 적어두고 다음 세션에서 그 파일만 읽히는 게 훨씬 싸다. 내 경우엔 그게 그 기록 파일이었다.

남은 한계

몇 가지는 짚어둬야겠다.

세션을 제목으로 분류했다. 기록에 세션 고유번호가 안 남아서 어느 세션 것인지 정확히 가려내지는 못한다.

AI가 따로 띄운 보조 세션이 쓴 토큰은 저장 위치가 달라서 이 집계에 안 들어갔다. 48건이다. 실제 총량은 이보다 크다.

캐시 저장 단가를 1.25배로 잡았다. 캐시를 오래 물고 있는 설정이면 2배가 된다. 어느 쪽이든 긴 세션이 비싸다는 결론은 그대로다.

h

hyos

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

IT/blnk.co 2026. 6. 22. 22:45

프롬프트 대거 변경 진행(1차 : POC-SW 전문 기획자)

측근 POC를 통해서, AI 퀄리티가 현저하게 떨어지는 것을 확인하였음

 

Pain Point 1 : 일러스트/실사화 위주의 프롬프트 구성

- 고 퀄리티, 신기한 이미지를 위주로 생성하여 시각적 자극을 주어서 구매를 유도하자! 라는 것이 Point였는데, 실상 폰케이스를 구매하는 사람들은 '여성' 유저임, 대다수의 여성 유저들은 귀여운 것, 예쁜 것들이 제품/디자인을 고르는 기준이 됨

 

=> 실사화/일러스트 프롬프트 조건 삭제, 이미지 분위기 설정


Pain Point 2 : 키워드를 풍성하게 하는 것(비전공자 시점의 검증 필요-2차 POC 예정)

- 사용자가 기본 키워드를 던지면, 해당 내용을 풍성하게 해서 그 중에 고르게 하자!

 

하지만!

 

요즘 사용자들은 이미지 생성을 위해 자신의 생각과 Needs를 AI에게 전달하기 때문에 프롬프트에서 다듬어서 이미지를 생성하는 것은 유저의 needs에 저해되는 행동일 수 있음

 

=> 프롬프트 수정 진행(A/B 테스트 진행 필요함)


Pain Point 3 : 휴대폰 케이스 Back image라는 고정 관념

- 프롬프트에서 phone case back design 이라는 요소를 넣으니, 이미지 자체를 휴대폰 뒷면으로 출력해서, 렌즈가 겹치고, 기종이 다르게 나오는 등 퀄리티가 떨어지는 문제가 발생했음

-> 배경을 지우는 기능이 이미 들어가 있기 때문에, phone case back design 가 아닌 AI를 활용한 이미지 생성으로만 진행해도, 이미지를 사용이 가능한 상황임

 

=> 프롬프트 수정(비율 9:16)

 


Check Point 1. 누끼 비용 절감

- 이미지 생성 시 누끼를 따는 API를 타는데 AI를 타는거라서 비용이 들어감(1실행 시 비용 4배)

 

=> 사용자 실행 시 배경 제거 진행하도록 로직 수정

 

이랬는데요
요래됐습니다~~~

 

나중에 모델바꿔야겠다 ㅠㅠㅠ

h

hyos

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

IT 2026. 6. 12. 21:44

블로그 꽃단장 파일 공유(w/claude)

skin-share.html 코드 가이드

— 파일 구조, 동작 원리, 커스터마이징 지점

tistory-skin-guide.md(제작 과정/이슈 해결기)와 함께 보는 코드 레퍼런스입니다.
이 문서는 "코드가 어떻게 생겼고, 어디를 고치면 무엇이 바뀌는가"에 집중합니다.


1. 파일 한 장 요약

skin-share.html 하나에 HTML + CSS + JS가 전부 들어있습니다. (약 1,300줄)

skin-share.html
├─ <head>
│   ├─ Google Fonts 로드 (Nanum Pen Script / Noto Serif KR / Noto Sans KR)
│   └─ <style>  ······································ 약 10~590행
│       ├─ ① 디자인 토큰 (:root / body.dk)
│       ├─ ② 베이스 & 레이아웃 (헤더, 그리드, 사이드바)
│       ├─ ③ 글 카드 + 미리보기 클램프
│       ├─ ④ 페이지네이션
│       ├─ ⑤ 사이드바 위젯 (검색/카테고리/태그/RSS)
│       ├─ ⑥ Tistory 자동 삽입 요소 덮어쓰기 (!important 지대)
│       ├─ ⑦ 첨부파일 재스타일 + 확장자 칩
│       └─ ⑧ 상세 페이지 모드 (body.detail …)
├─ <body class="tt-body-category">
│   ├─ 헤더 (블로그명, 카테고리 내비, 다크모드 토글)
│   ├─ 메인 컬럼: <s_list> 글 목록 + <s_article_rep> 글 상세
│   │   └─ 카드 내부에 태그/명함/댓글 등 "상세 전용 요소" 동봉
│   ├─ 사이드바: 검색 / 카테고리 / 태그 클라우드 / RSS
│   └─ 푸터
└─ <script>  ········································ 약 724~1330행
    ├─ (a) localStorage 캐시 정리
    ├─ (b) 첨부파일 DOM 재구성
    ├─ (c) 페이지네이션 재구성
    ├─ (d) 페이지 타입 감지 + 상세 모드 토글  ← 가장 큰 블록
    │   ├─ 사이드바 카테고리 재구성
    │   ├─ 글 태그 정리(멀티 태그 분리) + 폴백
    │   ├─ author-box / atags 중복 제거
    │   └─ 사이드바 태그 클라우드 정리
    ├─ (e) 다크모드 토글 + 복원
    └─ (f) 스크롤 진행 바

2. 디자인 토큰 — 색/스타일을 바꾸려면 여기만

모든 색상은 CSS 변수로 선언되어 있고, 라이트/다크가 같은 변수명을 공유합니다.
변수만 바꾸면 전체 테마가 일괄 변경됩니다.

:root {                                  /* 라이트 모드 */
  --ac:#B07828;                          /* 액센트 (브론즈) — 링크 호버, 현재 페이지, 칩 */
  --ac-a:rgba(176,120,40,.13);           /* 액센트 연한 배경 */
  --bg:#F8F6F3;  --nav:#EFE9E2;          /* 페이지 배경 / 내비 배경 */
  --tx:#1A1814;  --sub:#4A4238;  --mt:#6E665E;  /* 본문 / 보조 / 메타 텍스트 */
  --bd:#E4DDD5;  --tb:#EDE7DF;  --cb:#FFFEFB;   /* 보더 / 태그 배경 / 카드 배경 */
}
body.dk { /* 다크 모드 — 같은 변수를 어두운 값으로 재정의 */ }
바꾸고 싶은 것 수정 위치
포인트 컬러 --ac, --ac-a (라이트/다크 각각)
전체 배경 톤 --bg, --cb, --bd
본문 폰트 body{font-family:...} + <head>의 Google Fonts 링크
로고 손글씨체 Nanum Pen Script 사용처 (헤더 로고, 아바타 이니셜)

규칙: 색을 하드코딩하지 말 것. 새 요소를 추가할 때도 var(--ac) 등 변수를 쓰면
다크모드가 공짜로 따라옵니다. (예외: 확장자 칩 색상은 파일 형식 고유색이라 하드코딩)


3. 한 장 두 모드: 목록 ↔ 상세

이 스킨의 핵심 트릭입니다. 카드(.card) 마크업은 하나인데,
body 클래스에 따라 두 가지 모습으로 렌더됩니다.

목록 모드 (기본)                상세 모드 (body.detail)
┌─ .card ──────────┐           .card → 보더/배경 제거, 아티클화
│ 제목 (.pt)        │           .pt   → 28px 대제목
│ 미리보기 2줄 (.pe) │           .pe   → 클램프 해제, 전문 표시
│ 태그 (compact)    │           .rep-extra → 표시 (명함, 댓글 등)
└──────────────────┘           + "← 목록으로" 링크 JS 삽입

동작 순서:

  1. <body class="tt-body-category"> → Tistory가 tt-body-page(상세) 등으로 치환
  2. JS(d블록)가 클래스를 읽어 body.detail 클래스를 추가/생략
  3. CSS의 body.detail ... 섹션(⑧)이 카드를 아티클로 변환
// 정식 판별 우선, 변수 미처리 시 휴리스틱 폴백
if (/tt-body-/.test(bodyCls)) {
  isDetail = /tt-body-page(\s|$)/.test(bodyCls);
} else {
  isDetail = cards.length === 1;
}

상세 전용 요소 패턴: 명함·댓글처럼 상세에서만 보일 요소는 카드 안에
class="rep-extra"로 넣어두고 기본 display:none, body.detail에서만 표시합니다.
새 상세 전용 요소를 추가할 때 이 클래스만 붙이면 됩니다.


4. 미리보기 클램프 — .pe의 방어 설계

목록의 본문 미리보기는 Tistory가 어떤 HTML이든 넣을 수 있는 영역입니다.
그래서 3중 방어를 합니다:

.pe{ max-height:53px !important; overflow:hidden !important;
     display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }
.pe img,.pe figure,.pe video,.pe iframe,.pe table{ display:none !important; }  /* 미디어 제거 */
.pe *{ font-size:14px !important; margin:0 !important; ... }                   /* 평탄화 */

상세 모드에서는 이걸 전부 해제합니다 (body.detail .pe{max-height:none !important;...}).
미리보기 줄 수를 바꾸려면 -webkit-line-clamp 값과 max-height(줄수 × line-height)를 함께 수정하세요.


5. !important 지대 — Tistory 덮어쓰기 레이어

⑥~⑦ 섹션은 거의 모든 선언에 !important가 붙어 있습니다. 버그가 아니라 의도입니다.
Tistory가 런타임에 자체 CSS와 인라인 스타일을 주입하기 때문에, 이를 이기려면 필요합니다.

주요 덮어쓰기 대상:

대상 처리
공감/구독/프로필 위젯 display:none (스킨 자체 디자인으로 대체)
another_category (카테고리의 다른 글) 테이블 → 이전 글/다음 글 2칸 카드 그리드로 변환. tr:first-child::before{content:'← 이전 글'} 같은 가상요소로 라벨링
첨부파일 블록 기본 아이콘 숨기고 확장자 칩 + DOWNLOAD 텍스트 링크로 재구성
본문 표 border-collapse + 변수 기반 보더로 통일
댓글 React 앱 [class*="tt_"] 셀렉터로 폰트/색만 덮어씀 (DOM은 건드리지 않음)

여기를 수정할 때 주의: 셀렉터가 div[class*="another_category"]처럼 부분 일치인 이유는
Tistory가 클래스명을 바꾸는 경우가 있어서입니다. 정확한 클래스명에 의존하지 마세요.


6. JS 모듈별 가이드

전부 IIFE(즉시실행함수)로 독립되어 있어 하나가 죽어도 나머지는 동작합니다.
중요 로직은 try/catch로 감싸고, 실패 시 console.warn('[hyos] ...')을 남깁니다.

(b) 첨부파일 재구성

  • .tt_attachment 등에서 파일명/크기/링크를 파싱
  • 확장자를 추출해 <span class="file-ext-ico" data-ext="pdf"> 칩 삽입
  • 새 확장자 색을 추가하려면: CSS의 .file-ext-ico[data-ext="..."] 규칙 한 줄 추가

(c) 페이지네이션 재구성

  • 서버가 렌더한 번호 링크에서 현재 페이지(href 없는 항목), 전체 페이지, URL 패턴을 수집
  • ‹ 1 … 4 5 6 … 23 › 형태로 다시 그림
  • 윈도우 크기 변경: var win = 2 (현재 ±2) 값 수정
  • 변수 미치환([##_ 잔존) 시 페이지네이션 전체 숨김 — raw 텍스트 노출 방지

(d) 페이지 타입 감지 블록 (메인)

가장 큰 블록. 내부 순서가 중요합니다:

1. body_id로 상세/목록 판별 → body.detail 토글
2. 상세면: "← 목록으로" 링크 삽입
3. 사이드바 카테고리 재구성  ← try/catch (실패해도 원본 노출)
4. 글 태그 정리: '#' 멀티 태그 분리 → 칩 재구성
   └ 폴백 사다리: s_tag_label 결과 → 본문 /tag/ 링크 → 페이지 JSON
     → 모바일 페이지(/m/...) fetch → 전부 실패 시 숨김
5. author-box / atags 중복 제거
6. 사이드바 태그 클라우드 정리 (멀티 태그 분리 동일 적용)

태그 폴백은 0ms / 800ms / 2500ms 3회 재시도합니다 — Tistory React가
비동기로 마운트되기 때문. 이 패턴은 React 영역을 읽는 모든 코드에 필요합니다.

(e) 다크모드

document.getElementById('b').classList.toggle('dk', dk);   // className= 금지!
localStorage.setItem('hyos-dark', dk ? '1' : '0');
  • classList.toggle을 쓰는 이유: className =으로 덮어쓰면 Tistory의
    tt-body-page 클래스가 날아가 레이아웃이 깨집니다 (실제 겪은 버그)
  • 새로고침 시 localStorage에서 복원

(f) 스크롤 진행 바

헤더 위 2px 바(#prog)의 너비를 스크롤 비율로 갱신. 필요 없으면
#prog 요소와 마지막 scroll 리스너만 지우면 됩니다.


7. 공통 패턴 (새 기능 추가 시 따라할 것)

패턴 1 — 미치환 변수 가드

if (/\[##_/.test(el.innerHTML)) { /* 변수 미처리 → 폴백 or 숨김 */ }

모든 동적 영역의 첫 줄. raw 텍스트가 사용자에게 노출되는 것을 막습니다.

패턴 2 — 폴백 사다리

정식 치환자 → DOM 정규화 → 대체 소스(RSS, /m/ 페이지) → 깔끔하게 숨김

어느 단계에서 성공하든 결과 UI는 동일하게. 전부 실패하면 빈 껍데기 대신 섹션 자체를 숨깁니다.

패턴 3 — 비동기 재시도

if (!run()) {
  setTimeout(function(){ run(); }, 800);
  setTimeout(function(){ run(); }, 2500);
}

Tistory React 마운트를 기다리는 표준 방법. MutationObserver보다 단순하고 충분합니다.

패턴 4 — 네임스페이스

  • CSS 클래스: hyos-file, hyos-cmt 처럼 접두사 사용 (Tistory 클래스와 충돌 방지)
  • 콘솔 로그: console.log('[hyos] ...') — 필터링 가능
  • localStorage 키: hyos-dark, hyosTagCache_v1 — 버전 붙여서 마이그레이션 대비

8. 커스터마이징 빠른 레시피

하고 싶은 것 방법
포인트 컬러 변경 :root와 body.dk의 --ac, --ac-a 수정
미리보기 3줄로 .pe의 -webkit-line-clamp:3 + max-height 재계산
사이드바 위젯 순서 변경 <aside class="sb"> 안의 .ss 블록 순서 바꾸기
사이드바 위젯 제거 해당 .ss 블록 삭제 (JS는 요소 없으면 자동 skip)
페이지네이션 윈도우 JS의 var win = 2 수정
확장자 칩 색 추가 .file-ext-ico[data-ext="확장자"]{background:...} 추가
다크모드 기본값 ON (e) 복원 IIFE에서 localStorage 체크 앞에 dk=true;... 분기 추가
명함(author-box) 수정 class="author-box" 블록 — 이름/소개/이니셜은 플레이스홀더 검색
댓글 영역 스타일 #hyos-cmt 하위 CSS — DOM 구조는 Tistory React 소유, CSS만 건드릴 것

9. 수정 시 지켜야 할 것 (안 깨뜨리는 법)

  1. <s_...> 블록 구조를 옮기지 마세요. 치환자는 자기 블록 안에서만 동작합니다.
    특히 <s_tag_label>, <s_random_tags>(반복 단위 주의), <s_paging_rep>.
  2. 는 href="..."로 감싸면 안 됩니다. 속성 전체를 출력하는 변수입니다.
  3. body 클래스는 classList로만 조작하세요.
  4. React 마운트 포인트(data-tistory-react-app) 내부 DOM을 JS로 수정하지 마세요.
    리렌더 시 덮어써집니다. CSS 덮어쓰기만 허용.
  5. JS 추가는 새 IIFE로. 기존 블록에 끼워 넣지 말고 독립 블록 + try/catch로 추가하면
    실패해도 다른 기능이 살아 있습니다.
  6. 수정 후에는 5종 페이지를 모두 확인: 홈 / 글 상세 / 카테고리 / 태그 검색 / 마지막 페이지(글 1개).

 

깃허브로 따로 관리를 하고있지 않아서 파일로 전달 드리니 참고바랍니다~

 

h

hyos

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

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-category를 사용한다.

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

렌더되면 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-category 페이지 타입 (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 · 스타트업 · 개인기록. 만들고, 실패하고, 기록합니다.

IT/blnk.co 2026. 5. 23. 22:50

[1인 개발 - blnk.co] 방향성 문제 고민

1. 퀄리티 문제

flux-2로 돌렸는데, 퀄리티가 맘에 안든다. 그래서 큰맘먹고 nano-2로 바꿨는데

퀄리티는 좋다.

 

한화이글스 케이스, 간지난다....

근데 내가 생각한건 한화이글스의 수리를 모티브로한 디자인인데..... 맘에 들지 않아... 멋있긴한데... 맘에 안들어.....

 

2. 처음부터 본질적인 부분을 고민하기 시작

 

시장분석부터 다시 진행
아이템 자체는 한국에 없는 아이템임

 

여러가지를 확인해본 결과

시장 자체는 죽어있는게 아님, 근데 내가 걱정하는건 다른 것과 차별점이 있는가?

최초 구매부터 재구매까지 이어질 수 있는가? 에 대한 시작-지속성의 문제였음

 

3. 설문조사를 위한 opensurvey 가입

- 설문조사 진행 필요함(가입만..)

 

너무 답답해서 밖에 산책하다가 해결책을 찾아냈음

 

★4. 개인의 맘에 드는 디자인이 중요함 ★

- 아무리 잘 만든 컨텐츠여도, 내가 맘에 들지 않는다면 구매하지 않음

--->> 그럼 너의 취향은????

 

==> 프롬프트에 개인의 취향을 포함시키는 방향으로 진행하면 개인화가 더 명확해질 것으로 생각됨

> 멋있는것, 귀여운것, 매니악한 것 등 취향이 다 다름 그걸 4가지 결과로 뽑아내기엔 너무 방대하다.

 

① 사전에 레퍼런스 목업을 준비해서, 취향에 드는 항목을 셀렉함,

② 해당 레퍼런스 자료에 대한 프롬프트 or 태그 값을 main service 프롬트에 적용

③ 개인화 된 result 값 반영(구매확률 ↑)

h

hyos

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

IT/blnk.co 2026. 5. 23. 22:26

[1인 개발 - blnk.co] 2차 문제 직면..

#TODO 1번 : 이미지 합성 작업 진행

1. png 파일의 배경을 투명화를 시키는 작업을 진행함(근데 Back에 진행해야하는데 Front로 mockup을 연결해놨음-(?))

> 수정하니까 이미지랑 mockup이랑 붙어서 정상적으로 나옴

ㄱㅇㅇ

2. 이번엔 이미지 생성할 때 카메라랑 겹치는 이슈가 있음

> 프롬프트를 수정하기로함

 

3. 책지피티야 데이터 낋여와

 

4. 프롬프트에 카메라 영역 프롬프트로 전달해서 이미지 생성하도록 시킴

 

흠.................. 이게 맞나...................

------------------

배경 유무에 따라서 Needs차이도 있고, 퀄리티 차이가 좀 나는 것 같아서, 배경은 ON/OFF 하기로 했음

 

그래서 누끼를 따는 모델을 하나더 도입함

클로드 추천 모델들

 

바로 프로토타입 따기 진행

곰돌이 ㄱㅇㅇ

 

그리고 바로 인프라 설정하고, 배포 진행했는데

넌 뭐야

이상한 애들이 나오는 거임, 그래서 확인해보니, Claude API 과부하로 프롬트 작성하는애가 동작을 안했음(한글 번역도 안됨)

그래서 fallback 모델(sonnet) 추가헀음

 

 

---------------

생각해보자

- 케이스 mockup (1차 생성 완료)

- mockup+AI 이미지 합성 완료

 

주변 사람 반응

- 카메라 모양 더 맞춰야함

- 이미지 퀄리티 올려야할 것 같음(좀더 화려한 내용이 필요하다했음)

 

잔여 작업(user)

- QC 내용기반으로 mockup이미지 변경, 퀄리티용 프롬프트 진행 필요

- 옵션(그립톡, 무선충전, 색상)에 대한 렌딩 처리

h

hyos

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

IT/blnk.co 2026. 5. 20. 04:28

[1인 개발 - blnk.co] 1달차 - 4주만에 647커밋

회고용으로 작성하는 블로그글!

ㅋㅋㅋㅋ '4주만에 647 커밋 미쳤네' 라고 AI가 쓴거ㅋㅋㅋㅋㅋㅋ 열심히 일해줘서 고맙다~~

 

중간에 퇴사한 회사 프리일좀 도와주느라 정신없어서, 방향 잃고 좀 방황헀는데

 

정신차려보니까 엠생도 이런 엠생이 없어서 다시 정신차림! (ESTJ 특 쉬면 지루함)

 

 

AI가 말아주는 milestones

 

 

# 지금 서비스 올린지 3주정도 지났음(서비스 오픈x)

- User, Admin 페이지 구성했고, AI도 붙여놨음

 

# 인프라

Service 는 MS Azure로 했고, storage는 MS blob으로 했음

(왜 ms 임? 스파크랩 엑셀러레이팅 신청했는데, azure 지원해준다고해서 그냥 azure로함-연락주세요...)

 

-  언어는 Next.js, react로 구성했음

-  Github에 배포하면 자동으로 azure에 배포됨

- ORM은 Prisma

- DB는 Neon postgre (Neon은 Serverless Postgres service임-무료임)

 

# AI

- 전반적으로는 Cluade 사용함(max, opus)

-  이미지 생성 AI는 Fal.ai를 사용하는데 여기서 모델을 선택할 수 있음(모델 학습 있던 것 같은데 못찾겠음)

> 처음에는 flux 1모델을 썼는데 퀄리티가 별로였음

> Flux-2-Pro도 있고 그 안에 text 2 image, image 2 image 로 할 수 있는 세부 모델들이 있음

※ Fal.ai를 선택한 이유? => 금액 저렴해야함, API 지원 가능, 이미지 생성 특화 모델이어야했음

※ 왜 flux로 하느냐? => 제일 저렴함(중요), nano-bna도 선택할 수 있는데 비쌈(flux는 $0.03인데 nano-bna는 $0.08임)

 

# Issue. 사용자한테 입력받아서 이미지 생성 AI한테 넘기니까 문제가 좀 있음

- 한글 지원 안됨( fal.ai가 API로 사용할때는 한글 안받아줌, Web에서 Playground 할 때는 됨)

- 퀄리티가 너무 떨어짐, 원하는 프레임 구성이 안나옴

 

# 그래서 저는 문제를 해결하고자! Prompt 노예를 늘렸습니다!

- Claude console에서 따로 API를 요청해서 사용할 수 있음

금액도 저렴함(사용량이 적어서 그런 것 같음)

1. 한글 지원

- 클로드한테 한글 번역하라고 시킴 API로 한글 번역해서 return함

 

이런식으로 한글 번역하는 애를 따로 만들었음 그리고 규칙도 따로 설정함

 

2-1. 이미지 퀄리티 문제

- 1차 시도는 관리자가 기본 프롬트를 수정할 수 있도록 하는 방향으로 진행했음(AI 도입 이전)

유저 프롬트 입력 창이 있으니 AI 한테는

예)이미지를 생성해야하는데 $1(옵션 1)을 기반으로 $2(내용)을 바탕으로 $3(추가옵션)을 반영해서 생성하고 $4(사진)을 참조해서 4개이상의 값을 줘!(좀 더 상세하게 쓰긴했음 ㅎㅎ..)

 

라고 하니까 퀄리티가 똥임

- 모델 자체가 가지고있는 데이터가 적을뿐더러, 매번 유저가 요청하는 프롬트가 명확하지 않음

 

- 그래서 얘도 AI 시켰음

 

프롬1번 노예가 한글로 넘겨주면, 얘가 그걸 가공해서 쫙 풀어줌

 

2-2. 이미지 합성

- 원래는 AI로 이미지를 생성하려고 했는데, 학습 데이터가 부족한건지 프롬트 2노예로 돌려도 안나오길래

- 그냥 mockup으로 합성하는게 제일 깔끔하겠다 싶었음

- 근데 mockup 이미지를 어디서 구하냐!

> AI로 만들었음 (Claude.ai/design - stitch)

 

와이어프래임 짤라고 챗지랑 제미니만 써봤는데, 클로드 디자인이 html코드로도 떨궈줘서 쓰기 제일 좋았음(지금보니 이것도 반영 작업해야되네)

 

근데 얘도 좀 멍청해서, 제미니한테 이미지 생성에 필요한 상세한 정보를 md로 넘겨달라해서 던졌는데, 좀 못알아들음...

그래서 일단 대충 맛 만나는 이미지를 쓰기로함...(이미지 생성 AI 추천좀..)

 

3. 프롬프트 검수 진행

여기서 통과되면 최종적으로 이미지 생성 진행!

 

프롬트4는 이미지 품질 검증도 할 예정

 

아래가 단순 생성, 위에가 프롬트 수정

 

----

#잔여 업무

- 이미지 합성 기능(MVP) 도 붙여야하고, 사진 업로드도 붙여야함

- azure가 DB 읽어오는 속도가 너무 느림.... 구조적인 문제일 것 같음... 나중에 리팩토링을 하던, 스케일업을 하던해야지...

- 관리자 페이지 리팩토링

 

h

hyos

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

IT 2026. 4. 30. 20:28

[Claude] Claude 엄청남, 엄청남, 엄청남, 평서문

🚀 [AI 활용 백서] 챗GPT의 가장 강력한 라이벌, '클로드(Claude)' 완벽 가이드: 왜 다들 클로드로 넘어갈까?

요즘 주변에서 "진짜 제대로 된 결과물을 뽑으려면 클로드(Claude)를 써야 해"라는 말, 한 번쯤 들어보셨나요?

챗GPT가 AI 시대를 열었다면, 클로드(Claude)는 우리가 AI를 일상과 업무에 사용하는 방식을 한 차원 끌어올린 '숨은 강자'입니다. 미국 실리콘밸리의 앤스로픽(Anthropic)이라는 기업에서 개발한 이 AI는 현재 전 세계 수많은 헤비 유저들의 최애 툴로 자리 잡고 있습니다.

도대체 클로드가 뭐길래 이렇게 난리인지, 그리고 당장 내 삶에 어떻게 써먹을 수 있는지 가장 쉽고 직관적으로 정리해 드립니다.


🧠 1. 클로드(Claude), 도대체 뭐가 그렇게 특별할까?

AI가 다 거기서 거기 아니냐고요? 클로드를 한 번이라도 써본 사람들은 다음 3가지 압도적인 장점 때문에 다시 돌아가지 못한다고 말합니다.

① "기계 냄새가 안 난다" : 소름 돋게 자연스러운 글쓰기

기존 AI로 블로그 글이나 이메일을 쓰게 해보고, '아, 이건 딱 봐도 번역기 돌린 AI 말투네' 하고 실망하신 적 있으시죠? 클로드의 가장 큰 무기는 바로 '인간보다 더 인간적인 문장력'입니다. 미묘한 뉘앙스, 부드러운 어조, 센스 있는 비유까지 찰떡같이 소화합니다. 정중한 사과 이메일, 통통 튀는 인스타그램 마케팅 문구, 감성적인 에세이까지 어떤 글이든 기가 막히게 써냅니다.

② 책 한 권을 통째로 외우는 '압도적인 기억력'

클로드는 한 번에 읽고 기억할 수 있는 정보의 양(컨텍스트 윈도우)이 어마어마합니다. 수십 장짜리 PDF 논문, 두꺼운 회사 규정집, 혹은 긴 소설 텍스트를 통째로 업로드해도 맥락을 절대 놓치지 않습니다. "이 100페이지짜리 문서에서 30대 여성에게 해당하는 혜택만 3줄로 요약해 줘"라고 하면 단 1초 만에 정확한 답을 찾아냅니다.

③ 눈앞에서 결과물이 뚝딱! 마법 같은 '아티팩트(Artifacts)'

클로드의 하이라이트 기능입니다. AI에게 뭔가를 부탁하면 텍스트로만 답을 주는 게 아니라, 대화창 옆에 아예 완성된 결과물(UI, 표, 다이어그램 등)을 띄워줍니다. 예를 들어 "오늘 섭취한 칼로리를 계산할 수 있는 웹 화면을 짜줘" 혹은 "복잡한 역사를 연도별 타임라인 그래픽으로 그려줘"라고 하면 그 자리에서 눈에 보이는 결과물을 만들어냅니다.


🎯 2. 나에게 맞는 클로드 모델 고르기

클로드에 접속해 보면 여러 가지 모델이 있어서 당황하실 수 있습니다. 딱 이 기준만 기억하세요!

  • ⚡ Haiku (하이크): 엄청 빠르고 가볍습니다. 단순한 요약, 빠른 번역, 가벼운 아이디어 스케치에 딱 맞습니다.
  • 🌟 Sonnet (소네트): 가장 강력히 추천하는 메인 모델입니다. (현재 3.5 Sonnet). 속도와 지능의 밸런스가 완벽하며, 글쓰기, 코딩, 복잡한 문서 분석 등 99%의 작업에서 최고의 성능을 냅니다. 무조건 이걸 쓰시면 됩니다.
  • 👑 Opus (오퍼스): 가장 무겁고 똑똑하지만 속도는 조금 느립니다. 매우 고차원적인 논리 문제나 고난도 추론이 필요할 때만 가끔 꺼내 쓰는 필살기입니다.

🛠️ 3. 지금 당장 클로드 시작하는 법

설치나 복잡한 세팅은 전혀 필요 없습니다. 웹 브라우저만 있으면 누구나 바로 1분 만에 시작할 수 있습니다.

  1. 웹사이트 접속: Claude.ai 에 접속합니다.
  2. 간편 가입: 구글(Google) 계정 등으로 10초 만에 가입을 완료합니다.
  3. 앱 다운로드 (선택): 클로드를 매일 쓰고 싶다면 화면 하단이나 설정에서 Mac/Windows용 데스크톱 앱, 혹은 스마트폰 앱을 다운로드하세요. 접근성이 훨씬 좋아집니다.

🏃‍♂️ 마무리하며: 일단 아무거나 던져보세요!

AI 도구는 눈으로 읽기만 해서는 절대 내 것이 되지 않습니다. 지금 바로 클로드를 켜고, 평소에 귀찮았던 일이나 궁금했던 것을 편하게 물어보세요.

"냉장고에 계란, 양파, 베이컨이 있는데 이걸로 15분 만에 만들 수 있는 자취생용 레시피를 인스타그램 감성으로 써줄래?"

아마 첫 대답을 보는 순간, 여러분도 클로드의 매력에 푹 빠지게 되실 겁니다. 지금 바로 클로드와 함께 똑똑한 하루를 시작해 보세요!

h

hyos

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

COMMENTS