표준화된 도구 통합 및 외부 API 활용 설계 - 100-hours-a-week/KTB4-4th-wiki GitHub Wiki

표준화된 도구 통합 및 외부 API 활용 설계

1단계는 백엔드와 AI 서버의 REST 계약을, 3단계는 데이터 소유권과 배포 경계를, 5단계는 취향 프로필로 상품을 찾는 검색 증강 추천을 정했다. 6단계는 이 기능을 외부 AI 에이전트가 어떻게 안전하게 사용하고, 니쥬가 외부 컨텍스트와 커머스 도구를 어디까지 이용할지를 정한다.

니쥬는 하나의 범용 Remote MCP 서버를 만들고 PlayMCP, Claude, ChatGPT 등 MCP를 지원하는 여러 AI Host에 같은 엔드포인트와 Tool 계약을 제공한다. 추천 Tool은 사용자 동의와 공개 범위 안에서 취향 요약, 어떤 물건이 적합한지에 대한 추천 의도, 니쥬가 보유한 실제 상품 후보를 한 번에 반환한다. MCP는 내부 REST를 대체하지 않고 외부 에이전트에 공개할 얇은 표준 어댑터로만 사용한다.

검증 기준일: 2026-09-14. MCP Host마다 지원 기능, 요금제, 관리자 설정과 결과 UI가 다르다. PlayMCP는 원격 Streamable HTTP 서버 등록을 지원하고, Claude는 Remote MCP custom connector를, ChatGPT는 MCP 기반 custom app 연결을 제공하지만 실제 사용 가능 범위는 계정·워크스페이스 정책에 따라 달라질 수 있다. 따라서 니쥬는 공통분모인 Tool, OAuth, structuredContent와 텍스트 폴백만 필수 계약으로 삼고 Host별 연결 시험을 통과한 경우에만 지원 대상으로 표시한다. 카카오 선물하기 도구의 상품 검색·구매 이동 범위 역시 tools/list와 실제 호출로 확인하기 전에는 가정하지 않는다.

설계 결론 프리뷰

MCP는 외부 진입점에만 둔다

flowchart LR
    U["사용자"] --> H["MCP Host<br/>PlayMCP · Claude · ChatGPT · 기타"]
    H -->|"① 취향 기반 추천 요청"| N["니쥬 Remote MCP"]
    N -->|"② 취향 요약 + 추천 의도<br/>+ 실제 상품 + 다음 행동"| H
    H -->|"③ Host 방식으로 설명·카드·링크 표시"| U

    subgraph OPTIONAL["Host가 선택적으로 조합"]
        K["커머스 MCP<br/>카카오 선물하기 등"]
        C["캘린더 · 지도 MCP"]
    end

    H -."검색·구매 이동".-> K
    H -."기념일·지역의 최소값".-> C

    subgraph NIJU["니쥬 서비스"]
        MG["mcp-gateway<br/>Streamable HTTP"]
        BE["Spring Backend<br/>프로필 · 추천 · 권한 소유"]
        AI["AI Server<br/>추천 생성"]
    end

    N --- MG
    MG -->|"내부 REST"| BE
    BE -->|"기존 계약"| AI

    W["기상청 API"] -."비동기 갱신".-> WC[("컨텍스트 캐시")]
    WC -."선택적 snapshot".-> BE
Loading

설계 판단

질문 결정
니쥬 자체 MCP를 만드는가 만든다. 추천을 외부 에이전트가 재사용할 수 있는 제품 경계이기 때문이다
내부 서비스 통신도 MCP로 바꾸는가 바꾸지 않는다. 백엔드·AI 서버의 REST 계약은 이미 명확하고 MCP로 바꿀 실익이 없다
MCP 서버가 AI 서버 DB를 직접 읽는가 읽지 않는다. 사용자 데이터와 추천 리스트를 소유한 Spring Backend만 호출한다
MCP 호출 때 추천을 새로 생성하는가 생성하지 않는다. 활성 상태의 최신 추천 리스트를 조회한다
결과에 취향과 상품 중 무엇을 보내는가 둘 다 보낸다. 단, 전체 프로필이 아니라 외부 공유용 요약과 추천에 필요한 공개 신호만 보낸다
추천할 물건 유형과 실제 상품을 분리하는가 응답 안에서 recommendationIntents와 items로 분리해 함께 보낸다
니쥬 MCP가 선물하기 API를 직접 호출하는가 초기에는 호출하지 않는다. 가능한 Host가 니쥬와 커머스 MCP를 조합한다
결제·선물 발송을 자동 실행하는가 하지 않는다. 상품 후보를 보여주고 사용자가 확인한 뒤 공식 화면으로 넘긴다
날씨 API를 대화의 필수 단계로 넣는가 넣지 않는다. 캐시된 임시 컨텍스트만 선택적으로 주입한다

MCP를 도입하는 이유는 REST 호출을 한 번 더 감싸기 위해서가 아니다. tools/list로 기능을 발견하고, JSON Schema로 입력을 제한하며, PlayMCP·ChatGPT·Claude 같은 호스트에서 같은 추천 기능을 호출할 수 있게 만드는 것이 목적이다.

왜 니쥬를 MCP로 제공하는가

취향 분석 결과를 앱 화면 밖의 기능으로 만든다

MCP가 없으면 니쥬의 취향 분석과 추천은 니쥬 앱 화면에서만 소비된다. MCP로 제공하면 사용자는 다른 AI 서비스에서 자연어로 니쥬의 추천 기능을 호출할 수 있다.

앱 전용 구조
사용자 → 니쥬 앱 진입 → 친구 선택 → 추천 목록 확인 → 선물하기 이동

범용 MCP 구조
사용자 → 사용 중인 AI에게 선물 요청
       → 니쥬가 취향 요약 + 추천 물건 유형 + 실제 상품 제공
       → Host가 설명·상품 카드·링크를 표시
       → 필요하면 Host가 연결된 커머스 도구로 추가 탐색

새로운 추천 알고리즘을 만드는 것이 아니라, 이미 검증한 추천 기능을 사용자가 있는 채널로 확장하는 것이다. 모바일 화면, PlayMCP 대화, 다른 MCP Host가 같은 활성 추천 버전을 읽으므로 채널마다 추천 로직이 갈라지지 않는다.

추천에서 실제 행동까지의 단절을 줄인다

니쥬의 핵심 산출물은 상품명 목록만도, 해석되지 않은 프로필만도 아니다. profileContext는 왜 이 추천이 맞는지, recommendationIntents는 어떤 물건을 찾으면 되는지, items는 지금 선택할 수 있는 실제 후보가 무엇인지를 담당한다. 세 정보를 함께 반환해야 외부 AI가 니쥬의 취향을 다시 추측하지 않고도 추천을 설명하거나 다른 커머스 도구로 탐색을 이어갈 수 있다.

공개용 취향 요약
→ 추천 물건 유형과 필수 조건
→ 니쥬 실제 상품 후보
→ 필요한 경우 외부 커머스 재탐색
→ 사용자 확인
→ 공식 구매 화면

