Skip to main content
Summary

빈 페이지보다 선택한 문장을 먼저 돕자

AI 글쓰기 도우미를 만들자고 하면 많은 사람이 먼저 '블로그 글을 자동으로 써 주는 앱'을 떠올립니다. 제목을 넣으면 서론, 본론, 결론이 한 번에 나오고, 사용자는 복사해서 붙여 넣기만 하면 되는 도구 말입니다. 처음에는 그럴듯해 보입니다. 빈 화면이 순식간에 글로 채워지기 때문입니다.

하지만 실제 글쓰기 작업은 그렇게 단순하지 않습니다. 사람은 대부분 완전히 빈 페이지 앞에서만 막히지 않습니다. 오히려 이미 한두 문장을 써 놓고 이런 고민을 합니다. 이 표현이 너무 딱딱한가? 문장이 길어서 읽기 어렵나? 고객에게 보내기에는 공격적으로 들리나? 핵심은 좋은데 조금 짧게 줄일 수 없을까?

그래서 이번 장에서 만들 글쓰기 도우미의 중심은 '초안 생성'이 아니라 '편집 보조'입니다. 사용자가 쓴 문장을 선택하고, '짧게', '부드럽게', '전문적으로', '더 명확하게' 같은 요청을 보내면, 도우미는 원문의 뜻을 보존하면서 더 나은 표현을 제안합니다. OpenAI의 글쓰기 학습 자료에서도 ChatGPT를 글의 초안 작성뿐 아니라 수정과 다듬기 과정에 활용하는 흐름을 다룹니다1. 제품 관점에서 더 중요한 부분도 바로 이 지점입니다. LLM을 글쓰기 제품에 넣는다는 것은 기능 버튼을 많이 만드는 일이 아니라, 사용자가 글을 쓰는 순간순간의 흐름을 끊지 않는 일입니다.

이번 장의 목표는 문장 개선, 톤 변환, 요약, 확장 기능을 갖춘 작은 글쓰기 보조 도구를 만드는 것입니다. 완성된 앱은 사용자가 원문을 입력하거나 선택한 뒤 작업을 고르고, 결과를 원문과 나란히 비교하고, 마음에 들면 삽입하고, 마음에 들지 않으면 되돌릴 수 있는 구조를 갖습니다.

AI 글쓰기 도우미 만들기

글쓰기 도우미의 네 가지 기본 기능

처음부터 모든 글쓰기 기능을 만들 필요는 없습니다. 좋은 제품은 많은 메뉴보다 자주 쓰는 작업을 빠르게 처리합니다. 이 장에서는 네 가지 기능으로 시작하겠습니다.

기능사용자의 말모델이 해야 할 일
문장 개선더 명확하게 다듬어 줘원문의 의미를 유지하면서 문장 구조와 표현을 개선한다
톤 변환더 부드럽게 바꿔 줘독자와 상황에 맞게 말투를 바꾸되 핵심 주장은 유지한다
요약절반 길이로 줄여 줘중요한 정보만 남기고 반복과 부연을 줄인다
확장조금 더 풍부하게 써 줘원문에 담긴 생각을 풀어 쓰되 새 사실을 지어내지 않는다

여기서 중요한 것은 네 기능이 모두 '원문을 바탕으로 한 변환'이라는 점입니다. AI에게 처음부터 글 전체를 맡기면 출력은 빠르지만 사용자의 의도와 멀어질 수 있습니다. 반대로 사용자가 이미 쓴 문장을 중심에 두면 LLM은 공동 저자라기보다 편집자에 가까워집니다. 좋은 편집자는 글쓴이를 밀어내지 않습니다. 글쓴이가 말하려던 것을 더 잘 들리게 해 줍니다.

실제 글쓰기용 LLM은 작업별로 강점이 다릅니다. 어떤 모델은 문장을 자연스럽게 다듬는 데 강하고, 어떤 모델은 지시를 엄격하게 따르는 데 강하며, 어떤 모델은 긴 자료를 읽고 구조화하는 데 강합니다. 따라서 '가장 좋은 모델 하나'를 고르기보다, 우리가 만들 기능별 샘플을 준비해 직접 비교하는 편이 좋습니다.

