본문 바로가기
공부/Project

[AI Skill] 내 작업 흐름에 맞는 에이전트 스킬 만들기

by Electrohyun 2026. 6. 23.

< technical-decision-record 스킬 사용하러 가기 >

https://github.com/electrohyun/technical-decision-record

 

GitHub - electrohyun/technical-decision-record: 🤖 A Codex Skill for recording technical decisions as reusable Markdown decisi

🤖 A Codex Skill for recording technical decisions as reusable Markdown decision records. 📘 - electrohyun/technical-decision-record

github.com

 

공부하자 공부

 

 안녕하세요! electrohyun입니다. 오늘은 다들 한 번쯤은 들어보셨을 법한 Skill에 대한 내용을 다루려고 합니다. 저도 잘 모르는 내용이라 공부를 하기 위해 이렇게 글을 작성하게 되었고, 스킬이란 무엇인지, 그리고 스킬을 직접 제작해 보며 느낀 점들을 공유해보려고 합니다. 그럼 시작하겠습니다!

 

 


(1) 스킬이란?

 

 AI Agent와 함께 코딩을 하다 보면, 반복해서 같은 지시를 하게 되는 순간이 있었습니다. 코드를 작성한 뒤에 "이 방법이 가장 좋은 게 맞나"같은 질문을 종종 하게 되었습니다. 이런 반복되는 지시를 매번 프롬프트로 작성하는 대신, 재사용 가능한 규칙으로 묶어 사용할 수 있도록 하는 것이 바로 스킬(Skill)입니다.

 

 공식 문서에서도 스킬은 에이전트의 기능을 확장하기 위한 방식으로 설명됩니다. Claude Code에서는 SKILL.md 파일에 지침을 작성하면 Claude가 이를 자신의 도구 목록에 추가하고, 관련 상황에서 사용하거나 사용자가 직접 호출할 수 있다고 설명합니다. 또한 같은 지시사항, 체크리스트, 여러 단계의 절차를 반복해서 붙여 넣고 있다면 이를 스킬로 분리할 수 있다고 안내합니다.

 

 Codex에서도 스킬은 비슷한 개념으로 사용됩니다. Codex 문서에서는 스킬을 특정 작업을 위한 지침, 참고 자료, 선택적인 스크립트를 묶어 에이전트가 워크플로우를 안정적으로 따를 수 있게 하는 단위로 설명합니다. 

 

 정리하면 스킬은 AI 에이전트에게 특정 작업을 더 잘 수행하게 하기 위한 다시 사용할 수 있는 지침 묶음입니다. 작업 절차, 판단 기준, 체크리스트, 예시, 참고자료를 기반으로 정리되어 사람이 매번 직접 프롬프트로 요청하는 것보다 더 정형화되고, 예측 가능한 결과를 유도할 수 있다는 것이 장점입니다.

 (2) Claude와 Codex에서의 Skill

 Claude Code와 Codex 모두 스킬을 SKILL.md 파일 중심으로 구성합니다. 이 파일에는 스킬의 설명과 실제로 에이전트가 따라야 할 지침이 들어갑니다.

 

 Claude Code의 경우 SKILL.md는 YAML frontmatter와 본문 지침으로 구성됩니다. frontmatter에는 스킬이 언제 사용되어야 하는지를 설명하는 description을 작성할 수 있고, 이 설명은 Claude가 해당 스킬을 자동으로 사용할지 판단하는 기준이 됩니다. 사용자가 직접 /skill-name 형태로 호출할 수도 있습니다. [1]

 

 Codex 역시도 SKILL.md를 중심으로 스킬을 구성합니다. 다만 Codex에서는 namedescription을 필수 메타데이터로 사용합니다. Codex는 사용 가능한 스킬들의 이름, 설명, 파일 경로를 먼저 보고 있다가, 작업과 맞는 스킬이 있다고 판단되면 그때 전체 SKILL.md 내용을 읽어 사용합니다. [2]

 

 저장 위치에도 차이가 있습니다. Claude Code에서 개인 스킬은 ~/.claude/skills/<skill-name>/SKILL.md에 둘 수 있고, 프로젝트 전용 스킬은 .claude/skills/<skill-name>/SKILL.md에 둘 수 있습니다. 반면 Codex는 개인 스킬을 $HOME/.agents/skills에 두고, 프로젝트에서는 .agents/skills 디렉터리를 사용합니다.

 

 양쪽 모두 스킬의 핵심 구조는 비슷합니다. SKILL.md 반복 가능한 작업 절차를 작성하고, 필요할 직접 호출하거나 에이전트가 상황에 맞게 자동으로 사용하도록 만드는 방식입니다. 다만 Claude Code /skill-name 기반의 호출 방식과 .claude/skills 구조가 중심이고, Codex는 .agents/skills, $ mention, 그리고 플러그인을 통한 배포 흐름이 강조됩니다.

 

(3) Codex에서 Skill 만들기

 이번에는 제가 실제로 사용 중인 Codex에서 스킬을 한 번 만들어보려고 합니다. 앞에서 정리한 것처럼 Codex Skill은 SKILL.md 파일을 중심으로 구성됩니다. 가장 단순하게는 하나의 폴더 안에 SKILL.md 파일만 있어도 스킬로 사용할 수 있고, 필요하다면 references, scripts, assets 같은 보조 폴더를 함께 둘 수 있습니다.

 

 저는 이번에 두 가지 스킬을 만들어보기로 했습니다.

 

 (1) 기술 의사기록 결정 스킬입니다. 프로젝트를 진행하면서 항상 고민이 되는 부분이 왜 이걸 골라야 할까? 왜 이 구조로 작성해야 할까?라는 점입니다. 그 판단의 이유를 남기기 위한 스킬로써, 문서화를 진행하는 데에 그 목표를 두었습니다.

 

 (2) 제가 제작 중인 서비스 '꼬깃'의 캐릭터 프롬프트 기반 그림 에셋 생성 스킬입니다. 꼬깃 프로젝트의 그림 에셋은 대부분 생성형 AI로 생성한 그림으로 이루어져 있고, 그림체나 색감, 분위기 등이 흔들리지 않도록 기준을 정하는 데에 그 목표를 두었습니다.

 

 공통점은, 역시 둘 다 반복되는 작업이란 점입니다.

 

 $HOME/.agents/skills


 우선, Codex에서 개인적으로 사용할 스킬은 이 위치에 둘 수 있습니다.

.agents/skills

 

 프로젝트에 포함해 사용할 스킬이라면, 레포지토리 안에 이렇게 위치시킬 수 있습니다. 이번에는 제 프로젝트 안에서 사용할 목적이기 때문에, 프로젝트 내부에 .agents/skills 디렉터리를 만들었습니다.

ggogit/
└─ .agents/
   └─ skills/
      ├─ technical-decision-record/
      │  └─ SKILL.md
      └─ ggogit-character-prompt/
         └─ SKILL.md

 

 위에서 알아봤듯, Codex 스킬의 SKILL.md에는 name과 description을 작성해주어야 합니다. Codex가 이 정보를 먼저 보고, 현재 작업에 어떤 Skill이 필요한지 판단합니다. description은 언제 이 스킬을 사용해야 하는지 알려주는 트리거로서 작성해 주는 것이 좋겠습니다.

 

(4) 만든 Skill 살펴보기

 이번에 만든 스킬은 두 가지입니다.

 

 첫 번째는 technical-decision-record입니다. 이 스킬은 프로젝트를 진행하면서 기술 선택이나 구조 변경이 발생했을 때, 그 판단의 이유를 기록하기 위해 만들었습니다. 개발을 하면서 당시에는 당연하게 느껴지더라도, 나중에 돌이켜봤을때 왜 그것을 골랐는지 고민해 보면 실제로는 기억이 나지 않았을뿐더러, 실제로 좋은 다른 선택지도 있었던 경우가 많았습니다. 그래서 이 스킬은 코드 변경이나 리팩터링, 버그 해결, 라이브러리 도입 같은 상황에서 기술 의사결정을 기록하도록 설계했습니다. 판단의 근거나 대안, 트레이드오프를 남기는 것이 목적입니다. 내용은 다음과 같습니다.

 

---
name: technical-decision-record
description: Use when making technical decisions, introducing libraries, changing architecture, fixing bugs, refactoring code, or preparing explanations about why a specific implementation was chosen.
---

# Technical Decision Record Skill

## When to use this skill

Use this skill when the user makes, explains, reviews, or documents a meaningful technical decision.

Use this skill for:
- choosing a library or framework
- changing architecture
- fixing a bug
- refactoring code
- introducing a new pattern
- replacing an existing implementation
- explaining why a specific implementation was chosen
- preparing project retrospectives, blog posts, portfolios, or technical interview answers

## Purpose

This skill exists to help the user record the reasoning behind technical decisions.

The goal is not to simply describe what was implemented.
The goal is to explain why the implementation was chosen, what alternatives were considered, and what trade-offs were accepted.

## Core rule

Do not simply praise the implementation.

Help the user turn a technical choice into a reusable decision record that can later be used in:
- project retrospectives
- blog posts
- portfolio descriptions
- technical interviews
- issue comments
- pull request descriptions
- architecture notes

## What to focus on

When documenting a technical decision, focus on:

- What problem was being solved?
- What solution was chosen?
- What alternatives were considered?
- Why were the alternatives rejected?
- What trade-offs were accepted?
- What improved after the change?
- Is there evidence, metric, or concrete result?
- What would be changed next time?

## Missing context

If important context is missing, ask for it before writing a final decision record.

Ask about:
- the original problem
- the previous implementation
- the chosen solution
- rejected alternatives
- constraints such as time, team size, performance, maintainability, or project scope
- concrete results after the change
- metrics, logs, screenshots, user feedback, or test results if available

Do not force the user to answer every question.
Ask only for the missing information that would meaningfully improve the record.

## Decision record format

When preparing a technical decision record, use the following structure:

## Decision summary

Briefly summarize the decision in one or two sentences.

## Problem

Explain what problem, limitation, bug, or uncertainty existed before the decision.

## Chosen solution

Describe the solution that was selected.

Focus on what changed and how it solves the problem.

## Alternatives considered

List the realistic alternatives that were considered.

Include options that were rejected, postponed, or intentionally avoided.

## Why alternatives were rejected

Explain why each alternative was not chosen.

Use concrete reasons such as:
- too complex for the current scope
- poor maintainability
- unnecessary dependency
- performance concerns
- weak type safety
- difficult testing
- poor user experience
- mismatch with project architecture
- too much migration cost

## Trade-offs accepted

Explain what was gained and what was sacrificed.

Good technical decisions usually have trade-offs.
Do not pretend that the chosen solution is perfect.

## Result

Explain what improved after the decision.

Use concrete evidence when possible:
- reduced code duplication
- simpler API
- fewer bugs
- faster rendering
- better readability
- easier testing
- clearer responsibility separation
- improved user flow
- measurable performance improvement

## Evidence

Include metrics, examples, logs, screenshots, test results, or before-and-after comparisons if available.

If there is no concrete evidence yet, clearly say that the result is based on implementation reasoning or qualitative observation.

## What I would change next time

Explain what could be improved if the same decision were made again.

Mention future improvements, remaining risks, or follow-up tasks.

## Writing style

Prefer concise and reusable writing.

Write in a way that can be reused later in:
- a blog post
- a portfolio project description
- a technical interview answer
- a pull request description
- a project retrospective

Avoid vague praise such as:
- "This is a good implementation."
- "This was a clean solution."
- "It improved the code a lot."

Prefer specific explanations such as:
- "This reduced duplicated validation logic by moving the responsibility into a shared schema."
- "This made the dependency direction clearer by preventing feature modules from importing each other directly."
- "This avoided adding a new library because the required behavior could be implemented with the existing platform API."

