Skip to content

chore: MCP 서버 전역설치 및 심볼릭 링크 생성, 빌드타임 확인 명령어 추가#398

Merged
wannabeing merged 1 commit intodevfrom
chore/service-dockerfile
Aug 12, 2025
Merged

chore: MCP 서버 전역설치 및 심볼릭 링크 생성, 빌드타임 확인 명령어 추가#398
wannabeing merged 1 commit intodevfrom
chore/service-dockerfile

Conversation

@wannabeing
Copy link
Member

@wannabeing wannabeing commented Aug 12, 2025

🔎 작업 내용

  • MCP 서버 전역 설치하여 /user/local~ 에러 방지
  • MCP 서버 바로가기(심볼릭 링크) 생성
  • Dockerfile에서 실패시 빌드가 중단되게 변경

🛠️ 변경 사항

  • 구현한 주요 로직, 클래스, 메서드 등을 bullet 형식으로 기술해주세요.
  • 예)
    • UserService.createUser() 메서드 추가
    • @Email 유효성 검증 적용

🧩 트러블 슈팅

  • 구현 중 마주한 문제와 해결 방법을 기술해주세요.
  • 예)
    • 문제: @Transactional이 적용되지 않음
    • 해결: 메서드 호출 방식 변경 (this.AopProxyUtils. 사용)

🧯 해결해야 할 문제

  • 기능은 동작하지만 리팩토링이나 논의가 필요한 부분을 적어주세요.
  • 예)D
    • UserController에서 비즈니스 로직 일부 처리 → 서비스로 이전 고려 필요

📌 참고 사항

  • 기타 공유하고 싶은 정보나 참고한 문서(링크 등)가 있다면 작성해주세요.

🙏 코드 리뷰 전 확인 체크리스트

  • 불필요한 콘솔 로그, 주석 제거
  • 커밋 메시지 컨벤션 준수 (type : )
  • 기능 정상 동작 확인

Summary by CodeRabbit

  • 업무
    • 컨테이너 빌드에 추가 모듈을 포함하고 런타임 도구를 설치해 실행 여부를 검증하도록 개선했습니다.
    • 빌드/런타임 단계에서 경로 확인 및 헬스 체크를 강화해 신뢰성을 높였습니다.
    • APT 정리 최적화로 이미지 용량을 감소시켰습니다.
  • 문서
    • 주석 표현을 간결하게 정리하고 사소한 서식 요소를 정돈했습니다.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 12, 2025

Walkthrough

Dockerfile 업데이트로 멀티모듈 복사(cs25-entity 추가), Node.js 설치와 server-brave-search 글로벌 설치 및 심볼릭 링크 생성, 빌드 시 실행 가능 여부 검증 절차 추가, APT 정리 강화, 코멘트 경미 수정이 포함되었습니다.

Changes