예를 들어 같은 원문을 놓고 다음 요청을 각각 테스트합니다. '고객에게 보내는 이메일처럼 부드럽게', '투자자에게 보내는 보고서처럼 전문적으로', 'SNS 게시물처럼 짧고 선명하게', '초등학생도 이해하도록 쉽게' 바꿔 보게 하는 식입니다. 결과를 비교할 때는 문장이 멋진지만 보지 말고, 원문의 숫자와 고유명사를 지켰는지, 새로운 사실을 넣지 않았는지, 요청한 길이를 지켰는지 함께 확인해야 합니다.

원문을 지키는 구조화 출력

글쓰기 도우미에서 가장 무서운 실패는 문장을 예쁘게 고치면서 뜻을 바꿔 버리는 것입니다. 예를 들어 원문에 '3월 15일까지 제출'이라고 되어 있는데 모델이 '3월 말까지 제출'로 바꾸면 문장은 자연스러워졌을지 몰라도 정보는 틀렸습니다. '환불이 가능합니다'가 '언제든 환불이 가능합니다'로 바뀌는 것도 위험합니다. 글쓰기 도우미는 표현을 고치는 도구이지 사실을 창작하는 도구가 아닙니다.

그래서 프롬프트에는 반드시 보존해야 할 규칙을 넣어야 합니다. '새 사실을 추가하지 말 것', '고유명사, 숫자, 날짜, 핵심 주장을 유지할 것', '불확실한 내용은 추정하지 말 것', '변경 이유를 한 줄로 설명할 것' 같은 제약이 필요합니다. 그리고 출력은 자유로운 문장이 아니라 원문, 수정문, 변경점, 경고를 담은 구조화된 형태로 받겠습니다.

먼저 데이터 구조를 정의합니다.

# schemas.py
from pydantic import BaseModel, Field
from typing import Literal

class Change(BaseModel):
    before: str = Field(description='원문 표현')
    after: str = Field(description='수정 표현')
    reason: str = Field(description='변경 이유 한 줄')

class AssistRequest(BaseModel):
    text: str
    task: Literal['improve', 'tone', 'summarize', 'expand']
    tone: str | None = None
    length: Literal['short', 'normal', 'long'] = 'normal'
    source_mode: bool = False
    sources: list[str] = []
    variant_count: int = Field(default=1, ge=1, le=3)

class AssistResult(BaseModel):
    original: str
    revised: str
    alternatives: list[str] = []
    changes: list[Change]
    reason: str
    warnings: list[str] = []

이 구조의 장점은 후속 코드가 결과를 안정적으로 다룰 수 있다는 점입니다. 사용자는 수정문만 볼 수도 있지만, 제품은 변경점을 따로 보여 줄 수 있습니다. 숫자나 고유명사가 바뀌었을 때 경고를 띄울 수도 있습니다. 나중에 품질 평가를 할 때도 '사용자가 어떤 변경을 수락했는가', '어떤 경고가 자주 발생했는가'를 기록하기 쉽습니다.

이제 작업별 지시문을 만들겠습니다.

# prompts.py
TASK_GUIDE = {
    'improve': '문장을 더 명확하고 자연스럽게 다듬는다.',
    'tone': '요청한 톤에 맞게 표현을 바꾼다.',
    'summarize': '핵심 의미를 보존하면서 짧게 줄인다.',
    'expand': '원문에 담긴 생각을 더 친절하게 풀어 쓴다.'
}

def format_sources(sources: list[str]) -> str:
    if not sources:
        return ''

    blocks = []
    for index, source in enumerate(sources, start=1):
        trimmed = source.strip()[:4000]
        blocks.append(f'[S{index}] {trimmed}')

    return (chr(10) + chr(10)).join(blocks)

def build_messages(req):
    task_instruction = TASK_GUIDE[req.task]
    source_text = format_sources(req.sources)

    source_rule = '일반 창작 모드다. 원문 밖의 새 사실을 만들지 마라.'
    if req.source_mode:
        source_rule = '자료 기반 모드다. 아래 참고 자료에 있는 내용만 사용하라. 자료에 없는 정보는 추정하지 말고 warnings에 적어라.'

    user_prompt = f'''
작업: {task_instruction}
희망 톤: {req.tone or '원문 톤 유지'}
희망 길이: {req.length}
후보 개수: {req.variant_count}

반드시 지킬 규칙:
- 새 사실을 추가하지 않는다.
- 고유명사, 숫자, 날짜, 핵심 주장을 임의로 바꾸지 않는다.
- 원문의 의도를 보존한다.
- 바꾼 이유를 짧게 설명한다.
- 결과는 JSON 객체 하나로만 답한다.
- 키는 original, revised, alternatives, changes, reason, warnings를 사용한다.

작업 모드:
{source_rule}

원문:
{req.text}

참고 자료:
{source_text}
'''

    return [
        {
            'role': 'system',
            'content': '너는 원문의 의도와 사실을 보존하는 전문 편집자다. 문장을 개선하되 글쓴이의 통제권을 빼앗지 않는다.'
        },
        {
            'role': 'user',
            'content': user_prompt
        }
    ]

프롬프트에서 '글쓴이의 통제권'이라는 표현을 넣은 이유가 있습니다. 글쓰기 도우미는 사용자를 대신해 최종 결정을 내려서는 안 됩니다. 모델의 역할은 제안입니다. 제품의 역할은 비교와 되돌리기를 제공하는 것입니다. 최종 선택은 사용자가 해야 합니다.

클라우드 LLM으로 편집 요청 보내기

이제 LLM API를 호출하는 코드를 작성해 보겠습니다. 여기서는 이해를 돕기 위해 OpenAI 호환 방식의 예시를 사용합니다. 실제 프로젝트에서는 앞 장에서 만든 API 호출 래퍼를 재사용해도 됩니다. 모델 이름은 사용하는 서비스에 맞게 바꾸면 됩니다.

# assistant.py
import json
import os
from openai import OpenAI
from schemas import AssistRequest, AssistResult
from prompts import build_messages

client = OpenAI()

MODEL_NAME = os.getenv('LLM_MODEL', 'gpt-4.1-mini')

def assist(req: AssistRequest) -> AssistResult:
    messages = build_messages(req)

    response = client.chat.completions.create(
        model=MODEL_NAME,
        messages=messages,
        response_format={'type': 'json_object'},
        temperature=0.2
    )

    raw = response.choices[0].message.content
    data = json.loads(raw)

    return AssistResult.model_validate(data)

글쓰기 기능에서는 temperature를 너무 높게 잡지 않는 편이 안전합니다. 창작 글에서는 다양성이 필요하지만, 편집 도구에서는 보존성이 더 중요합니다. 특히 요약이나 전문적인 톤 변환에서는 모델이 멋대로 내용을 보태는 것보다 조금 밋밋하더라도 원문을 지키는 쪽이 낫습니다.

그렇다고 항상 낮은 온도만 써야 하는 것은 아닙니다. '대안 3개 보여 주기' 기능에서는 온도를 약간 올려 서로 다른 표현을 만들게 할 수 있습니다. 다만 그 경우에도 숫자, 날짜, 고유명사, 핵심 주장을 검사하는 후처리 단계가 있으면 좋습니다.

FastAPI 엔드포인트 만들기

프런트엔드가 사용할 간단한 API를 만듭니다. 입력은 AssistRequest, 출력은 AssistResult입니다.

# api.py
from fastapi import FastAPI
from schemas import AssistRequest, AssistResult
from assistant import assist

app = FastAPI()

@app.post('/assist', response_model=AssistResult)
def assist_endpoint(req: AssistRequest):
    return assist(req)

실행은 다음과 같습니다.

uvicorn api:app --reload

이제 http://127.0.0.1:8000/assist로 요청을 보내면 글쓰기 도우미가 수정 결과를 돌려줍니다.

Streamlit으로 편집 화면 만들기

제품의 핵심은 모델 호출보다 사용 흐름입니다. 사용자는 원문을 넣고, 작업을 고르고, 결과를 비교한 뒤, 마음에 들면 가져가야 합니다. 이 루프가 길어지면 글쓰기 흐름이 끊깁니다.

아래는 Streamlit으로 만든 간단한 UI입니다. 원문과 수정문을 나란히 보여 주고, difflib를 이용해 변경된 부분을 HTML diff로 표시합니다. LLM 글쓰기 도구 예제들에서도 원문과 수정문 비교, 변경점 표시, 수정 강도 조절 같은 인터페이스가 중요한 요소로 다뤄집니다5.

# app.py
import difflib
import requests
import streamlit as st
import streamlit.components.v1 as components

API_URL = 'http://127.0.0.1:8000/assist'

st.set_page_config(page_title='AI 글쓰기 도우미', layout='wide')
st.title('AI 글쓰기 도우미')

text = st.text_area('고치고 싶은 문장을 입력하세요', height=220)

