제품 생태계 소개와 온보딩 교육 자료 : 내려받아 외부에 공유
우리 그룹의 이름이 FDE입니다. 그런데 정작 "FDE가 뭐냐"고 물으면 한 문장으로 답하기가 쉽지 않습니다. 이 강의는 그 정의부터 일하는 방식까지를 정리합니다.
AI를 도입한 회사 대부분은 데모까지만 성공하고 실제 업무에는 못 올립니다.
수백억을 들여 AI를 도입했는데 PoC(개념검증, 되는지만 확인하는 소규모 시범)로 끝나고 사라진 프로젝트가 흔합니다. 투자사 Insight Partners는 이 현상을 'AI 가치 격차(AI Value Gap)' 라고 부릅니다. 제품이 아무리 좋아도 고객 현장에서 마지막 구간('라스트마일')을 깔아주는 사람이 없으면 데모 한 번으로 끝납니다.
이 마지막 구간을 메워 '박스를 완성(complete the box)' 하는 사람이 FDE입니다.
데모 성공 → [AI 가치 격차: 대부분 여기서 죽음] → 프로덕션 가치. FDE가 이 라스트마일 구간을 메워 박스를 완성한다.
현장의 간극은 이런 모습입니다. 오너는 "우리도 AI로 뭐 해야 하지 않아?"라고 재촉하고, 중간관리자는 우왕좌왕하고, 실무자는 AI에 뭘 시켜야 할지도 모릅니다. 이 간극을 메우는 것이 FDE의 주 업무입니다.
FDE는 고객사에 배치되어 문제를 직접 만들어 해결하는 빌더(builder)입니다.
Forward Deployed Engineer, 우리말로 전방 배치 엔지니어입니다. 기원은 팔란티어가 20년 전 만든 개념입니다. 국방부 같은 곳에 AI 소프트웨어를 납품했는데 고객이 쓸 줄을 몰라, 엔지니어를 현장에 상주시켜 필요한 걸 직접 만들어준 데서 출발했습니다. (용어는 팔란티어가 맞지만, 이 일하는 방식 자체를 팔란티어가 발명한 건 아닙니다.)
컨설팅펌처럼 리포트만 주고 빠지는 게 아니라, 고객사에 들어가 워크플로우를 짜고, 앱을 만들고, 교육까지 하고, 스스로 돌아가게 해놓고 나옵니다. 쉽게 말해 회사에 임시 CTO처럼 들어가는 것입니다.
비유하자면 출장요리사입니다. 고객 주방에 가서, 고객 재료로, 고객 입맛에 맞는 요리를 해줍니다.
고객 주방·재료·입맛 → FDE(출장요리사, 임시 CTO)가 고객 맞춤 솔루션을 짓고 교육·자립. 레시피·기구는 자사 해자. (단, 고유 레시피와 요리 기구는 자사만의 경쟁력으로 남깁니다.)
여기에 핵심 반전이 하나 있습니다. FDE는 영구직이 아닙니다. 결과가 나오면 제품팀에 넘기고 다음 현장으로 떠납니다. ServiceNow의 한 리더는 팀에게 이렇게 말합니다. "글자 그대로 자신의 일자리를 없애는 것이 당신의 목표입니다."
"그럼 컨설턴트랑 뭐가 달라요?"라는 질문이 안 나올 수가 없습니다. 확실히 다릅니다.
컨설턴트·SE·CSM(정해진 범위 납품 후 이탈) vs FDE(범위 없는 문제를 받아 마지막 구간까지 만들고 결과 소유)
| 구분 | 그 역할은 | FDE는 |
|---|---|---|
| 컨설턴트 / 전문서비스(PS) | 정해진 범위의 산출물을 납품하고 떠난다. 범위 밖은 추가 비용. | 범위가 정의되지 않은 모호한 문제를 받아 마지막 구간까지 만들고 결과를 소유한다. |
| 세일즈 엔지니어(SE) | 딜을 닫으려 제품을 시연한다. 거기까지. | 데모를 만드는 사람이 아니다. 고객 실제 환경에서 프로덕션까지 간다. |
| CSM / 구현팀 | 이미 팔린 것의 도입·정착·지원을 담당. | 무엇을 팔았는지와 무관하게 고객의 가장 어려운 문제를 새로 정의하고 없던 것을 만든다. |
Databricks에서는 아예 프리세일즈와 포스트세일즈가 하나로 합쳐져 있습니다. 3만 달러짜리 PoC로 시작해 수백만 달러 계약으로 커진 사례도 있습니다. 원칙은 하나입니다. "시간과 인원이 아니라 성과(outcomes)."
Q. FDE는 결국 외주 SI(고객이 시킨 걸 만들어주는 개발 용역)와 같은 것 아닌가요?
A. 다릅니다. SI는 정해진 범위를 받아 그대로 납품합니다. FDE는 범위조차 정해지지 않은 문제를 받아 '무엇이 진짜 문제인지'부터 정의하고, 결과(성과)까지 책임집니다. 만들고 끝이 아니라 고객이 스스로 굴릴 수 있게 넘기고 떠나는 것이 목표입니다.
FDE는 아래 5단계 순서로 한 고객을 상대합니다. 어느 단계에서 멈추는지가 곧 진단의 시작입니다.
① 어려운 문제 → ② 숫자 붙이기 → ③ 실환경 구축(3~14주) → ④ 고객 인계(자립) → ⑤ 제품 환류 → (다시 ①로: 일이 복리로 쌓인다)
한 사람 안에서 세 역할이 번갈아 나옵니다.
Customer Truth Miner(현장 발굴) → Execution Architect(실행·GTM 설계) → Change Operator(조직 설득·변화 실현)
FDE의 본질은 '삼각융합형 인재' 입니다. 한 사람 안에 영업 20% + 제품 30% + 엔지니어링 50%가 결합돼 있다는 뜻입니다. (외부 기업 Databricks는 실제 소프트웨어 엔지니어링 비중을 약 40%로 보고합니다. 우리 기준은 이 밴드 안에 있습니다.)
FDE는 전략을 말하는 팀이 아니라 현장에서 변화를 만드는 팀입니다. 아래 원칙이 정체성을 지킵니다.
일하는 태도의 뿌리는 세 가지입니다. 실행력·집요함·속도인 GRIT, 워크플로우를 표준화하는 로직(Logic), 신뢰를 쌓는 관계(Relationship). "신뢰가 최종 경쟁력"이라는 말이 여기서 나옵니다.
아래에서 위로: ① GRIT(실행력·집요함·속도) → ② 로직(워크플로우 표준화) → ③ 관계(신뢰=최종 경쟁력)
FDE는 희소하고 특수한 사람입니다. 그래서 무엇을 보고 뽑는지가 조직의 성패를 가릅니다. 이 강의는 우리가 FDE를 채용할 때 실제로 채점하는 기준을 정리합니다.
선발 기준은 학위·스펙이 아니라 잠재력과 태도입니다.
핵심 문장은 하나입니다. "Spark를 뽑고 도구는 가르친다(Hire for spark, then teach the tools)." Spark란 결과를 자기 것으로 안고 가는 기질입니다. 도구(툴 스택) 숙련도는 나중에 채워지는 후행 변수입니다.
여기서 가장 중요한 원칙이 나옵니다. 도메인 경력은 가점이 아닙니다.
평가 대상은 '그 도메인을 아는가'가 아니라 '그 도메인의 킬러 문제를 정의할 수 있는가'입니다. 이 둘은 다른 영역의 지능입니다. 도메인 지식은 현장에서 단기 습득할 수 있지만, 문제를 구조화해 정의하는 지능은 대체하기 어렵습니다. 오히려 도메인을 너무 잘 알면 '잘 만드는 행위'에 집착해 '무엇을 왜 만드는가'를 놓치기도 합니다.
FDE의 직무 구성은 대략 영업 20% + 제품 30% + 엔지니어링 50% 의 삼각융합입니다.
한 사람 안에 영업 20% + 제품 30% + 엔지니어링 50%가 결합된 삼각융합형 인재
아래 여덟 가지가 FDE를 다른 직군과 구분 짓는 변별력입니다. 대부분 우선순위가 높습니다(high).
8개 특화 역량: 문제 정의(1순위)·도메인 번역·풀사이클 실행·성과 책임·신규 도메인 학습·현장 배치(medium)·자산화·AI 네이티브 빌드
| 역량 | 한 줄 정의 |
|---|---|
| 문제 정의 (Critical Thinking / Audit) | 표면 요청 뒤의 진짜 문제를 재정의하고, '무엇을 안 만들지'까지 정의한다. FDE의 1순위 역량. |
| 도메인 번역·합의 (비즈니스 문해력) | 고객 문제를 기술 요구로 번역하고, 이해관계가 다른 부서 사이에서 합의를 이끈다. |
| 풀사이클 실행력 (야전 사령관) | 발견→설계→납품 전 과정을 소수로 완주한다. 계획을 기다리지 않고 실행으로 학습한다. |
| 성과 책임 (Maker→Closer) | 산출물에서 멈추지 않고 KPI·실제 임팩트까지 책임진다. '이 방향 틀렸다'며 멈출 수 있다. |
| 신규 도메인 단기 습득 | 어제 몰랐던 산업을 오늘 배워 내일 솔루션을 제안한다. 빠른 학습 자체에서 재미를 느낀다. |
| 현장 배치·변화관리 (고객 상주, medium) | 고객사에 밀착해 사람(거부감·부서 갈등)을 설득하고 일하는 방식을 바꾼다. |
| 자산화 사고 (Code Harvesting / Fat Skills) | 현장 솔루션을 재사용 자산으로 일반화한다. 코어와 같은 품질이어야 제품팀이 인수한다. |
| AI 네이티브 빌드 (바이브코딩) | Claude Code·Cursor로 E2E를 빠르게 만들고, 여러 모델을 조합해 비용을 최적화한다. |
특히 세 가지는 채점 포인트가 통념과 다릅니다.
주의 신호(감점)도 분명합니다. 모든 문제에 AI를 기본값으로 대입하는 것, 샌드박스·슬라이드에서 멈추고 실환경 배포 이력이 없는 것, 만들 것만 나열하고 안 만들 것을 정의하지 못하는 것, 생성된 코드의 설계 이유를 설명하지 못하는 것입니다.
특화 역량과 별개로, 모든 지원자에게 공통으로 보는 축이 있습니다.
| 축 | 핵심 | 결핍 시 |
|---|---|---|
| 메타인지 (우선 1) | 자기 한계를 객관화하고 피드백으로 보정 | 과대일반화·피드백 거부 → 신뢰 붕괴 |
| Giver 정신 (우선 1) | 지식 공유·타인 기여·이타성 | taker 패턴 → 조직핏 붕괴 |
| 커뮤니케이션 (우선 1) | 비기술 이해관계자와 문제 정의·합의 | 현장에서 합의 실패 |
| 문제 분해·구조화 (우선 1) | 크고 모호한 문제를 다룰 단위로 쪼갬 | 착수 불가 |
| 실패의 빠른 발견·인정·학습 (우선 1) | 틀렸음을 빨리 인정하고 방향 전환 | 매몰비용에 매달림 |
| 오픈·공유·협력 파트너십 (우선 2) | 경계를 넘어 개방·상호호혜 네트워크 구축 | 신뢰자산 형성 실패 |
| 협동정신 (우선 2) | 팀 신뢰·조율·정보 공유 | 개인기 높아도 팀 흐름 깸 |
| 자기주도 학습능력 (우선 3) | 독학·빠른 습득 | (이 풀에선 거의 전원 충족, 변별력 낮음) |
이 인재상의 철학은 "Open. Share. Collaborate." 입니다.
Open·Share·Collaborate(개방·공유·협력) → 신뢰 → 혁신 정보가 희소하지 않은 시대에는, 정보를 얼마나 아느냐가 아니라 무엇이 중요한지 판단하는 능력이 중요해집니다. 그리고 AI는 경쟁자가 아니라 최고의 팀원입니다.
면접·레퍼런스 체크에서 아래 신호를 확인합니다.
Spark(결과 소유 기질, 못 가르침, 선발로 봄) ≠ 도구·툴 스택(가르칠 수 있음, 후행 변수)
단일 채널로는 벤치(대기 인재풀)가 차지 않습니다. 채널마다 강점과 재교육 포인트가 다릅니다.
전 창업자·SI 출신·빅테크·컨설팅펌·얼리커리어·사내 전환 등 여러 채널이 함께 FDE 벤치를 채운다(단일 채널로는 안 참)
| 채널 | 강점 | 검증·재교육 포인트 |
|---|---|---|
| 전 창업자 | 모호함 내성·결과 소유가 이미 검증됨 | (강한 신호) |
| SI·구현 파트너 출신 | 현장·레거시 통합 경험이 즉시 전이 | '정해진 범위 납품' 습관은 재교육 대상 |
| 빅테크 엔지니어 | 엔지니어링 깊이 | 고객 대면·모호함 내성 별도 검증 |
| 상위 컨설팅펌 출신 | 문제 구조화·경영진 커뮤니케이션 | 빌더 전환 의지 필수 확인(전략만 말하면 부적합) |
| 대학 파트너십·얼리커리어 | 창의성·유연성 | 역량은 사내 Academy가 채움 |
| 사내 해커톤·내부 전환 | 리스크가 가장 낮은 채널 | (검증된 문화핏) |
마지막으로, 채용 여부는 여섯 개 질문으로 확정합니다.
포지션 적합·기여도·대체불가·FDE 적합·ROI·충성도 6개 게이트를 모두 통과해야 채용(대체불가 답 못 하면 보류)
| 기준 | 질문 |
|---|---|
| 포지션 적합성 | 직무 요건에 부합하는가? |
| 기여도 | 회사가 이 사람으로 직접 받는 도움은? |
| 대체불가능성 | 이 포지션에 꼭 이 사람이어야 하는 대체불가 역량은? (답 못 하면 채용 보류) |
| FDE 적합성 | 현장 딜리버리·고객 대면이 가능한가? |
| ROI | 연봉 대비 직접 가치가 정당한가? |
| 충성도 | 조직에 결속됐는가, 특정 개인(추천자)에 결속됐는가? (객관 기록 기반으로만 평가) |
FDE는 뽑는 것으로 끝나지 않습니다. "채용 ≠ 완성"입니다. 뽑은 사람을 어떤 축으로 평가하고, 어떻게 키우고, 어떻게 오래 함께 가는지가 이 강의의 주제입니다.
FDE 평가는 여섯 개 카테고리로 나뉩니다.
FDE 평가 6 카테고리: FDE 특화역량·AI/개발 역량·경영지원 역량·보편 인재상·5대 경영역량·직무 적합
| 카테고리 | 보는 것 |
|---|---|
| FDE 특화역량 | 문제정의·도메인번역·풀사이클 실행·성과책임·신규도메인 학습·현장배치·자산화 (핵심 변별력) |
| AI 및 개발 역량 | AI 네이티브 빌드·엔지니어링 깊이·인프라/비용 최적화·코드 품질 |
| 경영지원 역량 | 재무·정산·계약·인사·업무 자동화·거버넌스 (필요 트랙) |
| 보편 인재상 | 메타인지·giver·협동·커뮤니케이션·문제 분해·실패 학습 |
| 5대 경영역량 | 전략비전·실행/후속조치·B2B영업·이해관계자 관리·팀 리더십 |
| 직무 적합 | 지원 직무-경력 정렬·정량 성과·도구 실증·T자형 확인 |
개발 역량에서 두 가지를 특히 봅니다.
FDE는 연차가 아니라 대상 고객 × 요구 핵심 역량 × 월 매출 기여로 티어를 나눕니다.
T1 하이엔드(3,000만+) 위→아래 T4 교육·양성(1,000만+) 피라미드. 연차가 아니라 고객·역량·월매출 밸류 래더. 영업 quota는 T4에만.
| 티어 | 대상 고객 | 핵심 역량 | 월 매출 |
|---|---|---|---|
| T1 하이엔드 (Staff FDE) | 대기업 경영진·투자사 | 문제 정의, 도메인 번역·합의, 성과 책임 | 3,000만+ |
| T2 정부·엔터프라이즈 | 공공·대형 엔터프라이즈 | 풀사이클 실행력, 도메인 번역·합의 | 2,000만+ |
| T3 리피터·그로우 | 리피터·성장 고객 | 풀사이클 실행력, AI 네이티브 빌드 | 1,200만+ |
| T4 교육·양성 (Enablement Lead) | 사내·Academy·고객 내부 양성 | 자산화 사고, 현장 배치·변화관리 | 1,000만+ |
이렇게 넷으로 나누는 이유는 이렇습니다.
역량은 사내 Academy 3단계로 채웁니다.
Academy 3단계: Foundation(4주) → Domain Specialization(4주) → Field Deployment(4~8주)
성장의 비중은 70-20-10을 따릅니다.
현장 경험 70% + 관계·멘토링 20% + 정규 교육 10%
성과와 잠재력을 두 축으로 하는 9칸으로 각자의 위치를 진단하고, 칸별로 다른 액션을 씁니다.
성과(가로축, 저→고) × 잠재력(세로축, 저→고) 3x3 그리드. 고성과·고잠재='스타', 저성과·저잠재='개선 필요' 등 9칸별 권장 액션이 다르다.
| 칸 | 권장 액션 |
|---|---|
| 스타 (고성과·고잠재) | 차세대 리더·핵심 프로젝트. 멘토 역할 부여, 지분·명성 보상으로 리텐션. |
| 고성과·중잠재 | 전문성 심화 + 자산화 리드. 스트레치 과제로 상향 탐색. |
| 핵심 전문가 (고성과·저잠재) | 현장 핵심 유지·전문가 트랙. 지식 자산화로 영향력 확장. |
| 성장주 (중성과·고잠재) | 스트레치 과제·집중 코칭·페어링으로 성과를 끌어올림. |
| 핵심 인력 (중성과·중잠재) | 70-20-10 균형 개발. 차기 역량 1~2개에 집중. |
| 안정 기여 (중성과·저잠재) | 현 역할 안정·동기 유지. 정체·번아웃 신호 점검. |
| 잠재 미발현 (저성과·고잠재) | 역할 미스핏 가능. 페어링/도메인 재배치 + 단기 집중 코칭. |
| 관찰 필요 (저성과·중잠재) | 명확한 기대 설정 + 단기 개선계획 + 진단 1:1. |
| 개선 필요 (저성과·저잠재) | 개선계획(PIP) 또는 재배치. 정체성 점검 선행. |
리텐션(잔류)을 위해 아래 신호를 조기에 잡습니다.
정체성 혼란·영구 접착제화·front door 붕괴·히어로 의존 → 리텐션 위험. 개인 각오가 아니라 구조(팟·로테이션)로 막는다.
번아웃과 이탈은 개인의 노력이 아니라 구조로 막습니다. 외부 톱티어 4개사(Insight Partners 3부작)의 공통 관측입니다.
고객 한 맥락을 엔지니어 복수 + 프로그램 매니저 + 아키텍트가 팟으로 함께 맡고, 회사가 뒤를 받친다(히어로 의존 방지)
프로덕션 가치까지의 시간(실측 밴드 3~14주): 이 기한 안에서 데모가 아니라 고객 실환경에서 돌아가는 것까지를 목표로 잡습니다.
| 회사 | 소요 | 운영 방식 |
|---|---|---|
| Rocketlane | 3~4주 | FDE가 제품 조직에 리포트. 발견과 가치 정량화에 집중. |
| nCino | 6~8주 | CS에 리포트하되 제품 엔지니어 옆에 앉는다. 고객 자립도 성공으로 계산. |
| ServiceNow | 12~14주 | 경영진 비즈니스 성과에서 착수, 프로세스 마이닝으로 병목 식별. |
| Wonderful | 고객별 상이 | 에이전트를 레거시·모던 시스템에 배선하는 systems engineer 성격. |
번아웃 방지의 구조는 세 가지입니다.
조직 배치도 인센티브를 결정합니다. 제품·R&D 소속이면 현장 학습이 로드맵으로 직결되지만 매출 가시성이 낮고, 매출 조직에 걸치면 확장을 함께 책임지지만 영업 압력이 엔지니어 동기를 침식할 위험이 있습니다(Sales Quota 금지 원칙과 충돌 주의).
standarda · standarda-core · standarda-template · standarda-devtools, 이 네 폴더가 각각 무엇이고, 어떻게 맞물려 프로젝트를 만드는지 이 챕터에서 다룹니다. 이번 강의는 그 출발점으로, 왜 이런 구조인지부터 짚습니다.
이 챕터를 마치면
대상은 standarda 구조를 처음 접하는 팀원(비개발자 포함)입니다. 위에서 아래로 순서대로, 개념을 하나씩 쌓아 올리도록 배치했습니다.
우리 팀은 비슷하게 생긴 AI 프로젝트를 여러 개 만듭니다. 겉보기엔 달라도 속을 열어 보면 똑같은 것을 반복합니다.
이걸 프로젝트마다 처음부터 만들면 두 가지 문제가 생깁니다.
그래서 팀은 "매번 반복되는 것"을 성격별로 세 묶음으로 분리해 두었습니다. 그리고 그 세 묶음으로 찍어낸 실제 제품들이 따로 있습니다.
앞의 두 문제(낭비·제각각)는 '손해를 막는' 이야기입니다. 그런데 이 구조에는 그보다 훨씬 큰 이득이 하나 더 있습니다. 이게 진짜 이유에 가깝습니다.
한 사람의 배움이 팀 전체의 자산이 됩니다.
예를 들어 PDF 읽는 코드를 사흘에 걸쳐 훨씬 정확하게 개선했다고 가정해 보겠습니다.
배운 것의 성격에 따라 흘려보내는 곳이 다릅니다. 앞으로 배울 네 폴더는 그래서 단순한 코드 보관함이 아니라, 각기 다른 배움이 모이는 통로입니다.
| 무엇을 배웠나 | 어디로 | 누가 받나 |
|---|---|---|
| 여러 프로젝트가 쓸 기능(PDF·메일·LLM) | core 로 승격 | 재설치하는 모든 프로젝트 |
| 더 나은 뼈대·설정·자동화 | template 에 반영(sync) | 앞으로 태어날 모든 프로젝트 |
| 프로젝트 생성·삭제 절차 개선 | devtools 에이전트 수정 | 다음에 실행하는 사람 |
| 판단 기준·맥락('왜 그렇게 했나') | wiki · changelog | 찾아보는 사람, 미래의 나 |
마지막 줄이 특히 중요합니다. 코드만 공유하면 '무엇'만 전해지고, 기록까지 공유해야 '왜'가 전해집니다. 그래서 changelog 에 "이건 어느 프로젝트에서 필요해 만들어졌다"는 한 줄을 남깁니다.
팀원 5명이 각자 한 달에 재사용할 부품 1개씩 만든다고 하면:
복사 방식: 한 달 뒤 내가 가진 부품 = 1개 (내가 만든 것뿐)
분리 구조: 한 달 뒤 내가 가진 부품 = 5개 (팀 전체가 만든 것)
1년 뒤 → 복사 방식: 12개 / 분리 구조: 60개
차이는 더하기가 아니라 곱하기로 벌어집니다. 가장 큰 수혜자는 새로 합류한 사람입니다. 첫날부터 팀이 쌓아 온 부품을 전부 갖고 출발하기 때문입니다. 맨바닥이 아니라 팀이 이미 쌓아 온 것 위에서 시작하는 셈입니다.
그래서 이 구조는 '통제'가 아니라 '협업'에 가깝습니다. 내 코드를 core 에 올리는 것은 관리받는 게 아니라, 내 사흘이 동료의 사흘을 아껴 주는 일입니다. 반대로 지금 내가 편하게 쓰는 부품들도 누군가 먼저 만들어 올려둔 것입니다.
단, 저절로 되지는 않습니다. 구조는 통로를 열어 둘 뿐이고, 실제로 배움이 흐르게 하는 것은 사람의 행동입니다. 올리는 쪽은 core 승격 PR 과 changelog 를 남기고, 받는 쪽은 새로 만들기 전에 카탈로그와 changelog 를 먼저 확인해야 합니다. 둘 중 하나만 빠져도 통로는 막힙니다.
이 챕터 전체를 관통하는 열쇠는 두 가지입니다.
앞으로 나오는 모든 설계 결정은 이 둘 중 하나에서 나옵니다. 어떤 결정을 만나면 "이건 방어인가, 성장인가?"를 물어보세요.
큰 그림을 프랜차이즈(체인점) 사업에 비유해 봅니다. 본사가 여러 매장을 여는 상황입니다.
| 비유 (프랜차이즈) | 폴더 | 역할 |
|---|---|---|
| 매장 표준 설계도 | standarda-template | 새 매장(프로젝트)을 낼 때 복제하는 인테리어·집기 세트 |
| 본사 공용 원재료 | standarda-core | 모든 매장이 똑같이 받아 쓰는 재료(코드). 버전을 붙여 배송 |
| 매장 개·폐점 시공팀 | standarda-devtools | 매장을 열고·정리하고·닫는 일을 대신 해 주는 자동화 도구 |
| 영업 중인 1호점 | standarda | 위 셋으로 만들어진 실제 서비스(제품) |
앞의 셋은 "만드는 데 쓰는 것"(도구·재료)이고, 마지막 standarda 는 그것들로 "만들어진 결과물"입니다. 성격이 근본적으로 다릅니다.
즉 standarda 를 비롯한 여러 제품은 모두 같은 재료·도구로 찍어낸 형제 프로젝트입니다.
아닙니다. 이름 앞에 다 standarda 가 붙어 한 집안처럼 보이지만, 계층이 다릅니다.
standarda-core·standarda-template·standarda-devtools (접두어 있음) = 공용 인프라(도구·재료)standarda (접두어 없음) = 그 인프라로 만들어진 제품 하나. 다른 제품들과 형제.특히 헷갈리는 지점이 하나 있습니다.
standarda폴더 안에는 팀 공용 venv(가상환경)도 함께 얹혀 있어, 팀원들이source ~/standarda/bin/activate로 이 폴더의 venv 를 빌려 씁니다. 이렇게 공용 개발환경 역할까지 겸하다 보니 특별해 보이지만, 프로젝트로서의 정체성은 다른 제품들과 완전히 동등합니다. (venv 가 여기 얹힌 것은 역사적 사정이며, venv 가 무엇인지는 core 편에서 다룹니다.)
standarda- 가 붙으면 공용 인프라, 안 붙으면 제품입니다.프로젝트의 생성·복제·삭제를 자동으로 처리해 주는 도구입니다. 특이하게 파이썬 코드가 0줄이고, Claude 에게 시키는 자연어 절차서(에이전트) 3개가 전부입니다. Claude 가 이 지시서를 읽고 실제 명령(cookiecutter·git·psql·certbot 등)을 대신 실행합니다.
standarda-devtools/
├── README.md # 사용법 + '런처 디렉토리' 개념
└── .claude/agents/ # 핵심: 절차서 3개(전부 마크다운)
├── create-project.md # 새 프로젝트 생성
├── clone-repo.md # 기존 repo 를 표준 레이아웃으로 셋업
└── delete-project.md # 프로젝트 + 부수자원 일괄 정리(DESTRUCTIVE)
create-project (생성)
slug 도출·이름 충돌 확인 → 포트 할당(dev+prod) → cookiecutter 실행(여기서 template 을 찍어냄) → 메모리 연결 → setup.sh 실행 → 초기 commit·push. template(표준 양식)과 포트·DB·메모리 설정을 한 번에 처리합니다. template·core 가 여기서 실제로 조립됩니다(각각 무엇인지는 바로 다음 두 강의에서 자세히 봅니다).
clone-repo (복제·가져오기)
slug 결정 → 폴더 생성 → git clone → 메모리 연결 → .gitignore 정합성 → (Django 면) venv 생성·패키지 설치. 새로 만드는 게 아니라, 이미 있는 repo 를 표준 레이아웃($HOME/<project>/src/)으로 서버에 올릴 때 씁니다.
delete-project (삭제 · 가장 신중, DESTRUCTIVE) 수동으로 삭제하면 자원이 여기저기 남아 쌓이는 문제를 해결합니다. 3단계 안전장치로 동작합니다.
Phase 1 (읽기전용): 뭐가 있는지 스캔만 (절대 안 지움)
Phase 2 (확인): 삭제 목록 요약 → 사용자 'yes' 받기
Phase 3 (실행): DB → 포트 → Apache → SSL → DNS → GitHub repo
→ 위키 포트표 → 프로젝트 폴더 → 메모리 순서로 정리
프로젝트 하나에 딸린 8~9종의 흩어진 자원을 빠짐없이 정리합니다. (폴더 안 .env 에 DB 비밀번호·포트가 있어 폴더 삭제는 맨 마지막입니다.)
Q. devtools 를 왜 별도로 구분해?
A. devtools 는 프로젝트를 만드는 메타 도구라 어느 프로젝트·template·core 에도 소속될 수 없습니다. - template 안? 모든 프로젝트에 create/delete 에이전트가 복제돼 흩어짐(삭제 도구가 모든 집에? 위험). 게다가 template 은 복사 후 남남이라 개선도 반영 안 됨. - core 안? core 는 프로젝트가 import 하는 런타임 부품이고, devtools 는 Claude 실행 절차서입니다. 성격이 완전히 다릅니다. - 특정 프로젝트 안? 옆 프로젝트를 만들려고 이 프로젝트를 열어야 하는 모순.
→ 팀 전체가 같은 최신본을 안전하게 공유하려면 독립 repo(SSOT) 가 유일하게 깔끔한 자리입니다.
Q. 그럼 FDE 가 직접 안 해도 되게 해주는 거야?
A. 정확히는 "남이 대신"이 아니라 "본인이 직접 하되, 손으로 일일이 안 해도 되게" 자동화한 셀프서비스입니다. 실행 주체는 여전히 FDE 본인(자기 홈에 생성). 달라진 건 "어떻게": 포트 찾기·DB 생성·cookiecutter 옵션·vhost·인증서·DNS·삭제 시 자원 정리를 도구가 대신합니다. 장점: 수고 제거 · 표준화 · 실수/누락 방지(특히 삭제) · 셀프서비스(admin 요청 없이 즉시).
새 프로젝트를 만들 때 복사해 쓰는 표준 양식입니다(실제로는 cookiecutter 라는 도구로 동작합니다). 매번 로그인·설정·폴더 구조·자동화 도구를 처음부터 만들지 않도록, 완성된 시작점을 통째로 제공합니다.
문서 양식을 복사해 새 문서를 만드는 것과 같습니다. 빈 양식을 복사한 뒤 프로젝트 이름·설정만 채워 넣으면, 매번 같은 구조의 프로젝트가 나옵니다.
cookiecutter 는 그냥 복사(cp)가 아니라, 복사하면서 이름·설정을 끼워 넣어 주는 도구입니다. 실제로 일어나는 3단계:
1. 물어봄: "프로젝트 이름이 뭐야?" → 당신: "Skyrocket Agent"
2. 복사함: template 폴더를 통째로 복사
3. 채워넣음: 복사하면서 빈칸(변수)들을 답으로 치환
치환의 예:
[template 원본] [찍혀 나온 결과]
{{cookiecutter.project_slug}}/ ──▶ skyrocket_agent/
DB_NAME = "{{...db_name}}" ──▶ DB_NAME = "skyrocket_agent"
TIME_ZONE = "{{...timezone}}" ──▶ TIME_ZONE = "Asia/Seoul"
일반 복사 (cp -r) |
cookiecutter | |
|---|---|---|
| 하는 일 | 폴더 통째로 복사 | 복사 + 빈칸을 답으로 치환 |
| 결과 | 원본과 100% 동일 | 이 프로젝트용으로 이름·설정이 채워진 버전 |
이 "빈칸 목록"이 바로 cookiecutter.json 파일입니다(프로젝트명·slug·DB명·타임존 등).
Q.
{{cookiecutter.project_slug}}는 예시 프로젝트명이야?A. 아닙니다.
{{ }}는 "여기에 값을 채워라"는 빈칸(자리표시)입니다. 두 이름의 차이를 알아 두세요. -project_name= 사람이 읽는 이름 → "Skyrocket Agent" (띄어쓰기·대문자 OK) -project_slug= 그걸 컴퓨터용으로 변환 →skyrocket_agent(소문자, 공백→_)slug 는 띄어쓰기가 있으면 안 되는 곳(폴더명·DB명·깃허브 repo명)에 쓰는 버전입니다.
Q. template 에서 직접 개발하는 거야?
A. 아닙니다. 이게 가장 중요한 구분입니다.
standarda-template/ ~/skyrocket_agent/ (찍어낸 결과물)
(표준 양식·원본) ──▶ (내 프로젝트)
깨끗하게 유지 ← 여기서 기능 추가·수정
~/skyrocket_agent)에 추가합니다.그럼 template 은 언제 고칠까요? 딱 한 경우: "앞으로 새로 만들 프로젝트들이 물려받을 공통 뼈대를 개선" 할 때입니다.
| 상황 | 고치는 곳 |
|---|---|
| 지금 이 프로젝트에 기능 추가/수정 | 찍어낸 프로젝트 폴더 (~/내프로젝트/src) |
| 앞으로 만들 모든 프로젝트의 공통 뼈대 개선 | standarda-template |
그래서 CLAUDE.md 에 "공통 파일을 고치면 template 에도 반영(sync)하라"는 규칙이 있습니다.
{{cookiecutter.project_slug}}/ 폴더 안이 통째로 복사되어 새 프로젝트가 됩니다. 주요 구성:
{{cookiecutter.project_slug}}/
├── setup.sh # 생성 후 첫 셋업 자동화(venv·DB·migrate)
└── src/
├── manage.py # Django 조종석
├── {프로젝트}/settings/ # 설정 3분할(base/local/production)
├── accounts/ profiles/ emails/ sms/ projects/ # 공통 앱 5종(이미 완성)
├── utils/ # 공통 헬퍼(예외·응답·검증 등)
├── requirements.txt # 설치 목록(Django + core + LLM 라이브러리)
├── templates/ static/ # 화면(HTML)·CSS/JS
├── docs/ e2e_tests/ # 문서 규격·기본 테스트
└── .claude/ # 자동화(skills·agents·hooks)
.claude/ 의 자동화 도구(/dev·/release·pdf-parser·ui-tester 등)가 처음부터 장착된 채 시작합니다.cookiecutter 는 찍어낸 직후 뒷정리 스크립트(hooks/post_gen_project.py)를 자동 실행합니다. 즉 "복사만" 하는 게 아니라:
cookiecutter 실행
├─ 1. 질문 → 답
├─ 2. 폴더 복사 + 빈칸 치환
└─ 3. 뒷정리 자동 실행
├─ ALLOWED_HOSTS 에 이 서버 IP 자동 주입
├─ git init + 원격 연결 + private repo 생성 시도
└─ '다음 단계' 안내 출력
그다음 사용자가 ./setup.sh 를 실행하면: venv 생성 → pip install(Django+core) → SECRET_KEY 생성 → DB 생성·migrate → 관리자 계정 생성까지 이어집니다.
이 강의가 이 챕터에서 가장 중요합니다. 왜 core 를 따로 뺐는지부터 시작합니다.
상황: 5개 프로젝트가 모두 "PDF 읽는 코드"(예: 200줄)를 필요로 합니다.
import 만 합니다. 버그를 고치면 core 한 곳만 고치고 버전을 올립니다. "원본이 하나"라 절대 제각각이 되지 않습니다 → SSOT(단일 출처).❌ 방법 A: 복사본 5개 ✅ 방법 B: 원본 하나 + 설치
제품 A/ → pdf.py (200줄) standarda-core/ → pdf.py (200줄) ← 원본 "딱 하나"
제품 B/ → pdf.py (200줄) │ pip install (버전 태그로)
제품 C/ → pdf.py (200줄) ├──▶ 제품 A (from standarda_core... import)
제품 D/ → pdf.py (200줄) ├──▶ 제품 B
제품 E/ → pdf.py (200줄) └──▶ 제품 C · 제품 D · 제품 E
| 복사 (A) | core 로 분리 (B) | |
|---|---|---|
| 코드 위치 | 프로젝트마다 복사본 N개 | 원본 딱 1개 |
| 버그 수정 | N군데 다 고쳐야 | 한 곳만 고치면 끝 |
| 시간 지나면 | 제각각으로 어긋남 | 항상 동일 |
from standarda_core... import ... 한 줄의 뜻은 "이 코드는 내 프로젝트 안에 없다. 별도 패키지(core)에 있는 걸 설치해서 불러 쓴다"입니다. 한 문장으로: "같은 걸 여러 번 만들지 말고, 한 번 만들어 다 같이 쓰자."
core 의 부품은 성격별로 세 갈래로 나뉩니다.
standarda_core/
├── clients/ ← 외부 서비스 연결 (구글과 통신)
│ gmail·sheets·drive·docs·auth
├── standard_utils/ ← 문서 → 텍스트 변환 (파일을 AI 가 읽게)
│ pdf/excel(text·vision)·document_text·sheets_text·llm_response
└── (루트) ← LLM·워크플로우 엔진 (AI 두뇌)
llm·llm_cache·tool_loop·verification·presentation
기억법: clients = 바깥세상(구글)과 통신, standard_utils = 파일을 AI 가 읽게 변환, 루트 = AI 두뇌·엔진.
Q. core 는 사용법 설명서야, 실제 실행 코드야?
A. 실제로 일하는 코드입니다. 설명서가 아닙니다. 예:
gmail_client.py의send_email_with_attachment()는 "메일 보내는 법을 적은 글"이 아니라, 호출하면 진짜로 구글에 접속해 메일을 발송하는 코드입니다.
단, 혼자 켜지지 않습니다. core 는 라이브러리(부품)라 "시작 버튼"이 없습니다. 프로젝트가 불러서 호출할 때만 작동합니다. (설명서가 아니라 실제로 도는 부품이지만, 프로젝트에 연결돼 호출될 때 비로소 작동한다는 뜻입니다.)
Q. 계정 같은 디테일은 어디서 관리하고, 실행은 누가 해?
A. 디테일(누구 계정이냐)은 프로젝트가 소유하고 core 에 인자로 넘깁니다. core 는 그 정보로 실제 실행만 합니다. - 프로젝트: "이 계정으로, 이 사람한테, 이 내용 보내줘" (디테일 제공) - core: 실제로 구글에 접속해 발송 실행 (계정 모르는 범용 기계)
프로젝트가 합쳐 쓰는 재료는 사실 3층입니다. 출처와 방식이 다 다릅니다.
| 층 | 무엇 | 만든 주체 | 방식 | 설치 후 위치 |
|---|---|---|---|---|
| ① Django | 웹 프레임워크 본체 | 남(오픈소스) | pip 설치(PyPI) | 프로젝트 venv 안 |
| ② standarda-core | 공용 기능 부품 | 우리 팀 | pip 설치(깃허브 태그) | 프로젝트 venv 안 |
| ③ template 뼈대 | ①②를 엮어 쓰는 내 코드 | 우리 팀 | cookiecutter 복사 | 프로젝트 폴더 안(내가 고침) |
집 짓기 비유:
① Django = 공구·자재 (망치, 목재) → 철물점에서 사 옴 (pip 설치)
② core = 미리 만든 부품 (창틀, 문) → 본사에서 배송 (pip 설치)
③ template = 설계도대로 지은 집 뼈대 → 설계도 복사해 시공 (cookiecutter)
Q. Django 는 standarda 폴더 중 하나야?
A. 아닙니다. Django 는
standarda-어디에도 속하지 않는 외부 오픈소스(전 세계가 씀)입니다. 우리 깃허브가 아니라 인터넷(PyPI)에 있습니다. 재밌는 점은 core 도 Django 와 똑같은 방식(requirements.txt + pip install)으로 들어온다는 것입니다. 차이는 "누가 만들었나"(PyPI vs 우리 깃허브)뿐입니다.💡 pip / venv - pip = 파이썬용 앱스토어(설치 도구).
requirements.txt= 설치할 목록. - venv(가상환경) = 프로젝트 전용 창고. pip 으로 설치한 것(Django·core)만 여기 들어갑니다. template 코드는 안 들어가고 프로젝트 폴더에 그냥 놓입니다. 프로젝트마다 창고를 따로 둬야 서로 다른 core 버전을 품고도 안 싸웁니다.
Q. 왜 template 은 복사하고 core 는 설치해? 둘 다 공통인데?
A. 판단 기준은 딱 하나: "이 코드는 프로젝트마다 달라져야 하나, 영원히 똑같아야 하나?" - 달라져야 하는 것(뼈대: settings·URL·화면) → 각자 뜯어고쳐야 함 → 복사하고 관계를 끊는다 → template - 똑같아야 하는 것(공통 기능: PDF·메일) → 다 같아야 좋고 개선되면 다 받아야 함 → 설치하고 연결을 유지한다 → core
Q. 실행할 때마다 core 원본/GitHub 에서 가져와? 배포 후에도?
A. 아닙니다. 아주 중요한 포인트입니다.
[pip install 시점: 딱 한 번]
GitHub 의 core → 다운로드 → 프로젝트 venv 안에 '복사본' 설치
[실행 시점: 매번]
Python 은 그 venv 안의 '복사본'에서 실행 ← GitHub 도, 원본 폴더도 안 봄
증거: 원본 폴더는 최신(0.21.0)인데 어떤 프로젝트 venv 의 설치 사본은 옛날(0.1.0)일 수 있습니다. 재설치 전까진 계속 옛 사본을 씁니다. "core 는 연결 유지"라는 말은 실시간 연결이 아니라, requirements.txt 에 원본 주소+버전을 남겨 재설치 명령 한 번으로 갱신 가능하다는 뜻입니다(느슨한 연결).
Q. 설치된 사본을 자동으로 계속 업데이트하면 안 돼?
A. 일부러 안 합니다. 그게 오히려 안전합니다. 배포된 프로그램의 제1원칙은 "어제 되던 게 오늘도 똑같이 된다". core 가 한밤중에 자동으로 바뀌면 예고 없는 고장·재현 불가·운영 사고·호환성 파손이 생깁니다. - 업계 표준 = 버전 고정(pinning) + 사람이 원할 때 수동 갱신. 그래서
@v0.20.0태그를 박아 둡니다. - 대가: 프로젝트가 옛 버전에 뒤처질 수 있음. 그건 안정성을 얻는 대가이며, 필요할 때 태그를 바꿔 재설치 → 테스트 → 배포합니다.
무엇을 넣나: 공통 + 범용 + 안정적인 것만. 많다고 좋은 게 아닙니다. core 는 모든 프로젝트에 설치되므로, 아무거나 넣으면 다들 안 쓰는 코드까지 떠안고 불필요하게 얽힙니다.
Q. 누가 결정하고, 중복 개발은 어떻게 막아?
A. 결정권자 = 코어 관리자(한 명). core 는 두 겹 장치로 승인을 강제합니다: CODEOWNERS(모든 변경에 그 관리자를 자동 리뷰어로 지정) + Branch protection(master 직접 push 금지, PR → 승인 → merge). 제안은 누구나 PR 로 올리되 문지기는 한 명입니다. 애매한 부품은 처음부터 안 넣고, 두 번째 프로젝트가 필요해질 때 core 로 승격합니다(PR → 승인 → 태그 → changelog).
Q. changelog 기록은 자동이야?
A. 아닙니다. 태그를 push 한다고 저절로 써지지 않습니다. core 변경은 태그 push 후 사람이 직접 엔트리를 추가합니다(강제 훅 없는 '규율 의존' 장치). 그래서 CLAUDE.md 가 "(필수)"로 강조합니다.
이제 네 폴더가 어떻게 맞물리는지 전체를 한 번에 봅니다.
[생성] ~/standarda-devtools 에서 create-project 실행 ← devtools = 자동화 도구(프로젝트에 안 들어감)
devtools 가 아래 둘을 대신 수행:
├─ cookiecutter → standarda-template 복제·이름맞춤 → 내 프로젝트 뼈대(내 홈)
└─ setup.sh → pip install → standarda-core 설치 → venv 안 부품 사본(+Django)
▼
~/<내프로젝트>/src 탄생 (= standarda 같은 완성품)
[개발] /dev 로 서버·dev도메인 → 고유 기능 작성(공통앱은 이미 완성). core 는 import 로 호출
[운영] /release 로 prod 배포. core 갱신은 태그 올려 재설치(수동·의도적)
[삭제] delete-project → DB·포트·vhost·SSL·DNS·repo·메모리 일괄 정리
| 폴더 | 역할 | 결과물과의 관계 |
|---|---|---|
| devtools | 실행자(자동화 도구) | 실행은 하지만 프로젝트 안에 안 들어감 |
| template | 복제되는 뼈대 | 복사돼 내 프로젝트가 됨(이후 남남, 내가 고침) |
| core | 설치되는 부품 | 원본은 밖에, 사본이 venv 에 들어옴(버전으로 갱신) |
devtools(자동화 도구, 프로젝트엔 안 들어감)를 실행하면, 그것이 template 을 복제·맞춤해 내 프로젝트 뼈대를 만들고 core 를 설치해 공용 기능을 넣어 줍니다. 그 결과 내가 본격적으로 개발할 프로젝트가 내 홈에 완성됩니다.
복제·설치를 실행하는 주체는 devtools 가 맞지만, devtools 자신은 결과물 안에 들어가지 않습니다. (집을 짓는 시공사가 그 집에 살지는 않는 것과 같습니다.)
/release 로, 정리는 delete-project 로. 이 전체가 앞 강의의 두 열쇠, 방어(반복 제거·일관성)와 성장(집단지성)을 실현하는 구조입니다.이 챕터에서 나온 핵심 용어를 한곳에 모았습니다. 마지막으로 자가 점검 질문에 스스로 답해 보며 이해를 확인하세요.
| 용어 | 뜻 |
|---|---|
| cookiecutter | 틀을 복사하면서 빈칸(이름·설정)을 채워 새 프로젝트를 찍어내는 도구 |
| slug | 이름을 컴퓨터용으로 바꾼 문자열(소문자·언더스코어). 폴더·DB·repo 명에 사용 |
| pip / pip install | 파이썬 코드(패키지)를 설치하는 표준 도구(=파이썬 앱스토어) |
| venv | 프로젝트별 가상환경 = 전용 창고. pip 설치물(Django·core)만 들어감(template 코드는 안 들어감) |
| SSOT (단일 출처) | 원본을 한 곳에만 두어 제각각 어긋나지 않게 하는 원칙 |
| 버전 고정(pinning) | @v0.20.0 처럼 특정 버전을 박아 자동 변경을 막고 예측 가능하게 함 |
| 승격(promote) | 프로젝트 안의 코드를 공통이라 판단해 core 로 끌어올림(PR→승인→태그) |
| DESTRUCTIVE | 되돌리기 어려운 삭제 작업. 반드시 확인 단계를 거침 |
| 런처 디렉토리 | 도구를 실행하는 위치. 결과물은 여기가 아니라 실행 유저의 홈에 생김 |
답을 스스로 말해 보세요. (답은 각 강의의 Q&A 참고)
{{cookiecutter.project_slug}} 는 예시 프로젝트명인가?이 문서는 core의 코드 구현이 아니라 AI 하네싱 관점의 동작 원리를 다룹니다. core가 왜 존재하고, 무엇을 표준화하며, 무엇이 자동으로 굴러가는지가 주제입니다.
standarda-core는 LangChain 위에 얇게 얹은 의견 있는 표준 계층입니다.
핵심은 영리한 코드가 아니라, 모든 프로젝트가 같은 문으로 LLM·구글 API에 접근한다는 사실입니다. 그래서 프로젝트마다 제각각 다시 구현하다 어긋나는 일이 없어집니다.
core가 제공하는 능력은 여섯 가지입니다.
각 능력에서 무엇이 자동이고 무엇이 직접 켜야 하는지를 먼저 표로 못 박습니다. 이 구분이 core를 가장 헷갈리게 하는 지점입니다.
| 능력 | 자동(무설정) | 직접(opt-in) |
|---|---|---|
| LLM 접근 | 모델·온도·키 env 기본값, 키 없으면 None, 추론모델 온도 quirk 자동 처리 | 프로바이더(팩토리) 선택 |
| 관측(트레이싱) | 트레이싱 env가 있으면 LangChain이 자동 적용 | env 설정 + core 우회 금지 |
| 비용·지연(캐싱) | tool-loop 안에서는 캐싱 기본 ON | 그 밖에선 캐싱 헬퍼·비용 집계 직접 호출 |
| 문서 파싱 | (없음) | 파서 서브에이전트가 방식 결정 |
| 응답 처리 | (없음) | parse_json_from_llm 호출 |
| 구글 API | 토큰 갱신·재인증·스코프 검사 | credentials 준비 |
core의 LLM 팩토리는 어느 프로바이더든 동일한 시그니처로 준비된 모델을 돌려줍니다.
get_anthropic_llm() · get_openai_llm() · get_google_llm() 은 각각 LangChain의 ChatAnthropic·ChatOpenAI·ChatGoogleGenerativeAI를 감쌉니다.
호출부는 팩토리만 바꾸면 프로바이더를 교체할 수 있고, 돌려받는 객체는 어느 쪽이든 .invoke() 되는 LangChain 모델입니다.
기본으로 녹아 있는 것:
None을 돌려줘, 호출부가 널 체크로 처리합니다.get_openrouter_llm() 은 키 하나로 여러 회사 모델을 조합하고, 실제 청구 비용까지 응답에 실어올 수 있습니다.LangSmith 트레이싱은 core가 무언가를 설정해서가 아니라, core가 항상 LangChain 객체를 돌려주기 때문에 붙습니다.
core 안에는 트레이싱 설정 코드가 한 줄도 없습니다. 대신 (1) 팩토리가 늘 LangChain 모델을 돌려주고, (2) 프로젝트 환경에 트레이싱 env가 있으면, LangChain 런타임이 그 호출을 알아서 트레이스에 실어 보냅니다.
그래서 core를 우회하면 트레이스가 조용히 사라집니다.
직접 anthropic.Anthropic() 같은 SDK 클라이언트를 만들면 LangChain을 거치지 않으니 관측에서 빠지고, 온도 quirk·캐싱·비용 로직도 각자 다시 구현하게 됩니다.
"모든 LLM 호출은 core로"라는 규칙의 강제 이유가 바로 이 관측 일관성입니다.
같은 프리픽스를 반복 호출할 때, core의 캐싱 헬퍼로 입력 토큰 재청구와 지연을 줄입니다.
cached_system_message · with_cache_control 로 system 블록에 캐시 마커를 붙이면, 캐시 읽기는 입력가의 약 0.1배로 떨어집니다(쓰기는 약 1.25배).track_usage() 로 감싸고 record_usage() 를 부른 뒤 estimate_cost_usd() 로 추정합니다. core가 자동으로 집계하지는 않습니다.core는 형식마다 저렴한 텍스트 경로와 정확한 비전 경로를 나눠 두지만, 둘 중 무엇을 쓸지는 사람이 눈대중으로 고르지 않습니다.
방식 선택은 파서 서브에이전트(pdf-parser · excel-parser)가 샘플로 품질을 테스트해 결정합니다. 로직 흐름은 이렇습니다.
Excel에는 한 갈래가 더 있습니다. 컬럼 인덱스가 고정된 정형 데이터는 LLM 없이 openpyxl로 바로 읽습니다(가장 저렴).
어느 경로든 LLM은 함수 안에서 만들지 않고 인자로 주입해, 호출부가 프로바이더를 고릅니다.
LLM 응답에서 JSON을 꺼낼 때는 parse_json_from_llm 하나만 씁니다.
이 함수는 마크다운 코드펜스로 감싼 JSON, 산문 속에 박힌 {…}, 순수 JSON을 모두 처리합니다.
프로젝트마다 펜스를 문자열로 잘라내던 코드를 복붙하다 조금씩 어긋나던 것을, 하나의 정본으로 통일한 것입니다.
Gmail·Sheets·Drive·Docs 네 클라이언트가 하나의 인증 믹스인을 공유합니다.
DEFAULT_SCOPES 한 곳이 단일 소스입니다.Credentials 객체를 주입할 수 있고, 이때 토큰은 메모리에서만 갱신되고 디스크에 쓰지 않습니다.여섯 능력을 관통하는 두 원칙이 core의 나머지를 설명합니다.
단일 출처(single source). JSON 추출도, 구글 스코프도, 캐싱 헬퍼도 하나뿐입니다. 프로젝트들이 예전엔 각자 복붙해 두고 어긋났는데, core가 정본을 쥐면 그 드리프트가 사라집니다.
고정 git 태그로 설치(editable 금지). core는 특정 태그(git+...@vX.Y.Z)로 설치합니다. editable 설치는 한 곳을 고치면 그 core를 공유하는 모든 프로젝트에 조용히 번져 금지입니다.
업데이트는 자동이 아닙니다. 새 태그가 나와도 각 프로젝트가 자기 requirements.txt의 태그를 직접 올려 재설치할 때까지 기존 버전에 머뭅니다. 그래서 하위호환이 하드 룰입니다.
새 standarda 프로젝트는 standarda-template(cookiecutter)로 찍어내고, 그 생애는 standarda-devtools가 관리합니다. 이 문서는 코드가 아니라, 프로젝트가 태어나고(생성) → 무엇을 갖고 태어나며(하네스) → 어떻게 일하는가(개발) 의 흐름을 따라갑니다.
프로젝트의 생성·복제·삭제는 standarda-devtools가 담당합니다.
devtools는 template을 소비하는 별도의 메타 저장소입니다. 그 안에서 Claude Code를 켜면, 실행한 사용자의 홈에 프로젝트를 만들고 정리합니다.
| 단계 | 자동화하는 것 |
|---|---|
| create | 슬러그 도출 · dev+prod 포트 2개 할당(위키 포트 표) · cookiecutter 생성 · GitHub repo · 메모리 심링크. 대화형 setup.sh는 사람에게 인계 |
| clone | 기존 repo를 표준 레이아웃으로 clone · 메모리 심링크 · (Django면) venv·의존성 |
| delete | 파괴적 3단계(조회 → 사용자 확인 → 삭제): 포트 프로세스 · DB · 위키 포트 행 · Apache vhost · 인증서 · Route53 레코드 · GitHub repo · 프로젝트/정적 디렉토리 정리 |
관계는 깔끔합니다. template = 프로젝트가 무엇인가, devtools = 그 생성·복제·삭제입니다.
create의 핵심인 프로젝트 생성 순간, 사람 손 없이 자동으로 벌어지는 일들입니다.
ALLOWED_HOSTS에 주입(어느 박스에서 만들어도 하드코딩 없이 그 호스트가 들어감).git init + 원격 등록 + (인증돼 있으면) 비공개 GitHub repo 생성.core.hooksPath 설정).이어지는 대화형 setup.sh(사람이 실행)에서는 venv·의존성 설치와 함께 랜덤 시크릿 키를 gitignore된 .env에 생성하고(시크릿은 커밋 안 됨), DB 비밀번호를 실제 psql로 검증한 뒤 DB·마이그레이션·슈퍼유저를 만듭니다.
프로젝트는 만들어지는 순간 세 가지 하네스(스킬·에이전트·훅)를 물려받습니다. 셋은 서로 포함하는 계층이 아니라 역할이 다르고, 관계가 정해져 있습니다.
| 층 | 무엇 | 역할 |
|---|---|---|
| 스킬(skills) | /develop·/release·/dev 등 |
이름 붙은 작업 절차(슬래시 또는 자연어로 호출) |
| 서브에이전트(agents) | spec-verifier·debug-server-log 등 |
별도 컨텍스트 + 도구 제한으로 위임되는 검증·조사 |
| 훅(hooks) | Claude 도구 훅 + git 훅 | 규칙을 사람이 안 지켜도 자동 차단하는 강제 장치 |
관계를 정리하면 이렇습니다. 스킬이 에이전트를 호출(위임) 합니다(예: /develop이 spec-verifier·merge-master를 부른다). 에이전트는 스킬을 부르지 않습니다. 훅은 누가 부르는 게 아니라 도구 호출·git 동작 시점에 자동 발동해 위반을 막는 가드레일입니다. 즉 스킬→에이전트만 호출 관계이고, 훅은 이벤트로 동작하며, 셋은 서로 포함하지 않습니다.
프로젝트가 기본으로 갖는 스킬을 용도별로 정리하면 이렇습니다.
| 용도 | 스킬 | 역할 |
|---|---|---|
| 개발 워크플로우 | /develop |
모든 코드 변경의 기본 절차(스펙→구현→검증→문서→머지) |
/dev |
개발 서버 기동 + 첫 실행 시 포트·도메인 자동 세팅 | |
/release |
프로덕션 배포 트리거 | |
| 문서 | /feature-doc |
기능 문서 |
/structure-doc |
구조 문서 | |
/update-skill-agent-list |
스킬·에이전트 목록 재생성 | |
| 고객 산출물 | /client-usage-guide |
사용 가이드(md + Word) |
/client-test-guide |
테스트 체크리스트 | |
/manual |
스크린샷 슬라이드·PDF 매뉴얼 | |
/create-docx |
스타일 Word 생성 | |
| 템플릿 동기화 | /sync-from-template |
템플릿 → 프로젝트 반영 |
/sync-to-template |
프로젝트 공통 파일 → 템플릿 역류 |
스킬이 부르는 위임 자산들입니다. 대부분 읽기 전용이라 코드를 건드리지 않고 조사·검증만 합니다.
| 에이전트 | 역할 |
|---|---|
spec-verifier |
구현이 docs/specs/{app}.md 스펙과 맞는지 검증(어긋나면 머지 차단) |
merge-master |
스펙·문서 체크리스트·충돌 점검 후 머지·정리 |
debug-server-log |
디버깅 시 서버 로그를 먼저 읽어 traceback을 찾는 강제 선행 단계 |
lesson-finder |
팀 위키 교훈 색인에서 관련 교훈 조회(다른 프로젝트 실수 반복 방지) |
pdf-parser · excel-parser |
샘플로 추출 품질을 시험해 텍스트/비전 전략 결정 |
api-tester · output-verifier |
API 테스트 · 기록 결과를 소스와 대조 검증 |
llm-usage-doc · backlog-manager |
LLM 사용 인벤토리 · 백로그 관리 |
규칙은 사람이 잊어도 훅이 자동으로 막습니다. 두 층이 독립적으로 겹쳐 있습니다.
1층: Claude 도구 훅(Claude가 도구를 부르기 직전 PreToolUse에 발동)
| 훅 | 무엇을 막나 |
|---|---|
| 버그수정 이슈문서 | 커밋 메시지에 버그 키워드가 있는데 docs/issues/ 문서가 없으면 차단 |
| 기능 문서 | 기능 키워드 + 앱 소스 변경인데 docs/specs 또는 docs/features 없으면 차단 |
| except 로거 | except 블록에서 traceback을 버리는 logger.error/warning 신규 추가를 AST로 차단 |
| 스킬 목록·설명 | 스킬·에이전트 변경 시 목록 갱신 없으면, 또는 SKILL.md 설명이 너무 짧으면 차단 |
2층: git 훅(실제 git 동작에서 발동, Claude 훅을 우회해도 잡는 backstop)
| git 훅 | 강제 |
|---|---|
| commit-msg · pre-commit | 버그수정 커밋은 이슈 문서, 스킬 변경은 목록 갱신 포함 |
| pre-push | 지정된 원격(자기 repo) 외 push 차단 |
| reference-transaction · pre-rebase | main은 fast-forward 전용, main rebase 차단 |
git 훅은 작업 트리 바깥에 설치돼(core.hooksPath), reset --hard로도 스스로 꺼지지 않습니다.
물려받은 하네스로 실제 개발을 굴리는 것이 /develop입니다. 모든 코드 변경의 기본 절차이자, 여러 단계를 자동으로 엮는 파이프라인입니다.
worktree 격리 → 스펙 작성(docs/specs/{app}.md, 사이클의 단일 소스) → 구현 → 검증 라운드(spec-verifier 통과할 때까지 머지 차단) → 문서 생성 라운드 → merge-master.
검증은 스펙 통과까지 머지를 막고, 문서·마이그레이션은 자동으로 처리되며, push만 사람 몫으로 남습니다.
/develop으로 개발합니다. 훅은 두 층(Claude 도구 + git)으로 겹쳐 문서 누락·traceback 유실·잘못된 push·main 되감기를 자동 차단합니다.reset --hard로도 안 꺼집니다. 규칙을 "잊어도" 막아주는 안전망이지 만능은 아닙니다.이 문서는 앞의 두 문서(core·template)에서 만든 AI 하네스가 실제 클라우드 서버 위에서 어떻게 돌아가는가를 다룹니다. 보안을 위해 구체적 IP·인스턴스 식별자·계정 번호는 생략하고, 구성요소와 데이터 흐름 중심으로 봅니다.
인프라는 같은 클라우드 계정·같은 VPC 안의 prod 박스와 dev 박스 두 대로 나뉩니다.
두 박스 모두 같은 스택을 올려 둡니다.
| 구성요소 | 역할 |
|---|---|
| Apache 2.4 | 외부에서 닿는 유일한 관문. 80(→HTTPS 리다이렉트)·443(TLS 종단) + 리버스 프록시 |
| 앱 서버 | prod=Gunicorn(systemd 데몬) · dev=Django runserver(포그라운드) |
| PostgreSQL 14 | localhost:5432. prod DB=<project>_prod · dev DB=<project> |
| Redis · huey | 비동기 작업 큐(쓰는 프로젝트만, prod는 별도 systemd 서비스) |
| 정적 "CDN" 디렉토리 | Apache가 직접 서빙하는 파일 디렉토리(<slug>_static_cdn/) |
| Route53 · Let's Encrypt | DNS · 인증서 자동 발급/갱신 |
핵심 규칙 두 가지: - 앱 포트(8000번대)는 VPC 내부에서만 닿습니다. 외부 요청은 언제나 Apache 443을 거칩니다. - 프로덕션은 배포자 개인 홈에서 개인 계정으로 돌립니다(SSH·DB·git 동작이 개인 단위로 추적됨).
같은 코드베이스가 dev인지 prod인지는 환경변수 하나로 갈립니다.
<PROJ>_PRODUCTION=True 이면 production 설정 + .env.production + <project>_prod DB로 뜨고, 설정이 없으면 local 설정 + .env + <project> DB로 뜹니다.
그래서 한 코드베이스가 dev·개인 dev·prod 여러 인스턴스로 동시에 존재할 수 있고, 이들을 가르는 것은 오직 .env와 이 스위치입니다.
개발자는 자기 clone에서 runserver로 프로젝트를 띄웁니다.
포트는 8000번대에서 하나 배정받고, /dev 스킬이 그 포트에 대해 Apache vhost·Let's Encrypt 인증서·Route53 레코드를 자동 세팅해 <slug>-dev 도메인으로 HTTPS 접근을 엽니다.
DB는 로컬 PostgreSQL의 dev DB를 씁니다.
개발 요청의 데이터 경로는 이렇습니다.
정적 파일은 dev(DEBUG=True)에선 runserver가 직접 내보냅니다.
/release는 dev 박스에서 실행돼 prod 박스로 SSH하는 2-호스트 원격 배포입니다. master 병합만으로는 배포되지 않고, /release가 유일한 배포 경로입니다.
변경 델타를 분석해 필요한 단계만 조건부로 실행합니다.
git fetch, 배포 델타 계산. 새 커밋 없으면 SKIP, 트리가 더러우면 BLOCKED.git pull --ff-only(또는 태그 checkout). 코드가 GitHub에서 prod로 들어옴.pip install. core를 고정 태그로, playwright 등도 함께 설치.collectstatic이 내용 해시된 파일을 정적 CDN 디렉토리에 씀.tasks.py 변경 시 huey 소비자 서비스도 재시작.프로덕션 요청은 동기(웹) 와 비동기(작업 큐) 두 갈래로 흐릅니다.
동기 경로: 브라우저 → Route53 → prod 박스 Apache 443(TLS 종단).
여기서 갈립니다. /static·/media는 Apache가 정적 CDN 디렉토리에서 직접 내보내고, 나머지 동적 요청만 내부 포트의 Gunicorn → Django(production, DEBUG=False) → PostgreSQL prod DB로 갑니다.
비동기 경로: Django 뷰가 작업을 큐에 넣으면(enqueue) → Redis/huey 큐 → 별도 huey 소비자 프로세스가 꺼내 LLM 등 긴 작업을 실행 → 결과를 prod DB에 씁니다.
주의: 소비자가 실제로 떠 있어야 합니다. 안 그러면 "비동기" 작업이 gunicorn 워커 안에서 돌다 타임아웃으로 죽습니다.
외부로 나가는 LLM·구글 API 호출은 core를 거쳐 나가며 트레이싱됩니다(standarda-core 참조).
runserver이며, 정적은 Apache가 CDN 디렉토리에서 직접 내보냅니다. /release는 dev→prod SSH로 코드·의존성·정적·서비스 재시작을 조건부로 처리합니다.