Cohort / File(s) Summary of Changes
Docker 환경 및 빌드 파이프라인
cs25-service/Dockerfile
- 멀티모듈 복사 확장: COPY cs25-entity cs25-entity/ 추가
- NodeSource를 통한 Node.js 설치
- server-brave-search 글로벌 설치(npm i -g) 및 /usr/local/bin/server-brave-search로 symlink 생성
- 빌드 시 검증: npm 글로벌 bin 경로 출력, 바이너리 존재 확인, server-brave-search --help 실행 실패 시 비정상 종료
- 빌드 로그에 경로/헬스 체크성 출력 추가
- 이미지 슬림화: apt-get clean/var/lib/apt/lists/* 제거 등 정리 강화
- 주석 문구 경미 수정(포트 표현) 및 EOF 개행 조정(기능 변화 없음)

Sequence Diagram(s)

sequenceDiagram
  participant Dev as Developer
  participant Docker as Docker Build
  participant Img as Image
  participant NPM as npm Registry

  Dev->>Docker: Build cs25-service image
  Docker->>Docker: COPY cs25-service/, cs25-entity/
  Docker->>NPM: Install Node.js setup (NodeSource)
  Docker->>NPM: npm i -g server-brave-search
  Docker->>Docker: Create symlink to /usr/local/bin/server-brave-search
  Docker->>Docker: Print npm bin path, list binary
  Docker->>Docker: Run server-brave-search --help
  alt Verification fails
    Docker-->>Dev: Build fails (non-zero exit)
  else Verification succeeds
    Docker->>Img: Produce final image (cleaned APT caches)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Possibly related PRs

Suggested reviewers

  • jong-0126
  • Ksr-ccb
  • Kimyoonbeom
  • crocusia
  • HeeMang-Lee

Poem

토끼는 도커 속에서 통통 뛰며 말해요 🐇
노드 깔고 브레이브를 길들였지요—띠링!
bin 경로 확인, --help로 점검 완료✧
캐시 쓸어 담고, 레이어는 가뿐하게—휙
이제 런타임에 “준비 완료!” 하고 귀를 쫑긋 🥕

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/service-dockerfile

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Collaborator

@Kimyoonbeom Kimyoonbeom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 그래 바로 봐주마

@wannabeing wannabeing merged commit c091ecb into dev Aug 12, 2025
1 of 2 checks passed
@wannabeing wannabeing deleted the chore/service-dockerfile branch August 12, 2025 08:49
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
cs25-service/Dockerfile (2)

13-15: 주석과 실제 동작 불일치(테스트 생략 관련).

주석은 “테스트 생략”이라 되어 있으나, 현재 명령은 bootJar만 실행하며 기본적으로 테스트를 수행하지 않습니다. 혼동을 줄이기 위해 주석을 정정하거나, 테스트 미실행을 명시적으로 표현해 주세요. 저는 명시적 표현을 권장합니다.

적용 제안:

-# 테스트 생략하여 빌드 안정화
-RUN ./gradlew :cs25-service:bootJar --stacktrace --no-daemon
+# bootJar만 실행(일반적으로 테스트 미실행). 테스트 미실행을 명시적으로 표현.
+RUN ./gradlew :cs25-service:bootJar -x test --stacktrace --no-daemon

55-55: ENTRYPOINT 설정 LGTM.

단일 JAR 실행에 적절합니다. 추후 보안 강화를 위해 비루트 사용자(USER) 전환도 검토해 주세요.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec70200 and 9404eb1.

📒 Files selected for processing (1)
  • cs25-service/Dockerfile (4 hunks)
🔇 Additional comments (4)
cs25-service/Dockerfile (4)

42-46: 불필요 패키지/캐시 정리 LGTM.

npm cache clean, apt purge/autoremove/clean, rm -rf /var/lib/apt/lists/*로 이미지 슬림화가 잘 되어 있습니다.


51-52: 포트 공개 주석 정리 LGTM.


6-12: cs25-entity 모듈 설정 확인 완료
settings.gradle에서 이미 include 'cs25-entity'가 선언되어 있어, 멀티모듈 복사 후 컴파일·패키징에 문제가 없습니다.


25-46: 확인 완료: server-brave-search는 런타임에 실제 호출됩니다.

  • cs25-service/src/main/resources/application.properties (71행)
    spring.ai.mcp.client.stdio.connections.brave.command=server-brave-search 설정으로 Java 서비스가 해당 바이너리를 실행하도록 구성되어 있습니다.
  • 따라서 Dockerfile에 Node.js 및 server-brave-search를 포함하는 현 구성은 필수이며, 별도 사이드카나 init 컨테이너 분리는 필요하지 않습니다.

Comment on lines 26 to 30
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& npm install -g @modelcontextprotocol/server-brave-search \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

curl | bash(노드소스 설치) 보안/재현성 개선 필요.

  • curl | bash 패턴은 보안상 바람직하지 않습니다. GPG 키링을 사용한 apt 소스 등록을 권장합니다.
  • 빌드 실패 시 즉시 중단·디버깅 강화를 위해 set -euxo pipefail 추가를 권장합니다.
  • Node 및 글로벌 패키지 버전 고정으로 재현성 확보를 권장합니다(예: ARG로 버전 주입).

보안/재현성 개선 예시:

-RUN apt-get update \
- && apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
- && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
- && apt-get install -y --no-install-recommends nodejs \
- && npm install -g @modelcontextprotocol/server-brave-search \
+RUN set -euxo pipefail; \
+  apt-get update \
+  && apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
+  # NodeSource GPG 키 등록 및 소스 추가(20.x 고정)
+  && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
+    | gpg --dearmor -o /usr/share/keyrings/nodesource.gpg \
+  && echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" \
+    > /etc/apt/sources.list.d/nodesource.list \
+  && apt-get update \
+  && apt-get install -y --no-install-recommends nodejs \
+  # 글로벌 패키지 버전 고정 및 불필요한 동작 비활성화
+  && npm config set fund=false audit=false \
+  && npm install -g @modelcontextprotocol/server-brave-search@${MCP_SERVER_VERSION:-latest} \

추가로, Dockerfile 상단(해당 단계 시작부)에 다음 ARG를 선언하면 버전 고정이 용이합니다:

ARG MCP_SERVER_VERSION

원하시면 위 변경을 반영한 전체 RUN 블록을 정리해 드리겠습니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& npm install -g @modelcontextprotocol/server-brave-search \
# (Ensure you have `ARG MCP_SERVER_VERSION` declared above this stage for version pinning)
RUN set -euxo pipefail; \
apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
# NodeSource GPG 키 등록 및 소스 추가 (20.x 고정)
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
| gpg --dearmor -o /usr/share/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" \
> /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends nodejs \
# 글로벌 패키지 버전 고정 및 불필요한 동작 비활성화
&& npm config set fund=false audit=false \
&& npm install -g @modelcontextprotocol/server-brave-search@${MCP_SERVER_VERSION:-latest} \
🤖 Prompt for AI Agents
In cs25-service/Dockerfile around lines 26-30, replace the insecure curl | bash
NodeSource install with adding NodeSource's APT repository using its GPG key and
signed repo entry, declare ARGs for NODE_MAJOR (or NODE_VERSION) and
MCP_SERVER_VERSION at the top and use them to pin the node and global npm
package versions, add a shell safety header (set -euxo pipefail) at the start of
the RUN step to fail fast and aid debugging, and ensure apt-get commands use
--no-install-recommends and apt-get clean && rm -rf /var/lib/apt/lists/* to keep
image small and reproducible.

Comment on lines +31 to +41
&& ln -sf "$(npm bin -g)/server-brave-search" /usr/local/bin/server-brave-search \
\
# ===== 실행 가능 여부 확인 =====
&& echo "=== npm bin 경로 확인 ===" \
&& npm bin -g \
&& echo "=== server-brave-search 바이너리 확인 ===" \
&& ls -l "$(npm bin -g)/server-brave-search" \
&& ls -l /usr/local/bin/server-brave-search \
&& echo "=== server-brave-search --help 실행 ===" \
&& /usr/local/bin/server-brave-search --help || (echo "[ERROR] server-brave-search 실행 실패" && exit 1) \
\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

심볼릭 링크 자기참조(무한 루프) 가능성 및 검증 로직 보강 제안.

npm bin -g/usr/local/bin을 반환하는 환경에서 현재 명령은 자기 자신을 가리키는 심볼릭 링크를 만들 수 있어(ELOOP) 빌드가 실패합니다. 대상/목적지가 동일할 경우 링크 생성을 생략하도록 가드하고, 바이너리 검증은 command -v로도 확인하면 좋습니다.

적용 제안:

- && ln -sf "$(npm bin -g)/server-brave-search" /usr/local/bin/server-brave-search \
- \
- # ===== 실행 가능 여부 확인 =====
- && echo "=== npm bin 경로 확인 ===" \
- && npm bin -g \
- && echo "=== server-brave-search 바이너리 확인 ===" \
- && ls -l "$(npm bin -g)/server-brave-search" \
- && ls -l /usr/local/bin/server-brave-search \
- && echo "=== server-brave-search --help 실행 ===" \
- && /usr/local/bin/server-brave-search --help || (echo "[ERROR] server-brave-search 실행 실패" && exit 1) \
+ && BIN_DIR="$(npm bin -g)" \
+ && TARGET="${BIN_DIR}/server-brave-search" \
+ && DEST="/usr/local/bin/server-brave-search" \
+ && if [ "${TARGET}" != "${DEST}" ]; then ln -sf "${TARGET}" "${DEST}"; fi \
+ \
+ # ===== 실행 가능 여부 확인 =====
+ && echo "=== npm bin 경로 확인 ===" \
+ && echo "${BIN_DIR}" \
+ && echo "=== server-brave-search 경로 확인(command -v) ===" \
+ && command -v server-brave-search \
+ && echo "=== server-brave-search 바이너리 확인 ===" \
+ && ls -l "${TARGET}" \
+ && if [ -e "${DEST}" ]; then ls -l "${DEST}"; fi \
+ && echo "=== server-brave-search --help 실행 ===" \
+ && server-brave-search --help \
🤖 Prompt for AI Agents
In cs25-service/Dockerfile around lines 31 to 41, the current ln -sf step can
create a self-referential symlink when npm bin -g resolves to /usr/local/bin
causing ELOOP; update the Dockerfile to (1) resolve the absolute paths of the
global npm bin and the intended link target and compare them, skipping ln when
they are identical to avoid creating a self-link, (2) maintain the existing ls
checks but add a command -v server-brave-search check to validate the binary is
on PATH, and (3) ensure the help invocation is still run and that failures emit
a clear error and exit non‑zero.

@@ -35,8 +48,8 @@ RUN apt-get update \
# jar 복사
COPY --from=builder /build/cs25-service/build/libs/*.jar app.jar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

JAR 복사 글롭 충돌 가능성(다중 매칭 시 실패).

*.jar 글롭은 build/libs에 plain jar와 boot jar가 동시에 존재할 경우 다중 매칭으로 실패할 수 있습니다. 아래 중 하나로 안정화해 주세요.

대안:

  • Gradle에서 plain jar 비활성화(권장): jar { enabled = false } (KTS: tasks.jar { enabled = false }). 이렇게 하면 bootJar만 남아 글롭 충돌이 사라집니다.
  • bootJar 파일명을 고정: bootJar { archiveFileName = "app.jar" } 후 Docker에서는 COPY --from=builder /build/cs25-service/build/libs/app.jar app.jar.
  • 최소한 패턴을 좁힘: cs25-service-*-SNAPSHOT.jar 등(단, 여전히 단일 매칭을 보장해야 함).

원하시면 Gradle 설정 변경까지 포함한 PR 보조 패치를 제안드릴 수 있습니다.


🏁 Script executed:

#!/bin/bash
# cs25-service 모듈의 Gradle 설정에서 JAR 관련 태스크가 어떻게 정의됐는지 확인
rg -n "tasks\\.jar" -n cs25-service
rg -n "bootJar" -n cs25-service
rg -n "archiveFileName" -n cs25-service

Length of output: 235


JAR 복사 glob 충돌 위험: 패턴 안정화 필요

현재 cs25-service/Dockerfile(49행)의

COPY --from=builder /build/cs25-service/build/libs/*.jar app.jar

글롭 패턴 *.jar은 build/libs에 plain JAR과 boot JAR이 공존할 경우 다중 매칭으로 실패할 수 있습니다. 또한 cs25-service/build.gradle(55행)에는 bootJar 블록만 정의되어 있고 plain JAR 비활성화나 파일명 고정 설정이 없어 두 개의 JAR이 생성됩니다. 아래 대안 중 하나를 적용해 단일 JAR을 안정적으로 복사하도록 해 주세요:

  • Gradle plain JAR 비활성화 (권장)
    cs25-service/build.gradle에 추가

    tasks.jar { enabled = false }

    → bootJar만 남아 glob 충돌 해소

  • boot JAR 파일명 고정
    cs25-service/build.gradle의 bootJar 블록 수정

    bootJar {
      archiveFileName.set("app.jar")
    }

    Dockerfile도 함께 변경

    - COPY --from=builder /build/cs25-service/build/libs/*.jar app.jar
    + COPY --from=builder /build/cs25-service/build/libs/app.jar app.jar
  • glob 패턴 구체화

    - COPY --from=builder /build/cs25-service/build/libs/*.jar app.jar
    + COPY --from=builder /build/cs25-service/build/libs/cs25-service-*-SNAPSHOT.jar app.jar

위 방법 중 하나를 선택해 Docker 이미지 빌드가 항상 단일 JAR을 복사하도록 수정해 주세요.

🤖 Prompt for AI Agents
In cs25-service/Dockerfile around line 49 the COPY uses a fragile glob
"build/libs/*.jar" that can match multiple outputs if both plain and boot JARs
are produced; fix by ensuring only one JAR is emitted or by targeting a single
filename: either (A) disable the plain jar in cs25-service/build.gradle by
adding tasks.jar { enabled = false } so only bootJar remains, or (B) set bootJar
archiveFileName to a fixed name like "app.jar" in build.gradle and update the
Dockerfile COPY to reference that exact filename, or (C) tighten the COPY glob
to match the boot JAR filename pattern (for example the boot JAR classifier) so
the Docker step always copies exactly one file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants