Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-tracing-bridge-otel'
implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.6'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
compileOnly 'org.projectlombok:lombok'
Expand All @@ -47,6 +49,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.web3j:core:4.10.0'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
runtimeOnly 'io.micrometer:micrometer-registry-otlp'

}

Expand All @@ -58,4 +61,3 @@ tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}


21 changes: 20 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,26 @@ management:
endpoints:
web:
exposure:
include: health
include: health,info,metrics
otlp:
metrics:
export:
url: http://ipiece-otel-collector.monitoring:4318/v1/metrics
step: 5s
Comment on lines +43 to +47
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash

# First, find and read the application.yml file
find . -name "application.yml" -type f | head -20

Repository: Woori-FISA-Go/IPiece-server


<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0

stdout:

./src/main/resources/application.yml
./src/test/resources/application.yml

</shell_result>


Script executed:

#!/bin/bash

# Read the main application.yml to see the exact configuration
cat -n ./src/main/resources/application.yml | head -70

Repository: Woori-FISA-Go/IPiece-server


<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0

stdout:

     1	spring:
     2	  application:
     3	    name: IPiece
     4	  profiles:
     5	    active: local
     6	  servlet:
     7	    multipart:
     8	      max-file-size: 50MB
     9	      max-request-size: 50MB
    10	
    11	
    12	  datasource:
    13	    url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
    14	    username: ${DB_USER}
    15	    password: ${DB_PASS}
    16	
    17	  data:
    18	    redis:
    19	      host: ${REDIS_HOST}
    20	      port: ${REDIS_PORT}
    21	
    22	  jpa:
    23	    hibernate:
    24	      ddl-auto: update
    25	    properties:
    26	      hibernate:
    27	        format_sql: true
    28	        highlight_sql: true  # (Spring Boot 3.1+) SQL 색상 강조
    29	    show-sql: true        # SQL 쿼리 출력
    30	
    31	
    32	server:
    33	  error:
    34	    include-message: always
    35	    include-stacktrace: never
    36	    include-binding-errors: never
    37	
    38	management:
    39	  endpoints:
    40	    web:
    41	      exposure:
    42	        include: health,info,metrics
    43	  otlp:
    44	    metrics:
    45	      export:
    46	        url: http://ipiece-otel-collector.monitoring:4318/v1/metrics
    47	        step: 5s
    48	
    49	  metrics:
    50	    tags:
    51	      application: ${spring.application.name}
    52	      namespace: ${K8S_NAMESPACE:unknown}
    53	
    54	  simple:
    55	    metrics:
    56	      export:
    57	        enabled: false
    58	  prometheus:
    59	    metrics:
    60	      export:
    61	        enabled: false
    62	
    63	jwt:
    64	  secret: ${JWT_SECRET}
    65	  expiration-ms: 241920000          # AccessToken 28일 -> 개발 완료 후 조정 필요
    66	  refresh-expiration-ms: 604800000 # RefreshToken 7일
    67	
    68	krwt:
    69	  contract:
    70	    address: ${KRWT_CONTRACT_ADDRESS}

</shell_result>


Script executed:

#!/bin/bash

# Check for Spring profile-specific configuration files
find ./src/main/resources -name "application*.yml" -o -name "application*.yaml" | sort

Repository: Woori-FISA-Go/IPiece-server


<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0

stdout:

./src/main/resources/application.yml

</shell_result>


Script executed:

#!/bin/bash

# Search for OTEL or OTLP references in the codebase
rg -i "otel|otlp" --type yaml --type md --type java --type kotlin -C 3 | head -100

Repository: Woori-FISA-Go/IPiece-server


<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0

stdout:

src/main/resources/application.yml-    web:
src/main/resources/application.yml-      exposure:
src/main/resources/application.yml-        include: health,info,metrics
src/main/resources/application.yml:  otlp:
src/main/resources/application.yml-    metrics:
src/main/resources/application.yml-      export:
src/main/resources/application.yml:        url: http://ipiece-otel-collector.monitoring:4318/v1/metrics
src/main/resources/application.yml-        step: 5s
src/main/resources/application.yml-
src/main/resources/application.yml-  metrics:

</shell_result>


Script executed:

#!/bin/bash

# Check for README and documentation
find . -maxdepth 2 -type f \( -name "README*" -o -name "*.md" \) | head -20

echo "---"

# Look for docker-compose or k8s files that might reference the monitoring namespace
find . -type f \( -name "docker-compose*" -o -name "*.yaml" -o -name "*.yml" \) | grep -v ".git" | grep -E "(docker|k8s|kube|deployment)" | head -20

Repository: Woori-FISA-Go/IPiece-server


<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0

stdout:

./README.md
---

</shell_result>


Script executed:

#!/bin/bash

# Read README.md to understand deployment context
cat ./README.md

Repository: Woori-FISA-Go/IPiece-server


<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0

stdout:

# IPiece

</shell_result>


Script executed:

#!/bin/bash

# Search for Docker, K8s, and build files
find . -type f \( -name "Dockerfile*" -o -name "docker-compose*" -o -name "pom.xml" -o -name "build.gradle*" -o -name "*.yaml" -o -name "*.yml" \) | grep -v ".git" | grep -v "target/" | grep -v "node_modules/" | head -40