## Output behavior

When the user asks for a technical decision record, output a clean markdown record.

When the user is still thinking through a decision, help compare options first.

When the user only provides code or a short explanation, infer what you can, but clearly mark uncertain parts and ask for missing context if needed.

## One-line rule

Do not just explain what was built.
Record why it was built that way.

 

 두 번째는 ggoggo-character-assets입니다. 제가 제작 중인 프로젝트 꼬깃에는 꼬꼬라는 병아리 마스코트가 있는데요, 캐릭터 에셋을 계속 만들다 보면 같은 설명이 반복되고, 프롬프트가 조금씩 달라질 때가 있습니다. 그럴 때마다 캐릭터의 느낌이 조금 달라졌던 기억이 나네요.

 

마스코트 꼬꼬

 

 이 스킬은 꼬꼬 캐릭터의 노란 병아리 캐릭터, 빨간 벼슬, 주황색 부리와 발 등 세부 묘사를 담아 표현했고, 새 캐릭터를 만들지 마라, 같은 세계관으로 제작해라 라는 지침은 에이전트의 도움을 받아 추가하게 되었습니다.

 

---
name: ggoggo-character-assets
description: Use when creating ggoggo character assets, GGoGit mascot illustrations, crayon-style chick images, or image-generation prompts that must stay visually consistent with existing ggoggo reference images.
---

# ggoggo Character Asset Skill

## When to use this skill

Use this skill when creating, editing, or preparing prompts for ggoggo, the mascot character of the GGoGit service.

Use this skill for:
- ggoggo character assets
- GGoGit mascot illustrations
- crayon-style chick images
- UI-friendly mascot images
- image-generation prompts that need to match existing ggoggo references

## Purpose

This skill exists to avoid repeating the same character description every time a new ggoggo asset is needed.

For GGoGit, the most important goal is not making each individual image perfect on its own.
The goal is making every mascot asset feel like it belongs to the same GGoGit world.

## Core rule

Do not design a new chick mascot.

Create another ggoggo asset that matches the existing character identity.

## Reference images

Use the existing ggoggo reference images as the primary source of character identity.

Place reference images in:

- assets/mascot/ggoggo-greet.webp
- assets/mascot/ggoggo-adventure.webp
- assets/mascot/ggoggo-podium.webp
- assets/mascot/ggoggo-smile.webp
- assets/mascot/ggoggo-thumbs.webp

When preparing an image prompt, use 3 to 5 reference images if possible.

Do not copy only one reference image.
Do not overfit to a single pose, expression, or composition.

Instead, infer the shared traits across the reference images.

Focus on:
- silhouette
- face shape
- eye style
- beak shape
- cheek blush
- red comb shape
- body proportions
- rough black outline
- crayon or colored-pencil texture
- warm childlike doodle atmosphere

## Character identity

ggoggo is a yellow chick mascot for the GGoGit service.

Preserve these traits:
- round and simple chick silhouette
- yellow body
- red comb on top of the head
- orange beak
- orange feet
- round cheek blush
- black, slightly rough hand-drawn outline
- crayon or colored-pencil texture
- cute, warm, friendly, childlike doodle style
- simple mascot design that fits inside a casual learning-service UI

## Priority order

When creating a new ggoggo asset, prioritize the following:

1. The result must still look like ggoggo.
2. The crayon-like hand-drawn texture must be preserved.
3. The asset must feel natural beside existing GGoGit UI and mascot assets.
4. The requested pose, expression, action, prop, or situation must be reflected.
5. The result must stay simple, cute, and not overly polished.

## Allowed variations

The following elements may change depending on the request:
- facial expression
- pose
- action
- small props
- simple clothing or accessories
- simple background doodles
- UI-related objects such as cards, buttons, books, laptops, commits, branches, badges, medals, trophies, or signs

However, these changes must not make ggoggo look like a different character.

## Avoid

Avoid the following:
- 3D rendering
- realistic chick anatomy
- smooth vector illustration
- glossy mascot design
- overly polished corporate illustration
- Pixar, Disney, anime, or game-character style
- complex feather details
- dramatic lighting
- excessive shading
- excessive depth or gloss
- sharp or aggressive facial features
- major silhouette changes
- redesigning the mascot instead of extending the existing asset set

## How to use references

When writing an image-generation prompt, do not describe ggoggo too much in text.

The reference images should define the character identity.
The text prompt should mainly describe the new pose, action, expression, situation, or prop.

Use this structure:

1. Say that the attached reference images define ggoggo's character identity.
2. Describe the new asset to create.
3. Add a short consistency instruction.
4. Add avoid or negative style constraints.

## Prompt template

Using the provided ggoggo reference images as the character identity reference, create a new asset of ggoggo [describe the requested action, pose, expression, prop, or situation].

Keep the same yellow chick mascot identity, red comb, orange beak and feet, round cheek blush, rough black crayon outline, and childlike colored-pencil texture.

The result should feel like another asset from the same GGoGit UI world, not a redesigned character.

Avoid 3D rendering, smooth vector art, realistic chick details, glossy mascot design, excessive shading, and overly polished corporate illustration style.

## If reference images cannot be attached

If the current tool or environment cannot directly attach reference images, do not pretend that the images were used.

Instead:
1. Prepare the prompt based on this skill.
2. Tell the user to attach 3 to 5 ggoggo reference images together with the prompt.
3. Keep the prompt concise so the reference images can guide the character identity.

## Output format

When asked to prepare a ggoggo image prompt, output the following sections:

## Reference images to attach

List 3 to 5 reference image paths from the assets/mascot directory.

## Final prompt

Write the final image-generation prompt.

## Avoid

List the styles or changes to avoid.

## Filename suggestion

Suggest a concise filename if useful.

## One-line rule

Do not create a new mascot.
Create a new ggoggo asset from the same world.

 

 이렇게 두 가지 스킬을 소개해드렸지만, 이번 글에서는 편의를 위해 첫 번째 스킬인 기술 결정 관련 스킬만을 다뤄보도록 하겠습니다.

 

(5) 스킬 사용해 보기

 

 이제 직접 사용해 보겠습니다. 잘 동작할지 기대되는 부분인데요. 우선 프로젝트 안에 스킬을 하나 작성해 줍니다.

 

 현재는 SKILL.md 말고도 눈에 들어오는 파일이 하나 있습니다. 바로 agents/openai.yaml입니다. 이 파일에는 다음과 같은 내용이 들어 있습니다.

 

interface:
  display_name: "Technical Decision Record"
  short_description: "Record technical choices and trade-offs"
  default_prompt: "Use $technical-decision-record to document why this implementation was chosen."

 

 SKILL.md는 스킬의 본체, agents/openai.yaml은 스킬을 소개하기 위한 메타데이터입니다. 스킬이 실제로 어떤 방식으로 동작해야 하는지는 SKILL.md에 작성하고, openai.yaml에는 사용자에게 보여줄 이름, 짧은 설명, 기본 예시 프롬프트를 적어둡니다. 

 

 Codex에는 skill-creator라는 시스템 스킬이 있고, 저는 Codex에게 이 스킬을 사용해서 프로젝트 전용 스킬을 만들어달라고 요청했습니다. skill-creator는 말 그대로 스킬을 만들기 위한 스킬입니다. 새 스킬을 만들 때 어떤 폴더 구조를 가져야 하는지, SKILL.md에는 어떤 내용을 넣어야 하는지, agents/openai.yaml 같은 메타데이터 파일은 어떤 역할을 하는지 안내해 줍니다. 또한 스킬 이름은 어떤 규칙을 따라야 하는지, 필요하다면 scripts, references, assets 같은 보조 리소스를 어떻게 나눌지도 정해줍니다.

 

 이번에는 위에서 정리한 SKILL.md를 넘겨주었고, Codex에게 technical-decision-record라는 프로젝트 전용 스킬을 만들어달라고 요청했습니다. 그 결과 .agents/skills/technical-decision-record 경로 아래에 SKILL.md와 agents/openai.yaml이 생성되었습니다.

즉, 저는 “이런 목적의 스킬을 만들고 싶다”라고 요청했고, Codex는 내장된 skill-creator 스킬을 활용해 Codex가 이해할 수 있는 표준 구조로 스킬을 만들어준 셈입니다.

 

 그러면 우선, '기술', '의사결정' 같은 키워드를 담아 채팅을 보내보면...

 

 

 됩니다! 스킬을 인식하고, 기준으로서 참고합니다. 이어서, 현재 열려있는 렌더링 성능 개선 이슈를 골라 담론을 이어가 보겠습니다.

 

 "45번 이슈에 대해 이야기해 보자. 현재 원인이 뭐야?"

 

 

 Codex는 원인을 크게 세 가지로 정리했습니다.

 1. 첫 화면 이미지가 많고 priority/sizes 기준이 명확하지 않음
 2. AppShell이 클라이언트 컴포넌트라 초기 JS 번들이 커질 가능성
 3. 클릭 후 필요한 모달/메뉴/사운드 코드가 초기 로드에 섞여 있음

 

 그리고 다음으로 가장 중요한, 이 스킬의 핵심 역할 답변 부분이 나옵니다.

 

 

 스킬이 의도했던 바처럼, 원인을 파악하는 데에서 멈추지 않고, 바로 다음 작업으로 나아갈 수 있도록 질문을 제시해 줍니다. 이번 경우엔 첫 화면에서 필요한 리소스와 클릭 이후에 필요한 리소스를 분리할 것인지가 핵심 결정이 되었네요. 다음 단계에서는 스킬을 한번 더 사용해서, 이를 글로 정리할 수 있도록 해보겠습니다.

 

 "$technical-decision-record - 그 분석을 기반으로 이미지의 우선순위를 정리하고 사운드, 모달, 메뉴 관련 코드를 지연 로드해 보면 좋겠네. 이제 이런 의사결정을 마크다운 문서로 정리해 보자."

 

작업 결과

 

 이렇게 문서가 생성되었습니다. 자세한 내용은요...

 

# Issue #45 초기 렌더링 성능 개선 의사결정

## Decision summary

`/lobby`의 초기 렌더링 성능을 개선하기 위해 첫 화면에 필요한 리소스와 사용자 상호작용 이후에만 필요한 리소스를 분리한다.

첫 화면에서 항상 보이는 이미지에만 명확한 우선순위를 부여하고, 사운드, 모달, 프로필 메뉴 관련 코드는 사용자 입력이 발생하거나 해당 기능이 실제로 필요해지는 시점까지 지연 로드한다.

## Problem

`/lobby` 페이지는 FCP/LCP 성능이 낮게 측정될 가능성이 있다. 원인은 초기 로드 시점에 중요한 작업과 중요하지 않은 작업이 함께 실행되기 때문이다.

현재 코드에서 확인한 주요 원인 후보는 다음과 같다.

- 헤더와 로비 카드에 여러 이미지가 렌더링되지만, 어떤 이미지가 첫 화면의 핵심 이미지인지에 대한 `priority`와 `sizes` 전략이 명확하지 않다.
- `AppShell`이 클라이언트 컴포넌트이며 사운드 처리, 프로필 메뉴, 로그인 진입, 아이콘, 이미지 에셋을 함께 가져온다.
- 로그인 모달, 프로필 메뉴, 사운드 재생처럼 클릭 이후에만 필요한 코드가 초기 JavaScript 경로에 포함될 수 있다.

## Chosen solution

두 가지 방향으로 최적화한다.

첫째, 이미지 로딩 우선순위를 명확히 정한다.

- 첫 viewport에서 항상 보이고 LCP 후보가 될 가능성이 높은 이미지에만 `priority`를 적용한다.
- 반응형 이미지에는 실제 표시 크기에 맞는 `sizes`를 지정한다.
- 첫 화면에 항상 보이지 않거나 조건부로 보이는 마스코트 이미지는 preload 대상에서 제외한다.

둘째, 상호작용 전용 JavaScript를 지연 로드한다.

- `howler`가 `/lobby` 초기 번들에 불필요하게 포함되지 않도록 사운드 관련 코드를 지연 로드한다.
- 로그인 모달과 인증 모달의 내부 콘텐츠는 모달이 열릴 때 로드한다.
- 프로필 메뉴는 초기 헤더에 필요한 아바타 버튼과, 클릭 후 필요한 메뉴 내부 로직을 분리한다.

## Alternatives considered

- 보이는 모든 이미지에 `priority`를 추가한다.
- 로비 페이지의 마스코트 이미지를 제거하거나 크게 줄인다.
- 현재 구조를 유지하고 브라우저 캐시에 의존한다.
- `AppShell` 전체를 대부분 서버 컴포넌트로 다시 설계한다.
- 사운드 코드만 지연 로드하고 모달/메뉴 코드는 그대로 둔다.

## Why alternatives were rejected

보이는 모든 이미지에 `priority`를 추가하는 방식은 선택하지 않았다. preload 후보가 너무 많아지면 브라우저가 중요하지 않은 리소스까지 높은 우선순위로 가져오게 되고, 오히려 핵심 이미지 로딩을 방해할 수 있기 때문이다.

마스코트 이미지를 제거하는 방식도 선택하지 않았다. 꼬꼬는 서비스의 정체성을 만드는 중요한 요소다. 문제는 마스코트 이미지 자체가 아니라, 어떤 이미지를 먼저 로드해야 하는지 정리되어 있지 않은 점이다.

브라우저 캐시에 의존하는 방식은 첫 방문 또는 제한된 네트워크 환경의 성능 문제를 해결하지 못한다. Lighthouse의 Mobile / Navigation 측정은 초기 로드 비용을 드러내므로, 캐시는 근본적인 해결책이 아니다.

`AppShell` 전체를 서버 컴포넌트 중심으로 재설계하는 방식은 보류했다. 장기적으로는 의미가 있지만, 이슈 #45의 범위에서는 변경 비용이 크다. 먼저 이미지 우선순위 정리와 상호작용 코드 지연 로드로 해결 가능한지 확인하는 편이 적절하다.

사운드 코드만 지연 로드하는 방식도 충분하지 않다. 모달과 프로필 메뉴 역시 클릭 전에는 필요하지 않은 코드이며, 초기 JavaScript 비용에 영향을 줄 수 있기 때문이다.

## Trade-offs accepted

이 결정은 초기 로드 경로를 줄이는 대신 컴포넌트 경계가 조금 더 복잡해지는 것을 받아들인다.

모달, 메뉴, 사운드 코드를 지연 로드하면 사용자가 해당 기능을 처음 열 때 약간의 지연이 생길 수 있다. 하지만 이 기능들은 첫 렌더링 이후에 사용되므로, FCP/LCP에 직접 영향을 주는 초기 로드 비용을 줄이는 편이 더 중요하다고 판단했다.

이미지 우선순위 정책도 더 신중한 판단을 요구한다. 앞으로는 `priority`를 일반적인 성능 개선 옵션처럼 사용하는 대신, 정말 첫 viewport에서 중요한 이미지인지 확인한 뒤 적용해야 한다.

## Result

기대하는 결과는 다음과 같다.

- `/lobby` 첫 렌더링 중 중요하지 않은 리소스 경쟁이 줄어든다.
- LCP 후보 이미지가 더 명확한 우선순위로 로드된다.
- 사운드, 모달, 메뉴 코드가 초기 JavaScript 번들에 주는 부담이 줄어든다.
- 마스코트 이미지를 제거하거나 로비를 재설계하지 않고도 이슈 #45의 범위 안에서 성능 개선을 시도할 수 있다.

## Evidence

현재 근거는 코드 분석과 이슈 #45에 기록된 Lighthouse 관찰 내용을 기반으로 한다.

코드에서 확인한 신호는 다음과 같다.

- `AppShell`이 `playClickSound`를 import하고, 이 경로를 통해 `soundPlayer`와 `howler`가 연결된다.
- `StartButton`이 모달과 로그인 콘텐츠를 직접 import한다.
- `AppShellProfileMenu`가 프로필 메뉴 동작과 사운드 설정 UI를 직접 포함한다.
- `/lobby`에는 여러 마스코트 이미지와 헤더 이미지가 렌더링되지만, 첫 viewport 이미지 우선순위 정책이 문서화되어 있지 않다.

후속 작업에서는 다음 기준으로 실제 개선 여부를 확인한다.

- `pnpm build`
- `next start`
- Chrome Lighthouse `/lobby` Mobile / Navigation 측정
- 변경 전후 LCP breakdown 비교
- unused JavaScript 항목이 계속 높을 경우 번들 분석 추가

## What I would change next time

이 변경 이후에도 LCP가 높다면 Lighthouse의 LCP breakdown을 기준으로 후속 작업을 분리한다.

- TTFB: 서버 데이터 fetching과 Supabase query waterfall을 확인한다.
- Load Delay: 이미지 preload와 request priority를 확인한다.
- Load Time: 이미지 크기와 인코딩을 확인한다.
- Render Delay: hydration, CSS, main-thread JavaScript 비용을 확인한다.

unused JavaScript 항목이 계속 높다면, 정적인 레이아웃은 서버 렌더링으로 유지하고 상호작용 컨트롤만 작은 클라이언트 컴포넌트로 분리하는 더 큰 `AppShell` 구조 개선을 검토한다.

 

 이렇게 정리가 된 모습을 보실 수 있습니다. 느리다고 분석하고 끝이 아니라, 원인의 후보를 찾고, 결정에 대한 질문을 건네고, 유저가 선택한 방법대로 대안과 트레이드오프, 검증 이 세 가지를 문서로 정리하는 모습입니다. 스킬로서 작동하도록 의도한 점이 정말 잘 나타나고, 멈춰 설 수 있는 부분에서 질문과 추진력을 붙여주는 것이 이점이라고 생각이 되네요.

 

(5) 개선하기

 사용해 보니 바로 개선할 점이 눈에 들어왔습니다. 세 가지 정도 있네요.

 

 (1) 문서로 남길 것 -> 위에서는 문서로 기록된 모습이지만, 사실 채팅으로 뱉어준 내용입니다. 실제 문서로 남겨준다면 나중에 참고하기가 더욱 좋을 것 같다는 생각입니다.

 (2) 한국어로 기록할 것 -> 스킬이 영어로 작성되어 있기 때문인지, 작성 내용도 영어로 이루어져 있었습니다. 실제로 기록하고 회고에 활용할 수 있도록 한국어로 출력하라는 것을 명시해 주도록 하겠습니다.

 (3) 질문을 1가지 -> 3가지로 늘리면 어떨까? 하는 생각이 듭니다. 개인적으로는 보이는 게 많을수록 더 많은 것을 떠올리고 판단할 수 있을 거란 생각입니다. 예를 들면 #45 이슈에서는 이런 질문이 더 있을 수 있습니다.

 

 - LCP 후보 이미지를 뭘로 볼 것인가?

 - 초기 번들에서 반드시 제외해야 하는 코드는 무엇인가?

 - 단기 최적화와 장기적인 AppShell 구조 개선 중 어디까지 이번 이슈의 범위로 볼 것인가?

 

 구체적이면 구체적일수록, 그리고 작으면 작을수록, 소요되는 시간도, 비용도 작아지면서 추진력을 더 올려줄 수 있지 않을까요? 바로 시작해 보겠습니다. 

 

(5-1) 문서로 남기기

# Technical Decision Record

## Purpose

## Core Rule

## Workflow

## Context To Gather

## Missing Context

## Decision Record Format

## Decision summary

## Problem

## Chosen solution

## Alternatives considered

## Why alternatives were rejected

## Trade-offs accepted

## Result

## Evidence

## What I would change next time

## Alternative Rejection Reasons

## Result Examples

## Writing Style

## Output Behavior

 

 현재 SKILL.md의 목차입니다. "문서로 남겨달라"라는 지시는 명백히 가장 밑의 Output Behavior 쪽입니다. 추가해 보겠습니다.

 

밑줄친 부분이 추가된 부분

 

 첫 번째 개선점입니다. 결과를 채팅 안에서만 끝내지 않아야 합니다. 문서로 남길 수 있어야 합니다. 실제로는 이슈, PR, 회고 문서에 붙여 넣어야 하므로, 독립적인 Markdown 문서 형태로 출력하도록 지침을 추가했습니다.

 

(5-2) 한국어로 남기기

 이번에는 Writing Style 안쪽에 추가해 보겠습니다.

 

 

 두 번째 개선점입니다. 출력 언어입니다. 제가 실제로 기록하고 회고나 블로그에 활용하려면 한국어로서 기록해 두는 편이 더 자연스럽기 때문에, 사용자의 언어를 따르고 한국어 요청에는 한국어로 기록하도록 지침을 추가했습니다.

 

(5-3) 질문 3가지로 늘리기

 마지막 개선점은 질문 방식입니다. 이번에는 Workflow Missing Context 양쪽에 관련 지침을 추가했습니다. 여기서 Missing Context는 의사결정 기록을 작성하기 전에 정보가 부족할 때, AI가 어떤 내용을 되물어봐야 하는지 정해두는 영역입니다.

 

 예를 들어 사용자가 “이번에 Zustand 대신 TanStack Query로 바꿨어.”라고만 말했다고 해봅시다.

 

 프론트엔드 경험이 있다면 이 문장만으로는 조금 어색하게 느껴질 수 있습니다. Zustand와 TanStack Query는 완전히 같은 역할을 하는 도구라기보다는, 각각 클라이언트 상태와 서버 상태 관리에 더 강점을 가지는 도구이기 때문입니다. 따라서 이 문장만 보고 바로 의사결정 기록을 작성하면, 실제 맥락과 다른 기록이 만들어질 수 있습니다.

 

 물론 사용자가 정말로 두 도구의 역할을 혼동했을 수도 있고, 반대로 프로젝트 내부에만 존재하는 숨겨진 맥락이 있을 수도 있습니다. 그래서 AI가 바로 단정하지 않고, “왜 바꿨는지”, “기존 문제는 무엇이었는지”, “역할을 완전히 대체한 것인지 아니면 분리한 것인지”, “결과는 어땠는지”를 먼저 확인하도록 했습니다.

 

 즉, Missing Context는 AI가 부족한 정보를 임의로 채워 넣지 않게 하기 위한 방지 장치입니다. 질문을 통해 의사결정의 맥락을 충분히 확보한 뒤, 그 내용을 바탕으로 기록을 남기게 하는 것이 목적입니다.

 

 

 

 Workflow에는 “기록을 작성하기 전에 핵심 결정 질문을 먼저 정리한다”는 흐름을 추가했고, Missing Context에는 “질문은 한 번에 최대 3개까지만 하고, 의사결정에 직접 도움이 되는 질문을 우선한다”는 규칙을 추가했습니다.

 

(5-4) 확인하기

 이제 다시, 4번의 과정을 반복해 보겠습니다. 체크리스트는 다음과 같습니다. 기존 스킬의 결과로 생성된 문서는 삭제합니다.

 

 (1) 문서로 기록할 것

 (2) 한국어로 기록할 것

 (3) 질문을 3개 던질 것

 

 

 첫 질문입니다. 역시 스킬 참고를 잘해주고 있습니다.

 

현재의 대답 마무리 부분

 

 이번에는 아까와 달리, 첫 질문부터 3개의 질문을 합니다. 아까는 어떻게 했냐면요...

 

