💎 Gem Programming: 개발자는 이제 보석을 캐고, 조합한다
AI가 코드를 다시 만들 수 있는 시대에는 코드를 그대로 복사하기보다, 검증된 프로젝트에서 좋은 설계와 판단을 ‘Gem’으로 캐내고 새로운 프로젝트에 맞게 조합하는 방식이 더 유용할 수 있어요.

개발자는 오래전부터 코드를 재사용해왔어요.
Stack Overflow에서 괜찮은 코드를 발견하면 복사하고, GitHub에서 비슷한 구현을 찾고, 이전 프로젝트에서 잘 만들어둔 모듈을 통째로 옮기기도 했어요.
저 역시 그랬어요.
Project A
└─ 잘 만든 Auth 구현
↓ 복사
Project B
└─ 조금 수정
↓ 다시 복사
Project C
잘 만들어둔 코드가 있는데 굳이 처음부터 다시 만들 이유는 없었으니까요.
그런데 LLM이 등장하면서 한 가지 의문이 생겼어요.
이제 코드는 다시 만들 수 있는데, 굳이 예전 코드를 계속 들고 다녀야 할까?
NestJS로 만들었던 인증 구조를 Go로 다시 만들 수도 있고, React에서 사용했던 구조를 다른 프레임워크에 맞춰 다시 구현할 수도 있어요.
그렇다면 이전 프로젝트에서 정말 가져가야 하는 것은 코드 자체가 아닐지도 몰라요.
그 코드를 좋게 만들었던 설계와 판단이 더 중요할 수 있어요.
저는 이 생각을 게임에 빗대어 Gem Programming이라고 부르고 있어요.
코드를 복사하는 대신, 검증된 프로젝트에서 좋은 판단을 캐내고(Mine), 프로젝트에 묶인 부분을 걷어내 Gem으로 다듬고(Refine), 새로운 프로젝트에 꽂고(Socket), 필요하면 다른 Gem과 **조합(Craft)**하는 방식이에요.
🎮 장비를 복사하지 말고, 보석을 꺼내면 어떨까요?
RPG 게임을 생각해볼게요.
열심히 플레이해서 좋은 장갑을 하나 얻었어요.
[Old Gloves]
┌─────────────────────┐
│ Gloves │
│ │
│ ◇ Fire Gem │
│ ◇ Critical Gem │
│ ◇ Mana Gem │
└─────────────────────┘
그런데 새로운 캐릭터를 키우기 시작했다고 해볼게요.
새 캐릭터는 직업도 다르고, 레벨도 다르고, 필요한 능력치도 달라요. 예전 장갑을 그대로 가져오는 것이 오히려 맞지 않을 수 있어요.
하지만 장갑 안의 Fire Gem은 여전히 쓸 만할 수 있죠.
그렇다면 장갑을 통째로 복제할 필요가 없어요.
보석만 꺼내 새로운 장비에 다시 꽂으면 돼요.
저는 소프트웨어도 비슷하게 볼 수 있다고 생각했어요.
하나의 프로젝트에는 완성된 코드뿐 아니라 그 코드를 만들면서 내린 여러 판단이 들어 있어요.
예를 들어 인증 기능 하나만 해도 이런 판단이 숨어 있어요.
세션은 짧게 유지한다.
요청은 HMAC으로 서명한다.
Timestamp와 Nonce를 이용해 Replay Attack을 막는다.
인증이 만료되면 세션을 갱신한 뒤 요청을 한 번만 재시도한다.
AuthService.ts라는 파일 자체는 다음 프로젝트에서 필요하지 않을 수 있어요.
하지만 왜 세션을 짧게 만들었는지, 어떤 요청을 신뢰할 것인지, 실패했을 때 어떻게 복구할 것인지에 대한 판단은 기술 스택이 달라져도 다시 사용할 수 있어요.
코드는 프레임워크와 함께 낡을 수 있지만, 좋은 판단은 그보다 오래 살아남을 수 있어요.
⛏️ Mine: 코드가 아니라 판단을 캐내요
Gem Programming의 시작은 새로운 코드를 생성하는 것이 아니에요.
이미 잘 돌아가는 프로젝트를 다시 보는 것부터 시작해요.
저는 이 과정을 Mining이라고 부르고 있어요.
LLM에게 기존 코드를 보여주고 이렇게 물을 수도 있어요.
“이 코드를 설명해줘.”
하지만 Gem을 캐고 싶다면 질문을 조금 바꿔야 해요.
“이 구현에서 다른 프로젝트에서도 다시 사용할 가치가 있는 설계와 판단은 무엇일까?”
비슷해 보이지만 결과는 달라요.
첫 번째 질문은 현재 코드의 동작을 설명해요.
두 번째 질문은 코드 뒤에 숨어 있는 재사용 가능한 설계 지식을 찾으려고 해요.
실제 프로젝트에는 좋은 설계만 들어 있지 않아요. 프로젝트에만 필요한 요구사항도 있고, 급하게 만든 우회 코드도 있고, 특정 프레임워크 때문에 생긴 구조도 있어요.
그래서 Mining은 코드를 많이 건져내는 작업이 아니에요.
다음 프로젝트에서도 살아남을 판단을 골라내는 작업이에요.
어디까지가 한 컴포넌트의 책임인지, 서로 어떤 데이터를 주고받는지, 실패하면 어떻게 복구하는지, 어떤 보안 규칙은 반드시 지켜야 하는지 같은 것들이 Gem의 후보가 돼요.
✂️ Refine: 캐낸 원석에서 프로젝트의 흔적을 걷어내요
광산에서 캐낸 원석을 바로 장비에 꽂지는 않아요.
소프트웨어도 마찬가지예요.
처음 설계를 추출하면 원래 프로젝트의 흔적이 그대로 남아 있을 가능성이 커요.
NougatGuestAuthService
POST /api/nougat/session
NUTS_AUTH_SECRET
tb_nougat_guest_session
원래 프로젝트에서는 중요한 이름이지만, 다른 프로젝트에서는 대부분 필요하지 않아요.
그래서 한 번 더 다듬어요.
Source Code
↓
Mine
↓
Raw Gem
↓
Refine
↓
Gem
이 과정에서 특정 프로젝트의 변수명, Component 이름, API Path, 파일 구조 같은 것은 걷어내요.
대신 다시 구현하기 위해 필요한 내용은 남겨요.
예를 들어 Guest Authentication이라면 다음처럼 정리할 수 있어요.
Guest Authentication Gem
Session
- Guest Session은 짧은 TTL을 가져요.
- 서버가 Session 상태를 관리해요.
Request
- 요청은 HMAC으로 서명해요.
- Signature에 Timestamp와 Nonce를 포함해요.
Security
- 허용 시간을 벗어난 요청은 거부해요.
- 한 번 사용한 Nonce는 다시 허용하지 않아요.
Recovery
- Session이 만료되면 새 Session을 받아요.
- 인증 실패 요청은 갱신 후 한 번만 재시도해요.
여기에는 NestJS Controller도 없고 React Hook도 없어요.
반대로 “HMAC을 쓴다” 한 줄만 있는 것도 아니에요.
어떤 책임이 있고, 무엇을 지켜야 하며, 실패했을 때 어떻게 행동해야 하는지는 남아 있어요.
핵심은 코드를 요약하는 것이 아니라, 그 코드를 좋게 만든 판단을 증류하는 것이에요.

