1. 스프링AI - 인공지능의 개념과 스프링AI

 

 

이런 인공지능의 개념을 이해하면... 인공지능이 포괄적인게 개념이 잡힌다. 인공지능은 말그대로 어떤 목적.. 체스게임의 경우 체스룰안에서의 승리.. 자율주행은... 도로 위에서 안전한 운전(여러가지 경우의수의 판단, 핸들제어, 앞차와의 거리 등)을 위한 수많은 판단이다... 이게 사실 제일어려워 보인다. 그러나 이게 가능해지면서 과거 전투기나 이런 비싼 장비가 하던것을 드론이나 이런 저비용으로 상당한 퍼포먼스를 실제 우크라이나 전쟁에서 보고 있는등.. 이제 인공지능 사용능력은 이제 필수품이 된것 같다. 왜냐하면 과거 기계가 가공할 성능으로 수많은 일자리를 몰아내면서.. 기계파괴운동까지 있었다. 이것은 그러나 변리사, 변호사, 회계사 이런 전문직 들의 지능을 아주 평범하게 만들어 버린다. 누구나 gpt의 도움이면 간단한 법률지식, 회계지식을 얻는게 너무 쉬워졌다. 이건 결국 과거 사농공상 시대의 선비들의 자부심으로 내세운 수많은 책들을 얻은 지능을 아주 싸구려로 만들어 버린다. 그래도 변하지 않는건 인간세계의 지혜와 공의와 정의와 정직에 관해 인간스스로 기준을 세우고 판단해야 한다는 것이다.

 머신러닝은 통계기반으로 데이터를 학습해서 말한다고 하면 그냥 사주팔자가 나온 중국에서 온서적이나 기타 등등.. 여러 통계를 활용한 데이터 기반의 추측 및 판단이다.. 사실 여기까지 이미 머신러닝이 했고... 이 머신러닝은 인공지능과 딥러닝에 비하면 이미 기존에 보이던 것들이다. 

 딥러닝은 인공신경망 기반으로 고도화된 학습인데 ... 여기는 gpt 같이 엄청난 성능을 보여주지만.. 역시나 지금 엔비디아 주가와 gpu를 태운 블록체인 현상에서 보듯이 장비빨이 필요하다. 엄청난 돈이 필요한 것이다. 즉 인프라적으로 자본면에서나 대기업 등 기타 경우의 수에서 상당히 불리하다. 그러나 gpt, gemini, claude의 가공할 성능면에서 모듯이 개발자 측면에서 가장 쉽게 접근이 가능하고.. 이로인해 코드 생성의 비용이 0에 수렴할정도로 클로드 코드가 가공할 생산성을 보이고... 과거 집단지성의 지혜라고 정치권에서 한목소리 내던것을 ... 딥러닝을 통한 기술이.. 이미 웬만한 집단지성이 글로벌적인 마스터급 일반론이 보편화 되고 있다. 멀티미디어... 시스템... 컴퓨터에서 보이던 이미지, 동영상,텍스트 이런것들을 너무 쉽게 만든다.. 이제 어떻게 차별화 시키는가가 인간의 과제가 되어가고 있다.

 결국 이 딥러닝 기술이나 머신러닝 기술을 어찌 사용하나가.. 수많은 판도를 바꿀것이다. 

 

 

그중에 스프링AI는 LLM을 다룬다~! 자... LLM의 원리 질의문... 바이브 코딩을 한다고 해보자...

 

스프링부트가 모지?

 

를 물으면 이것을 쪼개서 메모리에 저장하는데 그 메모리 하나가 토큰(Token)이라는 형태로 나눈다고 할수 있다고 한다. 스프링 , 부트 , 란, 모지, ? 이렇게 바이브로 프롬프트가 가자마자 5개 정도의 토큰으로 메모리를 점유하며 나뉘는것이다. (위의는 예시이며 다른식으로 형태소를 쪼개는데 한국어는 Nori 형태분석소를 쓴다고 하니 그 기준이 있을듯하다.)

 그 와 별개로 비용산정을 하면 저 토큰(메모리 점유)하나가 결국 비용으로 청구된다.

 자 그 다음단계 임베딩.. 컴퓨터는 본질적으로 0,1이니 당연히 언어를 모른다. 이것을 계산하려면 자기들이 연산하는 방식인 숫자로 계산해야 한다. 즉 스프링이라는 단어에 수많은 벡터값을 가지고 이에 따라서 단어들 사이에 상관관계를 분석한다.  그에 따른 가중치를 숫자로 표현해 놓고 있다... 이것을 좌표상에 강아지와 개는 가깝고 자동차는 멀다... 흠... 이렇게 수많은 상관관계를 쪼개 연산하니.. 벡터db가 필요한듯하다.

 이 벡터 데이터가 LLM으로 가는순간 트랜스 포머블록으로 들어간다. 트랜스포머... selft-attention 즉.. 인간세계로치면 문맥기반.. 상화파악하는 과정속도다. feed forward는 어느정도 문맥과 상황파악을 했으면... 그것에 대해 답변할만한 지식이 있어야 한다. 

이 feed forward는 각 토큰(단어)의 위치에서 독립적으로 전형되는 비선형 신경망이다. 보통 두개의 선형 변환(Linear Layer)와 그 사이의 활성화 함수(주로 ReLU 또는 GELU)로 구성된다. 입력받은 데이터를 훨신 더 큰 차원으로 확대한뒤(Expansion), 핵심 정보를 남기고 다시 원래 차원으로 압축(Projection)한다.

 결국 핵심 역할은 지식의 저장소 및 정제로 방대한 데이터 중에 문맥과 상황에 맞는 적절하고 적합한 정보를 불러온다. 비선형성으로 인해 단순하지 않고 활성화 함수로 복잡한 논리를 처리한다.

 

즉 self-attention이 단어들을 서로 연결했다면, 피드 포워드는 각 단어의 벡터를 개별적으로 강화한다. 즉 self-attention은 상황과 문맥을 파악하기 위해 전문가들이 토론하고, feed-forward는 그 전문가들이 자신의 자리로 돌아가 지식을 총동원해서 적절한 답을 도출하기 위해 정리하는 것이다.

  

LLM은 문장을 한번에 완성하지 않고 다음에 올 가장 확률 높은 토큰을 하나씩 찾아낸다.  확률분포계산은 학습된 방대한 데이터를 방탕으로 후보군을 뽑고 선택한다. 즉 LLM은 본질적으로 다음에 올 가장 그럴싸한 단어를 맞히는 기계다

 

 이 다음 토큰 예측은 트랜스 포머 구조의 가장 마지막층인 출력층(Output Layer)에서 일어난다.

트랜스포머 블록의 통과 : 앞서 설명한 4단계 (Attention, Feed Forward)를 거치면, 모델 내부에는 문맥정보가 가득 담긴 추상적인 숫자 뭉치(벡터)가 생성된다. 선형 층 (Linear Layer)가 이 숫자 뭉치를 모델이 알고 있는 전체 단어 사전의 개수 만큼 넓게 펄쳐진다. 그리고 선형층에서 이 숫자벡터를 모델이 알고 있는 전체 단어 사전의 개수 만큼 넓게 펼친다... 국어사전/백과사전이 들어가 있었다.. (5만개의 단어면 5만개의 칸) 

 소프트맥스 함수는 펼쳐진 숫자들을 0에서 1사이의 확률값으로 변환한다. 모든 후보 단어의 확률합은 100%가 된다. (ex: Java:0.6, 프레임워크 :0.25, 무엇 : 0.1 ) 디코딩 전략으로 이 확률 분포에서 최종적으로 어떤 단어를 뽑을지 결정한다. 디코딩 전략은 이 확률 분포에서 최종적으로 어떤 단어를 뽑을지 결정한다. Greedy Searh는 무조건 확률이 가장 높은것만 선택하고 Sampling은 약간의 확률이 있는 다른 단어도 섞어서 더 창의적인 답변을 유도한다.

 결국 셀프어텐션은 상황파악해서, 피드포워드로 맞는 지식을 찾아내고, 최종 출력층에서 적절하다고 추린 답이 나온다.

 