이전의 대답 마무리 부분

 성공적으로 3개의 질문을 해주고 있지만, 한번 더 확인해 봅시다. 이슈를 선택한 후의 질문 3개가 원래 목적이었으니까요. 아까처럼 이어서 가봅시다. "45번 이슈에 대해 이야기해 보자. 현재 원인이 뭐야?"

 

현재의 대답 마무리 부분

 

 좋습니다. 계획한 대로 3가지 질문을 던져줍니다. 하나 완료했습니다.

 

 (1) 문서로 기록할 것

 (2) 한국어로 기록할 것

 (3) 질문을 3개 던질 것 ✅

 

 참고로 이전의 대답은 이랬습니다. 1개가 아니라 3개를 답변하도록 바꾸는 데에 성공했네요.

이전의 대답 마무리 부분

 

 그러면 이제 기록해 봅시다. 아까처럼 질문하겠습니다.

 

 

 일부러 문서화 관련 이야기는 하지 않았는데요, 어떻게 작동할까요?

 

 

와!

 

 결과적으로 의사결정이 문서화라는 결론으로 이어졌고, 출력도 한국어 Markdown 문서 형태로 잘 정리되었습니다. 처음 의도했던 것처럼 분석에서 멈추지 않고, 원인 후보를 정리하고, 결정해야 할 질문을 제시한 뒤, 사용자가 선택한 방향에 맞춰 대안, trade-off, 검증 방법까지 남기는 모습입니다. 세 가지 목표 모두 달성하였습니다!

 

 (1) 문서로 기록할 것

 (2) 한국어로 기록할 것

 (3) 질문을 3개 던질 것 ✅

 

 다만 아쉬운 점은, 처음 원인을 분석하는 단계에서는 스킬이 자연스럽게 트리거 되었지만, 이후 제가 “이번 #45의 범위는 이 정도만 하자. 이 방향으로 가자.”라고 말했을 때는 스킬을 명시하지 않으면 문서화를 하는 것이 아닌 바로 작업을 이어가는 상황이 되었네요. 이는 Codex가 해당 문장을 “의사결정을 더 검토해야 하는 상황”이 아니라, “사용자가 이미 방향을 확정했으니 바로 실행하면 되는 상황”으로 해석했기 때문이라고 보입니다. 자동 트리거는 편리하지만, 중요한 기록 작업이라면, 현재는 $technical-decision-record처럼 명시적으로 호출하는 편이 더 안정적이라는 것을 알 수 있었습니다.

 

 이 부분은 차후 개선할 여지가 있습니다. 예를 들어 description에 issue scope나 implementation direction 같은 표현을 더 강하게 넣거나, Trigger Examples 섹션을 추가해 “이 방향으로 가자”, “이번 이슈 범위는 여기까지로 하자” 같은 문장도 의사결정 기록의 신호로 인식하게 만들 수 있습니다. 또한 Output Behavior에 사용자가 방향만 확정했을 때는 바로 최종 문서를 작성하지 말고, 먼저 기록 여부를 확인하도록 하는 규칙을 추가할 수도 있습니다.

 

 이번 섹션에서는 여기까지 정리하려고 합니다. 실제 프로젝트 이슈에 적용해 보면서 부족한 점을 발견하고 다시 개선 방향을 잡아가는 과정을 통해 스킬을 고쳐가는 과정을 통해 더 알아갈 수 있었던 것 같습니다.

 

(6) 배포하기

로고도 만들어보았습니다. technical-decision-record의 3개의 질문은 3개의 관점을 나타냅니다.

 

 이렇게 technical-decision-record는 특정 프로젝트에 종속되지 않고 사용할 수 있을법한 스킬로서 설계되었습니다. 따라서 배포까지 진행해보려 합니다. 스킬을 별도 저장소로 분리하고, Codex Plugin 형태로 패키징 해보기로 했습니다.

 

 Codex에서 스킬은 작업 지침을 정의하는 단위이고, Plugin은 이러한 Skill을 설치 가능한 형태로 묶는 배포 단위입니다. 즉, 개인 프로젝트 내부에서만 사용할 스킬이라면 .agents/skills에 두는 것으로 충분하지만, 여러 프로젝트에서 재사용하거나 다른 사람에게 공유하고 싶다면 Plugin 형태가 더 적합하다고 볼 수 있습니다. 먼저 technical-decision-record를 별도 저장소로 분리했습니다.

 

 

 

 플러그인의 핵심은 .codex-plugin/plugin.json입니다. 이 파일에는 플러그인의 이름, 버전, 설명, 그리고 어떤 스킬을 포함하는지 작성합니다. 

 

{
  "name": "technical-decision-record",
  "version": "1.0.0",
  "description": "Record technical decisions, alternatives, trade-offs, and verification plans as reusable Markdown decision records.",
  "author": {
    "name": "electrohyun",
    "email": "dev.electrohyun@gmail.com",
    "url": "https://github.com/electrohyun"
  },
  "repository": "https://github.com/electrohyun/technical-decision-record",
  "license": "MIT",
  "keywords": [
    "codex",
    "skill",
    "technical-decision",
    "decision-record",
    "documentation"
  ],
  "skills": "./skills/",
  "interface": {
    "displayName": "Technical Decision Record",
    "shortDescription": "Turn technical choices into reusable decision records.",
    "longDescription": "A Codex skill for documenting technical decisions, alternatives, trade-offs, evidence, and follow-up plans as reusable Markdown records.",
    "developerName": "electrohyun",
    "category": "Productivity",
    "capabilities": ["Read", "Write"],
    "websiteURL": "https://github.com/electrohyun/technical-decision-record",
    "brandColor": "#FAFAFA",
    "logo": "./assets/logo.png"
  }
}

 

실제 스킬은 skills/technical-decision-record/SKILL.md에 배치했습니다. plugin.json에서는 "skills": "./skills/"로 해당 경로를 가리키도록 구성했습니다. 이후 Codex가 이 플러그인을 설치할 수 있도록 marketplace.json를 추가했습니다.

 