니쥬는 취향 해석과 추천 근거를 담당하고, 각 커머스 서비스는 최신 판매·재고·구매 경험을 담당한다. PlayMCP에서는 카카오 선물하기와 이어질 수 있고, Claude·ChatGPT 등에서는 니쥬 상품 링크를 보여주거나 해당 Host에 연결된 다른 커머스 도구와 이어질 수 있다. 특정 사업자에 종속되지 않으면서 하나의 사용자 요청으로 연결되는 것이 MCP를 적용하는 가장 직접적인 이유다.

전체 프로필 대신 필요한 기능만 공개한다

외부 AI가 추천을 이용한다고 해서 TasteProfile 전체를 읽을 필요는 없다. MCP Tool은 다음과 같이 공개 범위를 기능 단위로 좁힌다.

외부 AI가 필요한 것 니쥬가 제공하는 것 제공하지 않는 것
내 추천 확인 외부 공유용 취향 요약, 추천 물건 유형, 활성 상품과 공개 이유 대화 원문과 추출 중간값
친구 선물 추천 친구가 별도로 공개한 요약과 gift 결과 친구의 전체 취향·알레르기·기피 이유
외부 커머스 검색 검색어·카테고리·가격대·필수 상품 특성 프로필 원본과 민감 제약
피드백 반영 허용된 피드백 종류와 처리 결과 랭킹 내부 가중치와 다른 사용자 데이터

REST API를 그대로 외부에 공개하면 에이전트가 내부 DTO와 사용자 식별자를 알아야 한다. MCP Tool은 모델이 사용할 수 있는 이름·설명·입력 스키마를 제공하면서, 실제 사용자 식별과 권한 검사는 서버 안에 감춘다.

도구 조합의 책임을 Host에 둔다

니쥬가 카카오의 캘린더, 지도, 선물하기 API를 모두 직접 연동하면 공급자별 토큰과 장애가 니쥬 서버에 집중된다. MCP에서는 사용자가 허용한 도구를 Host가 각각 호출한다.

MCP Host
├─ 니쥬: 취향 요약 + 추천 의도 + 실제 후보
├─ 캘린더·지도: 기념일과 지역 맥락(선택)
└─ 커머스: 실제 판매 상품 탐색과 공식 화면 이동(선택)

PlayMCP 조합 예시
└─ 니쥬 + 톡캘린더 + 카카오맵 + 카카오 선물하기

니쥬는 다른 MCP 서버의 계정 토큰을 보관하지 않고, 외부 서비스 하나의 장애가 니쥬 추천 조회를 실패시키지 않는다. 새로운 도구를 붙일 때도 니쥬 추천 파이프라인을 수정하기보다 Host의 조합 순서를 확장할 수 있다.

니쥬의 추천 방식이 MCP Tool에 적합하다

니쥬의 특성 MCP에 적합한 이유
추천을 미리 생성해 저장 Tool 호출 중 LLM과 벡터 검색을 기다리지 않는다
self와 gift 출력이 구조화됨 JSON Schema로 입력·출력을 명확히 정의할 수 있다
추천 버전과 productId가 존재 호출 결과를 재현하고 피드백 대상을 추적할 수 있다
친구 공개 범위가 Backend에 있음 모델이 아니라 서버가 접근권한을 강제할 수 있다
추천 조회는 읽기 중심 반복 호출의 부작용이 작고 캐시하기 쉽다
구매는 니쥬 책임이 아님 추천 Tool과 외부 구매 행동을 분리할 수 있다

다른 연결 방식과 비교한다

방식 장점 한계 판단
니쥬 앱만 제공 구현이 가장 단순함 다른 AI와 도구가 추천을 재사용할 수 없음 기본 채널로 유지
선물하기 딥링크만 제공 이동 구현이 단순함 취향 추천과 상품 검색 과정이 구조적으로 연결되지 않음 최종 이동의 폴백
외부 AI마다 전용 REST 연동 각 채널을 세밀하게 제어 채널마다 인증·문서·어댑터를 반복 구현 채택하지 않음
니쥬 MCP 제공 도구 발견, 구조화 계약, 권한 기반 호출, Host 조합 공개 서버와 OAuth 운영 필요 외부 AI 연결의 기본 방식

MCP가 REST보다 항상 우수해서 선택하는 것은 아니다. 호출자가 고정된 내부 통신은 REST가 단순하고, 호출 모델과 Host가 달라지는 외부 경계는 MCP의 발견·스키마·조합 기능이 유효하다.

외부 시스템과 상호작용하는 시나리오

시나리오 시스템 호출 목적 사용자 대기 경로 판단
내 취향 맥락 조회 니쥬 MCP 외부 대화에서 쓸 수 있는 내 공개용 취향 요약 조회 포함 1차 구현
내 추천 조회 니쥬 MCP 내 취향 요약·추천 의도·최신 self 또는 gift 상품을 함께 조회 포함 1차 구현
친구에게 줄 선물 추천 니쥬 MCP 친구가 외부 공유를 허용한 요약과 gift 상품을 함께 조회 포함 1차 구현
커머스 상품 탐색 Host에 연결된 커머스 MCP 니쥬의 공급자 중립 검색 계획을 실제 판매 상품 탐색으로 연결 포함 도구 능력 확인 후 구현
구매 화면 이동 커머스 MCP 또는 상품의 공식 URL 사용자가 최종 선택한 상품의 공식 화면 열기 포함 명시적 사용자 확인 필수
날씨 맥락 기상청 단기예보 API 우천·폭염·한파·기온 같은 일시적 사용 상황 보강 제외 선택 도입
기념일 맥락 톡캘린더 API 선물 시기와 행사 유형 보강 호스트가 별도 호출 2차 검토
추천 공유 카카오톡 공유·메시지 API 추천 결과 URL 공유 별도 사용자 행동 2차 검토

외부 맥락은 추천의 보조 신호다. 사용자의 장기 취향과 섞지 않는다. 예를 들어 오늘 비가 온다는 사실은 TasteProfile에 저장하지 않고 만료 시간이 있는 ContextSnapshot으로만 사용한다.

범용 MCP Host와 니쥬의 역할

Host는 대화를 조율하고 니쥬는 추천 데이터를 제공한다

sequenceDiagram
    actor U as 사용자
    participant H as MCP Host
    participant N as 니쥬 MCP
    participant B as 니쥬 Backend
    participant G as 선택적 커머스 MCP

    U->>H: 민수에게 5만원 이하 선물 추천해줘
    H->>N: get_friend_gift_recommendations(recipientKey, budget)
    N->>B: 인증 주체와 친구 접근권한으로 최신 gift 조회
    B-->>N: 공개용 취향 요약 + 추천 의도 + 상품
    N-->>H: structuredContent + text fallback

    alt Host에 커머스 검색 도구가 연결됨
        H->>G: 확인된 도구 스키마로 상품 검색
        G-->>H: 판매 중인 상품 후보 또는 공식 이동 정보
    else 상품 검색 도구가 없음
        H->>H: 니쥬 결과와 허용된 구매 링크 표시
    end

    H-->>U: 후보 비교와 이동 전 확인
    U->>H: 이 상품 구매 페이지 열어줘
    H->>G: 공식 화면 이동 요청
    G-->>U: 공식 커머스 화면
Loading