이렇게 지속적으로 판단해서 답을 만든다. 

 

 

 

Spring Boot란 무엇인가? 에 대한 답변을 결국, 

 

"Spring Boot는 Java 기반의 오픈소스 프레임워크입니다."

그 추린답에 대한 판단은 인간의 몫인데... 이런거는 아주 국어사전/백과사전 기본지식에 속해서 틀리지 않는듯 하다.

 

LLM은 사용자의 질문을 받으면 내부적으로 [텍스트 → 숫자 → 문맥 분석 → 확률 계산 → 다시 텍스트]의 정교한 변환 과정을 거칩니다.

 

 

자 아까 점유했던 단어기반의 메모리 점유 , 즉 토큰

이것은 비용이다.

 

최근 핫한 클로드는

 

이렇다고 한다. 2배 성능에는 3배가격, 4배 성능에는 5배 가격이 적용된다.

최고성능을 자랑하는 opus지만, 비용효율면에서는 sonnect이 낫다.

max 플랜은 200$인데... 200$이상을 쓰면 일단... api 비용 기준으로 넘어가면 잘쓰고 있는것인가... 이런생각을 해본다.

그러나 api가 아니라 그냥 쓰면 200$로 opus나 sonnect을 마음껐 쓸수있는듯하다. 문맥도 1M.. 즉 100만 토큰을 기억할수 있는 클로드다. 이 100만 토큰 비중으로 api 비용이 계산된다는데 이게 보통 한 컨텍스트에서 생성형 ai 가 메모리에 가용하는 용량이라고  한다. 이게 꽉차면... 새로운 상황맥락이 없는 대화가 시작되는 것이다.

 api 사용시 한글보다 영어, 입력/출력형식을 정제하고 간단하게 하는 등의 기법을 써서 절약할수 있다고 한다.

 

자 이제 코드단으로 가면 코드 한줄수정으로 claude의 저 모델들을 교체할수 있다. 모델들은 추상화 되어 있어서 아주 편리하게 사용할수 있다. ChatClient를 빈으로 등록하여 스프링의 DI기능을 잘 활용할수 있다. AOP기능을 통해 보안,로깅,트랜잭션처리 관리도 할수 있다. 

 자 그리고 벡터 store를 지원하는 pinecone, redis, postgresql를 쓸수 있다. rag(검색 증강생성)은 외부 지식을 ai에게 전달하는 복잡한 파이프라인을 쉽게 설계 구축할수 있게 설계되어 있다.

 

 자 이 모두 스프링 AI를 쓰면 아주 간단하게, 엔터프라이즈급 AI서비스를 빠르게 구축할수 있게 해준다.

 

정말 간단하게 API key만 하면 , 비즈니스로직도 간단하게 해서 데이터베이스 연동까지 된다. 비용관리를 위해 처리량 제한을 걸수 있고 캐싱을 통해 API비용을 획기적으로 줄일수 잇다.

 

위의 내용은 프롬프트 템플릿을 만들어 사용자가 개떡같이 말해도 찰떡같이 알아듣고 대답하게 할수 있다.

 

백엔드 통합 방식 : 백엔드 통합의 5가지 핵심 장점 (✅ 권장)

브라우저는 우리 서버(Spring Boot)에 요청을 보내고, 서버가 안전하게 AI API와 통신하는 구조입니다.

 

1.보안 및 자산 보호

@Service
public class ChatService {
    
	@Value("${spring.ai.openai.api-key}")
	private String apiKey; // 서버 외부로 절대 유출되지 않음
	
}

API Key를 서버 내부(환경 변수, Secrets Manager)에 숨깁니다. 사용자에게는 절대 노출되지 않습니다.

 

2.정교한 비용 및 사용량 관리

public String chatWithLimit(String userId, String message) {
    if (usageService.getTodayUsage(userId) >= 10) {
        throw new UsageLimitException("오늘 사용량을 모두 소진했습니다.");
    }
    return chatClient.prompt().user(message).call().content();
}

- 사용자별 일일 호출 횟수를 제한하여 예기치 못한 비용 지출을 방지합니다.

 

 

3.개인화된 비즈니스 로직

예: "이 고객은 30대 남성이고 최근 등산화를 구매했어. 이 정보를 바탕으로 상품을 추천해줘."

 

@Service
public class ProductRecommendationService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private ProductRepository productRepository;
    
    public String recommendProduct(Long userId, String query) {
        // 1. DB에서 사용자 정보 조회
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException());
        
        // 2. 사용자 구매 이력 조회
        List<Product> purchaseHistory = productRepository
                .findByUserId(userId);
        
        // 3. 개인화된 프롬프트 생성
        String prompt = String.format("""
            다음 사용자에게 상품을 추천해주세요:
            - 연령대: %s
            - 관심사: %s
            - 구매 이력: %s
            - 질문: %s
            """, 
            user.getAgeGroup(),
            user.getInterests(),
            purchaseHistory.stream()
                .map(Product::getName)
                .collect(Collectors.joining(", ")),
            query
        );
        
        // 4. AI 호출
        return chatClient.prompt()
                .user(prompt)
                .call()
                .content();
    }
}

 

DB에 저장된 사용자 프로필, 구매 이력 등을 프롬프트에 결합하여 "나만을 위한 답변"을 생성합니다.

 

4. 응답 품질 관리 및 모니터링

@Service
public class ManagedChatService {
    
    public String chat(String message) {
        // 1. 입력 검증
        if (containsInappropriateContent(message)) {
            return "부적절한 내용이 포함되어 있습니다.";
        }
        
        // 2. 프롬프트 템플릿 적용 (일관된 응답 품질)
        String enhancedPrompt = """
            당신은 전문적이고 친절한 고객 지원 AI입니다.
            다음 규칙을 따르세요:
            1. 존댓말 사용
            2. 3문장 이내로 답변
            3. 확실하지 않으면 "정확한 답변을 드리기 어렵습니다"라고 답변
            
            사용자 질문: %s
            """.formatted(message);
        
        try {
            // 3. AI 호출
            String response = chatClient.prompt()
                    .user(enhancedPrompt)
                    .call()
                    .content();
            
            // 4. 로깅 (모니터링)
            log.info("AI 호출 - 입력 토큰: {}, 출력 토큰: {}, 비용: ${}",
                    inputTokens, outputTokens, cost);
            
            return response;
            
        } catch (Exception e) {
            // 5. 에러 처리
            log.error("AI 호출 실패", e);
            return "죄송합니다. 일시적인 오류가 발생했습니다.";
        }
    }
}
  1. 사용자가 대충 질문해도 백엔드에서 '전문가 페르소나'를 입혀 높은 품질의 답변을 유도합니다. 또한, AI가 답한 내용에 부적절한 표현이 있는지 검증한 뒤 사용자에게 전달합니다.
@Service
public class ManagedChatService {
    
    public String chat(String message) {
        // 1. 입력 검증
        if (containsInappropriateContent(message)) {
            return "부적절한 내용이 포함되어 있습니다.";
        }
        
        // 2. 프롬프트 템플릿 적용 (일관된 응답 품질)
        String enhancedPrompt = """
            당신은 전문적이고 친절한 고객 지원 AI입니다.
            다음 규칙을 따르세요:
            1. 존댓말 사용
            2. 3문장 이내로 답변
            3. 확실하지 않으면 "정확한 답변을 드리기 어렵습니다"라고 답변
            
            사용자 질문: %s
            """.formatted(message);
        
        try {
            // 3. AI 호출
            String response = chatClient.prompt()
                    .user(enhancedPrompt)
                    .call()
                    .content();
            
            // 4. 로깅 (모니터링)
            log.info("AI 호출 - 입력 토큰: {}, 출력 토큰: {}, 비용: ${}",
                    inputTokens, outputTokens, cost);
            
            return response;
            
        } catch (Exception e) {
            // 5. 에러 처리
            log.error("AI 호출 실패", e);
            return "죄송합니다. 일시적인 오류가 발생했습니다.";
        }
    }
}

 