col1, col2, col3 = st.columns(3)

with col1:
    task = st.selectbox(
        '작업',
        ['improve', 'tone', 'summarize', 'expand'],
        format_func=lambda x: {
            'improve': '문장 개선',
            'tone': '톤 변환',
            'summarize': '요약',
            'expand': '확장'
        }[x]
    )

with col2:
    tone = st.selectbox(
        '톤',
        ['원문 유지', '부드럽게', '전문적으로', '간결하게', '친근하게']
    )

with col3:
    length = st.selectbox('길이', ['short', 'normal', 'long'])

variant_count = st.slider('대안 개수', min_value=1, max_value=3, value=1)

source_mode = st.checkbox('자료 기반 모드 사용')
source_text = ''
if source_mode:
    source_text = st.text_area('참고 자료를 붙여 넣으세요', height=180)

if st.button('도움 받기', type='primary'):
    payload = {
        'text': text,
        'task': task,
        'tone': None if tone == '원문 유지' else tone,
        'length': length,
        'source_mode': source_mode,
        'sources': [source_text] if source_text.strip() else [],
        'variant_count': variant_count
    }

    response = requests.post(API_URL, json=payload, timeout=90)
    response.raise_for_status()
    data = response.json()

    left, right = st.columns(2)
    with left:
        st.subheader('원문')
        st.write(data['original'])

    with right:
        st.subheader('수정문')
        st.write(data['revised'])

    if data.get('alternatives'):
        st.subheader('다른 대안')
        for index, alt in enumerate(data['alternatives'], start=1):
            st.markdown(f'대안 {index}')
            st.write(alt)

    st.subheader('변경 이유')
    st.write(data['reason'])

    st.subheader('변경점')
    for change in data['changes']:
        st.markdown(f'- {change['before']} → {change['after']} : {change['reason']}')

    if data.get('warnings'):
        st.warning('확인이 필요한 내용이 있습니다.')
        for warning in data['warnings']:
            st.write(warning)

    st.subheader('변경 비교')
    diff = difflib.HtmlDiff(wrapcolumn=80).make_file(
        data['original'].splitlines(),
        data['revised'].splitlines(),
        fromdesc='원문',
        todesc='수정문'
    )
    components.html(diff, height=500, scrolling=True)

위 코드에는 한 가지 주의할 점이 있습니다. st.markdown(f'- {change['before']} ...')처럼 문자열 안에서 같은 따옴표가 중첩되면 파이썬 문법 오류가 납니다. 실제 파일에서는 바깥 문자열을 큰따옴표로 바꾸거나, 값을 변수에 먼저 담아 사용하세요. 예를 들면 다음처럼 고칠 수 있습니다.

before = change['before']
after = change['after']
reason = change['reason']
st.markdown(f'- {before} → {after} : {reason}')

이제 사용자는 결과를 그냥 복사하는 대신, 무엇이 어떻게 바뀌었는지 확인할 수 있습니다. 이 차이가 중요합니다. 글쓰기 도구의 신뢰는 '좋은 문장'에서만 나오지 않습니다. 사용자가 통제하고 있다는 느낌에서 나옵니다.

자료 기반 모드와 일반 창작 모드 구분하기

글쓰기 도우미에는 두 가지 성격의 작업이 섞여 있습니다. 하나는 일반 창작 모드입니다. 예를 들어 '이 문장을 더 부드럽게 바꿔 줘'라는 요청은 원문을 바탕으로 표현만 다듬으면 됩니다. 다른 하나는 자료 기반 모드입니다. 사용자가 회의록, 제품 설명서, 강의 노트, 논문 초록 같은 자료를 넣고 '이 자료를 바탕으로 소개문을 써 줘'라고 요청하는 경우입니다.

이 둘을 구분하지 않으면 환각이 늘어납니다. 일반 창작 모드에서는 어느 정도 자연스러운 표현 확장이 허용되지만, 자료 기반 모드에서는 사용자가 제공한 소스 안에서만 요약, 정리, 재작성해야 합니다. Google NotebookLM은 사용자가 제공한 소스를 분석하고 내용을 정리하는 연구 도구로 소개되며2, 관련 가이드에서도 업로드한 자료를 바탕으로 답변하고 인용을 통해 근거를 확인하는 흐름을 중요한 특징으로 설명합니다3. 우리가 만드는 글쓰기 도우미도 같은 원칙을 따를 수 있습니다.

자료 기반 모드에서는 프롬프트를 더 엄격하게 만들어야 합니다. '참고 자료에 없는 정보는 추가하지 말 것', '자료에서 확인되지 않는 표현은 경고에 넣을 것', '가능하면 어떤 자료 조각을 바탕으로 바꿨는지 표시할 것' 같은 규칙을 넣습니다. 예를 들어 제품 소개문을 다듬을 때 참고 자료에 '무료 체험 14일'이라고만 있는데 모델이 '30일 무료 체험'이라고 쓰면 안 됩니다. 이때 warnings에 '무료 체험 기간은 자료에서 14일로 확인됨' 같은 경고가 들어가면 사용자가 바로 잡을 수 있습니다.

문서가 짧다면 방금 만든 sources 필드에 그대로 넣으면 됩니다. 문서가 길다면 앞 장에서 만든 RAG 파이프라인을 연결합니다. 사용자가 선택한 문장과 요청을 쿼리로 삼아 관련 자료 조각을 검색하고, 검색된 조각만 프롬프트에 넣는 방식입니다. 즉, 자료 기반 글쓰기 도우미는 RAG 챗봇의 변형입니다. 차이는 답변의 목적이 질문 응답이 아니라 '사용자 글의 개선'이라는 점입니다.

클라우드 LLM과 로컬 LLM 선택하기

글쓰기 데이터는 민감할 때가 많습니다. 일기, 계약서, 투자자 보고서, 고객 이메일, 논문 초안, 출간 전 원고는 외부 서버로 보내기 꺼려질 수 있습니다. 그래서 글쓰기 도우미를 제품화할 때는 클라우드 LLM과 로컬 LLM의 선택지를 함께 생각해야 합니다.

클라우드 LLM은 대체로 품질이 좋고 운영이 편합니다. API 키만 있으면 최신 모델을 사용할 수 있고, 서버에서 무거운 추론을 직접 돌리지 않아도 됩니다. 반면 사용자의 문서가 외부 API로 전송될 수 있으므로 개인정보 고지, 데이터 보관 정책, 학습 사용 여부, 로그 저장 여부를 명확히 알려야 합니다.

로컬 LLM은 사용자의 기기나 사내 서버에서 모델을 직접 실행합니다. Ollama와 Open WebUI를 이용해 집이나 사무실 네트워크 안에서 개인용 글쓰기 도우미를 구성하는 사례처럼, 로컬 실행은 외부 의존성을 줄이고 작성 중인 문서를 더 강하게 통제할 수 있다는 장점이 있습니다4. 대신 모델 설치, 하드웨어 요구사항, 속도, 품질 편차를 감수해야 합니다.

Ollama를 사용한다면 호출 코드는 다음처럼 단순하게 만들 수 있습니다.

# local_client.py
import requests

OLLAMA_URL = 'http://localhost:11434/api/chat'

def call_ollama(messages, model='llama3.1:8b'):
    payload = {
        'model': model,
        'messages': messages,
        'stream': False,
        'format': 'json',
        'options': {
            'temperature': 0.2
        }
    }

    response = requests.post(OLLAMA_URL, json=payload, timeout=120)
    response.raise_for_status()
    return response.json()['message']['content']

제품에서는 두 모드를 이렇게 구분해 보여 줄 수 있습니다. '고품질 클라우드 모드'는 긴 글과 복잡한 편집에 적합합니다. '비공개 로컬 모드'는 민감한 문서와 오프라인 작업에 적합합니다. 사용자가 어떤 모드인지 모른 채 문서를 보내게 해서는 안 됩니다. 글쓰기 도우미가 신뢰를 얻으려면, 좋은 문장보다 먼저 데이터가 어디로 가는지 분명히 말해야 합니다.

브라우저 확장, 에디터 플러그인, 웹 앱의 차이

같은 LLM 기능이라도 어디에 붙이느냐에 따라 제품의 성격이 달라집니다. 웹 앱은 만들기 쉽고 배포가 간단합니다. 사용자가 원문을 붙여 넣고 결과를 복사해 가는 방식입니다. 하지만 글을 쓰던 곳에서 다른 화면으로 이동해야 하므로 흐름이 끊길 수 있습니다.

브라우저 확장은 사용자가 Gmail, Notion, 블로그 편집기, 고객지원 도구에서 선택한 문장을 바로 고칠 수 있습니다. 흐름은 가장 좋지만 권한 문제가 생깁니다. 확장이 현재 페이지의 텍스트를 어디까지 읽을 수 있는지, 선택한 문장만 보내는지, 페이지 전체를 보내는지 명확해야 합니다. 기본값은 '선택한 문장만 전송'이어야 합니다. 문서 전체가 필요할 때는 반드시 확인 창을 띄워야 합니다.

에디터 플러그인은 VS Code, Obsidian, 워드프로세서, 사내 문서 도구에 붙일 수 있습니다. 장점은 변경 비교와 되돌리기를 자연스럽게 제공할 수 있다는 점입니다. 원문을 통째로 바꾸는 대신 패치 형태로 제안하면 사용자는 변경 단위별로 수락하거나 거절할 수 있습니다.

배포 형태장점주의할 점안전장치
웹 앱구현과 배포가 쉽다복사와 붙여넣기가 번거롭다업로드 전 전송 범위 표시
브라우저 확장사용자가 쓰는 곳에서 바로 작동한다페이지 접근 권한이 민감하다선택 문장만 기본 전송
에디터 플러그인변경 비교와 되돌리기가 자연스럽다에디터별 구현이 필요하다패치 단위 수락과 거절 제공

처음 제품을 만들 때는 웹 앱으로 시작하는 것이 좋습니다. 기능의 쓸모를 확인한 뒤, 자주 쓰는 작업이 분명해지면 브라우저 확장이나 에디터 플러그인으로 확장합니다. 많은 팀이 반대로 시작합니다. 멋진 확장을 먼저 만들고 나중에 사용 흐름을 찾습니다. 하지만 LLM 제품은 모델보다 흐름이 먼저입니다.

선택, 요청, 비교, 삽입의 짧은 루프

AI 글쓰기 도우미의 핵심 루프는 네 단계입니다. 사용자가 문장을 선택합니다. 원하는 작업을 요청합니다. 원문과 대안을 비교합니다. 마음에 드는 결과를 삽입하거나 되돌립니다. 이 루프가 짧을수록 도구는 자주 쓰입니다.

여기서 '대안 비교'는 생각보다 중요합니다. LLM의 첫 답변이 항상 가장 좋지는 않습니다. 사용자는 '더 짧은 버전', '조금 더 따뜻한 버전', '더 단호한 버전'을 비교하면서 자기 의도에 맞는 표현을 고릅니다. 그러므로 글쓰기 도우미는 정답 하나를 강요하기보다 선택지를 보여 주는 편이 좋습니다.

또한 되돌리기는 필수 기능입니다. AI가 문서를 바꾼 뒤 사용자가 원래대로 돌아갈 수 없다면 불안해서 기능을 쓰지 않습니다. 브라우저 확장이나 에디터 플러그인에서는 변경 전 텍스트를 저장해 두고, '적용'과 '되돌리기'를 분리해야 합니다. 웹 앱이라면 적어도 원문과 수정문을 동시에 보여 주고 복사 버튼을 따로 제공해야 합니다.

좋은 글쓰기 도우미는 사용자를 놀라게 하지 않습니다. 사용자가 선택하지 않은 문서 전체를 읽지 않고, 사용자가 허락하지 않은 변경을 적용하지 않으며, 사용자가 이해할 수 없는 방식으로 문장을 바꾸지 않습니다. 이런 작은 안전장치가 쌓이면 사용자는 AI를 믿고 더 중요한 글을 맡기기 시작합니다.

품질을 어떻게 판단할 것인가

글쓰기 도우미의 품질은 단순히 '문장이 자연스러운가'로만 평가할 수 없습니다. 특히 제품으로 운영하려면 기능별 평가 기준을 따로 둬야 합니다.

문장 개선에서는 의미 보존과 명확성이 중요합니다. 톤 변환에서는 요청한 톤을 따르면서 과장하지 않는지가 중요합니다. 요약에서는 핵심 정보 누락이 가장 큰 문제입니다. 확장에서는 새 사실을 지어내지 않는지가 핵심입니다.

간단한 평가용 샘플 세트를 만들어 두면 모델을 바꾸거나 프롬프트를 수정할 때 도움이 됩니다. 샘플에는 고객 이메일, 블로그 문단, 보고서 문장, 제품 설명, 회의록 요약처럼 서로 다른 글을 넣습니다. 각 샘플마다 기대 결과를 하나만 정하기보다 '반드시 지켜야 할 사실'과 '피해야 할 변경'을 표시합니다. 예를 들어 '가격 19,000원 유지', '환불 가능 기간 7일 유지', '회사명을 줄여 쓰지 않기'처럼 적어 둡니다.

