Post

AI 서비스 구현 실습 회고: 개념을 설계 기준으로 바꾸기

AI 서비스 구현 실습 회고: 개념을 설계 기준으로 바꾸기

공부한 내용을 그냥 주제별로 모아두면 금방 흩어졌다. 그래서 이번에는 개념을 어떻게 실습 가능한 설계 기준으로 바꿀 수 있는지에 맞춰 다시 묶어봤다.

처음에는 RAG, OCR, Agent, 평가 지표를 각각 따로 봤다. 그런데 작은 예제를 직접 만들어보면 질문이 바뀐다. “이 개념이 무엇인가”보다 “이 개념을 어디에 붙여야 실패를 줄일 수 있는가”가 더 중요해진다.

학습 주제를 볼 때의 순서

새로운 주제를 볼 때 모델명부터 보면 길을 잃기 쉬웠다. 더 오래 남는 것은 문제 정의, 데이터 흐름, 평가 기준이었다.

flowchart LR
  P["Problem<br/>무엇을 줄이려는가"] --> D["Data<br/>무엇을 입력으로 쓰는가"]
  D --> F["Flow<br/>어떤 단계로 처리하는가"]
  F --> E["Evaluation<br/>무엇으로 검증하는가"]
  E --> L["Learning Rule<br/>내 실습 기준으로 바꾸기"]

이 순서를 잡으면 기술 이름에 끌려가지 않는다. 같은 RAG라도 문서 처리형 RAG인지, 금융 근거형 RAG인지, Agent가 붙은 RAG인지에 따라 봐야 할 기준이 달라진다.

개념을 구현 질문으로 바꾼다

개념을 읽는 것과 구현해보는 것은 다르다. 직접 만들어볼 때는 개념을 질문으로 바꿔야 한다.

개념구현 질문
PDF/OCR텍스트뿐 아니라 layout, table, figure를 보존했는가
RAG검색 실패와 생성 실패를 분리해서 볼 수 있는가
RerankerTop-K 후보 중 실제 근거가 앞쪽으로 오는가
G-Eval평가 기준이 prompt에 명확히 들어갔는가
Agent자율 실행 전에 tool permission이 정의되었는가
Multi-Agent역할 분리가 latency와 복잡도를 감당할 만큼 필요한가
Architecture원본, metadata, index, log가 분리되어 있는가

이렇게 바꾸면 글을 쓸 때도 단순 요약이 아니라 “내가 무엇을 확인했는지”가 드러난다.

직접 만들어볼 때 남길 산출물

학습 정리 글이 설득력을 가지려면 읽은 내용만으로는 부족했다. 작게라도 직접 만져본 흔적이 있어야 나중에 다시 읽을 가치가 생긴다.

산출물목적
최소 pipeline 코드개념을 실행 흐름으로 이해
작은 dummy dataset재현 가능한 비교 기준 확보
before/after 표변경 효과를 조건부로 설명
실패 예시한계를 숨기지 않고 원인 분리
trace schemaprompt, retrieval, model 변경 추적
checklist다음 구현에 재사용할 기준 정리

이때 코드를 길게 붙이는 것보다 학습용으로 재구성한 짧은 코드가 더 읽기 쉽다. 중요한 것은 이름이 아니라 설계 판단이다.

좋은 실습 코드는 작고 재현 가능해야 한다

실습 코드는 길다고 좋은 것이 아니다. 하나의 개념을 보여주고, 입력과 출력이 명확해야 한다.

예를 들어 RAG 평가를 공부했다면 전체 서비스를 만들기보다 다음 정도의 작은 단위가 더 낫다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from dataclasses import dataclass


@dataclass
class LearningCase:
    question: str
    expected_evidence_id: str
    retrieved_ids: list[str]
    answer: str


def split_rag_failure(case: LearningCase) -> str:
    # 검색 단계에서 근거를 못 찾았으면 생성 모델을 먼저 탓하지 않는다.
    if case.expected_evidence_id not in case.retrieved_ids:
        return "retrieval_failure"

    # 근거가 있었는데 답변이 어긋나면 prompt나 context 구성 문제로 본다.
    if not answer_uses_evidence(case.answer, case.expected_evidence_id):
        return "generation_failure"

    return "pass"

이 코드는 완성된 평가 시스템이 아니다. 하지만 내가 배운 핵심을 분명히 보여준다. RAG 실패를 하나로 보지 않고 retrieval failure와 generation failure로 나눠야 한다는 점이다.

글로 남길 때 조심할 표현

개인 학습 글에서는 표현을 조심해야 한다. 직접 확인한 범위를 넘겨 쓰면 학습 기록이 아니라 성과 주장처럼 보인다.

피해야 할 표현바꿀 표현
구현했다실습으로 재구성했다
성능을 입증했다제한된 조건에서 비교했다
전체 서비스를 완성했다작은 예제로 흐름을 확인했다
정확도를 높였다특정 기준에서 개선 가능성을 확인했다
완성했다최소 예제로 흐름을 확인했다

이 글의 목적은 성과 주장보다 학습 증거를 남기는 것이다. 그래서 수치가 있더라도 반드시 조건을 붙이고, 확인하지 않은 성공 claim은 쓰지 않는다.

학습 주제별 묶는 방식

전체 흐름은 다음 순서로 잡았다.

순서학습 질문
1PDF/OCR 문서 처리문서 구조를 어떻게 보존할 것인가
2RAG 구현 패턴검색 pipeline을 어떻게 나눌 것인가
3금융 RAG 근거 설계출처와 근거를 어떻게 분리할 것인가
4RAG 평가검색과 생성을 어떻게 따로 평가할 것인가
5LLM 서비스 평가ROUGE, BERTScore, G-Eval을 어떻게 조합할 것인가
6Agent WorkflowTool Calling과 실행 경계를 어떻게 둘 것인가
7LLM 서비스 아키텍처pipeline, storage, evaluation을 어떻게 연결할 것인가
8구현 실습 회고배운 개념을 다음 설계 기준으로 어떻게 바꿀 것인가

이 순서가 중요한 이유는 단순하다. 개념을 많이 아는 것보다, 어떤 상황에서 어떤 기준으로 선택할지 아는 것이 실습에 더 가깝기 때문이다.

다음 구현에 가져갈 질문

상황확인할 것
문서 기반 QA를 만든다문서 구조, metadata, evidence id
금융/리포트 QA를 만든다source type, period, table unit, citation
Agent를 붙인다tool permission, HITL, 실패 fallback
평가를 붙인다retrieval eval과 generation eval 분리
서비스로 만든다job status, trace, storage separation
블로그에 정리한다claim boundary, 재현 가능한 예제, 설계 기준

이 표가 이번 학습에서 가장 오래 남은 산출물이다. 각 기술을 외우는 대신, 다음 구현에서 던질 질문 목록으로 바꿨기 때문이다.

마지막에 남은 기준

여러 내용을 걷어내고 나니 마지막에 남은 것은 기준표였다.

이름을 덜어내면 오히려 문제, 데이터, pipeline, 평가, 한계가 더 잘 보인다.

자료를 따라 적는 데서 멈추지 않고, 반복해서 등장한 설계 판단을 내 언어와 코드로 다시 적어보는 것. 이 시리즈는 그 연습에 가깝다.

이전 글: LLM 서비스 아키텍처 실습 정리: Pipeline, Storage, Evaluation

This post is licensed under CC BY 4.0 by the author.