5. 성능 최적화 (캐싱)

@Service
public class CachedChatService {
    
    private final Cache<String, String> cache = 
        Caffeine.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(1, TimeUnit.HOURS)
            .build();
    
    public String chat(String message) {
        // 동일한 질문은 캐시에서 반환 (비용 절감)
        return cache.get(message, key -> {
            return chatClient.prompt()
                    .user(key)
                    .call()
                    .content();
        });
    }
}

 

Prompt Template 활용

프롬프트에 매번 같은 문구를 반복 입력하는 것은 비효율적입니다. Prompt Template은 프롬프트의 구조(뼈대)와 가변 데이터(변수)를 분리하여 재사용성을 극대화합니다.

  • 플레이스홀더: {variableName} 형식을 사용하여 동적 데이터를 삽입합니다.
  • 장점: 비즈니스 로직(Java)과 프롬프트 엔지니어링(Text)을 깔끔하게 분리할 수 있습니다.

실습 예제: 마케팅 문구 생성 서비스

 

  @GetMapping("/marketing")
  public String generateMarketing(
      @RequestParam(value = "productName") String productName,
      @RequestParam(value = "features") String features) {

    String template = """
        제품명 {productName}의 마케팅 문구를 작성하세요.
        주요 특징: {features}
        조건: 감성적이고 100자 이내로 작성할 것.
        """;

    return chatClient.prompt()
        .user(u -> u.text(template)
            .param("productName", productName)
            .param("features", features))
        .call()
        .content();
  }

 

 

 

System Message를 활용한 역할 정의

 

AI에게 '전문가'라는 페르소나를 부여하면 답변의 품질이 비약적으로 향상됩니다. System Message는 AI의 행동 지침과 배경 지식을 설정하는 데 사용됩니다.

  • 우선순위: 모델은 사용자 메시지보다 시스템 메시지의 지침을 더 근본적인 규칙으로 인식합니다.
  • 활용: 말투 설정(존댓말/반말), 금기 사항 설정, 특정 분야 전문가 설정 등.

System Message 활용 예제:

  @GetMapping("/translate")
  public String translate(
      @RequestParam(value = "text") String text,
      @RequestParam(value = "targetLanguage", defaultValue = "영어") String targetLanguage) {

    return chatClient.prompt()
        // 1. AI의 페르소나 설정 (System Message)
        .system("당신은 전문 번역가입니다. 주어진 텍스트를 문맥에 맞게 자연스럽게 번역해주세요.")

        // 2. 동적 파라미터 주입 (Prompt Template)
        .user(u -> u.text("다음 텍스트를 {lang}로 번역해주세요: {text}")
            .param("lang", targetLanguage)
            .param("text", text))
        .call()
        .content();
  }

 

return chatClient.prompt()
    // 1. 시스템 메시지로 AI의 성격 고정 (고정값)
    .system("너는 맛집 추천 전문가야. 답변은 항상 '반말'로 친근하게 해줘.") 
    
    // 2. 프롬프트 템플릿으로 사용자 입력 가공 (변수 사용)
    .user(u -> u.text("오늘 {location} 근처에서 {food} 맛집 3곳 추천해줘.")
                .param("location", "강남역")
                .param("food", "삼겹살"))
    .call()
    .content();

 

 

텍스트 응답 vs 구조화된 응답 비교

 

LLM(거대언어모델)은 기본적으로 '자연어(Text)'를 출력하도록 설계되어 있습니다. 하지만 우리가 만드는 백엔드 서비스는 '객체(Object)'나 '데이터(Data)'를 필요로 합니다. 이 간극을 메워주는 것이 바로 구조화된 응답 기능입니다.

일반 응답 (String):
"이 리뷰는 긍정적입니다. 점수는 8점이고, 제품 품질이 우수합니다."

구조화된 응답 (Java Object):
ProductAnalysis {
  sentiment = "positive",
  score = 8,
  summary = "제품 품질이 우수합니다"
}

 

// ❌ 기존 방식 - 문자열 파싱
String response = chatClient.prompt()
    .user("이 리뷰를 분석해주세요: " + review)
    .call()
    .content();

// 결과: "긍정적이며, 8점입니다. 품질이 좋습니다."
// 문제점:
// 1. 파싱 로직이 복잡함
// 2. 형식이 일정하지 않음
// 3. 타입 안정성이 없음
// 4. 에러 처리가 어려움

String sentiment = extractSentiment(response); // 😰 복잡한 파싱
int score = extractScore(response);            // 😰 에러 가능성

// ✅ 권장 방식 - 타입 안정성 확보 및 파싱 자동화
ProductAnalysis result = chatClient.prompt()
    .user("이 리뷰 분석해줘: " + review)
    .call()
    .entity(ProductAnalysis.class); // Spring AI가 JSON 스키마 강제 및 파싱을 알아서 수행

int score = result.getScore(); // 😃 안전하게 바로 사용!

 

 

 

변하는 것 (Transient Technology)

도구와 프로토콜: MCP(Model Context Protocol), 특정 라이브러리, 프레임워크 등은 기술적 수단일 뿐이며 언제든 더 효율적인 것으로 대체됩니다. 여기에만 매몰되면 기술의 변화에 휩쓸리게 됩니다.

 

변하지 않는 것 (Immutable Essence)

컴퓨터 공학의 정점: 인간이 복잡한 로직을 하나하나 코딩하지 않아도, AI가 스스로 판단하고 수행할 수 있다는 '지능의 자동화'라는 본질은 변하지 않습니다.

문제 해결: 기술이 무엇이든 결국 "사용자의 문제를 해결하고 가치를 창출한다"는 서비스의 목적은 불변합니다.

 

 

 

기술을 선택할 때 이 질문을 해보세요.

  • 이 기술이 1년 후에도 존재할 것인가?
  • 이 기술이 바뀌면 우리 서비스의 핵심 가치도 바뀌는가?
  • 우리가 해결하려는 문제의 본질은 무엇인가?

 

LLM을 배우다 보면 좀 복잡하다.. 시스템, user,assitant 흠...

 

제미나이가 멀티모달에 좋다고한다. 모... 유투브도 있고...

 

 

로컬환경에서 LLM모델을 연결해보자

 

 먼저 GPU 없이 CPU만으로도 원활한 실행이 가능한 Ollama의 설치 및 운영체제별 설정 방법을 익히고, 한국어 성능이 뛰어난 경량화 모델인 Alibaba Qwen3를 로컬에 직접 구축하여 다국어 처리 역량을 테스트합니다.
최종적으로는 Spring AI 프레임워크를 활용해 설정부터 컨트롤러 구현까지의 전 과정을 실습함으로써, 클라우드 API를 사용하는 것과 동일한 방식으로 Spring Boot 애플리케이션에 로컬 LLM을 완벽히 통합하는 기술을 습득하게 됩니다.
 
 

 
로컬환경 LLM모델 연결
gpu말고 cpu만으로 원활한 실행이 가능한 Ollama ( AI 모델계의 Docker) 라는 녀석을 설치하고 운영하는것은 처음해본다. 
로컬저장이라 보안이 좋고 비용이 절감되는 장점이 있다.

사양은 일단 이렇다...  크기 작고 한국어가 우수한데 8GB이상이면 되니 괜찮은듯 하다.
meta의 Llama를 알고 있었는데 구글의 Gemma 그리고 Microsoft의 Phi-3은 처음본다. 그리고 Qwen2.5와 Mistral 은 어떨까?
일단 여기서 Qwen이 작고 저사양에서도 돌아가고 다국어지원에 한국어 우수라 추천한듯하다.

 

# Ollama 컨테이너 실행 (데이터 보존을 위한 볼륨 설정 및 포트 매핑)

docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama

설치도 쉽다...

docker exec -it ollama ollama run qwen2.5:3b  성능확인도 해봤다..

 
익히 들어온 하드웨어와 gpu 빨이다...  권장사양을 보니 속도가 10배향상, 16GB는 다중작업 필수 SSD와 OS는 

클로드는 이런데... 

 

 

