토큰, 컨텍스트, 도구, 테스트로 설명하는 AI의 코드·결정 생성 방식에 대한 명확한 멘탈 모델과 한계 및 실무적 프롬프트 팁.

사람들이 “AI가 생각한다”고 말할 때 보통은 질문을 이해하고 추론해서 답을 내린다는 뜻을 떠올립니다.
텍스트 기반 현대 모델(LLM)에는 더 유용한 멘탈 모델이 있습니다: 모델은 다음에 올 텍스트를 예측합니다.
이 표현은 시시해 보일 수 있지만, “다음 텍스트”가 얼마나 많은 것을 만들어낼 수 있는지 보면 달라집니다. 모델이 학습한 패턴이 충분히 많으면, 다음 단어(그리고 그 다음 단어, 또 그다음)를 예측하는 것만으로 설명, 계획, 코드, 요약, 심지어 앱에서 쓸 수 있는 구조화된 데이터까지 생성할 수 있습니다.
좋은 AI 기능을 만들기 위해 기저 수학을 알 필요는 없습니다. 필요한 것은 동작을 예측할 실용적인 방식입니다:
이 글은 바로 그런 모델입니다: 과장도, 깊은 기술 논문도 아니라 신뢰할 수 있는 제품 경험을 설계하는 데 도움이 되는 개념들입니다.
앱 제작자 관점에서 모델의 ‘생각’은 입력(프롬프트, 사용자 메시지, 시스템 규칙, 검색된 콘텐츠)에 반응해 생성하는 텍스트입니다. 모델은 기본적으로 사실을 확인하지 않고, 웹을 탐색하지 않으며, 당신의 데이터베이스에 무엇이 있는지를 알지 못합니다—그 정보를 전달하지 않는 한요.
기대치를 적절히 설정하세요: LLM은 초안 작성, 변환, 분류, 코드와 유사한 출력 생성에 매우 유용합니다. 그러나 마법처럼 항상 진실을 말해주진 않습니다.
멘탈 모델을 몇 가지 부분으로 나누겠습니다:
이 개념들로 프롬프트, UI, 안전장치를 설계하면 AI 기능이 일관되고 신뢰받는 느낌을 줄 수 있습니다.
사람들이 AI가 “생각한다”고 말하면 사람이 하는 식으로 추론한다고 상상하기 쉽습니다. 더 유용한 모델은 간단합니다: 아주 빠른 자동완성(autocomplete)을 토큰 단위로 반복하는 것입니다.
토큰은 모델이 다루는 텍스트의 단위입니다. 때로는 전체 단어(“apple”), 때로는 단어의 일부(“app” + “le”), 때로는 구두점, 때로는 공백일 수 있습니다. 토크나이저에 따라 분할 방식이 달라지지만 요점은 모델이 문장을 깔끔하게 처리하는 것이 아니라 토큰을 처리한다는 것입니다.
모델의 핵심 루프는 다음과 같습니다:
그게 전부입니다. 모든 단락, 목록, ‘추론’ 체인은 이 다음 토큰 예측을 여러 번 반복해 만든 결과입니다.
모델은 방대한 텍스트를 학습했기 때문에 설명이 어떻게 흐르는지, 공손한 이메일이 어떻게 쓰이는지, 버그 수정을 보통 어떻게 서술하는지 같은 패턴을 학습합니다. 질문하면 학습한 패턴에 맞고 제공된 컨텍스트와 일치하는 답을 생성합니다.
이 때문에 틀릴 때도 자신감 있고 일관되게 들릴 수 있습니다: 모델은 현실을 확인하려고 최적화된 것이 아니라 다음에 올 텍스트를 예측하도록 최적화되어 있기 때문입니다.
코드는 모델에게 특별한 것이 아닙니다. JavaScript, SQL, JSON, 에러 메시지 모두 토큰의 연속입니다. 모델이 유용한 코드를 생성할 수 있는 것은 일반적인 코딩 패턴을 학습했기 때문이지, 팀의 엔지니어처럼 당신의 앱을 진짜로 ‘이해’해서가 아닙니다.
사람들이 “모델은 그 답을 어디서 얻었나?”라고 물을 때, 가장 유용한 모델은: 모델은 방대한 예시에서 패턴을 학습했고, 이제 그 패턴을 재조합해 다음에 올 텍스트를 생성한다는 것입니다.
훈련 중 모델은 많은 텍스트 조각(책, 기사, 코드, 문서, Q&A 등)을 보여주며 간단한 작업을 반복 연습합니다: 주어진 텍스트에서 다음 토큰을 예측하는 것. 예측이 틀리면 학습 과정이 내부 파라미터를 조금씩 조정해 다음 번에는 더 나은 예측이 나오게 합니다.
시간이 지나며 이 조정들이 누적되어 모델은 다음과 같은 관계들을 인코딩합니다:
모델은 통계적 규칙성을 학습하므로 고정된 한 문장을 암기하는 것이 아니라 패턴을 새로 결합할 수 있습니다. "개념을 설명하는 예시"를 많이 보고 "당신의 앱 상황"을 많이 보면, 둘을 합쳐 맞춤형 응답을 생성할 수 있습니다.
이 때문에 LLM은 틈새 제품에 대한 온보딩 이메일을 그럴듯하게 작성하거나 일반적인 API 통합 설명을 특정 스택에 맞게 조정할 수 있습니다. 모델은 단일 문단을 검색해오는 것이 아니라 학습한 패턴에 맞는 새 연속을 생성하는 것입니다.
훈련 데이터에 특정 사실(예: 요금제나 내부 정책)이 포함되었다 하더라도 모델이 그것을 신뢰성 있게 ‘조회’할 수 있다고 가정하면 안 됩니다. 훈련은 지식 기반을 인덱싱하는 방식이 아니라 압축과 비슷합니다: 많은 예시가 가중치로 응축되어 미래 예측에 영향을 줍니다.
따라서 모델은 유사한 문맥에서 보통 나타나는 것에 근거해 세부 정보를 추측하고 자신 있게 말할 수 있습니다.
패턴 학습은 유창하고 관련 있는 텍스트를 생성하는 데 강력하지만, 유창함이 진실과 같지는 않습니다. 모델은 다음과 같은 오류를 범할 수 있습니다:
앱 제작자에게 핵심은: LLM의 답은 보통 학습된 패턴에서 나오지, 검증된 사실에서 나오지 않는다는 점입니다. 정확성이 중요하면 출력물을 자체 데이터와 검사로 근거화해야 합니다(나중 섹션에서 다룹니다).
LLM이 응답을 쓸 때 단 하나의 ‘정답 문장’을 데이터베이스에서 꺼내는 것이 아닙니다. 각 단계에서 모델은 가능한 다음 토큰들의 범위를 예측하고, 각 토큰에 확률을 할당합니다.
모델이 항상 가장 가능성이 높은 단일 토큰만 선택하면 결과는 매우 일관되겠지만 반복적으로 단조롭고 어색할 수 있습니다. 대부분 시스템은 대신 확률에서 샘플링을 사용해 제어된 무작위성을 도입합니다.
두 가지 설정이 출력의 다양성에 영향을 줍니다:
앱을 만들 때 이 노브는 예술적 의미의 ‘창의성’보다 다음 중 선택하는 문제입니다:
모델은 그럴듯한 텍스트를 만들어내는 것을 최적화하므로 근거가 부족해도 단정적으로 말할 수 있습니다. 표현의 확신은 증거가 아닙니다. 그래서 사실 기반 작업에는 종종 근거(검색)나 검증 단계가 필요합니다.
LLM에 “배열에서 중복을 제거하는 JavaScript 함수를 써줘”라고 하면 다음과 같은 여러 정답을 받을 수 있습니다. 모두 유효합니다:
// Option A: concise
const unique = (arr) => [...new Set(arr)];
// Option B: explicit
function unique(arr) {
return arr.filter((x, i) => arr.indexOf(x) === i);
}
샘플링 설정에 따라 스타일(간결 vs 명시적), 성능·가독성의 트레이드오프, 엣지 케이스 처리 방식 등이 달라질 수 있습니다. 모델이 ‘마음대로 바꾼’ 것이 아니라 여러 높은 확률의 연속 중에서 선택한 것입니다.
AI 모델이 ‘대화를 기억한다’고 말할 때 실제로는 컨텍스트—지금 볼 수 있는 텍스트(최신 메시지, 시스템 지시, 대화의 일부)—를 말합니다. 컨텍스트 윈도우를 넘어간 내용은 모델의 시야에서 사라집니다.
컨텍스트 윈도우는 모델이 한 번에 고려할 수 있는 텍스트의 고정 한계입니다. 대화가 충분히 길어지면 초기 부분이 이 창 밖으로 밀려 나가 보이지 않게 됩니다.
그래서 다음과 같은 현상이 발생합니다:
대화를 계속 이어가면 최근의 대화가 공간을 차지합니다. 중요한 제약이 최근 메시지에 밀려나면 모델은 남아 있는 것만으로 무엇이 중요한지 추론해야 합니다—그 결과 자신 있게 보이지만 핵심 세부를 놓칠 수 있습니다.
실용적인 해결책은 주기적 요약입니다: 목표, 결정사항, 제약을 간결한 블록으로 정리해 다시 주입하세요. 앱에서는 자동 ‘대화 요약’을 만들어 프롬프트에 넣는 방식으로 구현합니다.
모델은 출력을 생성할 바로 앞에 있는 지시를 따르는 경향이 있습니다. 따라서 반드시 지켜야 할 규칙(형식, 톤, 엣지케이스)은 프롬프트의 끝부분—"이제 답을 생성하라" 바로 전—에 두세요.
앱을 설계할 때는 어떤 정보를 항상 컨텍스트에 두어야 하는지(요구사항, 사용자 선호, 스키마)를 결정하고 채팅 이력을 자르거나 간결한 요약을 추가해 보존하세요. 프롬프트 구조에 관해 더 알고 싶다면 /blog/prompting-as-interface-design을 참고하세요.
LLM은 유능한 개발자가 줄 법한 답처럼 들리게 텍스트를 만들어내는 데 매우 능숙합니다. 그러나 “들어맞는 소리”가 항상 “정확한 답”은 아닙니다. 모델은 다음 토큰을 예측할 뿐, 당신의 코드베이스나 의존성, 실제 동작을 확인하지 않습니다.
모델이 제안한 수정이나 리팩터, 새 함수는 여전히 텍스트일 뿐입니다. 명시적으로 도구를 연결하지 않으면 앱을 실제로 실행하거나 패키지를 임포트하거나 API를 호출하거나 프로젝트를 컴파일하지 않습니다.
핵심 대조:
AI가 실수할 때는 예측 가능한 방식으로 실패합니다:
이 오류들은 주변 설명이 일관되게 보이기 때문에 발견하기 어려울 수 있습니다.
AI 출력을 동료가 로컬에서 실행해보지 않은 빠른 초안으로 취급하세요. 신뢰도는 다음을 수행한 후에 급격히 높아집니다:
테스트가 통과하지 않으면 모델의 답은 출발점일 뿐이며 최종 수정이 아닙니다.
언어 모델은 무엇이 가능할지 제안하는 데 좋지만, 그 자체로는 여전히 텍스트만 생성합니다. 도구는 AI 기반 앱이 그 제안을 검증된 행동으로 바꾸게 해줍니다: 코드 실행, 데이터베이스 쿼리, 문서 검색, 외부 API 호출 등.
앱 워크플로에서 도구는 보통 다음과 같습니다:
중요한 변화는 모델이 결과를 ‘안다고 주장’하는 수준을 넘어서 실제로 확인할 수 있게 된다는 점입니다.
유용한 멘탈 모델은 다음과 같습니다:
이 방식이 추측을 줄이는 핵심입니다. 린터가 사용하지 않는 임포트를 보고하면 모델이 코드를 업데이트합니다. 단위 테스트가 실패하면 실패 원인에 맞춰 반복합니다(혹은 왜 못 고치는지 설명합니다).
eslint/ruff/prettier를 실행해 스타일과 문제를 잡습니다.도구는 강력하지만 위험할 수 있습니다. 최소 권한 원칙을 따르세요:
도구가 모델을 더 ‘똑똑하게’ 만들진 않지만 출력이 검증 가능해져 앱의 AI는 더 근거 있게 동작합니다.
모델은 볼 수 있는 텍스트를 요약·정리·추론하는 데 강력합니다. 하지만 최신 제품 변경사항, 회사 정책, 특정 고객의 계정 정보 같은 것을 자동으로 알지는 못합니다. RAG(검색 증강 생성)는 간단한 해결책입니다: 먼저 관련 사실을 가져오고, 그 다음 모델이 그 사실을 사용해 글을 쓰게 하세요.
RAG는 ‘오픈북 AI’로 생각하세요. 모델에게 기억에 의존해 답하게 하지 말고, 앱이 관련된 신뢰할 만한 문단(스니펫)을 검색해 프롬프트에 추가합니다. 모델은 제공된 자료에 기반해 응답을 생성합니다.
정확성이 외부 정보에 달려 있을 때 RAG를 기본으로 쓰는 것이 좋습니다:
제품 가치가 “우리 비즈니스에 맞는 정확한 답”에 달려 있다면, RAG는 모델이 추측하기를 바라는 것보다 훨씬 안전합니다.
RAG의 성능은 검색 결과 품질에 달려 있습니다. 검색 단계에서 오래되었거나 관련 없는 자료가 올라오면 모델은 자신 있게 잘못된 답을 할 수 있습니다—이제는 잘못된 출처에 ‘근거’를 둔 상태로요. 실제로 검색(청크 분할, 메타데이터, 최신성, 랭킹)을 개선하면 프롬프트 조정보다 정확도가 더 크게 올라갑니다.
“에이전트”는 모델이 루프를 돌며 계획을 세우고, 한 단계 실행하고, 결과를 보고 다음 행동을 결정하는 방식입니다. 단일 응답을 넘어서 목표 달성을 위해 반복합니다.
유용한 멘탈 모델은 다음과 같습니다:
Plan → Do → Check → Revise
이 루프가 단일 프롬프트를 작은 워크플로로 바꿉니다. 에이전트가 더 ‘독립적’으로 느껴지는 이유는 모델이 텍스트를 생성하는 것 외에 행동을 선택하고 순서를 정하기 때문입니다.
에이전트에는 언제 멈출지에 대한 명확한 규칙이 필요합니다. 일반적 종료 조건:
가드레일은 루프를 안전하고 예측 가능하게 만드는 제약입니다: 허용된 도구, 허용된 데이터 출처, 인간의 확인 단계, 출력 형식 제한 등입니다.
에이전트는 언제나 “한 단계 더”를 제안할 수 있기 때문에 실패 모드에 대비해야 합니다. 예산, 타임아웃, 단계 제한이 없으면 에이전트는 반복적으로 비슷한 동작을 하며 비용을 쌓을 수 있습니다.
실용적 기본값: 반복을 상한, 모든 행동 로깅, 도구 결과 검증 요구, 부분 답변과 시도한 내역을 함께 실패로 반환하는 방식으로 우아하게 실패 처리하세요. 이는 에이전트를 끝없이 돌리는 것보다 더 나은 제품 설계인 경우가 많습니다.
Koder.ai 같은 비브-코딩 플랫폼과 함께 빌드한다면 이 “에이전트 + 도구” 멘탈 모델이 특히 실용적입니다. 단순히 제안을 주고받는 것 이상으로, 어시스턴트가 기능을 기획하고 React/Go/PostgreSQL 또는 Flutter 컴포넌트를 생성하며 스냅샷과 롤백 같은 체크포인트로 빠르게 이동하되 변경 관리를 잃지 않게 돕는 워크플로를 구현할 수 있습니다.
LLM을 앱 기능 뒤에 두면 프롬프트는 단순한 텍스트가 아닙니다. 모델과 제품 사이의 인터페이스 계약입니다: 모델이 무엇을 하려는지, 무엇을 사용할 수 있는지, 그리고 당신의 코드가 신뢰성 있게 소비할 수 있도록 어떻게 응답해야 하는지 정의합니다.
좋은 관점은 프롬프트를 UI 폼처럼 다루는 것입니다. 좋은 폼이 애매함을 줄이고 선택을 제약하며 다음 행동을 명확히 하듯, 좋은 프롬프트도 마찬가지입니다.
배포 전에 프롬프트가 다음을 분명히 하는지 확인하세요:
모델은 패턴을 따릅니다. 원하는 패턴을 ‘가르치는’ 강력한 방법은 좋은 입력과 좋은 출력의 단일 예시를 포함하는 것입니다(특히 엣지 케이스가 있는 작업일 때). 하나의 예시로도 백앤드 왕복을 줄이고 앱이 표시할 수 없는 형식의 출력을 방지할 수 있습니다.
다른 시스템이 응답을 읽어야 한다면 구조화하세요. JSON, 테이블, 엄격한 목록을 요구하세요.
You are a helpful assistant.
Task: {goal}
Inputs: {inputs}
Constraints:
- {constraints}
Output format (JSON):
{
"result": "string",
"confidence": "low|medium|high",
"warnings": ["string"],
"next_steps": ["string"]
}
이렇게 하면 “프롬프트”가 예측 가능한 인터페이스 설계로 바뀝니다.
명시적 규칙을 하나 추가하세요: “핵심 요구사항이 누락된 경우, 답변하기 전에 명확한 질문을 하라.”
이 한 줄은 자신감 있어 보이지만 틀린 출력을 막아줍니다—모델이 추측하지 말고 멈춰서 필요한 필드를 요청하도록 허용(또는 요구)하기 때문입니다.
실무에서는 가장 신뢰할 수 있는 프롬프트가 제품의 빌드 및 배포 방식과 일치합니다. 예를 들어 플랫폼이 먼저 기획하고, 변경을 생성하고, 소스 코드를 내보내거나 배포하는 방식을 지원한다면 프롬프트 계약에도 그 단계를 반영하세요(기획 → 변경점/디프 생성 → 확인 → 적용). Koder.ai의 “플래닝 모드”는 프로세스를 명시적 단계로 바꿔 표류를 줄이고 팀이 배포 전 변경사항을 검토하게 하는 좋은 예입니다.
신뢰는 모델이 자신감 있게 들린다고 해서 생기지 않습니다. AI 출력을 제품의 다른 의존성과 똑같이 측정하고 모니터링하고 제약하는 방식으로 다뤄야 합니다.
우선 앱이 잘 수행해야 하는 소수의 실제 작업을 골라 반복 가능한 검사로 만드세요:
"괜찮은가?" 대신 "얼마나 자주 통과하는가?"를 추적하세요. 유용한 지표:
문제가 생겼을 때 재현할 수 있어야 합니다. 다음을 로깅하세요(적절히 마스킹):
이렇게 하면 "모델이 바뀌었나, 데이터나 도구가 바뀌었나?"를 구분해 디버깅할 수 있습니다.
몇 가지 기본값만 지켜도 많은 사고를 예방할 수 있습니다:
보통 모델이 일관성 있고 목표 지향적인 텍스트를 만들어내며, 그 모습이 이해와 추론처럼 보인다는 의미입니다. 실제로 LLM은 다음 토큰 예측(next-token prediction)을 수행합니다: 주어진 프롬프트, 지시문, 제공된 컨텍스트를 바탕으로 가장 그럴듯한 텍스트 연속을 생성합니다.
앱을 만드는 관점에서 유용한 결론은 “생각한다”는 것은 모델의 내부적 보증이 아니라 당신이 설계하고 제약할 수 있는 출력 행동이라는 점입니다.
토큰은 모델이 처리하고 생성하는 텍스트의 단위입니다(단어 전체, 단어의 일부, 구두점, 공백 등). 모델은 문장이 아니라 토큰 단위로 동작하기 때문에 비용, 한계, 자르기(truncation)가 모두 토큰 기반으로 계산됩니다.
실무적 포인트:
생성은 확률적이기 때문입니다. 각 단계마다 모델은 여러 가능한 다음 토큰에 확률을 부여하고, 대부분의 시스템은 항상 최상위 토큰만 고르지 않고 그 분포에서 샘플링합니다.
출력을 더 반복 가능하게 만들려면:
LLM은 그럴듯한 텍스트를 생성하도록 최적화되어 있고, 사실 검증을 하도록 설계된 것은 아닙니다. 훈련 데이터에서 자신감 있게 표현하는 패턴을 많이 배웠기 때문에 실제로는 추측인 내용도 단호하게 말할 수 있습니다.
제품 설계에서는 유창함을 “잘 쓴 글”로 보고, 정확성이 중요할 때는 RAG, 도구, 테스트, 승인 절차 등 검증 수단을 추가하세요.
컨텍스트 윈도우는 모델이 한 번에 볼 수 있는 최대 텍스트 분량(시스템 지시, 대화 이력, 검색된 스니펫 등)입니다. 대화가 길어지면 초기 정보가 윈도우 밖으로 밀려나 모델이 볼 수 없게 됩니다.
완화 방법:
기본적으로 모델은 웹을 탐색하거나 데이터베이스를 읽거나 코드를 실행하지 않습니다. 프롬프트에 포함한 정보와 명시적으로 연결한 도구만 볼 수 있습니다.
내부 데이터나 최신 정보가 필요하면, 프롬프트에 직접 넣거나 검색(RAG)·도구 호출을 통해 전달하세요.
결과가 검증된 실제 행동이나 확인이 필요할 때는 도구를 사용하세요. 대표적 예:
유용한 패턴은 제안 → 실행 → 조정입니다. 모델이 제안하면 도구로 결과를 확인하고, 모델이 그 결과를 반영해 수정하게 하세요.
RAG(검색 증강 생성)는 ‘오픈 북’ 방식의 AI입니다: 앱이 관련된 문단(스니펫)을 검색해 모델 입력에 포함시키면 모델이 그 근거로 답을 생성합니다.
RAG를 쓰면 좋을 때:
주의: RAG의 정확성은 검색 품질에 달려 있습니다. 검색 단계의 품질을 개선하면 프롬프트 조정보다 정확도가 더 크게 올라갑니다.
에이전트는 LLM이 루프를 돌며 계획을 세우고, 한 단계 실행하고, 결과를 확인하고, 계획을 수정하는 방식입니다. 단일 응답이 아니라 여러 단계로 목표를 달성합니다.
안전장치:
프롬프트를 인터페이스 계약으로 다루세요: 목표, 입력, 제약, 출력 형식을 분명히 정의해 앱이 결과를 신뢰할 수 있게 만드세요.
실용적 신뢰 구축 수단: