Conversation
WalkthroughDocker Compose에 서비스별 deploy.resources 제한 추가, app 환경변수에 NAVER_CLIENT_ID/SECRET 추가, Prometheus actuator 접근 검증 로직 확장, articles.source_url 길이 확장 및 comments 테이블에 인덱스 2개 추가가 적용되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant App as Application
participant Sec as SecurityConfig
note right of Sec `#DDEBF7`: Prometheus IP 검증 로직 변경
Client->>App: GET /actuator/prometheus
App->>Sec: 요청 IP 확인
alt IP in [localhost/::1, 127.0.0.1, private ranges, prometheusAllowIp]
Sec-->>App: AuthorizationDecision(permit)
App-->>Client: 200 OK (prometheus metrics)
else
Sec-->>App: AuthorizationDecision(deny)
App-->>Client: 403 Forbidden
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
요약개요부하 테스트 준비를 위해 Docker 컴포즈에서 데이터베이스 및 캐시 서비스의 리소스 제한을 설정하고, Naver 클라이언트 인증 정보를 환경변수로 추가했으며, Prometheus 접근 제어를 확대하고 댓글 조회 성능 개선을 위한 인덱스를 추가했습니다. 변경 사항
예상 코드 리뷰 노력🎯 3 (보통) | ⏱️ ~20분
관련 PR
추천 검토자
Pre-merge checks and finishing touches✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used🧠 Learnings (1)📚 Learning: 2025-10-28T02:10:38.305ZApplied to files:
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (1)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
monew/docker-compose.yml (2)
37-41: 리소스 예약(reservations) 추가 권장부하테스트 시 안정적인 리소스 할당을 위해 Redis와 Mongo에도 reservations 설정을 추가하는 것이 좋습니다.
다음과 같이 수정하는 것을 권장합니다:
deploy: resources: limits: cpus: "1.0" memory: 512m + reservations: + cpus: "0.5" + memory: 256m
52-56: 리소스 예약(reservations) 추가 권장Redis와 마찬가지로 Mongo에도 안정적인 리소스 할당을 위해 reservations를 추가하는 것이 좋습니다.
다음과 같이 수정하는 것을 권장합니다:
deploy: resources: limits: cpus: "2.0" memory: 1g + reservations: + cpus: "1.0" + memory: 512m
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
monew/docker-compose.yml(4 hunks)monew/src/main/java/com/spring/monew/auth/config/SecurityConfig.java(2 hunks)monew/src/main/resources/schema.sql(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-28T02:10:38.305Z
Learnt from: yuhandemian
Repo: codeit-monew/sb05-monew-team7 PR: 37
File: monew/src/main/java/com/spring/monew/comment/controller/CommentController.java:57-65
Timestamp: 2025-10-28T02:10:38.305Z
Learning: The monew project currently does not implement Spring Security authentication - SecurityConfig exists but uses .anyRequest().permitAll(). All controllers use RequestHeader(name = "Monew-Request-User-ID") UUID userId to receive user identification, not AuthenticationPrincipal.
Applied to files:
monew/src/main/java/com/spring/monew/auth/config/SecurityConfig.java
🔇 Additional comments (4)
monew/src/main/resources/schema.sql (2)
98-98: 변경사항 승인: URL 컬럼 크기 확장긴 URL을 수용하기 위한 합리적인 변경입니다. UNIQUE 제약조건이 유지되므로 데이터 무결성에 영향이 없습니다.
287-294: 댓글 조회 쿼리와 완벽하게 정렬된 인덱스 설계 확인됨코드 검증 결과, 두 인덱스 모두 실제 QueryDSL 쿼리 패턴과 완벽하게 일치합니다.
idx_comment_article_created: 생성일시 정렬 쿼리(orderBy=createdAt)에서(article_id, is_deleted, created_at DESC, id)순서로 필터링과 정렬을 모두 커버idx_comment_article_like: 좋아요 수 정렬 쿼리(orderBy=likeCount)에서(article_id, is_deleted, like_count DESC, created_at DESC, id)순서로 커서 페이지네이션과 안정적인 정렬을 지원인덱스는 커서 기반 페이지네이션 로직과 정렬 요구사항을 완벽히 만족하며, id 포함으로 커버링 인덱스의 이점까지 제공합니다.
monew/docker-compose.yml (1)
21-28: 적절한 리소스 제한 설정Postgres에 대한 리소스 제한이 PR 설명의 테스트 시나리오(CPU 4, Memory 2GB)와 일치합니다. limits와 reservations를 모두 설정한 것도 좋은 방식입니다.
monew/src/main/java/com/spring/monew/auth/config/SecurityConfig.java (1)
25-26: 기본값 추가 승인
prometheusAllowIp에 안전한 기본값(127.0.0.1)을 설정한 것은 좋은 변경입니다.
| NAVER_CLIENT_ID: ${NAVER_CLIENT_ID} | ||
| NAVER_CLIENT_SECRET: ${NAVER_CLIENT_SECRET} |
There was a problem hiding this comment.
🧩 Analysis chain
환경 변수 설정 확인 필요
네이버 API 자격증명을 환경 변수로 주입하는 방식은 적절합니다. 하지만 docker-compose up 실행 전에 해당 환경 변수가 설정되어 있는지 확인이 필요합니다.
다음을 확인해주세요:
.env파일 또는 셸 환경에NAVER_CLIENT_ID와NAVER_CLIENT_SECRET이 설정되어 있는지 확인- 프로덕션 환경에서는 Docker Secrets 사용을 고려
🏁 Script executed:
#!/bin/bash
# Description: Check if .env file exists and contains NAVER credentials
if [ -f "monew/.env" ]; then
echo "Found .env file:"
grep -E "NAVER_CLIENT_(ID|SECRET)" monew/.env || echo "NAVER credentials not found in .env"
else
echo ".env file not found. Make sure to set environment variables before running docker-compose."
fiLength of output: 90
---
🏁 Script executed:
```shell
#!/bin/bash
# Check for environment setup documentation and examples
echo "=== Checking for .env.example or similar ==="
fd -e env -e example monew/ 2>/dev/null | head -20
echo ""
echo "=== Checking for README or setup docs ==="
fd -i -e md monew/ 2>/dev/null | xargs grep -l "NAVER\|환경 변수\|environment" 2>/dev/null || echo "No matches found"
echo ""
echo "=== Checking docker-compose.yml for comments about credentials ==="
head -100 monew/docker-compose.yml
Length of output: 2406
---
🏁 Script executed:
```shell
#!/bin/bash
# Check root directory for setup documentation
echo "=== Root directory README and docs ==="
ls -la | grep -iE "readme|doc|setup|env|contributing" || echo "No matches in root"
echo ""
echo "=== Checking if root README mentions environment variables ==="
if [ -f "README.md" ]; then
head -50 README.md
else
echo "No README.md in root"
fi
echo ""
echo "=== Checking for any .env template files ==="
find . -maxdepth 2 -type f \( -name ".env*" -o -name "*.env" \) 2>/dev/null || echo "No .env template files"
Length of output: 455
.env.example 템플릿 파일 추가 필요
네이버 API 자격증명(NAVER_CLIENT_ID, NAVER_CLIENT_SECRET)이 환경 변수로 주입되도록 설정되어 있으나, 프로젝트에 .env.example 템플릿이 없어 개발자가 어떤 환경 변수를 설정해야 하는지 알 수 없습니다. monew/ 디렉토리에 .env.example 파일을 생성하여 필수 환경 변수를 명시해주세요.
예시:
NAVER_CLIENT_ID=your_naver_client_id
NAVER_CLIENT_SECRET=your_naver_client_secret
개발자는 docker-compose up 실행 전에 이 파일을 복사하여 .env 파일을 만들고 실제 값을 입력해야 합니다.
🤖 Prompt for AI Agents
In monew/docker-compose.yml around lines 79-80 the compose file expects
NAVER_CLIENT_ID and NAVER_CLIENT_SECRET from an environment file but the
repository lacks a .env.example template; create monew/.env.example listing the
required variables (NAVER_CLIENT_ID and NAVER_CLIENT_SECRET) with placeholder
values and a short comment instructing developers to copy it to .env and
populate real credentials before running docker-compose up.
| package com.spring.monew.auth.config; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; |
There was a problem hiding this comment.
사용되지 않는 로깅 어노테이션 제거 필요
@Slf4j 어노테이션이 추가되었지만 코드 내에서 log를 사용하는 곳이 없습니다.
다음과 같이 제거하는 것을 권장합니다:
package com.spring.monew.auth.config;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;-@Slf4j
@RequiredArgsConstructor
@Configuration
@EnableWebSecurityAlso applies to: 17-17
🤖 Prompt for AI Agents
In monew/src/main/java/com/spring/monew/auth/config/SecurityConfig.java around
lines 4 and 17, the Lombok @Slf4j import and annotation are unused; remove the
"import lombok.extern.slf4j.Slf4j;" line and delete the "@Slf4j" annotation on
the class declaration, and then run a build / static-analysis to ensure no
remaining references to log exist and no new unused-import warnings are
introduced.
| boolean allowed = | ||
| remoteAddr.equals("127.0.0.1") || | ||
| remoteAddr.equals("0:0:0:0:0:0:0:1") || // IPv6 localhost | ||
| remoteAddr.equals("localhost") || | ||
| remoteAddr.startsWith("172.") || // Docker 내부 네트워크 | ||
| remoteAddr.startsWith("192.168.") || | ||
| remoteAddr.equals(prometheusAllowIp); | ||
|
|
||
| return new AuthorizationDecision(allowed); |
There was a problem hiding this comment.
프로덕션 환경에서 과도하게 허용적인 Prometheus 접근 제어
Prometheus 메트릭 엔드포인트 접근을 IP 기반으로만 제어하고 있으며, Docker 네트워크 전체(172.*)와 사설 네트워크 전체(192.168.*)를 허용하고 있습니다. 개발 및 테스트 환경에서는 적절하지만, 프로덕션 환경에서는 보안 위험이 있습니다.
다음 개선사항을 고려해주세요:
- 환경별 설정 분리: 프로덕션과 개발 환경에서 다른 접근 제어 정책 적용
- 더 제한적인 IP 범위: 프로덕션에서는 특정 모니터링 서버 IP만 허용
- 추가 인증 계층: IP 기반 필터링 외에 Basic Auth 또는 토큰 기반 인증 추가
// 환경별 설정 예시
@Value("${spring.profiles.active:local}")
private String activeProfile;
// 접근 제어 로직에서
boolean allowed;
if ("prod".equals(activeProfile)) {
// 프로덕션: 특정 IP만 허용
allowed = remoteAddr.equals(prometheusAllowIp);
} else {
// 개발/테스트: 넓은 범위 허용
allowed = remoteAddr.equals("127.0.0.1") ||
remoteAddr.equals("0:0:0:0:0:0:0:1") ||
remoteAddr.startsWith("172.") ||
remoteAddr.startsWith("192.168.") ||
remoteAddr.equals(prometheusAllowIp);
}🤖 Prompt for AI Agents
In monew/src/main/java/com/spring/monew/auth/config/SecurityConfig.java around
lines 36 to 44, the current logic allows broad IP ranges (172.*, 192.168.* and
localhost variants) which is too permissive for production; change to
environment-aware authorization by injecting the active profile (e.g.
@Value("${spring.profiles.active:local}") private String activeProfile) and
branch the decision: if profile equals "prod" only allow the specific monitoring
IP(s) (prometheusAllowIp or a configured list) and reject all others; if
non-prod keep the current relaxed checks; additionally, add an extra auth layer
for the metrics endpoint in prod (Basic Auth or token-based check) and ensure
prometheusAllowIp is validated/parsed as a single IP or CIDR list rather than
matching prefixes.
Issues
✔️ Check-list
🗒️ Work Description
부하테스트 (동접 테스트)
인덱싱 사용 O, X로 비교를 하였음.
📷 Screenshot
유저 1000명 : 인덱싱화 안하고 요청 + CPU, 메모리 상한 없이 + DB Max Connection 300
유저 2000명 : 인덱싱화 하고 요청 + CPU, 메모리 상한 없이 + DB Max Connection 300
유저 2000명 : 인덱싱화 하고 요청 + CPU 4 , 메모리 2 상한 없이 + DB Max Connection 100
📚 Reference
Summary by CodeRabbit
New Features
Performance Improvements
Infrastructure