올라마에서... 비용절감과 효율성을 위해 튜닝설정을 좀해야 한다.

 

 

미니 테스트로 좋은 올라마.. 도커스럽다... 어쨌건 llm도 cpu만으로 테스트할수 있었다!!

LIST

ChatGPT에게 "이메일 써줘"라고 하면 그럭저럭 결과가 나온다. 그런데 "이런 톤으로, 이런 구조로" 예시를 2~3개 먼저 보여주면 결과가 완전히 달라진다. 이것이 Few-Shot Prompting이다.

Fine-tuning처럼 모델을 재훈련하는 것도 아니고, RAG처럼 외부 데이터를 붙이는 것도 아니다. 그냥 프롬프트 안에 예시를 몇 개 넣는 것뿐인데, 왜 이렇게 효과가 큰 걸까?

Few-Shot이란 무엇인가

기계학습에서 Few-Shot Learning은 원래 "적은 데이터로 새로운 태스크를 학습하는 능력"을 뜻한다. 수천 장의 고양이 사진 없이도 3~4장만 보고 고양이를 인식하는 것처럼.

LLM 시대에서 Few-Shot은 의미가 약간 달라졌다. 모델을 재훈련하는 게 아니라, 프롬프트 안에 예시를 넣어서 모델의 출력 패턴을 유도하는 기법이다. GPT-3 논문(2020)에서 본격적으로 정의한 개념으로, 이후 프롬프트 엔지니어링의 가장 기본적인 테크닉이 되었다.

용어를 정리하면 이렇다.

  • Zero-Shot: 예시 없이 지시만 내림. "이 문장의 감정을 분석해줘."
  • One-Shot: 예시 1개 제공. "예: '배송이 빨라요' → 긍정. 이제 이 문장을 분석해줘."
  • Few-Shot: 예시 2~5개 제공. 패턴을 더 명확하게 잡아줌.

왜 예시 몇 개가 이렇게 강력한가

LLM은 본질적으로 패턴 매칭 기계다. 다음에 올 토큰을 예측하는 것이 전부인데, 프롬프트 안에 입력-출력 쌍을 넣으면 모델이 "아, 이 패턴을 반복하면 되는구나"라고 추론한다. 학습이 아니라 문맥 내 추론(In-Context Learning)이다.

핵심은 암묵적 규칙의 전달에 있다. "JSON으로 응답해줘"라고 말로 설명하는 것보다, 실제 JSON 예시를 3개 보여주는 게 훨씬 정확하다. 말로 표현하기 어려운 톤, 구조, 포맷, 판단 기준 같은 것들이 예시를 통해 자연스럽게 전달된다.

실제로 이런 차이가 난다.

Zero-Shot 예시

 
 
다음 고객 리뷰의 감정을 분석해줘.
"배송은 빨랐는데 포장이 엉망이었어요"

모델 응답: "이 리뷰는 긍정과 부정이 혼합되어 있습니다. 배송 속도에 대해서는 만족하지만..."
→ 장황하고, 출력 포맷이 일정하지 않다.

Few-Shot 예시

 
고객 리뷰를 분석해서 아래 형식으로 응답해.

리뷰: "제품 품질이 정말 좋아요"
결과: { "감정": "긍정", "키워드": ["품질"], "점수": 0.9 }

리뷰: "환불 처리가 너무 느려요"
결과: { "감정": "부정", "키워드": ["환불", "느림"], "점수": 0.2 }

리뷰: "가격 대비 괜찮은데 AS가 아쉬워요"
결과: { "감정": "혼합", "키워드": ["가격", "AS"], "점수": 0.5 }

리뷰: "배송은 빨랐는데 포장이 엉망이었어요"
결과:

모델 응답: { "감정": "혼합", "키워드": ["배송", "포장"], "점수": 0.4 }
→ 포맷 정확, 판단 기준 일관, 후처리 파싱 가능.

예시 3개를 추가했을 뿐인데 출력의 품질과 일관성이 완전히 달라졌다.

실전에서 Few-Shot을 잘 쓰는 법

1. 예시의 다양성이 핵심이다

비슷한 예시 3개보다 서로 다른 케이스 3개가 낫다. 위의 감정 분석 예시에서도 긍정/부정/혼합을 골고루 넣었다. 모델이 "긍정만 답하면 되나?"라고 오해할 여지를 차단하는 것이다.

2. 예시 순서가 결과에 영향을 준다

LLM은 마지막 예시에 더 강하게 영향받는 경향이 있다(recency bias). 가장 전형적인 케이스를 마지막에 배치하거나, 어려운 케이스를 뒤에 놓으면 까다로운 입력에 대한 처리가 좋아진다.

3. 네거티브 예시를 포함하라

"이렇게 하지 마라"를 말로 쓰는 것보다, 잘못된 출력과 올바른 출력을 대비시키는 게 효과적이다.

 
 
# 나쁜 예시 (이렇게 하지 말 것)
입력: "서버 에러 500"
출력: "서버에 문제가 있는 것 같습니다. 관리자에게 문의하세요."

# 좋은 예시 (이렇게 할 것)
입력: "서버 에러 500"
출력: "500 Internal Server Error. 1) 서버 로그 확인 2) 최근 배포 변경사항 점검 3) DB 연결 상태 확인"

4. 3~5개가 최적 구간이다

1개는 우연일 수 있고, 10개는 토큰 낭비다. 대부분의 태스크에서 3~5개 예시면 모델이 패턴을 충분히 파악한다. 단, 출력 구조가 복잡할수록(중첩 JSON, 다단계 추론) 예시를 늘려야 한다.

Few-Shot vs 다른 기법들

Few-Shot이 만능은 아니다. 상황에 따라 다른 기법이 더 적합할 수 있다.

Fine-tuning이 나은 경우: 동일한 태스크를 수만 번 반복 실행할 때. 매번 프롬프트에 예시를 넣는 토큰 비용보다 모델을 한 번 튜닝하는 게 경제적이다. 의료 진단, 법률 문서 분류처럼 도메인 특화 정확도가 중요할 때도 마찬가지.

RAG가 나은 경우: 모델이 모르는 최신 정보나 내부 문서를 참조해야 할 때. Few-Shot은 "어떻게 답할지"를 가르치고, RAG는 "무엇을 참고할지"를 제공한다. 둘은 경쟁이 아니라 조합 관계다.

Chain-of-Thought가 나은 경우: 수학 문제, 논리 추론처럼 단계별 사고가 필요한 태스크. 이때는 Few-Shot 예시 안에 추론 과정을 포함시키는 "Few-Shot CoT"가 가장 강력하다.

실무에서 가장 흔한 조합은 Few-Shot + RAG다. RAG로 관련 문서를 검색하고, Few-Shot으로 응답 포맷을 지정하는 패턴이다.

개발자를 위한 실전 패턴

패턴 1: 코드 변환기

# TypeScript → Python 변환기

TypeScript:
const greet = (name: string): string => `Hello, ${name}`;

Python:
def greet(name: str) -> str:
    return f"Hello, {name}"

---

TypeScript:
const sum = (arr: number[]): number => arr.reduce((a, b) => a + b, 0);

Python:
def sum_arr(arr: list[int]) -> int:
    return sum(arr)

---

TypeScript:
{변환할 코드}

Python:

패턴 2: API 응답 정규화

다양한 외부 API 응답을 우리 내부 포맷으로 변환해.

입력: { "user_name": "kim", "created": "2024-01-15T09:00:00Z" }
출력: { "name": "kim", "createdAt": "2024-01-15", "source": "external" }

입력: { "firstName": "lee", "timestamp": 1705312800 }
출력: { "name": "lee", "createdAt": "2024-01-15", "source": "external" }

입력: {실제 API 응답}
출력:

패턴 3: 커밋 메시지 생성

git diff를 보고 Conventional Commits 형식으로 커밋 메시지를 작성해.

diff: +const validateEmail = (email) => /^[^\s@]+@[^\s@]+$/.test(email);
message: feat: add email validation utility function

diff: -timeout: 3000 +timeout: 5000
message: fix: increase API timeout to prevent request failures