운영 중에는 사용자의 행동도 좋은 평가 신호가 됩니다. 사용자가 제안을 바로 적용했는지, 적용 후 다시 수정했는지, 되돌렸는지, 같은 문장으로 다시 요청했는지 기록하면 품질을 추정할 수 있습니다. 물론 글쓰기 로그는 민감하므로 원문 전체를 저장하지 않는 설계가 바람직합니다. 필요한 경우 익명화된 작업 유형, 길이, 수락 여부 정도만 저장하는 방식으로 시작하세요.

개인정보와 통제권을 화면에 보여 주기

글쓰기 도우미는 사용자의 생각이 들어 있는 문서를 다룹니다. 그래서 개인정보 안내는 약관 깊숙한 곳에 숨겨 둘 문제가 아닙니다. 사용자가 버튼을 누르는 화면에서 바로 보여야 합니다.

예를 들어 클라우드 모드에서는 '선택한 문장이 외부 LLM API로 전송됩니다'라고 표시합니다. 자료 기반 모드에서는 '첨부한 참고 자료도 함께 전송됩니다'라고 알려야 합니다. 로그를 저장한다면 무엇을 저장하는지, 얼마나 보관하는지, 사용자가 끌 수 있는지 명확히 해야 합니다. 로컬 모드를 제공한다면 '이 모드에서는 문서가 이 기기 밖으로 전송되지 않습니다'처럼 사용자가 이해할 수 있는 문장으로 설명합니다.

제품 설정에는 적어도 다음 항목이 있어야 합니다.

  • 외부 API 전송 여부

  • 원문 로그 저장 여부

  • 로컬 처리 옵션

  • 민감정보 자동 감지와 전송 전 경고

  • 문서 전체 전송 전 확인

  • 결과 적용 전 변경 비교와 되돌리기

이 항목들은 부가 기능이 아닙니다. 글쓰기 도우미의 신뢰를 구성하는 핵심 기능입니다. 사용자는 AI가 더 똑똑해지는 것보다, 자신의 글이 어디로 가고 어떻게 바뀌는지 알 수 있기를 바랍니다.

작은 편집자에서 시작하라

이번 장에서 만든 AI 글쓰기 도우미는 거대한 자동 작가가 아닙니다. 사용자가 쓴 문장을 읽고, 더 나은 표현을 제안하고, 바뀐 이유를 설명하는 작은 편집자입니다. 하지만 이 작은 편집자가 실제 제품에서는 더 강력할 때가 많습니다.

초안 생성기는 한 번 놀랍고 끝날 수 있습니다. 반면 편집 보조 도구는 매일 쓰입니다. 이메일을 보내기 전, 블로그 문단을 다듬을 때, 제안서의 표현을 부드럽게 바꿀 때, 회의록을 짧게 요약할 때 계속 필요합니다. 그리고 사용자는 매번 같은 루프를 반복합니다. 선택하고, 요청하고, 비교하고, 삽입하거나 되돌립니다.

LLM을 제품에 넣는다는 것은 모델이 할 수 있는 일을 나열하는 것이 아닙니다. 사용자가 이미 하고 있는 작업의 흐름을 이해하고, 그 흐름에서 가장 귀찮고 불안한 순간을 짧게 줄여 주는 일입니다. 이 관점을 잊지 않으면 AI 글쓰기 도우미는 단순한 '문장 생성기'가 아니라 사용자가 믿고 쓰는 작업 도구가 됩니다.

다음 장에서는 이 흐름을 한 단계 더 확장합니다. 지금까지는 사용자가 명시적으로 요청한 한 번의 작업을 처리했습니다. 이제는 목표를 주면 스스로 계획을 세우고, 필요한 도구를 호출하고, 중간 결과를 확인하면서 일을 이어 가는 간단한 AI 에이전트를 만들어 보겠습니다.

참고

1OpenAI Writing with ChatGPT

2Google NotebookLM

3A Complete How-To Guide to NotebookLM

4Setting Up My Personal AI Writing Assistant: A Local LLM Journey

5LLM-Writing-Assistant GitHub

책 목록

처음 만나는 LLM: 원리부터 Mini GPT 구현, RAG 서비스 개발까지

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기