💎 그래서 Gem은 정확히 무엇일까요?
제가 생각하는 Gem은 이렇게 정의할 수 있어요.
Gem은 실제 구현 경험에서 추출한, LLM이 다른 프로젝트에서도 다시 구현할 수 있을 만큼 구체적인 설계 단위예요.
Gem은 일반적인 Design Pattern보다는 구체적이고, 실제 Code보다는 추상적이에요.
Design Pattern
↑
│ 더 추상적
│
Gem
│
│ 더 구체적
↓
Code
예를 들어 “Adapter Pattern을 사용한다” 정도라면 너무 추상적이에요.
반대로 특정 프로젝트의 StreamingAdapterService.ts를 그대로 보관한다면 Code에 너무 가까워요.
Gem에는 그 중간의 정보가 들어가요.
무엇을 해결하는 설계인지, 각 부분의 책임이 어디까지인지, 서로 어떤 약속을 지켜야 하는지, 어떤 상태를 허용하는지, 실패하면 어떻게 복구하는지 같은 내용이에요.
여기서 중요한 조건이 하나 더 있어요.
Gem은 사람이 읽기 좋은 문서에서 끝나지 않아야 해요.
AI Agent가 Gem을 읽고 실제 구현까지 이어갈 수 있어야 해요.
그래서 저는 Gem을 일종의 LLM-executable Design Asset, 즉 LLM이 구현에 사용할 수 있는 설계 자산으로 보고 있어요.
🔌 Socket: 새 프로젝트에는 필요한 Gem만 꽂아요
새 프로젝트는 새로운 장비라고 생각할 수 있어요.
New Project
Security [ ]
Transport [ ]
Frontend [ ]
LLM [ ]
모든 설계를 백지에서 다시 시작하는 대신, 예전에 만들어둔 Gem을 찾아볼 수 있어요.
Security에는 Guest Authentication Gem을, Transport에는 NDJSON Streaming Gem을, LLM 영역에는 Structured UI Gem을 가져오는 식이에요.
저는 이 과정을 Socketing이라고 부르고 있어요.
여기서 중요한 점은 예전 코드를 그대로 복원하지 않는다는 거예요.
같은 Auth Gem을 사용해도 결과물은 달라질 수 있어요.
Auth Gem
↓
┌───────┼───────┐
↓ ↓ ↓
NestJS Go Rust
NestJS에서는 Guard가 나올 수 있고, Go에서는 Middleware로 구현할 수도 있어요.
괜찮아요.
Gem Programming의 목표는 같은 코드를 만드는 것이 아니기 때문이에요.
대신 처음 Gem에 담겨 있던 설계 의도와 지켜야 할 조건을 유지하는 것이 중요해요.
🧩 Craft: 좋은 Gem 두 개도 바로 맞지 않을 수 있어요
제목에 **‘캐고, 조합한다’**라고 쓴 이유가 여기 있어요.
Gem을 가져오는 것만으로 항상 문제가 해결되지는 않아요.
예를 들어 서로 다른 프로젝트에서 다음 두 Gem을 얻었다고 해볼게요.
NDJSON Streaming Gem
+
LLM UI Generation Gem
각각 따로 사용할 때는 잘 동작했어요.
그런데 둘을 한 프로젝트에서 처음 연결하려고 하니 서로 기대하는 데이터 구조와 상태가 달라요.
Streaming 쪽에서는 Event가 순서대로 흘러오지만, UI 쪽에서는 완성된 Spec을 기대할 수도 있어요.
둘 다 좋은 Gem인데 서로 맞물리는 부분의 약속이 다른 것이에요.
이때 한쪽을 억지로 뜯어고칠 수도 있어요.
하지만 두 Gem의 역할을 그대로 살리고 싶다면 다른 질문을 할 수 있어요.
“두 설계를 유지하면서 사이를 연결하려면 어떤 Adapter가 필요할까?”
Gem A Gem B
↓ ↓
└─ Contract Gap ───┘
↓
Adapter
저는 이 과정을 Crafting이라고 부르고 있어요.
보석 두 개를 녹여 하나로 만드는 것이 아니라, 각자의 역할을 유지하면서 함께 사용할 수 있는 접합부를 만드는 것에 가까워요.
🧬 보석을 조합하면 새로운 보석이 생기기도 해요

이 과정이 흥미로운 이유가 하나 더 있어요.
두 Gem을 조합하다 보면 이전에는 없었던 문제가 보이기도 해요.
예를 들어 Streaming으로 UI Spec이 조금씩 들어온다고 해볼게요.
도착하는 데이터를 바로 화면에 반영하면 아직 완성되지 않은 상태가 사용자에게 노출될 수 있어요.
그렇다면 이런 구조가 필요할 수 있어요.
Streaming Patch
↓
workingSpec
↓
Validation
↓
renderSpec
↓
UI
들어오는 데이터는 우선 작업 중인 workingSpec에 반영하고, 검증을 통과한 상태만 실제 화면에 사용하는 renderSpec으로 넘겨요.
필요하다면 마지막으로 정상 동작한 상태를 유지하는 복구 정책도 추가할 수 있어요.
중요한 것은 이 설계가 처음부터 Streaming Gem이나 UI Gem에 들어 있던 것이 아니라는 점이에요.
두 Gem을 조합하면서 새로운 문제가 발견됐고, 그 문제를 해결하며 새로운 Engineering Knowledge가 생긴 거예요.
그리고 이 지식 역시 다른 프로젝트에서 쓸 수 있다면 새로운 Integration Gem으로 저장할 수 있어요.
그래서 Gem Programming에서 조합은 단순히 A + B = AB가 아니에요.
때로는 A + B → A + B + C가 돼요.
과거의 지식을 재사용하면서 새로운 지식까지 얻는 거예요.
⚙️ LLM은 플레이어보다 Crafting Engine에 가까워요
여기까지 읽으면 이런 생각이 들 수 있어요.
“결국 LLM에게 알아서 설계하고 구현하라고 하는 것 아닌가?”
제가 생각하는 방향은 오히려 반대예요.
판단과 구현의 역할을 나누는 것에 가까워요.
Engineer
Gem 선택
중요한 조건 정의
연결 규칙 정의
검증 기준 정의
↓
LLM
↓
Implementation
어떤 Gem을 사용할지, 어떤 규칙은 반드시 지켜야 하는지, 어디까지를 허용할지는 개발자가 결정해요.
LLM은 그 재료와 규칙 안에서 현재 프로젝트에 맞는 구현을 만드는 역할을 맡아요.
게임으로 보면 LLM은 플레이어보다 Crafting Engine에 가까워요.
재료와 제작 규칙을 정해주면 실제 아이템을 만들어주는 시스템인 셈이에요.
그리고 LLM이 같은 Gem에서 매번 조금 다른 코드를 만든다고 해서 반드시 문제가 되는 것도 아니에요.
구현은 달라도 중요한 규칙을 지키면 돼요.
LLM
↓
여러 구현 가능
↓
┌─────────────────────────┐
│ Gem의 제약조건 │
│ 입출력 규칙 │
│ Schema │
│ Security Rule │
│ Validation │
│ Automated Test │
└────────────┬────────────┘
↓
Accepted Result
Replay Protection이 필요한 Gem이라면 구현 과정에서 빠져서는 안 돼요.
정해진 Schema가 있다면 통과해야 하고, 보안 규칙과 테스트도 만족해야 해요.
LLM의 결과를 하나로 고정하는 대신, LLM이 움직일 수 있는 경계를 고정하는 방식이에요.
🔄 결국 하나의 반복되는 게임 루프가 돼요
지금까지를 하나로 줄이면 Gem Programming은 꽤 단순해요.
Existing Project
↓
Mine
↓
Raw Gem
↓
Refine
↓
Gem
↓
Stash
↓
New Project
↓
Socket / Craft
↓
Generate
↓
Validate
↓
새로운 판단 발견
↓
Mine Again
Mine → Refine → Stash → Socket → Craft → Validate → Mine Again.
프로젝트를 진행할수록 이 루프를 반복해요.
그러면 프로젝트가 끝났을 때 Source Code만 남지 않아요.
Auth Gem이 하나 남을 수도 있고, Streaming Gem이 하나 남을 수도 있어요. 둘을 연결하면서 발견한 Integration Gem이 새롭게 남을 수도 있고요.
게임 용어를 걷어내면 대부분 익숙한 Software Engineering 활동이에요.
| 게임에서는 | 개발에서는 |
|---|---|
| Mining | 기존 구현에서 설계와 판단 추출 |
| Refining | 프로젝트 의존성을 제거하고 일반화 |
| Gem | 재사용 가능한 설계 자산 |
| Stash | Gem을 모아두는 저장소 |
| Socketing | 현재 프로젝트에 Gem 적용 |
| Crafting | Gem 사이의 Adapter와 연결 설계 |
| Validation | Contract·Test·Security 검증 |
| Upgrade | 실제 사용 결과를 Gem에 다시 반영 |
Gem Programming이 완전히 새로운 Software Engineering 기법을 발명하려는 것은 아니에요.
개발자는 예전부터 좋은 설계를 추출하고, 추상화하고, 재사용해왔어요.
다만 LLM이 등장하면서 재사용 단위를 반드시 코드나 라이브러리까지 내려보내지 않아도 되는 가능성이 생겼다고 생각해요.
충분히 구체적인 설계를 남겨두면 LLM이 현재 프로젝트의 언어와 프레임워크에 맞춰 다시 코드로 내려갈 수 있기 때문이에요.
저는 그 중간에 있는 재사용 단위를 Gem이라고 부르고 있어요.
📦 제가 캐낸 Gem은 GitHub에 공개하려고 해요
이 아이디어를 글로만 설명하고 끝내고 싶지는 않아요.
실제로 프로젝트에서 추출하고 다듬은 Gem을 모아두는 GitHub Repository도 공개하려고 해요.
단순한 Code Snippet 저장소가 아니라, 개발하면서 얻은 설계와 판단을 모아두는 Gem Stash에 가까운 형태를 생각하고 있어요.
Gem Stash
├─ Authentication
│ └─ Guest HMAC Auth
├─ Transport
│ └─ NDJSON Streaming
├─ Frontend
│ └─ Overlay Architecture
├─ LLM
│ └─ Structured UI Generation
└─ Integration
└─ Streaming × UI Adapter
각 Gem에는 코드만 넣기보다 어떤 문제를 해결하는지, 어떤 책임을 가지는지, 무엇을 반드시 지켜야 하는지, 실제 구현에서 어떤 선택을 했는지를 남기려고 해요.
물론 아직은 초안 단계예요.
Gem에 어느 정도까지 정보를 담아야 Agent가 안정적으로 구현할 수 있는지, Gem 하나의 크기는 어느 정도가 적당한지, Gem끼리의 의존성을 어떻게 표현해야 좋은지도 계속 실험하고 있어요.
그래서 Repository 역시 처음부터 완성된 정답집으로 만들 생각은 없어요.
직접 사용하면서 구조를 바꾸고, 부족한 Gem을 다듬고, 새로운 Gem을 추가해나가려고 해요.
더 좋은 구조나 추상화 방법이 보인다면 의견을 남겨주세요.
Issue도 좋고, PR은 더 좋아요.
Gem Programming이라는 이름과 구조 자체도 여러 프로젝트에서 실제로 사용해보면서 함께 다듬어지면 좋겠어요.
⛏️ Code Reuse에서 Decision Reuse로
결국 제가 Gem Programming에서 가장 중요하게 생각하는 변화는 하나예요.
예전의 Code Reuse가 구현을 옮기는 것에 가까웠다면, Gem Programming은 구현을 만든 판단을 옮기는 것에 가까워요.
Code reuse moves implementations.
Gem Programming moves engineering decisions.
프로젝트는 언젠가 끝나요.
프레임워크도 바뀌어요.
몇 년이 지나면 그때 작성했던 코드가 더 이상 좋은 코드가 아닐 수도 있어요.
하지만 그 프로젝트에서 어렵게 발견한 좋은 판단까지 함께 사라질 이유는 없어요.
그래서 저는 요즘 좋은 프로젝트를 완성품으로만 보지 않으려고 해요.
좋은 프로젝트는 하나의 완제품이면서, 동시에 다음 프로젝트를 위한 광산이에요.
그 안에서 다시 쓸 가치가 있는 판단을 캐내고, 프로젝트의 흔적을 걷어내 Gem으로 다듬어요.
새 프로젝트가 시작되면 필요한 Gem을 꺼내 꽂고, 서로 맞지 않는 Gem은 새로운 Adapter로 연결해요.
그리고 그 과정에서 더 좋은 판단을 발견하면 다시 Gem으로 남겨요.
결국 Gem Programming에서 개발자는 코드를 만드는 사람에만 머물지 않아요.
좋은 판단을 캐는 광부이면서, 서로 다른 보석을 조합해 새로운 시스템을 만드는 Crafter가 돼요.
이것이 제가 생각하는 Gem Programming이에요.
Mine proven software.
Refine the decisions.
Stash the Gems.
Socket and craft them.
Regenerate the code.
검증된 프로젝트에서 보석을 캐고,
좋은 판단만 다듬어 남기고,
필요한 보석을 새로운 프로젝트에 꽂고 조합해,
코드는 다시 만들어요.