diff: {실제 diff}
message:

Few-Shot의 한계와 주의점

만능이 아닌 지점도 분명하다.

토큰 비용: 예시 5개 × 200토큰이면 매 요청마다 1,000토큰이 추가된다. 대량 처리 시 비용이 누적되므로, 안정화된 태스크는 Fine-tuning으로 전환을 고려해야 한다.

예시 편향: 예시가 특정 패턴에 치우치면 모델도 치우친다. 긍정 예시만 3개 넣으면 부정 입력에도 긍정으로 답하는 경향이 생긴다. 의도적으로 엣지 케이스를 포함시켜야 한다.

복잡한 추론의 한계: Few-Shot만으로 다단계 논리 추론을 유도하기 어렵다. 이때는 Few-Shot CoT(Chain-of-Thought)로 예시 안에 추론 과정을 명시해야 한다.

마치며

Few-Shot Prompting은 프롬프트 엔지니어링에서 가장 투자 대비 효과가 큰 기법이다. 모델을 재훈련하지 않고, 외부 시스템을 구축하지 않고, 프롬프트에 예시 몇 줄을 추가하는 것만으로 출력 품질이 극적으로 달라진다.

"AI를 잘 쓴다"는 것은 결국 "AI에게 내가 원하는 것을 정확히 전달하는 것"이다. 그리고 인간이 무언가를 가장 정확하게 전달하는 방법은 예시를 보여주는 것이었다. 수천 년 전 도제식 교육에서도, 2025년 LLM 프롬프트에서도, 원리는 같다.

말로 백 번 설명하는 것보다 한 번 보여주는 게 낫다. Few-Shot은 그 오래된 진리의 AI 버전이다.

LIST


— 보안·감사·예산·업무절차, 네 가지 축으로 설계하는 엔터프라이즈 AI 오케스트레이션 전략
들어가며: AI 파일럿은 넘쳤고, 성과는 부족했다
2025년까지 대부분의 기업이 AI를 도입했다. 그러나 실제로 비즈니스 가치를 만들어낸 조직은 극소수에 불과하다. McKinsey에 따르면 약 80%의 기업이 생성형 AI를 사용하지만, 대부분은 여전히 눈에 보이는 수익 기여를 만들지 못하고 있다. 파일럿 프로젝트는 넘쳐나지만 운영 모델과 확장 체계가 기술의 속도를 따라가지 못하는 것이다.
이 격차를 메우는 핵심이 바로 AI 오케스트레이션이다. 단순히 여러 모델을 호출하는 것이 아니라, 어떤 모델이 어떤 작업을 어떤 순서로 수행하며 어떤 거버넌스 하에서 작동하는지를 관리하는 조율 계층이다.
그런데 오케스트레이션을 기술적 관점에서만 바라보면 절반만 본 것이다. 2026년, 엔터프라이즈 AI에서 진짜 중요한 질문은 다음과 같다.
"AI가 잘 작동하는가?"가 아니라, "AI가 안전하게, 추적 가능하게, 예산 내에서, 절차에 맞게 작동하는가?"
이 글에서는 보안, 감사, 예산, 업무절차라는 네 가지 축을 중심으로, 실무에서 AI 오케스트레이션을 어떻게 설계하고 운영해야 하는지를 다룬다.
1. 보안: AI 에이전트도 "직원"처럼 통제하라
문제: Shadow AI와 런타임 취약성
기업 AI 보안에서 가장 위험한 영역은 생각보다 단순하다. 바로 회사가 모르는 AI 도구를 직원들이 이미 쓰고 있다는 사실이다. 이른바 Shadow AI다. 승인되지 않은 AI 도구 사용은 평균 400일 이상 발견되지 않으며, 이로 인한 추가 침해 비용은 건당 67만 달러에 달한다는 조사 결과도 있다.
런타임 단계의 보안도 핵심 과제다. AI 에이전트가 외부 웹페이지, 문서, 이메일의 정보를 처리하고 권한 있는 도구로 행동하는 과정에서, 프롬프트 인젝션 같은 전통적 소프트웨어와는 다른 유형의 취약점이 발생한다.
설계 원칙
첫째, Zero Trust 원칙을 AI 에이전트에도 적용한다. AI 에이전트도 사람 사용자와 마찬가지로 인증, 인가, 관찰의 대상이다. 에이전트가 접근할 수 있는 시스템과 데이터를 분리하고, 단일 에이전트에 권한이 집중되지 않도록 설계해야 한다.
둘째, AI Gateway를 중앙 제어 지점으로 활용한다. OpenAI, Anthropic, Google 등 여러 LLM 제공자에 대한 접근을 단일 인터페이스로 통합하고, 이 지점에서 DLP(Data Loss Prevention), 접근 제어, 토큰 제한 등의 정책을 일괄 적용한다. 이 접근은 MCP(Model Context Protocol)와 같은 표준화된 프로토콜과 결합될 때 더욱 효과적이다.
셋째, Control Plane과 Execution Plane을 분리한다. 정책, 인증, 라우팅, 평가, 관찰 가능성, 감사를 담당하는 Control Plane과 실제 에이전트, 도구, 워크플로우가 실행되는 Execution Plane을 아키텍처 수준에서 분리하는 것이 최신 레퍼런스 아키텍처의 핵심이다. 이렇게 하면 벤더에 종속되지 않으면서도 일관된 보안 정책을 강제할 수 있다.
2. 감사: 모든 AI 의사결정에 "왜?"라는 질문에 답할 수 있어야 한다
문제: 정책 문서는 있지만, 인프라 수준의 강제가 없다
많은 기업이 AI 거버넌스 정책을 가지고 있다. 문제는 그 정책이 PDF 문서나 윤리 위원회 수준에 머물러 있다는 점이다. AI 거버넌스는 정책이 아니라 증거를 만들어내는 운영 프레임워크여야 한다. 누가 AI에 대한 의사결정을 내릴 수 있는지, 그 결정이 어떤 증거를 남겨야 하는지, 통제가 전체 생명주기에 걸쳐 어떻게 강제되는지를 정의해야 한다.
설계 원칙
첫째, 모든 LLM 호출의 입출력을 로깅한다. 프롬프트, 응답, 사용 모델, 토큰 수, 지연시간, 호출 시각을 기록한다. 이것은 단순한 디버깅 도구가 아니라 감사 추적(Audit Trail)의 기반이다.
둘째, 의사결정 계보(Lineage)를 추적한다. 어떤 데이터가 어떤 모델에 입력되어 어떤 결론이 나왔는지를 추적할 수 있어야 한다. 멀티 에이전트 시스템에서는 개별 에이전트의 성능뿐 아니라 에이전트 간 상호작용과 시스템 수준 행동도 모니터링 대상이다.
셋째, AI 생성 콘텐츠에 라벨링을 적용한다. AI가 생성한 문서, 분석, 추천에는 출처와 생성 방식을 표기한다. 이는 내부 감사뿐 아니라 규제 대응에도 필수적이다. EU AI Act, 미국 콜로라도 AI Act 등 2026년부터 본격 시행되는 규제들은 고위험 AI 시스템에 대해 설명 가능성과 감사 준비 상태를 명시적으로 요구하고 있다.
넷째, 계층적 리포팅 체계를 구축한다. 월간 운영 대시보드(핵심 지표, 트렌드, 상위 리스크), 분기 전략 보고(규제 준수 현황, 주요 인시던트, 예산 대비 실적), 연간 이사회 보고(성숙도 평가, 외부 감사 결과, 동종업계 벤치마킹)로 이어지는 보고 체계가 필요하다.
3. 예산: "AI에 얼마를 쓸 것인가"보다 "어디에 어떻게 배분할 것인가"
문제: 벤치마크 복사의 함정
"보안 예산의 10%를 AI 보안에 투자하라"는 식의 벤치마크는 위험하다. 이런 수치는 Shadow AI 노출 수준, 산업 규제 강도, 기존 보안 인프라 성숙도가 완전히 다른 조직들의 평균이기 때문이다. 남의 리스크 프로필을 복사한 뒤, 18개월 후에야 잘못된 곳에 투자했다는 것을 깨닫는 경우가 흔하다.
또한 소비 기반(consumption-based) AI 요금 모델의 확산으로 예산 변동성이 크게 증가하고 있다. IT 리더의 78%가 소비 기반 또는 AI 요금 모델로 인한 예상치 못한 비용을 경험했다는 조사 결과도 있다.
설계 원칙
첫째, AI 보안 예산을 4개 기능으로 분배한다. 발견 및 가시성(3035%), 거버넌스 및 정책(2530%), 데이터 보호(2530%), 위협 방어(1015%)가 현재 권장되는 배분 비율이다. 보이지 않는 것은 통제할 수 없으므로, 발견과 가시성이 가장 높은 비중을 차지한다.
둘째, 모델 라우팅으로 비용을 최적화한다. 높은 신뢰도의 단순 작업은 경량 모델(예: Haiku급)로, 복잡한 추론이 필요한 작업은 고급 모델(예: Opus급)로 동적 라우팅한다. 이것이 오케스트레이션이 비용 통제 도구이기도 한 이유다.
셋째, 예산을 Foundation에만 집중하지 않는다. 데이터 거버넌스와 품질(Foundation)에만 예산을 쏟는 조직이 많다. 그러나 AI 활성화를 위한 번역·적용 계층(Translation & Application Layer), 즉 LLM 오케스트레이션, 시맨틱 레이어, 에이전트 인프라에도 균형 있게 투자해야 2027년에도 파일럿 단계에 머무르지 않을 수 있다.
넷째, 토큰 사용량과 모델별 비용을 실시간 모니터링한다. 오케스트레이션 계층에서 팀별, 프로젝트별, 모델별 사용량을 추적하고 한도를 설정한다. SaaS에 내장된 AI 기능의 추가 비용도 별도로 추적해야 한다.
4. 업무절차: "에이전트를 만드는 것"이 아니라 "에이전트를 관리하는 체계를 만드는 것"
문제: Agent Sprawl — 에이전트가 늘어나면 혼란도 늘어난다
로우코드, 노코드 플랫폼의 발달로 거의 누구나 AI 에이전트를 만들 수 있게 되었다. 그러나 에이전트를 만드는 것은 시작일 뿐이다. 에이전트가 늘어날수록 조율 없이는 단절된 자동화, 예측 불가능한 다운타임, 보안 노출이 발생한다. 이를 Agent Sprawl이라 부른다.
설계 원칙
첫째, 단계적 접근(Crawl → Walk → Run)을 채택한다. 거버넌스가 성숙해지는 속도에 맞춰 에이전트의 자율성을 점진적으로 확장한다. 처음에는 작고 영향력 높은 유스케이스에서 시작하고, 전사적 빅뱅 구현을 피한다.
둘째, 자율성과 권한을 조절 가능한 설계 변수로 취급한다. 결과의 영향이 큰 작업에는 사람의 승인이 필요한 시점을 명확히 설정하고, 핵심 시스템 접근은 분리한다. 저위험 단계는 자동화하되, 고위험 행동은 승인, 직무 분리(Separation of Duties), 에스컬레이션 워크플로우를 트리거한다.
셋째, 새로운 역할을 정의한다. Agent Ops Lead, AI Product Owner 같은 역할이 필요하다. 사람이 프롬프트 작성자에서 에이전트 관리자로 진화해야 한다. 이는 단순한 직무 변경이 아니라, AI 시대에 조직이 일하는 방식 자체의 재설계다.
넷째, Governance by Design을 적용한다. 거버넌스를 개발 워크플로우의 병목이 아니라 내장된 요소로 만든다. 자동화된 거버넌스 도구, 대시보드, 모델 관리 플랫폼을 활용해 승인 프로세스, 편향 테스트, 감사 로깅을 자동화한다. 위험 수준에 따른 계층적 거버넌스를 구현하면, 저위험 애플리케이션은 빠르게 이동하고 고위험 시스템은 적절한 검토를 받는다.
실무 적용: 최소 실행 가능한 오케스트레이션 아키텍처
이론은 충분하다. 실제 프로젝트에서 위 네 가지를 반영한 최소 구조는 다음과 같다.
┌─────────────────────────────────────────────────┐
│              Control Plane (제어부)                │
│  ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│  │ 인증/인가  │ │ 정책 엔진  │ │ 감사 로그 & 라벨링 │ │
│  └──────────┘ └──────────┘ └───────────────────┘ │
│  ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│  │ 비용 모니터 │ │모델 라우터 │ │ 승인 워크플로우    │ │
│  └──────────┘ └──────────┘ └───────────────────┘ │
└──────────────────────┬──────────────────────────┘
                       │ MCP / A2A Protocol
