AI & LLM

Spring AI 를 활용한 MCP 서버 구현 및 Claude AI에 적용하기

@deveely 2025. 10. 3. 03:37
반응형

1. MCP란?

  • Model Context Protocol의 약자로, AI 모델과 외부 데이터 소스를 연결하기 위한 표준 프로토콜
  • LLM이 외부 시스템의 데이터나 기능에 접근할 수 있도록 하는 개방형 표준입니다.
  • Tool과 Resource를 통해 AI가 실시간 데이터를 조회하거나 특정 작업을 수행할 수 있게 합니다.
  • 클로드 개발사인 Anthropic 이 주도하여 개발했으며, 다양한 언어의 SDK를 제공합니다.

MCP는 다양한 통신 방식을 지원하여 유연한 구현이 가능합니다.

  • HTTP 기반 JSON-RPC 방식으로 통신하며 STDIO(표준입출력), Streamable HTTP 방식을 지원합니다.
  • 초기에는 SSE(Server-Sent Events) 방식이 기본 스펙이었으나, Streamable HTTP로 변경되었고 SSE는 선택사항이 되었습니다.
  • MCP 서버가 원격지에 구성되어 있을 경우 표준입출력 통신이 불가능하기 때문에 HTTP 기반 통신방식을 사용할 수 있습니다.
  • 단일 endpoint만 제공해야 하며, 서버로 요청할 때는 POST 메서드를 사용해야 합니다.
  • MCP 서버는 클라이언트에세 서버가 제공하는 리소스, 프롬프트, 툴 목록과 설명을 제공합니다

상세한 스펙은 공식 문서를 참고하세요.

2. 간단한 MCP 서버 구현

간단한 MCP 서버를 구현하고 테스트해보고자 합니다.

마침 현재 여러 회사의 채용공고를 수집하여 제공하는 사이드 프로젝트를 운영하고 있습니다.

지금 DB에 수집되고 있는 채용정보를 LLM이 검색할 수 있도록 기능을 만들어서 제공하고, ChatGPT나 Claude 같은 서비스에서 사용할 것이기 때문에 Streamable HTTP 통신방식을 통해 구현해보겠습니다.

2.1 Resource vs Tool: 무엇을 선택할까?

MCP는 데이터 제공 방식에 따라 Resource와 Tool 두 가지 타입을 제공합니다.

Resource Tool

용도 정적이거나 반정형화된 데이터 제공 동적 데이터 조회 및 작업 수행
갱신주기 갱신되지 않거나 시간 / 일 단위로 느린 갱신 실시간 혹은 빠른 갱신
예시 Readme 파일, 정책 문서, 코드베이스 데이터베이스 검색, 주가 등 외부 데이터 검색, 데이터 변경 작업 수행

지금 구현하고자 하는 예시에서는 데이터베이스 조회를 통하기 때문에 Tool이 적합하다고 판단하였습니다.

2.2. Spring AI MCP 활용하기

MCP는 다양한 언어의 SDK를 제공하며, Java SDK도 그 중 하나입니다.

저는 이미 Spring Boot 기반으로 서비스를 운영 중이었고, 기존에 구현해둔 채용정보 검색 기능을 재사용하고 싶었습니다.

Spring AI 에서는 MCP 서버, 클라이언트를 쉽게 구현할 수 있도록 구현체를 제공합니다. MCP Java SDK를 래핑하여 Spring 환경에서 쉽게 사용할 수 있도록 해주며, 필요시 저수준 API(MCP Java SDK)도 그대로 활용할 수 있습니다.

3. 코드 작성

먼저 구현하고자 하는 방식에 맞는 적절한 starter 를 의존성을 추가해줍니다.

제 경우는 원격지에 서버를 구동시켜두고자 하여 웹 의존성이 있는 스타터를 사용하였습니다.

dependencies {
    implementation(platform("org.springframework.ai:spring-ai-bom:1.0.2"))
    implementation("org.springframework.ai:org.springframework.ai:spring-ai-starter-mcp-server-webmvc")
}

다음 아래와 같이 통신방식과 insturctions 를 설정해주었습니다.

가능한 모든 설정 목록은 공식문서를 확인하세요.

spring:
  application:
    name: mcp
  ai:
    mcp:
      server:
        protocol: stateless
        instructions: "XXX 서비스에서 제공하는 채용공고에 대한 검색 기능을 제공하는 MCP 서버"