Repository: Woori-FISA-Go/IPiece-server


<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0

stdout:

./Dockerfile
./src/main/resources/application.yml
./src/test/resources/application.yml
./build.gradle

</shell_result>


Script executed:

#!/bin/bash

# Read Dockerfile
echo "=== DOCKERFILE ===" 
cat ./Dockerfile

echo ""
echo "=== BUILD.GRADLE (OTEL-related dependencies) ===" 
rg -i "otel|micrometer|observ" ./build.gradle -A 2 -B 2

Repository: Woori-FISA-Go/IPiece-server


<shell_result>
Repository: Woori-FISA-Go/IPiece-server
Exit code: 0

stdout:

=== DOCKERFILE ===
# ===========================
# Stage 1: Build Stage
# ===========================
FROM gradle:8.5-jdk17-alpine AS builder

WORKDIR /app

# Gradle 캐시 레이어 (의존성만 먼저)
COPY build.gradle settings.gradle ./
COPY gradle ./gradle
RUN gradle dependencies --no-daemon || true

# 소스 코드 복사 및 빌드
COPY src ./src
RUN gradle clean build -x test --no-daemon --stacktrace

# JAR 파일 확인
RUN ls -la /app/build/libs/ && \
    test -f /app/build/libs/IPiece-0.0.1-SNAPSHOT.jar

# ===========================
# Stage 2: Runtime Stage (보안 강화)
# ===========================
FROM eclipse-temurin:17-jre-alpine

# 라벨 추가 (메타데이터)
LABEL maintainer="Woori-FISA-Go Team" \
      version="1.0" \
      description="IPiece Backend Server"

WORKDIR /app

# 보안: non-root 사용자 생성 및 디렉토리 권한 설정
RUN addgroup -S spring && \
    adduser -S spring -G spring && \
    chown -R spring:spring /app

# 필요한 패키지만 설치 (보안 업데이트 포함)
RUN apk update && \
    apk upgrade && \
    apk add --no-cache wget && \
    rm -rf /var/cache/apk/*

# JAR 파일 복사 (non-root 소유)
COPY --from=builder --chown=spring:spring /app/build/libs/*.jar app.jar

# 사용자 전환 (non-root로 실행)
USER spring:spring

# Health Check 설정
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1

# 환경변수 (기본값)
ENV SPRING_PROFILES_ACTIVE=prod \
    JAVA_OPTS="-XX:MaxRAMPercentage=75.0 \
               -XX:+UseContainerSupport \
               -Djava.security.egd=file:/dev/./urandom \
               -Dserver.port=8080" \
    TZ=Asia/Seoul

# 포트 노출
EXPOSE 8080

# 실행
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
=== BUILD.GRADLE (OTEL-related dependencies) ===
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-actuator'
	implementation 'io.micrometer:micrometer-tracing-bridge-otel'
	implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
	implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.6'
--
    implementation 'org.web3j:core:4.10.0'
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
	runtimeOnly 'io.micrometer:micrometer-registry-otlp'

}

</shell_result>


OTLP 수집기 URL이 환경 설정으로 외부화되지 않음

OTLP 메트릭 수집기 URL이 http://ipiece-otel-collector.monitoring:4318/v1/metrics로 하드코딩되어 있습니다(line 46). 이는 다음과 같은 문제를 야기합니다:

  1. 데이터베이스(DB_HOST, DB_PORT, DB_NAME), Redis(REDIS_HOST, REDIS_PORT), JWT 등 다른 설정들은 모두 환경 변수로 외부화되어 있으나 OTLP URL만 하드코딩됨
  2. Kubernetes 네임스페이스 monitoring이 고정되어 있어 다른 환경에서 배포 불가
  3. Dockerfile의 SPRING_PROFILES_ACTIVE=prod 설정에도 불구하고 profile별 application-*.yml 파일이 없어 환경 간 설정 분리 불가
  4. 로컬 개발 환경에서 별도의 OTEL 수집기가 없을 경우 실행 불가

권장사항: OTEL 수집기 URL을 환경 변수로 외부화하세요. Spring Boot/Micrometer는 OTEL_EXPORTER_OTLP_ENDPOINT 환경 변수를 기본적으로 지원합니다.

management:
  otlp:
    metrics:
      export:
        url: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4318/v1/metrics}
        step: 5s
🤖 Prompt for AI Agents
In src/main/resources/application.yml around lines 43 to 47, the OTLP metrics
exporter URL is hardcoded to
http://ipiece-otel-collector.monitoring:4318/v1/metrics which prevents
environment-specific configuration and breaks non-cluster/local runs; change it
to read from an environment variable (e.g. OTEL_EXPORTER_OTLP_ENDPOINT) with a
sensible default, update the YAML to use property substitution for the URL, and
ensure documentation/README and Docker/K8s manifests reference and pass this env
var (or define profile-specific application-*.yml files) so each deployment can
override the collector endpoint.


metrics:
tags:
application: ${spring.application.name}
namespace: ${K8S_NAMESPACE:unknown}

simple:
metrics:
export:
enabled: false
prometheus:
metrics:
export:
enabled: false

jwt:
secret: ${JWT_SECRET}
Expand Down