MCP 서버끼리 서로의 토큰을 넘겨 호출하지 않는다. 여러 도구를 가진 Host가 순서를 정하고 각각의 권한으로 호출한다. 이 구조는 니쥬가 카카오 계정 토큰이나 다른 커머스 권한을 보관하지 않게 한다.

Host별로 바뀌는 것은 표시 방식이지 추천 계약이 아니다

Host 니쥬 연결 방식 니쥬가 보장하는 것 별도 확인이 필요한 것
PlayMCP Remote Streamable HTTP 서버 등록 동일 Tool·OAuth·구조화 응답 등록 정책, 카카오 도구 조합 범위
Claude Remote MCP custom connector 동일 Tool·OAuth·구조화 응답 계정 플랜, connector와 UI 지원 범위
ChatGPT MCP 기반 custom app 동일 Tool·OAuth·구조화 응답 워크스페이스 설정, 앱 배포·검토 범위
기타 MCP Host 같은 /mcp 엔드포인트 표준 Tool과 텍스트 폴백 프로토콜 버전·인증·UI 호환성

첨부 화면과 같은 경험은 프로토콜과 UI를 구분해서 설계한다.

화면 요소 MCP 응답 필드 책임
“방수·휴대성·2~3인 크기를 우선” 같은 설명 profileContext.summary, recommendationIntents 니쥬가 의미를 제공하고 Host가 문장으로 표현
이미지·상품명·가격 카드 items.imageUrl, name, price, shortDescription 니쥬가 구조화 데이터 제공, Host가 가능한 UI로 렌더링
1순위와 추천 이유 items.rank, reason, matchedSignals 니쥬 랭킹 결과를 Host가 설명
구매 이동 items.purchaseUrl 또는 nextActions 사용자가 선택한 후 Host가 공식 URL 또는 커머스 Tool 사용

MCP만으로 모든 Host에서 동일한 카드 모양을 강제할 수는 없다. 이미지 자체를 매번 바이너리로 실어 보내면 지연과 응답 크기가 커지므로 초기 버전은 허용 도메인의 HTTPS imageUrl을 반환한다. 카드를 지원하지 않는 Host에서도 내용을 잃지 않도록 상품명·가격·이유를 content 텍스트로 함께 반환한다.

선물하기 연동 수준은 확인된 능력으로 판정한다

선물하기 MCP에서 확인된 기능 니쥬 연동 수준 처리
상품 검색 + 공식 상품 식별자 완전한 탐색 연동 니쥬의 recommendationIntents·nextActions를 선물하기 검색 입력으로 전달
보유·수령 선물 조회만 가능 추천 조회 연동만 받은 선물과 중복 확인 같은 보조 용도로만 사용
구매 화면 URL 또는 딥링크 제공 구매 이동 연동 최종 상품 확인 뒤 공식 화면을 연다
결제·발송 실행 도구 제공 초기 범위 제외 금액·수령인·상품 최종 확인과 별도 위험 검토 전에는 호출하지 않는다
필요한 기능이 없음 연동 보류 니쥬 추천까지만 제공하고 지원한다고 표현하지 않는다

공식 도구가 제공하는 입력 스키마에 니쥬를 맞춘다. 도구 이름이나 파라미터를 추측해서 코드에 먼저 고정하지 않는다.

니쥬 MCP 서버 경계

공개 어댑터를 별도 배포한다

mcp-gateway는 외부 인바운드를 받는 무상태 서비스다. 사용자 데이터와 추천 로직을 갖지 않고, 인증된 도구 호출을 내부 REST 요청으로 변환한다.

flowchart LR
    P["PlayMCP · Claude · ChatGPT<br/>기타 MCP Host"] -->|"HTTPS · Streamable HTTP"| M["mcp-gateway"]
    M --> A["OAuth 토큰 검증<br/>scope · audience"]
    A --> Z["입력 스키마 검증<br/>크기 · enum · limit"]
    Z --> B["Backend Client Port"]
    B -->|"mTLS 또는 서비스 토큰"| S["Spring Backend"]
    S --> ACL["사용자 · 친구 ACL"]
    S --> R["활성 추천 리스트"]

    M --> O["도구 호출 감사 로그<br/>원문·프로필 제외"]
Loading

이 분리는 기존 3단계의 소유권 결정을 유지한다.

데이터 소유 MCP에서의 처리
계정·친구 관계 Spring Backend 토큰 주체와 recipientKey의 접근권한만 확인
TasteProfile 원본 Spring Backend MCP 출력으로 제공하지 않음
외부 공유용 취향 요약 Spring Backend 본인 동의 또는 친구 소유자의 별도 공개 설정이 있을 때 최소 필드만 반환
추천 리스트 Spring Backend 활성 최신 버전만 조회. 비활성 이력은 외부에 노출하지 않음
추천 생성·랭킹 AI Server MCP 호출 중 실행하지 않음
MCP 세션 상태 없음 초기 서버는 Stateless Streamable HTTP로 운영
외부 API 키 Secret Manager 도구 결과나 로그에 포함하지 않음

내부 REST를 유지하는 이유

  • Spring Backend와 AI Server의 계약은 서비스 전용이고 이미 버전이 관리된다.
  • MCP는 모델이 발견하고 호출하는 공개 도구 표면이다. 내부 서비스 간 호출은 호출자가 고정되어 있어 발견 기능이 필요 없다.
  • 내부까지 MCP로 바꾸면 장애 지점, 프로토콜 버전, 인증 경로만 늘어난다.
  • MCP가 바뀌어도 추천 생성 파이프라인과 모바일 앱이 영향을 받지 않아야 한다.

MCP 도구 설계

초기 버전은 Tool만 제공한다. TasteProfile을 Resource로 노출하면 Host가 필요 이상으로 전체 취향을 반복 조회할 수 있고, Prompt는 니쥬 도구 없이도 Host가 작성할 수 있어 추가하지 않는다. 추천 Tool은 취향·추천 유형·상품을 하나의 원자적 응답으로 묶어 서로 다른 프로필 버전이 섞이는 문제와 추가 왕복 호출을 피한다.

도구 목록

Tool 성격 역할 사용자 확인
get_my_preference_context 읽기 외부 대화에서 사용할 내 공개용 취향 요약만 조회 preference-summary:read:self 연결 동의
get_my_recommendations 읽기 내 공개용 취향 요약·추천 의도·최신 self 또는 gift 상품을 함께 조회 연결 동의
get_friend_gift_recommendations 읽기 친구의 공개용 요약·추천 의도·gift 상품을 함께 조회 호출자 동의 + 친구 소유자의 외부 공유 설정 + 친구 ACL
record_recommendation_feedback 쓰기 좋아요·싫어요·이미 보유함 등 명시적 피드백 저장 호출 직전 확인

결제, 선물 발송, 프로필 원문 조회, 대화 원문 조회 도구는 만들지 않는다.

추천 요청에서는 profileContext, recommendationIntents, items를 항상 함께 반환한다. get_my_preference_context는 상품 추천이 아닌 일반 대화 개인화가 필요할 때만 쓰며, 친구 프로필만 단독 조회하는 Tool은 만들지 않는다.

추천 Tool의 입력 계약

{
  "name": "get_friend_gift_recommendations",
  "description": "니쥬에서 접근 권한이 있는 친구의 공개용 선물 추천을 조회한다. 상품을 구매하거나 발송하지 않는다.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "recipientKey": { "type": "string", "maxLength": 64 },
      "budgetMax": { "type": "integer", "minimum": 1000 },
      "occasion": {
        "type": "string",
        "enum": ["birthday", "anniversary", "thanks", "casual", "other"]
      },
      "usageContext": { "type": "string", "maxLength": 200 },
      "limit": { "type": "integer", "minimum": 1, "maximum": 10, "default": 3 },
      "cursor": { "type": "string", "maxLength": 256 }
    },
    "required": ["recipientKey"],
    "additionalProperties": false
  }
}

get_my_recommendations는 recipientKey 없이 mode(self 또는 gift), budgetMax, occasion, usageContext, limit, cursor를 받는다. userId는 어떤 Tool에서도 입력으로 받지 않는다. 호출자는 액세스 토큰의 sub에서 구하고, 친구 관계와 공개 범위를 Backend가 확인한다. 모델이 다른 사용자 ID를 만들어 넣어 권한을 우회할 수 없어야 한다.

DB에는 self와 gift 활성 목록을 각각 최대 20개 보관하되, 대화 응답은 기본 3개·최대 10개만 반환한다. 더 필요한 Host는 불투명한 nextCursor로 다음 페이지를 요청한다. 이는 화면과 토큰 크기를 제한할 뿐 기존 추천 저장 구조를 바꾸지 않는다.

추천 Tool의 출력 계약

Tool 정의에는 아래 구조와 동일한 outputSchema를 선언하고 서버와 Host가 검증한다. 아래 예시는 structuredContent의 값이다. 실제 MCP 결과는 이 객체를 structuredContent에 넣고, 하위 호환성을 위해 같은 객체를 compact JSON으로 직렬화한 TextContent도 content에 함께 넣는다.

{
    "schemaVersion": "niju.recommendation.v1",
    "subject": {
      "type": "friend",
      "displayName": "민수"
    },
    "profileContext": {
      "summary": "야외 활동을 즐기고, 실용적이며 휴대하기 쉬운 물건을 선호합니다.",
      "tasteKeywords": ["실용적", "휴대성", "미니멀"],
      "interests": ["캠핑", "커피"],
      "visibility": "external_gift_summary",
      "profileVersion": "profile-v12",
      "generatedAt": "2026-09-14T08:30:00Z"
    },
    "requestContext": {
      "mode": "gift",
      "occasion": "birthday",
      "budget": { "maxAmount": 50000, "currency": "KRW" },
      "usageContext": "가벼운 야외 활동"
    },
    "recommendationIntents": [
      {
        "intentId": "intent_1",
        "label": "휴대용 커피 도구",
        "description": "야외에서도 번거롭지 않게 커피를 즐길 수 있는 물건",
        "priority": 1,
        "requiredTraits": ["휴대성", "세척 용이", "5만원 이하"],
        "categoryHints": ["커피용품", "캠핑용품"],
        "searchQuery": "휴대용 커피 드리퍼 캠핑 5만원 이하"
      }
    ],
    "items": [
      {
        "recommendationId": "r_51",
        "productId": "p_102",
        "intentId": "intent_1",
        "rank": 1,
        "name": "휴대용 커피 드리퍼",
        "category": "커피용품",
        "price": { "amount": 32000, "currency": "KRW" },
        "imageUrl": "https://cdn.needu.example/p_102.jpg",
        "sellerName": "판매자명",
        "purchaseUrl": "https://shop.example/products/p_102",
        "shortDescription": "접어서 휴대할 수 있는 야외용 드리퍼",
        "reason": "캠핑 관심사와 휴대성을 중시하는 취향에 맞습니다.",
        "matchedSignals": ["캠핑", "휴대성"]
      }
    ],
    "nextActions": [
      {
        "type": "commerce_search",
        "label": "다른 판매 상품도 찾아보기",
        "searchQuery": "휴대용 커피 드리퍼 캠핑 5만원 이하",
        "categoryHints": ["커피용품", "캠핑용품"]
      },
      {
        "type": "open_url",
        "label": "1순위 상품 보기",
        "url": "https://shop.example/products/p_102"
      }
    ],
    "metadata": {
      "recommendationVersion": "gift-v7",
      "rankerVersion": "rar-v1",
      "generatedAt": "2026-09-14T09:00:00Z",
      "expiresAt": "2026-09-15T09:00:00Z",
      "resultCount": 3,
      "nextCursor": null
    }
}
응답 영역 필수 여부 포함 정보 외부 공개 원칙
content 필수 structuredContent와 같은 객체의 compact JSON 직렬화 구조화 결과를 지원하지 않는 Host의 하위 호환
schemaVersion 필수 니쥬 응답 계약 버전 MCP 프로토콜 버전과 별도로 관리
subject 필수 self/friend, 표시 이름 내부 사용자 ID는 제외
profileContext 필수 요약, 취향 키워드, 관심사, 프로필 버전 외부 공유 허용 필드만 포함
requestContext 필수 추천 모드, 예산, 용도, 기념일 이번 호출에만 쓰고 장기 취향으로 병합하지 않음
recommendationIntents 필수 추천할 물건 유형, 필수 특성, 검색어, 우선순위 판매처와 무관한 표현 사용
items 필수 실제 상품, 가격, 이미지·구매 URL, 순위·이유 활성 목록에서만 선택, 결과가 없으면 빈 배열 허용
nextActions 선택 추가 검색 또는 공식 URL 열기 실행·결제 명령이 아닌 제안
metadata 필수 추천·랭커 버전, 생성·만료 시각, cursor 재현·캐시·페이지 처리에 사용

profileContext는 외부 AI가 추천 이유를 설명할 만큼만 제공하고 내부 TasteProfile을 복제하지 않는다. 정확한 confidence, 대화 원문, 추출 중간값, 알레르기, 비공개 기피 조건은 넣지 않는다. 알레르기와 기피 조건은 니쥬 내부에서 후보를 제외하는 데만 사용한다. recommendationIntents는 특정 판매처 ID가 아닌 물건의 종류와 조건을 표현하므로 어느 Host든 추가 검색에 사용할 수 있다. items는 니쥬가 이미 확보한 상품 후보이며 URL과 이미지 도메인은 allowlist로 검증한다.

nextActions는 실행 명령이 아니라 Host가 선택할 수 있는 다음 행동의 데이터다. commerce_search를 카카오 선물하기나 다른 커머스 Tool로 변환할지는 Host의 연결 도구와 사용자 요청에 달려 있다. 결제·발송 파라미터는 포함하지 않는다.

프로토콜 수준의 공통 계약

구분 니쥬 MCP 계약 이유
전송 HTTPS Remote Streamable HTTP, 초기 구현은 stateless 여러 외부 Host가 같은 공개 엔드포인트를 호출하고 수평 확장하기 쉬움
발견 tools/list에 이름·설명·inputSchema·outputSchema 제공 모델이 임의 파라미터를 만들지 않도록 함
호출 tools/call 표준 MCP 호출 흐름 유지
구조화 결과 structuredContent 프로필 요약·의도·상품을 Host가 안정적으로 파싱
호환 결과 같은 객체를 직렬화한 content의 TextContent 구조화 결과를 지원하지 않는 Host와 이전 구현의 폴백
이미지 초기에는 검증된 HTTPS imageUrl 이미지 바이너리 전송에 따른 응답 크기·지연 방지
버전 응답의 schemaVersion과 MCP 버전 협상 프로토콜 버전과 니쥬 도메인 스키마 버전을 분리
오류 isError: true와 안정적인 응용 오류 코드 모델이 자연어 오류를 성공 결과로 오인하지 않게 함