{
  "name": "technical-decision-record",
  "interface": {
    "displayName": "Technical Decision Record"
  },
  "plugins": [
    {
      "name": "technical-decision-record",
      "source": {
        "source": "url",
        "url": "https://github.com/electrohyun/technical-decision-record.git",
        "ref": "main"
      },
      "policy": {
        "installation": "AVAILABLE",
        "authentication": "ON_INSTALL"
      },
      "category": "Productivity"
    }
  ]
}

 

 이제 Codex CLI에서 marketplace를 추가하고, 플러그인을 설치할 수 있습니다.

 

codex plugin marketplace add electrohyun/technical-decision-record --ref main
codex plugin add technical-decision-record@technical-decision-record

 

 

 이번 스킬은 여러 프로젝트에서 반복적으로 사용할 수 있는 도구이기 때문에, 특정 프로젝트에만 두기보다는 전역으로 설치해 사용하는 방식으로 설정했습니다. 설치 후에는 Codex의 plugin cache에 플러그인이 추가됩니다.

 

~/.codex/plugins/cache/technical-decision-record/technical-decision-record/1.0.0

 

설치가 끝난 뒤에, Codex를 재시작하고 /skills 명령어로 스킬이 정상적으로 인식되는지 확인합니다.

 

/skills

 

 목록에 technical-decision-record가 보이면 설치가 완료된 것입니다. 배포용 저장소인 만큼 README도 함께 정리했습니다. 스킬의 목적, 설치 방법과 사용 예시를 포함해 다른 사람이 바로 따라 할 수 있도록 구성했습니다. 또한 영어, 한국어, 일본어, 중국어 문서를 따로 작성하고, README 상단에서 각 언어 문서로 이동할 수 있도록 링크를 추가했습니다.

 

<p align="center"> 
  <a href="./README.md">English</a> | 
  <a href="./README.ko.md">한국어</a> | 
  <a href="./README.ja.md">日本語</a> | 
  <a href="./README.zh-CN.md">简体中文</a> 
</p>

 

 여기까지 진행함으로써, technical-decision-record를 Codex Plugin으로 배포할 수 있었습니다.

 

(7) 후기

 이번에 스킬을 만들어보면서 느낀 점은, 실제로 만들어보고 프로젝트에 적용해 보니 언제 이 스킬이 동작해야 하는지 설정하는 부분이 더 중요했던 것 같습니다. 예를 들면, technical-decision-record 스킬은 모든 기술 대화를 문서로 바꾸면 안 됩니다. 사용자가 아직 고민 중이라면 먼저 선택지를 비교하고, 맥락을 정리하는 쪽이 더 자연스럽습니다. 반대로 사용자가 “이 방향으로 가자”, “이번 이슈 범위는 여기까지로 하자”처럼 결정을 확정했다면, 그때는 의사결정 기록으로 남길 수 있어야 합니다. 이런 부분에서 편의성을 고를지, 아니면 편의성을 조금 희생하더라도 기준을 명확히 할지 고민하는 과정이 필요했네요.

 

 그 외에, 앞으로 스킬을 만들 때 이렇게 해야겠다 싶은 부분도 떠오릅니다. 총 세 가지 정도 떠오르는데요,

 

 (1) Skill의 목적을 좁게 잡아야 합니다.
 너무 많은 일을 하게 만들면 오히려 언제 사용해야 하는지 애매해집니다. technical-decision-record도 '기술 문서 작성 스킬'이 아니라 '기술 의사결정 기록 스킬'로 범위를 좁혀 작성했기 때문에 이렇게 글 하나로 끝낼 수 있었던 것 같네요.

 

 (2) 출력 형식보다 동작 조건이 중요합니다.
 Markdown 형식으로 예쁘게 출력하는 것도 필요하지만, 그보다 중요한 건 어떤 상황에서 질문을 해야 하고, 어떤 상황에서 바로 문서를 작성해야 하는지 정하는 것이었습니다.

 

 (3) 실제로 사용해 봐야 부족한 점이 보이는 것 같습니다.
 처음부터 완성된 스킬을 만들기는 어렵습니다. 실제 이슈에 적용해 보고, 원하는 방식으로 동작하지 않는 부분을 발견한 뒤, description이나 workflow를 수정하는 과정이 필요했습니다.

 

 이번 스킬 작업을 통해 AI Agent를 더 잘 사용하는 방법에 대해 고민하게 되었습니다. 이전에 eslint 플러그인을 만들었던 경험이 있는데, 그때처럼 반복되는 판단 기준과 작업 방식을 스킬로 분리해 두면서 이렇게 작업하면 앞으로 작업이 훨씬 안정적으로 흘러가겠구나 하는 느낌을 받았습니다.

 

 저의 경우 개발 과정에서 종종 “왜 이렇게 구현했는가, 혹은 구현해야 하는가”를 고민하거나 기록하는 일이 가끔씩 뒤로 밀리곤 했었는데, 나중에 회고를 하거나, PR을 설명하거나 할 때는 물론 개발 과정에서도 해당 스킬을 적극적으로 사용하면서 조금 더 의식적으로 고민하고 기록하는 습관을 들여보려고 합니다.

 

 technical-decision-record 스킬은 앞으로도 계속 다듬어볼 생각입니다. 프로젝트를 진행하면서 의미 있는 기술 선택이 생길 때마다 이 Skill을 사용해 기록을 남기고, 실제로 어떤 질문이 도움이 되었는지, 어떤 출력 형식이 더 재사용하기 좋았는지 고민해 보며 계속 개선해보려고 합니다.

 

 이번 글에서는 Claude와 Codex의 Skill 개념을 살펴보고, 직접 Codex Skill을 만들어 프로젝트에 적용한 뒤, Plugin 형태로 배포하는 과정까지 정리해 보았습니다. 지금까지 electrohyun이었습니다. 감사합니다. ⚡️


참고자료

[1] Anthropic, Claude Code Docs, “Extend Claude with skills” 
[2] OpenAI Developers, “Agent Skills”