┌──────────────────────▼──────────────────────────┐
│            Execution Plane (실행부)                │
│  ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│  │ Agent A   │ │ Agent B   │ │ Agent C           │ │
│  │ (경량모델) │ │ (고급모델) │ │ (도구 호출 전문)   │ │
│  └──────────┘ └──────────┘ └───────────────────┘ │
│  ┌──────────────────────────────────────────────┐ │
│  │ 외부 도구 / API / 데이터베이스 / SaaS         │ │
│  └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
핵심은 Control Plane을 먼저 구축하는 것이다. 에이전트를 더 만드는 것보다, 기존 에이전트를 안전하게 관리하는 체계를 먼저 갖추는 것이 우선이다.
마치며: 오케스트레이션은 기술이 아니라 운영 모델이다
2026년의 AI 오케스트레이션은 더 이상 기술적 선택지가 아니다. 보안 사고를 막고, 감사에 대비하고, 비용을 통제하고, 조직이 일관되게 AI를 활용하기 위한 운영 모델이다.
성공하는 조직의 공통점은 명확하다.
AI 예산이 가장 큰 조직이 아니라, 기존 인프라에서 최대 성과를 끌어내는 조직이 이긴다
완벽한 거버넌스를 기다리기보다, 빠르게 시작하고 반복하면서 거버넌스를 함께 성장시킨다
에이전트를 많이 만드는 것이 아니라, 에이전트를 관찰하고, 통제하고, 감사할 수 있는 체계를 먼저 만든다
AI가 똑똑해지는 속도보다, 그 AI를 안전하게 운영하는 체계를 만드는 속도가 기업의 경쟁력을 결정할 것이다.

LIST

Claude Code 에이전트는 결국 IaC다
바이브코딩의 본질은 코드 생성이 아니라 오케스트레이션이다
요즘 바이브코딩이라는 말이 유행이다. AI에게 "이거 만들어줘" 하면 코드가 나온다. 신기하다. 근데 결과물의 품질은? 보장 못 한다. 왜?
코드를 만드는 건 AI가 하지만, 뭘 만들지 결정하는 건 여전히 사람이다.
이 구조, 어디서 본 적 없는가?
Terraform을 떠올려보자
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}
Terraform에게 "EC2 하나 띄워줘"라고 선언한다. Terraform은 실행한다. 근데 어떤 AMI를 쓸지, 어떤 인스턴스 타입을 쓸지, 어떤 VPC에 넣을지 — 이건 전부 사람이 정의한다.
Terraform은 실행기일 뿐이다. 설계는 사람이 한다.
Claude Code도 똑같다
claude "LabNote 서비스에 글로벌 에러 핸들러 추가해줘"
Claude Code가 코드를 생성한다. 근데 어떤 서비스에, 어떤 패턴으로, 어떤 에러를 잡을지 — 이건 전부 프롬프트를 설계한 사람이 정의한다.
Claude Code는 실행기일 뿐이다. 설계는 사람이 한다.

