3주차 — 기업용 AI 에이전트 관리 시스템(어드민 사이트) 구현 시연
AI에게 자유를 주지 말고 스킬셋으로 꼼짝 못 하게 통제하라. 이번 주는 사내 AI 에이전트의 뼈대가 되는 어드민 사이트를 세션 키 인증·퍼미션 레이어·모델 관리·계층 조직 관리 순서로 구현하며, 그 통제가 어떻게 "사람이 만든 것 같은 정교함"으로 이어지는지 시연한다.
이번 주는 이론 설명과 구현 시현을 번갈아 진행하는 흐름에서 구현 시현 주에 해당한다. 지난주에 정리한 이론(토큰 정책, 세션 관리, 조직별 모델 권한 등)을 실제 어드민 사이트로 만들어 보여주는 회차다. 다음 주에는 이 어드민을 기반으로 실제 에이전트 서버·클라이언트를 만드는 이론으로 넘어간다.
0. 사전 필수 용어 (선행지식)
본문을 읽기 전에 아래 용어를 먼저 잡아 두어라. 입문자 기준으로 쉽게 정의한다.
1. 모노레포(Monorepo)
여러 개의 앱과 라이브러리를 한 저장소 안에 함께 두고 관리하는 방식이다. 아파트 한 동에 여러 세대가 사는 것과 같다 — 현관(저장소)은 하나지만 세대(앱·패키지)는 독립적이다. 3절과 4절의 apps·packages 폴더 구조에서 쓰인다.
2. 세션 키(Session Key) / 세션 토큰 로그인에 성공한 사용자에게 발급하는 "출입증"이다. 이후 요청마다 이 출입증을 제시해 "나 아까 로그인한 사람이야"를 증명한다. 관리자가 출입증을 회수하면 그 사용자는 즉시 로그아웃된다. 4절 Step 2와 6절에서 핵심이다.
3. 미들웨어(Middleware) 요청이 실제 처리 로직에 닿기 전에 반드시 지나가는 "검문소"다. 건물 로비의 보안 게이트처럼, 모든 사람이 사무실로 들어가기 전에 여기서 신분을 확인받는다. 5절 퍼미션 레이어가 이 검문소에 해당한다.
4. i18n(다국어 리소스 외재화) 화면에 보이는 글자를 코드 안에 직접 박지 않고 언어별 사전 파일(리소스)로 분리하는 것이다. 메뉴판의 글자를 여러 나라 말로 따로 인쇄해 두고 손님 국적에 맞춰 꺼내 쓰는 것과 같다. 6절에서 다룬다.
5. 스킬셋(Skillset) AI 코딩 도구에게 미리 걸어 두는 "작업 규칙집"이다. AI가 무엇을 할 때마다 이 규칙집을 강제로 참조하게 만들어, 정해진 구조 밖으로 벗어나지 못하게 한다. 이 강의 전체를 관통하는 핵심 개념으로, 8절·9절의 통제 철학과 직결된다.
📚 참고: 선행지식이 얕다면 웹 개발의 인증(로그인 상태 유지), 리버스 프록시/방화벽의 HTTP 헤더 처리, React의 상태 관리(state) 개념을 먼저 훑어 두면 4~6절의 이해가 크게 빨라진다.
1. 주제 정의
이 강의는 사내에서 운영할 기업용 AI 에이전트의 기반이 되는 "어드민 사이트"를 AI 스킬셋 기반으로 구현하는 과정을 시연한다. 대시보드에서 화려한 AI 기능을 보여주는 것이 아니라, 그 밑에 반드시 깔려 있어야 하는 관리 시스템 — 계정·세션·모델·조직·권한을 다루는 CRUD 테이블 데이터 — 을 만든다.
발표자는 이 어드민이 "순수한 테이블 데이터를 만드는 것뿐, AI를 하는 것은 아니다"라고 분명히 못 박는다. 그러나 동시에 "이 베이스가 없이는 기업용 에이전트를 만들 수가 없다"고 강조한다. 즉 화려하지 않지만 반드시 먼저 있어야 하는 토대다.
시연에 사용한 실제 프로젝트 이름은 ndx_business(엔덱스 비즈니스)이며, VS Code와 Docker, Codex(내장 브라우저를 가진 AI 코딩 도구) 3버전을 사용한다.
💡 실무 노하우: 어드민(대시보드)은 보통 제일 마지막에 만든다. 계정·세션·모델·조직 같은 실체 데이터가 먼저 만들어지고 나서야 그것을 모아 보여주는 화면을 만드는 것이 순서다.
2. 풀려는 문제
기업 환경에서 AI 에이전트를 운영하려면 "그냥 모델을 호출하는 코드" 이상의 것이 필요하다. 이 강의가 풀려는 문제는 다음과 같다.
- 누가 접근하는가(인증): 사내 직원만 써야 하고, 로그인한 사람이 언제·어디서·어떤 장비로 접속했는지 감사(audit)해야 한다. 기업마다 보안 설정상 이 로그 요구가 매우 강하다.
- 누가 무엇을 쓸 수 있는가(권한): 인사팀은 특정 모델만, 다른 조직은 다른 모델만 — 조직 단위로 모델 접근 권한을 세분화해야 한다.
- 모델을 어떻게 갈아 끼우는가(모델 관리): 사내에 배포한 모델, 돈 주고 쓰는 엔터프라이즈 엔드포인트를 중앙에서 등록·교체·프리셋 관리해야 한다.
- AI가 만든 코드를 어떻게 통제하는가(개발 통제): AI에게 자유롭게 맡기면 첫 결과물은 그럴듯해도 유지보수가 안 된다. 통제 가능한 정형화된 구조를 강제해야 한다.
⚠️ 주의: 발표자가 반복해서 경고하는 핵심 문제는 "AI만 알고 다 시키면 되지 않을까 싶지만, 그렇게 잘 되지 않는다"는 점이다. 아직은 개발 지식이 많이 필요하고, 자유롭게 풀어 둔 코드는 첫 산출 이후 유지보수가 되지 않는다. 그래서 "통제"가 이 강의 전체의 문제의식이다.
부차적으로, 서비스가 가장 많이 죽는 원인 1위가 로그 누적(세션 로그·서버 로그가 쌓여 디스크를 채움)이라는 현장 경험도 문제로 제기된다. EC2에서 서버가 죽는 원인 1등이 로그 누적이라는 것이다.
3. 핵심 개념·구조
3-1. 모노레포 아키텍처 (Turborepo 기반)
프로젝트는 Turborepo 기반 모노레포로, 최상위에 apps와 packages 두 폴더로 나뉜다.
apps: 독립 실행 애플리케이션. 지금은 어드민 사이트만 있고, 나중에 에이전트 등이 추가된다.packages: 공유 도메인 로직. 도메인마다 다시 세 갈래로 나눈다.common: 프론트엔드와 백엔드가 모두 써야 하는 통신 프로토콜 규격(예: OAuth 관련 프로토콜 타입). 반드시 여기에 기술한다.frontend: 프론트엔드 모델(Emitter) 쪽에서 쓰는 순수 객체.server: 백엔드 서버 구현.
⚠️ 주의:
packages안에는 프레임워크 관련 디펜던시가 들어가면 안 된다. 순수한 도메인·프로토콜만 둔다. 이것이 프론트/백 어디서나 안전하게 재사용되는 조건이다.
3-2. 세션 키 인증과 마스터 계정
로그인은 곧 세션 키를 발급하는 행위다. 관리자 화면에서 특정 세션 키를 제거하면 그 사용자의 로그인을 즉시 취소하는 것과 같다. 세션 토큰에는 요청 시간뿐 아니라 IP·컴퓨터 이름·사내 보안 프로그램이 헤더에 남기는 정보까지 옵션으로 저장할 수 있어야 한다.
마스터(슈퍼) 계정은 DB가 아니라 .env 파일로 지정한다. OCR로 확인되는 환경 변수는 MASTER_ADMIN_EMAIL 형태이며, 콤마로 여러 명을 넣을 수 있다. DB로는 이 계정을 조작할 수 없고, 마스터를 바꾸려면 환경 설정을 고친 뒤 서버를 완전히 재기동해야 한다.
3-3. 미들웨어 퍼미션 레이어
엔터프라이즈 솔루션은 미들웨어 단계에 퍼미션 레이어가 들어와야 한다. OCR상 실제 코드는 apps/admin/src/server/permission/index.ts의 function permissionFor(request: expressRequest) 형태다. 로그인·회원가입 같은 경로는 퍼미션을 따지지 않지만, 그 외 모든 페이지 요청은 전체 퍼미션 정책에 따라 걸러 거부한다.
3-4. 모델 관리와 조직 관리
- 모델 관리: 엔드포인트(URL·API 형식·인증 헤더)를 등록하고, 모델별 파라미터(컨텍스트 크기, temperature, minP/topP/topK, repeat penalty, reasoning on/off, modality)를 지정한다. 같은 모델도 파라미터가 다른 여러 프리셋으로 저장한다.
- 조직 관리: 다중 루트를 지원하는 계층 트리다. 조직마다 사용할 모델을 지정하고, 멤버에게 권한을 부여한다.
4. 실습·구현 가이드 (Step 1·2·3·4)
Step 1 — 스캐폴딩과 기술 스택 결정
AI 스킬로 모노레포 골격을 스캐폴딩한다. 처음부터 세세히 지시하지 말고 기본 틀을 먼저 잡게 한 뒤 기본 내용을 지시한다. DB는 미니멀하면 SQLite, 규모가 커지면 PostgreSQL을 쓴다. 퀴즈용 캐시나 MySQL 같은 것은 특별한 요구가 없으면 필요 없다.
💡 실무 노하우: 사내 비즈니스용은 어지간히 대규모 배포가 아니면 SQLite로 충분하다. 에이전트류를 만들 때 파일 시스템에 폴더를 나눠 JSON을 쓰는 방식은 폴더가 금방 지저분해지고 동시성이 더 나빠 한계가 금방 온다. 그래서 처음부터 DB를 쓴다.
Step 2 — 계정·세션 시스템
이메일·비밀번호로 계정을 정의하되, 회사 이메일은 퇴사 시 재발급되어 고유하지 않다는 점을 인지한다. 로그인 성공 시 세션 키를 발급하고, 세션마다 IP·컴퓨터 이름 등 감사 정보를 남긴다. 가입 승인은 수동 승인 / 자동 승인(필터 기반: IP 대역, 사번 DB 조회 등) / 정책 선택을 모두 제공한다. 세션 로그 보관 기간·자동 삭제 정책, 세션 헤더·쿠키 이름 커스터마이징 옵션도 노출한다.
⚠️ 주의: 사내망 보안 방화벽은 L7 레이어에서 헤더를 모두 감시한다. 우리 시스템이 로그인 시 어떤 헤더·쿠키 이름을 쓸지 미리 보안팀에 제출해 통과시켜야 통신이 된다. 그래서 헤더·쿠키 이름을 자유롭게 커스터마이징할 수 있어야 한다.
Step 3 — 퍼미션 레이어와 i18n
미들웨어에 퍼미션 레이어를 넣어 로그인·가입을 제외한 모든 요청의 권한을 검증한다. 동시에 i18n을 강제한다 — 8개 언어(한국어 제외) 리소스 외재화를 스킬로 강제하고, 뷰에서 string.liter(문자열 리터럴) 직접 사용을 금지한다. 리소스 키는 프론트엔드 페이지.메뉴.항목 네이밍으로 정의하고, 동적 JSON을 그대로 믿지 않고 키를 Enum 타입으로 선언해 컴파일 시점에 오타·누락을 잡는다.
Step 4 — 모델·조직 관리와 배포
모델 엔드포인트를 등록하고 파라미터·프리셋을 저장한다. 조직 트리를 만들어 조직별 모델과 멤버 권한을 할당한다. 배포는 web-deploy-docker 스킬로 디플로이 스크립트를 강제 실행해 Docker 업데이트까지 자동화한다. 테스트는 Codex 내장 브라우저로 스크린샷을 찍어 보고받고, 결과를 날짜별 테스트 폴더에 남긴다.
✅ 확인: 스캐폴딩 직후 바로 완성으로 "퀀텀 점프"하지 말고, 내장 브라우저 스크린샷으로 좌측 메뉴 구조·색상(Monotone)·다국어 드롭다운이 의도대로 나오는지 단계마다 확인한다. 시연 중에도 모델 목록이 안 잡히는 문제가 있었는데, 원인은 (1) Docker 안에서
localhost를 쓴 것, (2) 공유 NAS 드라이브 연결이 부팅 중 끊긴 것이었다.
5. 사례·적용
5-1. 모델 파라미터 실제 설정값
시연에서 로컬 모델(LM Studio 연동)을 수동 등록하며 제시한 실제 값이다.
- 컨텍스트: 풀 컨텍스트(262K).
- temperature: 코딩이 빡빡하게 되라고 0.4.
- topP: 보통 0.95.
- topK: 20은 너무 빡빡하고, 권장은 50~60개 정도, 시연에서는 50.
- repeat penalty: 원래 안 주지만, 작은 모델이 reasoning loop에 자주 빠지면 준다. 시연 중 이 값이 정수
0.02가 아니라 소수점으로 나와야 하는데 정수로 잘못 만들어진 버그를 발견했다. - reasoning: 쓰면 좋을 것 같지만 추론 루프에 자주 빠져 안 쓰는 경우도 있다.
- modality: 적재한 모델이 일부 모델리티를 제거한 것일 수 있어 어디까지 제공할지 골라 준다.
5-2. 조직 관리 UI
"관리자 근속 V0.1.0" 화면의 접근 제어 > 조직에서, 여러 루트와 하위 노드를 만들고 멤버·노드·하위 트리 책임자를 지정한다. 예: 인수테스트-그룹A, A-글로벌사업, A-글로벌-아시아, A-글로벌-유럽, A-전략기획 같은 계층. 조직마다 색상·아이콘도 바꾼다("괜히 만든 게 아니라 실제 니즈로 만든 기능").
5-3. 곁가지 시연 — WebGPU PDF 뷰어 "PDFit"
발표자가 별도로 만든 프로젝트로, 브라우저에서 GPU를 쓰는 최신 라이브러리 WebGPU와 크롬 내장 PDF 엔진 PDFium의 웹 어셈블리(WASM) 버전을 결합해 PDF를 빠르게 렌더링한다. 저해상도로 먼저 그린 뒤 고해상도로 교체하는 방식이라 체감 속도가 빠르다. 북스캔 713권을 태그·북마크로 관리하며, GitHub(hikaMaeng)에 공개돼 npm으로 설치할 수 있다.
📚 참고: 이 사례들의 공통점은 "AI가 대충 만든 게 아니라 사람이 기획자와 함께 만든 것 같은 정교함"이다. 그 정교함은 자유방임이 아니라 스킬셋으로 스케일을 조인 결과라는 것이 발표자의 결론이다.
6. 핵심 원리
6-1. 세션 키 = 발급·회수 가능한 신뢰
로그인이란 세션 키를 발급해 둔 상태다. 키는 만료되면 재발급받아야 하고, 관리자가 특정 세션 키를 제거하면 즉시 로그인이 취소된다. 이 모델의 힘은 인증 상태를 서버가 언제든 통제(회수)할 수 있다는 데 있다.
6-2. 마스터 권한은 시스템 차원(env)에서 고정
마스터 계정을 DB가 아닌 .env에 두는 이유는, DB를 조작해도 권한이 바뀌지 않게 하기 위함이다. 권한의 근원(root of trust)을 애플리케이션 데이터 밖(배포 환경)에 두어 DB 침해로도 최고 권한을 탈취할 수 없게 한다. 대가로, 마스터를 바꾸려면 서버를 재기동해야 한다.
6-3. 폴더 격리 + 파일 크기 제한 = AI 통제
발표자는 폴더를 아주 잘게 나눈다. AI가 수정할 때 폴더 경계를 넘어가지 못하게 하기 위해서다. monorepo-architecture-guard 스킬에는 400자 파일 길이 제한이 걸려 있어 파일이 커지면 강제로 나누게 된다. 또 Docker 포트는 다섯 자리(예: 18080, 18089)만 할당하도록 강제한다. 즉 "뽑기(생성)"를 하더라도 격리 구간 안에서만 하게 만들어, 결과를 사람이 읽고 통제할 수 있게 한다.
6-4. 모델 렌더러(useModel 훅)
React는 순수한 모델(데이터)을 그려 주는 뷰어일 뿐이다. 뷰를 감싸는 모델이 있고, useModel 훅은 그 스토어 모델이 갱신되면 emitting을 통해 관련 컴포넌트만 리렌더링한다. 개별 state를 일일이 잡는 대신 모델의 값 변화에 컴포넌트가 반응하게 하는 패턴이다.
6-5. 인수 테스트 우선
"코드상의 단위 테스트는 옛날 방식"이라는 것이 발표자의 주장이다. AI가 단위 테스트를 실패하면 다시 뽑기로 통과시킬 뿐이므로, 처음부터 인수 테스트(Acceptance Test)만 돌린다. 뽑기로 인수 테스트를 통과하는 편이 나중에 보기에도 훨씬 편하다.
7. 한계·트레이드오프
- AI 자율성 vs 통제: 자유롭게 풀면 첫 결과는 나오지만 유지보수가 안 된다. 반대로 스킬셋으로 꽉 조이면 통제는 되지만, 스킬셋을 미리 정교하게 짜 두는 선행 비용이 크다. 발표자조차 "유튜브·연예인들이 자유 프레임워크로 잘 됐다는 게 믿기지 않는다. 나는 의심이 많다"고 말한다.
- 마스터를 env로 고정한 대가: 보안은 강해지지만 마스터 교체 때마다 서버 재기동이 필요해 무중단 운영과 상충한다.
- 로그·세션 누적: 감사를 위해 세션 로그를 남기면 남길수록 쌓여서 서버가 죽는다(장애 원인 1위). 보관 기간·자동 삭제로 균형을 잡아야 한다.
- 로컬/공유 인프라 의존: 시연에서도 Docker
localhost오해와 공유 NAS 연결 끊김으로 모델 목록이 안 잡혔다. 로컬 GPU·공유 드라이브 기반 모델(2.2TB)은 편리하지만 연결 안정성이 취약하다. - 파라미터 버그 가능성: repeat penalty가 정수로 생성되는 등 AI 생성 코드에 미묘한 타입 오류가 섞일 수 있어, 정적 체크가 없으면 조용히 넘어간다.
⚠️ 주의: "AI만 알고 다 시키면 되지 않을까"라는 기대는 아직 이르다. 개발 지식과 통제 장치 없이는 통제 가능한 코드가 나오지 않는다.
8. 다른 접근과 비교
| 축 | 이 강의의 접근 | 대비되는 접근 |
|---|---|---|
| AI 활용 | 스킬셋으로 폴더·파일·포트·i18n을 강제 통제 | 자유로운 바이브 코딩(프롬프트만으로 맡김) |
| 테스트 | AI 내장 브라우저 기반 인수 테스트 | 코드상 단위 테스트 중심 |
| DB | 미니멀은 SQLite, 규모 시 PostgreSQL | 파일 시스템 + JSON 폴더 |
| 최고 권한 | .env로 고정(DB 무관) |
DB 플래그로 관리자 지정 |
| 상태 관리 | 모델 + useModel 훅(모델 렌더러) |
컴포넌트마다 개별 state |
| 브라우저 테스트 | Codex 3 내장 브라우저 | 별도 헤드리스 브라우저(Playwright) 중계 |
💡 실무 노하우(최신 모범사례): 과거에는 헤드리스 브라우저 테스트 스킬(
write-playwright-e2e-template.sh등)을 노드로 실행해 중계했지만, AI 도구에 내장 브라우저가 등장하면서 별도 헤드리스 브라우저가 거의 필요 없어졌다. 발표자는 각 프로젝트 유형별(웹은 React+Express용/Next.js용, 안드로이드용)로 스킬셋을 따로 두고, 프로젝트 성격에 맞는 스킬셋만 골라 적용한다 — 하나의 만능 스킬셋을 모든 곳에 쓰지 않는다.
또한 발표자는 Codex 릴리스 로그를 근거로 흥미로운 비교를 제시한다. OpenAI Codex의 이슈·버그 픽스·새 기능 대부분을 사람이 아니라 봇(copyberry)이 처리하며, 사람은 아주 드물게만 개입한다. "사람이 개발하는 시대가 얼마 안 남았다"는 관찰이다. 이는 이 강의의 통제 철학이 결국 사람이 아니라 봇이 스킬셋 안에서 개발하는 미래를 겨냥함을 시사한다.
9. 메타인지 자기평가
아래 질문에 스스로 답해 보며 이해도를 점검하라.
- 개념 확인: 세션 키를 "발급/회수"로 설명할 수 있는가? 마스터 계정을 DB가 아닌
.env에 두는 이유를 보안 관점에서 한 문장으로 말할 수 있는가? - 구조 확인: 모노레포에서
common·frontend·server에 각각 무엇이 들어가고,packages에 프레임워크 디펜던시가 들어가면 안 되는 이유를 설명할 수 있는가? - 적용 확인: Docker 컨테이너 안에서
localhost가 왜 문제이며 무엇으로 바꿔야 하는지 답할 수 있는가? 사내 방화벽 때문에 세션 헤더·쿠키 이름을 커스터마이징해야 하는 이유는? - 원리 확인: 폴더를 잘게 나누고 파일 400자 제한을 거는 것이 어떻게 "AI 통제"로 이어지는가? 단위 테스트 대신 인수 테스트를 택하는 논리는?
- 비판적 사고: 스킬셋 통제 방식의 트레이드오프(선행 비용, 유연성 저하)를 자신의 프로젝트에 적용한다면 어디까지 조이고 어디는 풀겠는가?
- 종합 설계: 우리 회사에 최소 기능 어드민을 만든다면, 계정·세션·모델·조직 중 어떤 순서로 만들고 대시보드를 언제 만들겠는가? (힌트: 대시보드는 마지막)
✅ 확인: 위 6개에 막힘없이 답할 수 있다면 이번 주 목표(구현 시현의 논리 재구성)를 달성한 것이다. 막히는 항목이 있으면 해당 절(3~6절)로 돌아가 근거 발화를 다시 확인하라.
다음 주 예고
기반 어드민이 완성됐으므로 다음 주부터는 실제 에이전트 서버·클라이언트를 만든다. 에이전트도 로그인해 세션 키를 받고, 그 세션 키 기반으로 계정이 속한 조직의 권한에 따라 중앙에서 통제받는 모델로 라우팅되어 돈다. 기본적인 에이전트 루프를 살펴보는 이론 회차가 이어진다.
클릭하거나 Space를 눌러 뒤집기