@Tool 어노테이션만으로 간단히 MCP Tool을 구현할 수 있습니다.

description 에 툴에 대해 설명을 명시하고, ToolParam 으로 해당 툴의 파라미터를 명시하여줍니다.

내부 로직은 자유롭게 구현하면 Spring 이 MCP 서버 제공 스펙에 맞춰 변환해줍니다.

(아래 예시는 빠른 구현을 위해 DTO 없이 Map을 반환했습니다. 실제 프로덕션 환경에서는 명확한 응답 모델을 정의하는 것을 권장합니다.)

@Tool(description = """
    # Request
    - searchKeyword 로 채용공고를 검색합니다. 제목 기반 like 검색 결과를 반환합니다.
    - companyGroup 이 지정되면 해당 회사 그룹 내에서만 검색합니다.
    
    # Response
    - infoNo : 공고번호. fetch 툴에서 상세 정보를 조회할 때 사용합니다.
    - title : 공고 제목
    - companyGroup : 회사 그룹 (예: 네이버, 카카오)
    - startAt : 공고 시작일 (yyyy-MM-dd), null 일 경우 확인 불가 케이스
    - endAt : 공고 마감일 (yyyy-MM-dd), null 일 경우 확인 불가 케이스
    - jobCategory : 직군 (예: 개발, 디자인)
    - recruitmentLink : 공고 URL
""")
fun search(
    @ToolParam(
        description = "회사 enum 값을 참고하여 네이버 -> NAVER, 카카오 -> KAKAO 와 같이 Enum 값으로 요청해야합니다.", 
        required = false
    ) companyGroup: CompanyGroup?,
    @ToolParam(description = "검색 키워드") searchKeyword: String
): List<Map<String, Any?>> {
    val searchResult = recruitmentInfoRepository.findAllBySearchParams(
        RecruitmentInfoSearchParams(
            title = searchKeyword,
            companyGroup = companyGroup
        )
    )
    
    return searchResult.map {
        mapOf(
            "infoNo" to it.infoNo,
            "title" to it.title,
            "companyGroup" to it.companyGroup.nameKr,
            "startAt" to it.startAt?.let { date -> TimeUtils.format(date, "yyyy-MM-dd") },
            "endAt" to it.endAt?.let { date -> TimeUtils.format(date, "yyyy-MM-dd") },
            "jobCategory" to it.jobCategory,
            "recruitmentLink" to it.recruitmentLink
        )
    }
}

참고로 여기서 Tool은 Spring AI 에서 제공하는 Tool로 꼭 MCP로만 제공되지 않아도 됩니다. 아직 마일스톤 버전이지만 1.1.0 에서는 McpTool 과 같이 명시적으로 MCP 용 애노테이션들이 제공되는것으로 확인하였습니다.

구현은 위가 전부입니다.

4. Claude AI에 연결하기

다음 서버를 배포한 후 서비스에 추가해봅니다.

커스텀 커넥터에 MCP 서버 주소와 이름을 입력해줍니다.

 

아래와 같이 올바르게 추가된 것을 확인할 수 있습니다.

 

MCP 연결을 하고나면 LLM 이 연결된 MCP를 올바르게 인식하고 있는지 확인해볼수 있습니다.

 

다음은 툴이 올바르게 동작하는지 확인하기 위해 질문을 해봅니다.

 

의도한대로 MCP 적절히 활용하여 대답하는것을 확인할 수 있습니다.

질문을 잘 해석하고 파라미터도 적절하게 사용하여 요청하는게 아주 놀랍습니다.

마치며

MCP를 활용하여 LLM이 우리의 데이터에 매우 간단하게 접근하도록 할 수 있었습니다.

또한 Spring AI MCP를 사용하여 기존 Spring Boot 애플리케이션에 쉽고 자연스럽게 통합할 수 있어 사용경험도 괜찮았습니다.

단점이라면 MCP의 단점은 아니지만 Spring AI 는 이제 막 1.0.0 릴리즈 수준으로 극 초기 단계이다보니 완성도 면에서 성숙하지는 못한 단계라고 느꼈습니다. 이는 시간이 지나면서 차차 개선되길 기대해봅니다.

긴 글 봐주셔서 감사합니다.

반응형