ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๋ฐ˜์‘ํ˜•

๐ŸŒฑ Spring AI vs ๐Ÿ”— LangChain4j: Java AI ํ”„๋ ˆ์ž„์›Œํฌ ์ „๊ฒฉ ๋น„๊ต

์ตœ๊ทผ AI ๊ธฐ์ˆ , ํŠนํžˆ LLM(๋Œ€๊ทœ๋ชจ ์–ธ์–ด ๋ชจ๋ธ)์„ ์ž์‹ ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ†ตํ•ฉํ•˜๋ ค๋Š” ๊ฐœ๋ฐœ์ž๋“ค์ด ๋Š˜์–ด๋‚˜๋ฉด์„œ Java ์ง„์˜์—์„œ๋„ ๋‘๊ฐ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋‘ ๊ฐœ์˜ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ Spring AI์™€ LangChain4j์ž…๋‹ˆ๋‹ค.

๋‘ ํ”„๋ ˆ์ž„์›Œํฌ ๋ชจ๋‘ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ์ง€ํ–ฅํ•˜๋Š” ์ฒ ํ•™๊ณผ ์‚ฌ์šฉ ๋ฐฉ์‹์— ์ฐจ์ด๊ฐ€ ์žˆ์–ด ํ”„๋กœ์ ํŠธ์˜ ์„ฑ๊ฒฉ์— ๋งž๋Š” ๊ธฐ์ˆ ์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธ€์—์„œ๋Š” ๋‘ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‹ฌ์ธต์ ์œผ๋กœ ๋น„๊ตํ•˜๊ณ , ์–ด๋–ค ์ƒํ™ฉ์—์„œ ๋ฌด์—‡์„ ์„ ํƒํ•ด์•ผ ํ• ์ง€ ๋ช…ํ™•ํ•œ ๊ฐ€์ด๋“œ๋ฅผ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค.


1. ์ •์˜: ๋‘ ๊ฑฐ์ธ์˜ ๋“ฑ์žฅ

๐ŸŒฑ Spring AI

Spring AI๋Š” Spring ๊ฐœ๋ฐœํŒ€์ด ์ง์ ‘ ๋งŒ๋“œ๋Š”, ์Šคํ”„๋ง ์ƒํƒœ๊ณ„์— AI ๊ธฐ๋Šฅ์„ '๋„ค์ดํ‹ฐ๋ธŒ'ํ•˜๊ฒŒ ํ†ตํ•ฉํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค. ์Šคํ”„๋ง ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ๋ˆ„๊ตฌ๋‚˜ ์ต์ˆ™ํ•  DI, AOP, ์ž๋™ ์„ค์ •(Auto-configuration)๊ณผ ๊ฐ™์€ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ฅด๋ฉฐ, ์ตœ์†Œํ•œ์˜ ๋…ธ๋ ฅ์œผ๋กœ AI ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

์ž๋™์ฐจ์— ๋น„์œ ํ•˜์ž๋ฉด, ์ œ์กฐ์‚ฌ๊ฐ€ ๋Œ€์‹œ๋ณด๋“œ์— ์™„๋ฒฝํ•˜๊ฒŒ ๋‚ด์žฅํ•ด ๋†“์€ ์ˆœ์ • ๋‚ด๋น„๊ฒŒ์ด์…˜๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๐Ÿ”— LangChain4j

LangChain4j๋Š” ํŒŒ์ด์ฌ์—์„œ ์‹œ์ž‘๋œ ์œ ๋ช… AI ํ”„๋ ˆ์ž„์›Œํฌ 'LangChain'์˜ Java ๋ฒ„์ „์ž…๋‹ˆ๋‹ค. ํŠน์ • ํ”„๋ ˆ์ž„์›Œํฌ์— ์ข…์†๋˜์ง€ ์•Š๋Š” ๋…๋ฆฝ์ ์ด๊ณ  ๋ฒ”์šฉ์ ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, AI ์—์ด์ „ํŠธ, ์ฒด์ธ ๋“ฑ ๋ณต์žกํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ AI ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ž๋™์ฐจ์— ๋น„์œ ํ•˜๋ฉด, ๊ธฐ๋Šฅ์ด ๋” ๋‹ค์–‘ํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ๊ณ ์„ฑ๋Šฅ ์™ธ์žฅ GPS ๊ธฐ๊ธฐ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.