대표 오류 코드는 NOT_AUTHENTICATED, NOT_AUTHORIZED, NOT_ACCESSIBLE, NO_ACTIVE_RECOMMENDATION, INVALID_ARGUMENT, UPSTREAM_TIMEOUT으로 제한한다. 친구가 존재하지 않는 경우와 권한이 없는 경우는 모두 NOT_ACCESSIBLE로 반환해 사용자 열거를 막는다. outputSchema가 있는 Tool의 structuredContent는 반드시 그 스키마를 만족한다. JSON 중복 비용은 존재하지만 기본 결과를 3개로 제한하고 이미지 바이너리를 보내지 않아 호환성을 우선한다.

인증과 권한 모델

사용자별 비공개 추천을 제공하는 니쥬는 공용 API Key가 아니라 MCP 원격 인증 규격에 맞춘 OAuth 2.1 Authorization Code + PKCE 기반 연결을 사용한다. Host마다 화면과 등록 절차가 달라도 토큰 대상은 니쥬 MCP이며 권한 검증 규칙은 같다.

sequenceDiagram
    actor U as 사용자
    participant P as MCP Host
    participant A as 니쥬 Authorization Server
    participant M as 니쥬 MCP

    U->>P: 니쥬 도구 연결
    P->>A: Authorization Code + PKCE
    A->>U: 니쥬 로그인과 scope 동의
    U-->>A: 승인
    A-->>P: authorization code
    P->>A: code + verifier 교환
    A-->>P: audience가 니쥬 MCP인 access token
    P->>M: tools/call + access token
    M->>M: 서명 · 만료 · audience · scope 검증
Loading

Scope

Scope 허용 기능
preference-summary:read:self 내 외부 공유용 취향 요약 조회
recommendations:read:self 내 self·gift 추천 조회
recommendations:read:friends 친구가 공개한 gift 추천 조회
recommendations:feedback 추천 피드백 기록

profile:read:raw, chat:read, purchase:write 같은 scope는 만들지 않는다. 도구가 존재하지 않으면 해당 권한도 요청할 이유가 없다.

보안 규칙

  • 액세스 토큰의 서명, 만료, 발급자, audience, scope를 매 호출 검증한다.
  • 어느 Host에서 받은 토큰도 카카오 선물하기나 다른 외부 API로 전달하지 않는다.
  • 친구 접근권한은 토큰 scope만으로 결정하지 않고 Backend의 현재 친구 관계와 친구 소유자의 externalGiftSummaryEnabled 설정을 매번 확인한다.
  • 도구 결과에는 대화 원문과 전체 프로필을 넣지 않는다.
  • 호출 로그에는 toolName, 익명화된 주체, 결과 개수, 지연, 오류 코드만 남긴다.
  • 쓰기 도구는 멱등 키를 받고, 호스트에서 사용자 확인 후 호출하도록 명시한다.
  • 외부 URL은 허용된 상품·이미지 도메인만 반환해 임의 URL 실행과 SSRF 경로를 막는다.
  • 외부 도구 결과의 자연어는 명령으로 신뢰하지 않고 데이터로 취급한다.

MCP 표준은 원격 HTTP 인증에서 OAuth 2.1 계열의 보호 리소스 메타데이터와 토큰 대상 검증을 요구한다. Host가 지원하는 프로토콜 버전과 메타데이터 형식은 연결 테스트에서 확정하고 호환성 매트릭스로 관리한다. 동의 철회 또는 친구 공개 설정 변경은 다음 호출부터 즉시 반영하고, 이미 외부 Host로 전달된 데이터의 보존 정책은 연결 동의 화면에 명시한다.

외부 API와 컨텍스트 보강

날씨는 영구 프로필이 아니라 임시 컨텍스트다

날씨가 추천에 의미가 있는 경우는 제한적이다.

사용자 상황 사용할 날씨 신호 가능한 효과
오늘 또는 며칠 안에 사용할 선물 강수, 기온, 특보 실내·야외 사용 맥락의 약한 재정렬
야외 취미 상품 비·눈·폭염·한파 당장 사용하기 어려운 상품의 과도한 노출 방지
계절성 선물 최저·최고기온 보온·냉감 상품의 맥락 보강
날짜·지역이 없는 일반 취향 분석 없음 날씨를 호출하지 않음

날씨로 사용자의 취향을 추론하지 않는다. 날씨는 관련 상품에 작은 컨텍스트 가중치를 주는 용도이며 기본 취향 유사도를 뒤집지 않는다. 정확한 가중치는 골드셋으로 검증하기 전에는 확정하지 않는다.

{
  "type": "weather",
  "regionKey": "11B10101",
  "observedAt": "2026-09-14T09:00:00+09:00",
  "validUntil": "2026-09-14T10:00:00+09:00",
  "signals": {
    "temperatureC": 24,
    "precipitationType": "rain",
    "severeAlert": false
  }
}

ContextSnapshot은 TTL이 지나면 사용하지 않으며 TasteProfile이나 장기 피드백에 병합하지 않는다.

기상청 API를 우선 검토한다

기상청 API허브는 초단기·단기예보의 기온, 강수형태, 강수량, 습도와 특보를 제공한다. 일반회원 기준 안내 호출량은 일 20,000건이고 무료지만 인증키 발급과 이용조건 확인이 필요하다.

항목 설계
Provider 기상청 단기예보 API
위치 정밀도 정확한 GPS를 저장하지 않고 시·군·구 또는 예보 격자 키 사용
캐시 키 regionKey + forecastSlot
Fresh TTL 60분. 실제 발표 주기와 사용 API에 맞춰 조정
Stale 허용 최대 6시간, 응답에 stale: true 표시
Foreground cache miss 외부 호출을 기다리지 않고 날씨 없이 진행
갱신 백그라운드 단일 비행 요청. 같은 키의 중복 호출 병합
재시도 백그라운드의 멱등 GET만 지수 백오프와 jitter로 1회
실패 추천·대화 성공 여부에 영향 없음

대화 경로에서 외부 API를 기다리지 않는다

sequenceDiagram
    participant B as Backend
    participant C as Context Cache
    participant W as Weather API
    participant A as AI API

    B->>C: 지역·시간 snapshot 조회
    alt fresh cache hit
        C-->>B: ContextSnapshot
        B->>A: 대화 요청 + snapshot
    else stale hit
        C-->>B: stale snapshot
        B->>A: 대화 요청 + stale 표시
        B-->>W: 비동기 갱신
    else cache miss
        C-->>B: 없음
        B->>A: 대화 요청, 날씨 생략
        B-->>W: 비동기 갱신
    end
Loading

모델이 응답을 생성하다가 날씨 Tool을 호출하게 하지 않는다. Backend가 구조화된 snapshot을 준비한 경우에만 프롬프트의 선택 블록으로 주입한다. 따라서 외부 API 지연과 장애가 SSE TTFT에 더해지지 않는다.

[OPTIONAL_CONTEXT]
type=weather
region=서울
validUntil=2026-09-14T10:00:00+09:00
precipitation=rain
temperatureBand=mild
instruction=현재 사용 상황을 묻거나 답할 때만 참고하고 장기 취향으로 저장하지 말 것

캘린더와 지도는 호스트 조합을 우선한다

캘린더와 지도 도구가 해당 Host에 함께 연결되어 있다면 니쥬 MCP가 그 도구를 직접 호출하지 않는다. 사용자가 기념일이나 지역 정보를 제공하도록 동의했을 때 Host가 최소값만 니쥬 도구 입력으로 넘긴다. PlayMCP에서는 톡캘린더·카카오맵이 그 예가 될 수 있다.

캘린더 원문 전체 → 니쥬 전달 금지
필요한 최소값      → occasion=birthday, daysUntil=5

정확한 현재 위치   → 니쥬 장기 저장 금지
필요한 최소값      → region=서울, contextTtl=1h

캘린더 도구가 없거나 권한이 없으면 사용자가 occasion을 직접 입력하면 된다. 외부 도구 부재 때문에 추천 기능이 막히지 않는다.

지연과 병목 방지

MCP 요청은 조회 경로다

추천은 프로필 확정 시 미리 생성해 Backend에 저장한다. MCP 호출에서 LLM, 임베딩, pgvector 검색을 다시 실행하지 않는다.

MCP tools/call
→ 토큰 검증
→ 입력 검증
→ Backend의 활성 추천 조회
→ 공개 필드 투영
→ 구조화 응답

초기 성능 예산

구간 초기 목표 초과 시 처리
MCP 인증·스키마 검증 p95 50ms 이하 토큰 검증키 캐시 확인
MCP → Backend 네트워크 p95 100ms 이하 같은 리전 배치, keep-alive
Backend 추천 조회 p95 100ms 이하 활성 목록 인덱스와 N+1 제거
공개 응답 조립 p95 50ms 이하 최대 10개, 필드 크기 제한
니쥬 MCP 전체 p95 300ms 이하 구간별 trace로 병목 분리
기상청 외부 네트워크 호출 사용자 경로 예산 0ms cache miss는 비동기 갱신

수치는 운영 보장이 아니라 7단계 부하 테스트의 초기 SLO다. PlayMCP·Claude·ChatGPT 등 Host 구간과 커머스 MCP 지연은 니쥬 MCP 지표와 분리해 측정한다. 외부 도구가 느리다고 니쥬 추천 조회의 회귀로 판정하지 않는다.

실패와 폴백

실패 처리 사용자에게 보이는 결과
니쥬 access token 만료 401과 재연결 유도 로그인 필요
친구 권한 없음 존재 여부를 숨기는 동일한 NOT_ACCESSIBLE 추천 표시 안 함
활성 추천 없음 재생성을 동기로 실행하지 않음 분석 또는 추천 준비 필요 안내
Backend 타임아웃 foreground 재시도 없음 잠시 후 다시 요청 안내
날씨 API 실패 캐시 또는 날씨 생략 기본 추천 정상 제공
외부 커머스 상품 검색 실패 니쥬 추천은 유지 외부 검색 연결만 실패로 표시
커머스 검색 도구 미지원 기능을 호출하지 않음 니쥬 상품 또는 공식 링크까지만 제공
쓰기 Tool 응답 불명 같은 멱등 키로만 재조회·재시도 중복 피드백 방지

읽기 호출도 foreground에서 연쇄 재시도하지 않는다. 에이전트가 같은 도구를 자동 반복하면 지연과 비용이 증폭되므로 retryAfterMs, 안정적인 오류 코드와 사용자별 rate limit을 제공한다.

외부 API 모듈화

from typing import Protocol

class RecommendationPort(Protocol):
    async def get_active(self, subject: str, mode: str, limit: int): ...
    async def get_friend_gift(self, subject: str, recipient_key: str, limit: int): ...

class ContextProvider(Protocol):
    async def get_cached(self, region_key: str, at: str): ...
    async def refresh(self, region_key: str, at: str): ...

class GiftHandoffProvider(Protocol):
    async def capabilities(self): ...
    async def search(self, plan): ...
    async def open_product(self, provider_product_id: str): ...

초기 mcp-gateway는 RecommendationPort만 사용한다. ContextProvider는 Backend의 선택적 컨텍스트 모듈이 구현한다. GiftHandoffProvider는 공식 커머스 API가 별도 파트너 계약으로 제공되어 니쥬가 직접 호출할 근거가 생길 때만 추가한다. Host가 다른 MCP를 조합하는 동안에는 니쥬 서버 안에 넣지 않는다.

# MCP SDK의 구체 문법이 아니라 권한과 호출 순서를 보여주는 의사코드다.
async def get_friend_gift_recommendations(ctx, recipient_key, budget_max=None, limit=3):
    token = ctx.verified_token
    require_scope(token, "recommendations:read:friends")

    if limit < 1 or limit > 10:
        raise InvalidArgument("limit")

    result = await backend.get_friend_gift(
        subject=token.subject,              # 입력 userId를 신뢰하지 않는다
        recipient_key=recipient_key,
        budget_max=budget_max,
        limit=limit,
        timeout_ms=500,
    )

    public_result = project_public_gift_fields(result)  # 원문·민감 취향 제거
    return build_mcp_result(
        text=summarize_for_text_fallback(public_result),
        structured_content=build_recommendation_contract(public_result),
        schema_version="niju.recommendation.v1",
    )

외부 공급자별 타임아웃, 재시도, rate limit, 회로 차단기는 각 Adapter에 둔다. 도메인 추천 로직은 공급자 SDK와 HTTP 오류 코드를 import하지 않는다.

자체 구축과 외부 서비스 사용 비교

기능 자체 구축 외부 API·MCP 사용 선택
취향 분석·추천 랭킹 니쥬만의 핵심 로직과 데이터 통제 범용 추천 API는 서비스 차별점과 맞지 않음 자체 구축
니쥬 MCP 권한·도구 스키마를 서비스에 맞게 설계 범용 프록시는 친구 ACL을 알지 못함 자체 구축
MCP 프로토콜 구현 공식 SDK 사용으로 표준 준수 직접 JSON-RPC를 구현하면 호환 비용 증가 공식 SDK 사용
선물하기 상품·구매 경험 직접 구축 불가능하고 최신 상품·재고를 소유하지 않음 카카오 공식 MCP 또는 제휴 API가 적합 외부 사용, 능력 확인 필수
날씨 직접 수집 가치가 없음 기상청이 최신 예보를 제공 외부 API + 캐시
지도·캘린더 직접 구축하면 권한과 데이터가 중복됨 각 Host의 기존 도구와 조합 가능 선택적 외부 MCP
대화·추천용 LLM 앞 단계에서 자체 서빙 결정 MCP 요청에 새 상용 LLM 호출은 불필요 기존 자체 서빙 유지

비용·성능·제약