IaC (Terraform/Ansible)
AI Agent (Claude Code)
입력
선언적 설정 파일 (.tf, .yml)
프롬프트 + 컨텍스트
실행
인프라 프로비저닝
코드 생성/수정
결과 보증
plan → apply → state 검증
생성 → 테스트 → 리뷰
오케스트레이션
모듈 분리, 의존성 그래프
에이전트 분리, 역할 지정
실패 시
rollback, state lock
컨텍스트 리셋, 재프롬프팅
핵심 역할 (사람)
아키텍처 설계
프롬프트 설계
에이전트 분리 = 모듈 분리
Terraform에서 네트워크, 컴퓨트, 스토리지를 모듈로 분리하듯이, Claude Code에서도 에이전트를 역할별로 분리해야 한다.
내가 실제로 쓰는 구조:
.claude/commands/
├── business-logic.md   # 비즈니스 로직 전담
├── docker.md           # 컨테이너화 전담
├── ci.md               # CI 파이프라인 전담
└── (cd.md)             # CD는 스택 확정 후 추가 예정
하나의 에이전트에 설계+구현+테스트+배포를 다 시키면? Terraform 하나의 .tf 파일에 VPC부터 Lambda까지 전부 때려넣는 것과 같다. 컨텍스트가 오염되고, 앞의 결정을 잊고, 결과물이 망가진다.
모델 선택 = 인스턴스 타입 선택
EC2에서 모든 워크로드를 c5.4xlarge로 돌리지 않는다. 트래픽 라우팅은 t3.micro로 충분하고, ML 학습은 p3.2xlarge가 필요하다.
Claude도 마찬가지다.
Haiku = t3.micro: 파일 읽기, 단순 수정, 분류 작업
Sonnet = m5.xlarge: 일반 개발, API 연동, 테스트 작성
Opus = p3.2xlarge: 아키텍처 리뷰, 복잡한 리팩토링, 보안 점검
모든 작업에 Opus를 쓰는 건 모든 EC2를 GPU 인스턴스로 돌리는 것과 같다. 비용만 날리고 성능은 비례하지 않는다.
검증 파이프라인이 없으면 둘 다 위험하다
Terraform에 terraform plan 없이 바로 apply를 치는 사람은 없다. 근데 Claude Code가 생성한 코드를 리뷰 없이 바로 머지하는 사람은 많다.
IaC의 검증 흐름:
terraform plan → review → apply → state 확인
AI 에이전트에도 같은 흐름이 필요하다:
코드 생성 → 테스트 실행 → Opus 리뷰 → 머지
내가 실제로 겪은 케이스: MSA 프로젝트에서 7개 서비스 중 6개에 글로벌 에러 핸들러가 누락되어 있었다. Claude가 생성한 코드였다. 검증 단계가 없었기 때문이다.
결론: DevOps 엔지니어가 AI 시대에 유리한 이유
IaC를 다뤄본 사람은 이미 알고 있다.
선언적으로 원하는 상태를 정의하는 법
실행을 모듈로 분리하는 법
검증 파이프라인을 설계하는 법
실패 시 롤백하는 법
이게 전부 AI 에이전트 오케스트레이션에 그대로 적용된다. 바이브코딩의 진짜 실력은 코드를 잘 짜는 게 아니라, AI를 잘 오케스트레이션하는 것이다. 그리고 그 오케스트레이션 능력은 DevOps에서 온다.
Terraform을 잘 쓰는 사람이 Claude Code도 잘 쓴다. 우연이 아니다. 본질이 같기 때문이다.

LIST

📌 본문

1. Spring AI란 무엇인가 (현실 정의)

Spring AI는 한 줄로 정리하면
👉 **“Spring Boot 방식으로 LLM을 쓰게 만들어주는 어댑터 계층”**입니다.

  • ChatClient = RestTemplate 느낌
  • application.yml 기반 설정
  • POJO 매핑 (DTO ↔ LLM 응답)
  • Spring DI / AOP / Actuator 그대로 활용

즉, **AI 프레임워크라기보다 “Spring 친화적인 LLM Integration Layer”**입니다.


2. Spring AI의 강점 (실무 기준)

✅ 1) 기존 Spring 생태계 완벽 흡수

  • DI, 설정, 모니터링 그대로 사용
  • 학습비용 거의 없음
  • 기존 서비스에 “AI 기능 추가”에 최적

👉 SI / 레거시 환경에서 매우 강력

Spring AI는 기존 Spring 개발자에게 “자연스러운 확장”이다


✅ 2) 엔터프라이즈 대응력 (이게 핵심)

  • Actuator 기반 모니터링
  • Micrometer metrics
  • Config / Secret 관리
  • 보안 정책 적용 용이

👉 **“운영 가능한 AI”**라는 점에서 차별화

Spring AI는 LLM을 일반 엔터프라이즈 의존성처럼 다룬다


✅ 3) MCP(Model Context Protocol) 대응 (2025~ 핵심 변화)

  • 외부 tool / 서비스 연동 표준화
  • 서비스 → AI → 서비스 구조 분리

👉 앞으로 Agent 아키텍처 표준화 방향과 맞닿아 있음


✅ 4) RAG, 벡터DB 통합 지원

  • Pinecone, Redis, Qdrant 등 지원
  • Document ETL 기능 내장

👉 “RAG 기본 구조”는 바로 구현 가능


✅ 5) 유지보수 친화적 구조

  • POJO 기반 응답 매핑
  • 타입 안정성 확보

👉 팀 단위 개발에서 매우 중요


3. Spring AI의 약점 (냉정하게)

❌ 1) Agent / Orchestration 약함

  • LangChain 대비 가장 큰 약점
  • multi-agent / workflow orchestration 부족

LangChain 계열이 agent 기능은 훨씬 앞서 있음

👉 결론
“AI를 쓰는 수준”은 가능하지만
“AI로 시스템을 설계하는 수준”은 부족


❌ 2) 생태계 규모 부족

  • LangChain: 수천 integrations
  • Spring AI: 상대적으로 제한적

👉 특히

  • tool ecosystem
  • agent tooling
  • workflow DSL

부족


❌ 3) Spring 종속성 (락인)

  • Spring Boot 강제
  • Quarkus / Node / Python과 단절

👉 멀티 스택 환경에서는 제약


❌ 4) 성능/경량성 이슈

  • Spring Boot 기반 → 메모리 큼
  • Cold start 느림 (~200~400ms 추가)

👉 서버리스/경량 서비스에는 불리


❌ 5) “AI 퍼스트 프레임워크”가 아님

  • AI 중심 설계 X
  • 기존 구조에 AI를 끼워 넣는 형태

👉 혁신보다는 안정성 선택


4. 2026년 3월 기준 최신 동향

🔥 1) Java AI 생태계 본격 성장

  • 2025년 → Spring AI 1.0 GA
  • LangChain4j 1.0 안정화

👉 이제 “실험 단계” 끝
👉 실서비스 적용 단계 진입


🔥 2) Agent 중심 패러다임 이동

  • LangGraph / multi-agent 구조 확산
  • tool calling → 기본 기능화

👉 방향성

단순 챗봇 → Agent 시스템 → 업무 자동화 플랫폼
 

🔥 3) MCP 등장 (중요)

  • OpenAI / Anthropic 중심 표준화 시도
  • Spring AI 빠르게 반영

👉 의미

  • “AI + 서비스” 연결 표준화 시작

🔥 4) RAG → Agentic RAG로 진화

  • 단순 검색 + 생성 → ❌
  • multi-step reasoning + tool 사용 → ✅

👉 Spring AI는 아직 초기 단계


🔥 5) 비용 최적화 / 캐싱 중요성 증가

  • LLM 비용이 병목
  • semantic caching 필수

👉 캐시 전략 없으면 운영 불가능 수준


5. 결론 (실무 판단 기준)

👉 Spring AI를 써야 하는 경우

  • 기존 Spring 시스템에 AI 붙이는 경우
  • 기업 내부 시스템 (SI, 공공, 금융)
  • 안정성 / 운영 / 보안 중요

👉 한 줄 결론
“AI 기능 추가용”


👉 쓰면 안 되는 경우

  • Agent 시스템 구축
  • 복잡한 AI workflow
  • 빠른 실험 / 프로토타입

👉 한 줄 결론
“AI 플랫폼 구축용으로는 부족”


6. 핵심 요약 (딱 잘라서)