2. ๋น„๊ต: ๋ฌด์—‡์ด ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€?

ํ•ญ๋ชฉ ๐ŸŒฑ Spring AI ๐Ÿ”— LangChain4j
ํ•ต์‹ฌ ์ฒ ํ•™ "AI ๊ธฐ๋Šฅ์„ ์Šคํ”„๋ง๋‹ต๊ฒŒ" <br> ์Šคํ”„๋ง ์ƒํƒœ๊ณ„์™€์˜ ์™„๋ฒฝํ•œ ํ†ตํ•ฉ "๊ฐ•๋ ฅํ•œ AI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์ถ•" <br> ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๊ณผ ์œ ์—ฐ์„ฑ ์ œ๊ณต
๊ฐœ๋ฐœ ์ฃผ์ฒด ์Šคํ”„๋ง ํŒ€ (VMware/Pivotal) ์ปค๋ฎค๋‹ˆํ‹ฐ ์ฃผ๋„ ์˜คํ”ˆ์†Œ์Šค
ํ†ตํ•ฉ ์ˆ˜์ค€ ์ตœ์ƒ (Native). ์Šคํ”„๋ง ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋งค์šฐ ์ต์ˆ™ํ•œ ํŒจํ„ด ์ œ๊ณต ์ข‹์Œ. starter๋ฅผ ํ†ตํ•ด ์Šคํ”„๋ง๊ณผ ์‰ฝ๊ฒŒ ํ†ตํ•ฉ๋˜์ง€๋งŒ, ํ•ต์‹ฌ์€ ๋…๋ฆฝ์ 
RAG ๊ตฌ์„ฑ ๋งค์šฐ ๊ฐ„๊ฒฐ. ์ž๋™ ์„ค์ • ๊ธฐ๋ฐ˜์œผ๋กœ ๋น ๋ฅด๊ฒŒ ๊ตฌํ˜„ ๊ฐ€๋Šฅ ๋งค์šฐ ๊ฐ•๋ ฅ. ๋ณต์žกํ•˜๊ณ  ์„ธ๋ฐ€ํ•œ ํŒŒ์ดํ”„๋ผ์ธ ์ œ์–ด์— ์œ ๋ฆฌ
์œ ์—ฐ์„ฑ ์Šคํ”„๋ง ์ƒํƒœ๊ณ„์— ๊ฐ•ํ•˜๊ฒŒ ์˜์กด ๋…๋ฆฝ์ . ์–ด๋–ค Java ํ”„๋กœ์ ํŠธ์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
๊ธฐ๋Šฅ ๋ฒ”์œ„ ํ•ต์‹ฌ ๊ธฐ๋Šฅ(Chat, RAG)์— ์ง‘์ค‘ ๊ด‘๋ฒ”์œ„ํ•จ (๋ณต์žกํ•œ ์ฒด์ธ, ์ž์œจ ์—์ด์ „ํŠธ ๋“ฑ)

3. ์˜ˆ์‹œ ์ฝ”๋“œ: RAG(๊ฒ€์ƒ‰ ์ฆ๊ฐ• ์ƒ์„ฑ) ๊ตฌํ˜„ ๋น„๊ต

๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ AI ๊ธฐ์ˆ ์ธ RAG๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋‘ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ์ฐจ์ด๋ฅผ ์ง์ ‘ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๐ŸŒฑ Spring AI ์˜ˆ์‹œ

application.properties์— ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋ชจ๋‘ ์„ค์ •ํ•˜๋ฉด, ์ฝ”๋“œ๋Š” ๋ฏฟ์„ ์ˆ˜ ์—†์„ ๋งŒํผ ๊ฐ„๊ฒฐํ•ด์ง‘๋‹ˆ๋‹ค.