대상 비용 성능 영향 주요 제약 관리 방식
니쥬 MCP 서버 CPU·네트워크·OAuth 운영비. GPU 불필요 조회 API 수준 공개 인바운드와 보안 패치 무상태 수평 확장, rate limit
PlayMCP 공개 가격·쿼터를 등록 전 확인해야 함 호스트와 도구 호출 네트워크 홉 원격 Streamable HTTP, 등록 심사·정책 호환 테스트와 별도 지표
Claude Remote MCP 니쥬 API 자체 비용 외에 이용 플랜 조건 확인 필요 Host와 원격 Tool 호출 홉 플랜·조직 정책과 connector 지원 범위 계정 유형별 연결·표시 contract test
ChatGPT custom app 니쥬 API 자체 비용 외에 이용 플랜 조건 확인 필요 Host와 원격 Tool 호출 홉 워크스페이스 관리자 설정과 앱 배포 정책 지원 계정에서 연결·표시 contract test
선물하기 MCP 도구별 가격·쿼터·상세 기능 미확정 외부 도구 지연 상품 검색·딥링크·구매 능력 미확정 tools/list 기반 capability gate
기상청 API 공식 안내상 무료, 일반회원 일 20,000회 hot path에서는 0ms 인증키·호출량·서비스 중단 가능 지역·발표시각 캐시, 비동기 갱신
카카오 메시지·공유 쿼터와 앱 권한 확인 필요 별도 사용자 행동 메시지 권한·심사·템플릿 정책 2차 기능, 실패 격리

비용이 미공개인 항목을 임의 숫자로 계산하지 않는다. 구현 스파이크에서 실제 쿼터와 호출 조건을 확인한 뒤 예상 DAU, 사용자당 호출 수, 캐시 적중률로 월 비용을 산정한다.

확장 전략

새 외부 도구를 추가할 때 다음 순서를 지킨다.

  1. 사용자가 얻는 기능과 필요한 최소 데이터를 정의한다.
  2. 연결 대상 Host의 기존 도구를 조합할 수 있는지 먼저 본다.
  3. 니쥬 서버가 직접 호출해야 할 근거가 있을 때만 Provider Port를 추가한다.
  4. 공급자 응답을 내부 표준 DTO로 변환하고 원문을 도메인에 넘기지 않는다.
  5. timeout, rate limit, cache, fallback, 개인정보 보존 기간을 Adapter 계약에 포함한다.
  6. 외부 호출이 없어도 니쥬의 기본 추천이 동작하는지 장애 테스트한다.
새 Provider
→ capability 확인
→ Adapter
→ 내부 DTO
→ 정책 검증
→ 기존 Tool 출력

Provider가 늘어나도 MCP Tool 이름을 공급자별로 늘리지 않는다. 추천 Tool의 recommendationIntents와 nextActions는 공급자 중립적으로 유지하고, Host 또는 내부 Adapter가 확인된 공급자 스키마로 변환한다. 단, 실제 구매나 발송처럼 위험과 권한이 다른 기능은 읽기 Tool에 섞지 않고 별도 도구와 scope로 분리한다.

검증 계획

구현 전에 하는 호환성·capability spike

  1. MCP Inspector에서 tools/list, tools/call, 입력·출력 스키마와 OAuth를 먼저 검증한다.
  2. 동일한 원격 엔드포인트를 PlayMCP, Claude, ChatGPT 지원 계정에 각각 연결한다.
  3. Host별 프로토콜 버전, 인증, structuredContent, 텍스트 폴백, URL·이미지 표시 결과를 호환성 매트릭스에 기록한다.
  4. PlayMCP에서 공개된 선물하기 도구의 tools/list 결과와 실제 읽기 호출을 기록한다.
  5. 상품 검색, 상품 식별자, 구매 URL, 받은 선물 조회 중 지원 범위를 구분한다.
  6. 테스트 계정과 샌드박스가 없으면 쓰기·구매 호출은 수행하지 않는다.
  7. 확인된 기능과 Host만 지원 대상으로 표시한다.

테스트 목록

테스트 방법 통과 기준
MCP 발견 Inspector와 지원 대상 Host에서 tools/list 4개 Tool의 이름·스키마 동일
Tool 계약 유효·경계·초과 입력 contract test 잘못된 입력은 안정적인 오류 코드
복합 결과 일관성 취향·의도·상품 snapshot test 세 영역의 profileVersion·recommendationVersion 조합이 유효
Host 표시 폴백 구조화 UI 지원/미지원 Host에서 호출 카드 미지원 시에도 텍스트로 상품명·가격·이유 확인 가능
사용자 분리 A 토큰으로 B의 개인 추천 요청 친구 공개 권한 없으면 항상 거부
최소 공개 gift 응답 snapshot 검사 대화 원문·알레르기·비공개 값 0건
토큰 대상 다른 audience 토큰 사용 모든 요청 401
지연 저장 추천 조회 부하 테스트 니쥬 MCP p95 300ms 이하
날씨 장애 timeout·5xx·rate limit 주입 대화·추천 성공률 변화 없음
선물하기 장애 MCP timeout·스키마 변경 주입 니쥬 추천은 반환되고 연결만 실패
중복 실행 같은 피드백 멱등 키 반복 효과 1회만 기록
위험 행동 구매·발송 의도 입력 사용자 확인 없이 실행 0건

기대 효과

도입 전후 변화

측면 MCP 도입 전 MCP 도입 후
사용 채널 니쥬 앱 화면에서만 추천 조회 PlayMCP·Claude·ChatGPT 등 외부 Host에서 같은 추천 기능 호출
추천 정보 취향 요약이나 상품 목록 중 한쪽만 전달될 수 있음 취향 요약·추천 물건 유형·실제 상품을 한 계약으로 전달
추천 이후 행동 사용자가 상품을 다시 검색 공급자 중립 nextActions를 연결된 커머스 탐색으로 전달
외부 연동 계약 채널마다 전용 API 문서와 어댑터 필요 Tool 이름과 JSON Schema로 공통 계약 제공
사용자 데이터 공개 외부 API가 내부 DTO를 알 가능성 공개용 추천 필드만 Tool 결과로 투영
권한 판단 외부 호출부마다 별도 구현 가능성 OAuth scope와 Backend 친구 ACL로 중앙화
추천 일관성 채널별 추천 구현이 갈릴 수 있음 모든 채널이 동일한 활성 추천 버전 조회
외부 장애 직접 연쇄 호출하면 전체 요청 실패 가능 Host 조합과 선택 컨텍스트로 실패 범위 분리
확장 공급자 추가 때 핵심 서비스 수정 Host 조합 또는 Provider Adapter 추가

서비스에 기대하는 효과

기대 효과 발생하는 이유 검증 지표
추천 접근성 확대 사용자가 니쥬 앱에 다시 들어오지 않아도 외부 AI에서 호출 MCP 연결 사용자 수, Tool 호출 성공 수
선물 탐색 단계 단축 추천 의도를 Host의 커머스 검색 입력으로 전달 추천 조회→외부 상품 탐색 전환율, 사용자 단계 수
추천 결과 일관성 앱과 MCP가 같은 활성 추천 리스트와 버전을 사용 채널 간 동일 버전 응답률 100%
설명 가능한 개인화 공개용 취향 요약과 상품별 일치 신호를 함께 반환 추천 이유 누락률, 사용자 추천 이해도
개인정보 최소 공개 전체 프로필 대신 목적 제한 요약과 공개용 추천만 반환 원문·알레르기·비공개 값 노출 0건
낮은 도구 응답 지연 MCP 호출에서 모델 추론·임베딩을 수행하지 않음 니쥬 MCP p95 300ms 이하
외부 장애 격리 날씨는 선택적이고 커머스 탐색은 별도 Tool 호출 외부 API 장애 시 니쥬 추천 성공률 변화 0
연동 유지보수 비용 감소 외부 Host가 공통 MCP Tool 계약을 사용 Host 추가 시 추천 도메인 수정 파일 0개
도구 추가 용이성 Provider별 Adapter와 내부 DTO를 사용 신규 Provider 추가 시 기존 Tool contract 회귀 0건

MCP 도입의 최종 효과는 Tool 호출 수가 많아지는 것이 아니다. 사용자의 취향 분석이 권한과 프라이버시를 유지한 채 실제 선물 탐색으로 이어지고, 그 과정에서 외부 서비스가 느리거나 실패해도 니쥬의 기본 추천이 유지되는 것이다.

제출 항목 대응

report.md 6단계 제출 항목 이 문서의 대응
MCP 또는 대체 프로토콜 통합 다이어그램과 각 역할·목적 설계 결론 프리뷰 · 범용 MCP Host와 니쥬의 역할 · 니쥬 MCP 서버 경계
상용 API 목록, 사용 이유, 비용·성능·제약, 내부 모듈화 외부 시스템 시나리오 · 외부 API와 컨텍스트 보강 · 자체 구축과 외부 서비스 비교 · 외부 API 모듈화
MCP 미도입 시 현재 인터페이스와 확장 계획 외부에는 MCP를 도입하고 내부에는 기존 REST를 유지하는 이유와 Port/Adapter 확장 전략 제시
확장성·유지보수성·비용 효율성 영향 지연과 병목 방지 · 확장 전략 · 기대 효과

report.md의 설계 과제도 다음과 같이 충족한다.

설계 과제 답변
외부 상호작용 시나리오 파악 취향 맥락·니쥬 추천 조회, 커머스 탐색·이동, 날씨, 캘린더, 지도, 공유로 구분
MCP 서버·클라이언트·권한·상용 API 구조 범용 Host → 니쥬/선택적 커머스 MCP 조합, OAuth scope와 친구 ACL 설계
자체 구축과 API의 비용·지연·보안 비교 핵심 추천은 자체, 커머스·날씨는 외부, 캐시·fallback·미확정 비용을 명시
REST/gRPC 대안과 외부 호출 관리 내부 REST 유지, Provider Adapter에 timeout·retry·rate limit·circuit breaker 배치
새로운 도구 확장성 capability 우선 확인, 안정적인 Tool 계약과 Provider Port로 확장

기존 설계에 미치는 영향

기존 설계 영향
Spring Backend가 프로필·추천 소유 유지. MCP는 Backend만 호출
AI Server는 사용자 프로필을 저장하지 않음 유지
추천 리스트 사전 생성 유지. MCP 호출 지연을 줄이는 근거가 됨
gift에서 비공개 원문을 숨김 유지하고 MCP 공개 응답에도 적용
대화에 외부 검색을 붙이지 않음 기본 유지. Backend가 미리 준비한 선택적 ContextSnapshot만 주입
프론트엔드 → AI Server 직접 호출 없음 유지
외부 인바운드 차단 AI Server에는 유지. mcp-gateway만 별도 공개 인바운드 허용

추가되는 계약은 두 가지다.

  1. 지원 대상 Host가 공통으로 호출하는 공개 /mcp Streamable HTTP 엔드포인트
  2. mcp-gateway가 활성 추천과 친구 ACL을 조회할 Backend 내부 API

날씨 snapshot을 대화에 넣기로 확정하면 POST /v1/chat/sessions에 선택 필드 contextSnapshot을 추가한다. 날씨를 채택하지 않으면 기존 API 계약은 바뀌지 않는다.

구현 순서

  1. 읽기 전용 get_my_recommendations와 niju.recommendation.v1 output contract를 만든다.
  2. MCP Inspector에서 Tool 발견, 구조화 결과와 텍스트 폴백을 검증한다.
  3. 원격 Stateless Streamable HTTP로 배포하고 OAuth와 scope 검증을 붙인다.
  4. PlayMCP 연결을 우선 검증하고 같은 엔드포인트로 Claude·ChatGPT 호환 시험을 진행한다.
  5. 친구 소유자의 외부 공유 설정, 친구 ACL과 공개용 gift 응답을 붙인다.
  6. 선물하기 MCP의 실제 capability를 조사한다.
  7. 지원되면 공급자 중립 nextActions를 공식 Tool 입력으로 연결해 E2E 흐름을 만든다.
  8. 날씨는 기본 흐름이 안정된 뒤 cache-only 실험으로 추가한다.
  9. p95, 오류율, 외부 API 호출량을 측정해 7단계 모니터링 설계로 넘긴다.

MCP 서버와 선물하기 연동을 동시에 만들지 않는다. 먼저 니쥬 Tool의 권한과 출력 계약을 고정해야 외부 커머스 도구의 문제와 니쥬 문제를 분리해서 검증할 수 있다.

미확정 항목

항목 확정 방법
선물하기 MCP의 Tool 목록과 입력·출력 PlayMCP 테스트 계정의 tools/list와 실제 읽기 호출
상품 검색·딥링크·구매 지원 범위 공식 도구 결과와 카카오 정책 확인. 공개 보도자료만으로 확정하지 않음
PlayMCP 등록 심사·쿼터·비용 개발자 콘솔과 최신 운영정책 확인
Host별 이용 가능 플랜과 배포 정책 PlayMCP·Claude·ChatGPT 지원 계정과 최신 공식 정책 확인
Host별 MCP 프로토콜·응답 UI 지원 연결 테스트로 structuredContent, 텍스트, URL, 이미지 표시 매트릭스 작성
니쥬 OAuth 제공 방식 기존 로그인과 계정 연결 방식에 맞춰 Backend 팀과 결정
친구를 식별하는 recipientKey 친구 API와 공개 프로필 설계 후 확정
외부 공유용 취향 요약 필드 추천 설명에 필요한 최소값을 평가하고 개인정보 정책 협의
친구 추천 공개 범위 친구 소유자의 명시적 외부 공유 설정과 철회 UX를 기획·개인정보 정책으로 확정
카카오 선물하기 상품과 니쥬 productId 매핑 공식 상품 ID 제공 여부와 크롤링 수집처 확정 후 결정
날씨 도입 여부 날씨가 있는 평가셋에서 추천 품질 개선과 API 호출량 비교
날씨 위치 동의와 정밀도 기획·개인정보 정책 협의
캘린더·지도 MCP 도입 1차 선물하기 흐름 완성 후 사용자 가치 검증
MCP p95 300ms 7단계 부하 테스트로 확정

확인한 공식 자료

⚠️ **GitHub.com Fallback** ⚠️