항목평가
생산성 👍 (Spring 개발자 기준 최고)
확장성 ⚠️ 제한적
Agent 기능 ❌ 부족
운영 안정성 👍 매우 강함
생태계 ⚠️ 성장 중

📌 한 줄 정리

👉 Spring AI는 “LangChain 대체재”가 아니라
“Spring용 LLM 어댑터”다.

LIST

📌 서론

최근 LLM 기반 애플리케이션 개발이 보편화되면서
LangChain 과
Spring AI 를 비교하는 이야기가 자주 나온다.
특히 많이 들리는 말이 있다.

“Spring AI는 그냥 LangChain 따라 만든 거 아니냐?”

이 질문은 절반은 맞고, 절반은 틀리다.
왜냐하면 두 기술은 겉으로는 비슷하지만, 설계 목적 자체가 다르기 때문이다.


📌 1. 왜 “카피 같다”는 말이 나오는가

표면적으로 보면 비슷한 구조가 맞다.

개념                                                        LangChain                                        Spring AI
Prompt 관리 PromptTemplate PromptTemplate
체인 구성 Chain ChatClient / Advisor
Memory Memory ChatMemory
RAG Retriever VectorStore
Tool 호출 Tool / Agent Function Calling

👉 결론
기능 단위로 보면 거의 1:1 대응된다
그래서 개발자 입장에서 보면 이렇게 느껴진다.

“이거 그냥 LangChain 자바판 아니냐?”

이 느낌, 틀린 건 아니다.
하지만 이건 “표면 구조”만 본 해석이다.


📌 2. 진짜 차이: 철학이 다르다

핵심은 여기다.

LangChain

  • 목적: LLM 중심 프레임워크
  • 철학: “AI 애플리케이션을 빠르게 조립하자”
  • 특징:
    • 실험, 프로토타이핑 최적화
    • Python 중심
    • 변화 속도 빠름 (unstable)
    • 에이전트, 체인 중심 사고

Spring AI

  • 목적: Spring 생태계 확장
  • 철학: “기존 엔터프라이즈 시스템에 AI를 안전하게 넣자”
  • 특징:
    • 안정성, 일관성
    • DI, Bean, 설정 기반
    • 기존 Spring 프로젝트에 자연스럽게 통합
    • 운영(Production) 중심

👉 한 줄 요약

LangChain = “AI 앱을 만들기 위한 프레임워크”
Spring AI = “기존 시스템에 AI를 붙이기 위한 어댑터”


📌 3. 설계 관점에서 보면 완전히 다르다

(1) LangChain은 "Flow 중심"

Prompt → LLM → Tool → Memory → Agent
 
  • 실행 흐름 자체가 핵심
  • "어떻게 흘러가느냐"가 중요

(2) Spring AI는 "Bean + Integration 중심"

@Service
→ ChatClient
→ VectorStore
→ OpenAIClient
 
  • 기존 서비스 계층 안에 들어감
  • 트랜잭션, DI, AOP와 같이 움직임

👉 즉

  • LangChain: 파이프라인 설계
  • Spring AI: 서비스 통합

📌 4. 왜 Spring은 굳이 따로 만들었을까

이건 SI/엔터프라이즈 관점에서 보면 명확합니다.
르무엘님 기준으로 보면 핵심 포인트입니다.

❌ LangChain 그대로 쓰면 문제

  • Python 중심 → Java 시스템과 괴리
  • 운영 안정성 부족
  • 트랜잭션/보안/설정 관리 분리됨
  • Spring Security, JPA와 통합 어려움

✅ Spring AI의 목적

  • 기존 Spring Boot에 자연스럽게 붙이기
  • 설정 기반 (application.yml)
  • Bean 관리
  • Observability (추적, 로깅)
  • 기업 환경 대응

👉 결론

“카피”가 아니라
Spring스럽게 재해석한 것


📌 5. 실제 현업 선택 기준

르무엘님 상황 기준으로 현실적으로 정리하면:

LangChain 쓰는 경우

  • RAG 실험
  • AI 프로토타입
  • 빠른 PoC
  • 데이터 사이언스 협업

Spring AI 쓰는 경우

  • 기존 Java/Spring 시스템
  • 결제 / 정산 / 승인 시스템에 AI 붙일 때
  • 운영 안정성 중요
  • MSA 내부 서비스로 붙일 때

👉 핵심 판단 기준

“AI가 중심인가?” vs “서비스가 중심인가?”


📌 6. 결론

“Spring AI는 LangChain의 카피인가?”
👉 답:

❌ 카피가 아니다
✅ 같은 문제를 다른 철학으로 푼 것이다


더 정확히 말하면

LangChain은 “AI First”
Spring AI는 “Enterprise First”


📌 마무리 한 줄

좋은 백엔드는 기술을 따라가는 게 아니라
운영 환경에 맞는 선택을 하는 것이다

LIST

1️⃣ pgvector 확장으로 벡터 검색 가능

PostgreSQL에는 pgvector 라는 확장이 있습니다.

이걸 설치하면 다음이 가능해집니다.

  • embedding vector 저장
  • cosine similarity
  • inner product
  • L2 distance 검색

 
CREATE EXTENSION vector;

CREATE TABLE document (
id bigserial PRIMARY KEY,
content text,
embedding vector(1536)
);

SELECT *
FROM document
ORDER BY embedding <-> '[0.12,0.98,...]'
LIMIT 5;
 

RDB에서 바로 Vector Similarity Search 가능합니다.


2️⃣ AI 서비스에서 구조데이터 + 벡터 같이 관리

AI 서비스는 보통 데이터가 두 종류입니다.

종류예
구조 데이터 user, document, metadata
벡터 데이터 embedding

document
├ id
├ title
├ content
├ author
└ embedding(vector)
 

PostgreSQL 하나로 해결 가능

RDB + Vector DB
 

따로 DB 두 개 운영할 필요 없습니다.


3️⃣ 인덱스 지원 (성능)

pgvector는 벡터 인덱스를 제공합니다.

대표적으로

  • IVFFlat
  • HNSW

 
CREATE INDEX ON document
USING ivfflat (embedding vector_cosine_ops);
 

→ 대량 벡터에서도 빠른 ANN 검색 가능


4️⃣ 기존 백엔드와 궁합이 좋음

르무엘님처럼 Java / Spring 백엔드에서는 이게 중요합니다.

PostgreSQL은 이미 대부분 시스템에서 사용 중입니다.

지원

  • JDBC
  • Spring Data
  • JPA
  • MyBatis

Spring Boot

PostgreSQL + pgvector
 

바로 붙습니다.


5️⃣ 운영이 단순

Vector DB를 따로 쓰면

Postgres (업무DB)
+
Pinecone / Milvus / Weaviate (Vector DB)
 

이렇게 됩니다.

운영 복잡도 ↑

하지만

Postgres + pgvector
 

이면

  • DB 하나
  • 백업 하나
  • 운영 하나

SI / 공공 프로젝트에서는 이게 훨씬 현실적입니다.


6️⃣ RAG 시스템에서 구조가 깔끔

RAG 시스템의 기본 구조입니다.

Document 저장


Embedding 생성


PostgreSQL (pgvector)


Similarity Search


LLM Prompt
 

RAG = Vector Search + Metadata Query
 

PostgreSQL이 둘 다 처리합니다.


📊 실제 AI 서비스에서 DB 선택 패턴

상황선택
스타트업 / MVP PostgreSQL + pgvector
SI / 공공 프로젝트 PostgreSQL + pgvector
초대형 벡터 (10억+) Milvus
SaaS 서비스 Pinecone
Graph 기반 AI Neo4j

그래서 지금 RAG 서비스 70% 이상은 Postgres 시작입니다.


정리 (개발자 관점)

왜 PostgreSQL 쓰냐?

1️⃣ 기존 RDB 그대로 사용
2️⃣ pgvector로 벡터 검색 가능
3️⃣ 메타데이터 + 벡터 같이 관리
4️⃣ Spring/JPA 호환
5️⃣ 운영 단순
6️⃣ RAG 구조에 딱 맞음

PostgreSQL = AI 서비스용 "현실적인 Vector DB"
LIST

+ Recent posts