application.properties

# ๋ชจ๋ธ ์„ค์ •
spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.chat.options.model=gpt-4o

# ๋ฒกํ„ฐ DB ์„ค์ • (PGVector ์‚ฌ์šฉ ์˜ˆ์‹œ)
spring.ai.vectorstore.postgres.host=localhost
spring.ai.vectorstore.postgres.database=mydb
# ...๊ธฐํƒ€ ์ ‘์† ์ •๋ณด

RagService.java

@Service
public class RagService {

    private final ChatClient chatClient;
    private final VectorStore vectorStore;

    // ๋ชจ๋“  Bean์ด ์ž๋™์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค.
    @Autowired
    public RagService(ChatClient chatClient, VectorStore vectorStore) {
        this.chatClient = chatClient;
        this.vectorStore = vectorStore;
    }

    public String answer(String question) {
        // 1. VectorStore์—์„œ ์œ ์‚ฌ๋„ ๊ฒ€์ƒ‰
        List<Document> similarDocs = vectorStore.similaritySearch(
            SearchRequest.query(question).withTopK(5)
        );

        // 2. ๊ฒ€์ƒ‰๋œ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ
        String documents = similarDocs.stream()
                .map(Document::getContent)
                .collect(Collectors.joining("\n"));

        PromptTemplate promptTemplate = new PromptTemplate("""
            ์ฃผ์–ด์ง„ ๋ฌธ์„œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์งˆ๋ฌธ์— ๋‹ต๋ณ€ํ•ด์ฃผ์„ธ์š”.
            ๋ฌธ์„œ: {documents}
            ์งˆ๋ฌธ: {question}
            """);
        Prompt prompt = promptTemplate.create(Map.of(
            "documents", documents, 
            "question", question
        ));

        // 3. LLM ํ˜ธ์ถœ
        return chatClient.call(prompt).getResult().getOutput().getContent();
    }
}

ํŠน์ง•: ๋งˆ์น˜ Spring Data JPA๋ฅผ ์‚ฌ์šฉํ•˜๋“ฏ, ์„ค์ •์€ ์™ธ๋ถ€ํ™”ํ•˜๊ณ  ์ฝ”๋“œ์—์„œ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ฃผ์ž…๋ฐ›์•„ ํ•ต์‹ฌ ๋กœ์ง์—๋งŒ ์ง‘์ค‘ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”— LangChain4j ์˜ˆ์‹œ (Spring Boot Starter ์‚ฌ์šฉ)

LangChain4j๋„ starter๋ฅผ ํ†ตํ•ด ์ž๋™ ์„ค์ •์„ ์ง€์›ํ•˜์ง€๋งŒ, AiService๋ผ๋Š” ์„ ์–ธ์  ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋กœ์ง์„ ๊ตฌ์„ฑํ•˜๋Š” ๋…ํŠนํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ๋ฐฉ์‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

application.properties

# langchain4j ์„ค์ •์€ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๊ฐ€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
langchain4j.chat-model.provider=openai
langchain4j.openai.chat-model.model-name=gpt-4o
# ...๊ธฐํƒ€ ์„ค์ •

Assistant.java (AI ์„œ๋น„์Šค ์ธํ„ฐํŽ˜์ด์Šค)

import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;

// ์ธํ„ฐํŽ˜์ด์Šค๋งŒ์œผ๋กœ RAG ๋กœ์ง์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
public interface Assistant {

    @SystemMessage("""
        You are a helpful assistant. Answer the following question
        based on the provided context: {{documents}}
    """)
    String chat(@UserMessage String question, @V("documents") String documents);
}

RagService.java

@Service
public class RagService {

    // AiServices๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋ฅผ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.
    private final Assistant assistant;
    private final ContentRetriever contentRetriever; // EmbeddingStoreContentRetriever๊ฐ€ ์ฃผ์ž…๋จ

    @Autowired
    public RagService(Assistant assistant, ContentRetriever contentRetriever) {
        this.assistant = assistant;
        this.contentRetriever = contentRetriever;
    }

    public String answer(String question) {
        // 1. ContentRetriever๋กœ ๊ด€๋ จ ๋ฌธ์„œ ๊ฒ€์ƒ‰
        List<Content> relevantContent = contentRetriever.retrieve(question);
        String documents = relevantContent.stream()
                .map(Content::text)
                .collect(Collectors.joining("\n\n"));

        // 2. AiService ํ˜ธ์ถœ
        return assistant.chat(question, documents);
    }
}

ํŠน์ง•: AiService๋ฅผ ํ†ตํ•ด AI์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋กœ์ง์„ ์„ ์–ธ์ ์œผ๋กœ ์ •์˜ํ•˜์—ฌ, ๋น„์ฆˆ๋‹ˆ์Šค ์ฝ”๋“œ์™€ AI ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ์šฐ์•„ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.


4. ๊ฒฐ๋ก : ์–ธ์ œ ๋ฌด์—‡์„ ์„ ํƒํ•ด์•ผ ํ• ๊นŒ?

๐ŸŒฑ Spring AI๋ฅผ ์„ ํƒํ•˜์„ธ์š”, ๋งŒ์•ฝ:

  • ์ด๋ฏธ ์Šคํ”„๋ง ์ƒํƒœ๊ณ„์— ๊นŠ์ด ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์ผ ๊ฒฝ์šฐ
  • ์›น API์— ์ฑ—๋ด‡, ์š”์•ฝ, ๋ฌธ์„œ Q&A ๋“ฑ 'AI ๊ธฐ๋Šฅ'์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์ผ ๊ฒฝ์šฐ
  • ๊ฐ€์žฅ ๋น ๋ฅด๊ณ  ๊ฐ„๊ฒฐํ•˜๊ฒŒ AI๋ฅผ ์—ฐ๋™ํ•˜๊ณ  ์‹ถ๊ณ , '์Šคํ”„๋ง๋‹ค์šด' ์ฝ”๋“œ ์Šคํƒ€์ผ์„ ์„ ํ˜ธํ•  ๊ฒฝ์šฐ

๐Ÿ”— LangChain4j๋ฅผ ์„ ํƒํ•˜์„ธ์š”, ๋งŒ์•ฝ:

  • AI๊ฐ€ ์Šค์Šค๋กœ ํŒ๋‹จํ•˜๊ณ  ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ณต์žกํ•œ ์ž์œจ ์—์ด์ „ํŠธ๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ
  • RAG ํŒŒ์ดํ”„๋ผ์ธ์„ ๋งค์šฐ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•˜๊ฑฐ๋‚˜ ๊ณ ๊ธ‰ ๊ฒ€์ƒ‰ ์ „๋žต์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ
  • ์Šคํ”„๋ง์ด ์•„๋‹Œ Quarkus, Micronaut ๋“ฑ ๋‹ค๋ฅธ Java ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์‚ฌ์šฉํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๊ฒฝ์šฐ

์ตœ์ข… ์ถ”์ฒœ

๋Œ€๋ถ€๋ถ„์˜ ์Šคํ”„๋ง ๋ถ€ํŠธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๋Š” Spring AI๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ ๊ฒฝํ—˜์ด ๋งค์šฐ ๋›ฐ์–ด๋‚˜๊ณ , ์ผ๋ฐ˜์ ์ธ AI ์—ฐ๋™ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ๋ชจ๋‘ ์ปค๋ฒ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ณ ๋„ํ™”๋˜์–ด Spring AI๋งŒ์œผ๋กœ ๋ถ€์กฑํ•œ ํŠน์ • ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•ด์ง„๋‹ค๋ฉด, ๊ทธ๋•Œ ๊ฐ€์„œ ๊ทธ ๋ถ€๋ถ„๋งŒ LangChain4j ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€๋กœ ๋„์ž…ํ•˜๋Š” ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ „๋žต์„ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
ยซ   2025/09   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
๋ฐ˜์‘ํ˜•
๊ธ€ ๋ณด๊ด€ํ•จ