Skip to content

[FEAT] 팔로우 리스트 조회 API 개발#102

Merged
Be-HinD merged 2 commits intomainfrom
feat/follow-list
Dec 13, 2025
Merged

[FEAT] 팔로우 리스트 조회 API 개발#102
Be-HinD merged 2 commits intomainfrom
feat/follow-list

Conversation

@Be-HinD
Copy link
Member

@Be-HinD Be-HinD commented Dec 13, 2025

📝 Pull Request

📌 PR 종류

해당하는 항목에 체크해주세요.

  • 기능 추가 (Feature)
  • 버그 수정 (Fix)
  • 문서 수정 (Docs)
  • 코드 리팩터링 (Refactor)
  • 테스트 추가 (Test)
  • 기타 변경 (Chore)

✨ 변경 내용

팔로우 리스트를 조회할 수 있는 API 개발을 진행하였습니다.
이번 PR로 인해 변경되는 점은 아래와 같습니다.

  • 팔로우 리스트 조회를 위한 QueryDSL 설정을 진행했습니다. (Gradle 의존성 추가, config 파일 추가)

    • Qtype 생성 위치 : wegobackend\build\generated\sources\annotationProcessor\java\main\team\wego\wegobackend
  • 테스트를 위한 초기값 세팅을 ApplicationRunner 인터페이스를 활용하여 추가해두었습니다. (local 프로필에서만 실행되도록 설정)

  • 팔로우 관련 레포지토리가 추가되었습니다. (FollowRepositoryCustom, FollowRepositoryImpl)


🔍 관련 이슈

해당 PR이 해결하는 이슈가 있다면 연결해주세요.
Closes #101


🧪 테스트

변경된 기능에 대한 테스트 범위 또는 테스트 결과를 작성해주세요.

  • 유닛 테스트 추가 / 수정
  • 통합 테스트 검증
  • 수동 테스트 완료

초기값 생성 쿼리 로그 (User 1 ~ 100)

image

초기값 생성 쿼리 로그 (Follow 1번 -> 2~50)

image

.http 테스트 결과 (초기 조회, cursor = null)

image

.http 테스트 결과 (cursor != null)

image

.http 테스트 결과 (cursor is last)

image

🚨 확인해야 할 사항 (Checklist)

PR을 제출하기 전에 아래 항목들을 확인해주세요.

  • 코드 포매팅 완료
  • 불필요한 파일/코드 제거
  • 로직 검증 완료
  • 프로젝트 빌드 성공
  • 린트/정적 분석 통과 (해당 시)

🙋 기타 참고 사항

팔로우 리스트 조회에 사용되는 cursor값은 Follow Entity의 id값으로 활용하였습니다.
또한 nextCursor의 값은 조회된 마지막 데이터의 id값을 주는 것으로 설정해두었습니다.

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 팔로우 목록 조회 기능 추가: 사용자가 팔로우하는 사람들의 목록을 페이지네이션으로 조회할 수 있습니다.
  • Chores

    • 백엔드 성능 최적화 인프라 개선
    • 로컬 환경 테스트 데이터 초기화

✏️ Tip: You can customize this high-level summary in your review settings.

@Be-HinD Be-HinD self-assigned this Dec 13, 2025
@Be-HinD Be-HinD added the ✨enhancement New feature or request label Dec 13, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 13, 2025

Walkthrough

QueryDSL을 Gradle에 통합하고 팔로우 리스트 조회 API를 구현했습니다. JPAQueryFactory 설정, 커서 기반 페이지네이션을 지원하는 리포지토리 구현, 그리고 컨트롤러 엔드포인트를 추가했으며, 로컬 프로필용 테스트 데이터 초기화 로직을 도입했습니다.

Changes

Cohort / File(s) 변경 요약
QueryDSL 및 빌드 설정
build.gradle, src/main/java/team/wego/wegobackend/common/config/QuerydslConfig.java
QueryDSL 라이브러리(querydsl-jpa, querydsl-apt) 의존성 추가, 애노테이션 프로세서 생성 소스 경로 구성, JPAQueryFactory 빈 설정
테스트 데이터 초기화
src/main/java/team/wego/wegobackend/common/support/LocalDataInitializer.java
로컬 프로필 활성화 시 101명의 사용자와 49개의 팔로우 관계를 생성하는 ApplicationRunner 구현
팔로우 리스트 조회 기능 - 리포지토리 계층
src/main/java/team/wego/wegobackend/user/repository/FollowRepository.java, src/main/java/team/wego/wegobackend/user/repository/FollowRepositoryCustom.java, src/main/java/team/wego/wegobackend/user/repository/FollowRepositoryImpl.java
FollowRepositoryCustom 인터페이스 추가, QueryDSL 기반 커서 페이지네이션 구현(FollowRepositoryImpl)
팔로우 리스트 조회 기능 - 응답 DTO
src/main/java/team/wego/wegobackend/user/application/dto/response/FollowListResponse.java, src/main/java/team/wego/wegobackend/user/application/dto/response/FollowResponse.java
FollowResponse(id, userId, profileImage, nickname, profileMessage)와 FollowListResponse(items, nextCursor) 레코드/클래스 신규 추가
팔로우 리스트 조회 기능 - 서비스 및 컨트롤러
src/main/java/team/wego/wegobackend/user/application/FollowService.java, src/main/java/team/wego/wegobackend/user/presentation/UserController.java, src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java
FollowService.followList() 메서드 추가, GET /api/v1/users/{userId}/follow 엔드포인트 구현, 커서 및 사이즈 파라미터 검증(Min/Max), Swagger 문서화
기타 수정
src/main/java/team/wego/wegobackend/group/presentation/GroupImageController.java, src/test/http/user/user-api.http
이미지 업로드 엔드포인트 consumes 명시, 경로 변수 매핑 명확화, HTTP 테스트 로그인 이메일 및 팔로우 조회 요청 추가

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant Controller as UserController
    participant Service as FollowService
    participant Repository as FollowRepositoryImpl
    participant Database as JPA/Database

    Client->>Controller: GET /api/v1/users/{userId}/follow?cursor=X&size=20
    activate Controller
    
    Controller->>Service: followList(userId, cursor, size)
    activate Service
    
    Service->>Repository: existsById(userId)
    activate Repository
    Repository-->>Service: true/false
    deactivate Repository
    
    alt User not found
        Service-->>Controller: UserNotFoundException
        Controller-->>Client: 404 Not Found
    else User exists
        Service->>Repository: findFollowingList(userId, cursor, size)
        activate Repository
        
        Repository->>Database: QueryDSL SELECT (follow.id, user.id, user.profileImage, etc.)
        activate Database
        Database-->>Repository: List<FollowResponse>
        deactivate Database
        
        Repository-->>Service: List<FollowResponse>
        deactivate Repository
        
        Service->>Service: compute nextCursor (last item.followId or null)
        Service-->>Controller: FollowListResponse(items, nextCursor)
        deactivate Service
    end
    
    Controller-->>Client: 200 OK + ApiResponse<FollowListResponse>
    deactivate Controller
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

주의 깊은 검토가 필요한 영역:

  • QueryDSL 쿼리 정확성: FollowRepositoryImpl의 JOIN 조건, 필터링 로직(ItCursor), 정렬 순서 및 페이지네이션 경계 케이스 검증
  • 커서 기반 페이지네이션: nextCursor 계산 로직(빈 리스트 시 null 처리, 마지막 항목 ID 사용) 및 중복/누락 데이터 가능성 확인
  • LocalDataInitializer: 트랜잭션 범위, 데이터 일관성, 테스트 전용 초기화 vs. 프로덕션 영향 범위 확인
  • 엔드포인트 파라미터 검증: @Min(1) @Max(100)의 size 제약 및 cursor nullable 처리가 의도대로 동작하는지 확인

Possibly related PRs

  • [FEAT] 팔로우 요청 API 개발 #83: 팔로우 기능 관련 Follow 엔터티/리포지토리/서비스 수정으로, 본 PR의 QueryDSL 기반 팔로우 리스트 조회가 #83에서 추가된 Follow 엔터티 및 리포지토리 구조에 직접 의존
  • [FEAT] 팔로우 취소 API 개발 #85: FollowService와 FollowRepository 계층을 수정하며, 본 PR의 팔로우 리스트 페이지네이션과 #85의 언팔로우 기능이 같은 도메인에서 보완적 기능 제공
  • [FEAT] Docs 작업(Swagger, Security, Cors) #77: UserControllerDocs 및 UserController API 계약을 수정하며, 본 PR이 추가하는 followList 엔드포인트 문서화와 #77의 컨트롤러 문서화 체계가 관련

Poem

🐰 쿼리로 유저를 따라가고,
커서 위에서 스크롤 춤을 춘다.
페이지는 무한, 팔로우는 짙어지고,
QueryDSL 마법으로 데이터 화르륵!
토끼의 승리, 리스트는 완성되었노라! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목 '[FEAT] 팔로우 리스트 조회 API 개발'은 변경사항의 주요 목적을 명확하게 요약하고 있습니다.
Linked Issues check ✅ Passed 팔로우 리스트 조회 API 개발 요구사항이 완전히 충족되었습니다. QueryDSL 설정, 커서 기반 페이지네이션, API 엔드포인트, 저장소 구현이 모두 포함되어 있습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 팔로우 리스트 조회 API 개발 요구사항과 직접적으로 관련되어 있으며, 범위를 벗어난 변경은 없습니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/follow-list

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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: 2

♻️ Duplicate comments (1)
src/main/java/team/wego/wegobackend/group/presentation/GroupImageController.java (1)

62-62: 명시적 value 속성은 선택적 스타일 변경입니다.

47번 라인과 동일하게, 명시적 value 속성 사용은 스타일 일관성을 위한 선택적 변경입니다.

🧹 Nitpick comments (7)
src/main/java/team/wego/wegobackend/group/presentation/GroupImageController.java (2)

47-47: 명시적 value 속성은 선택적 스타일 변경입니다.

@PatchMapping("/{groupId}")에서 @PatchMapping(value = "/{groupId}")로의 변경은 기능적 차이가 없는 스타일 일관성을 위한 변경입니다. 코드베이스 전체에서 일관된 스타일을 유지하고자 한다면 의미가 있지만, 필수는 아닙니다.


35-45: 사전 업로드 단계이므로 userDetails 매개변수의 필요성을 확인하세요.

이 메소드는 2단계 이미지 업로드 프로세스의 첫 단계입니다. API 문서에 따르면 uploadImages는 S3에 이미지를 먼저 업로드하고 URL을 반환하는 "사전 업로드" 단계이며, updateGroupImages에서 실제로 그룹과 연결될 때 HOST 권한을 검증합니다. uploadGroupImages 서비스 메소드가 userDetails를 받지 않는 것은 의도된 설계입니다. 다만 컨트롤러의 @AuthenticationPrincipal CustomUserDetails userDetails 매개변수가 실제로 사용되지 않으므로, 향후 기능(예: 사용자별 업로드 할당량 제한, 감사 로깅)이 필요하지 않다면 제거를 고려하세요.

src/main/java/team/wego/wegobackend/common/config/QuerydslConfig.java (1)

12-17: 생성자 주입 방식 고려

현재 @PersistenceContext 필드 주입을 사용하고 있습니다. Spring의 권장 사항에 따라 생성자 주입 방식을 고려해보세요.

다음과 같이 리팩터링할 수 있습니다:

 @Configuration
 public class QuerydslConfig {
 
-    @PersistenceContext
-    private EntityManager entityManager;
+    private final EntityManager entityManager;
+
+    public QuerydslConfig(@PersistenceContext EntityManager entityManager) {
+        this.entityManager = entityManager;
+    }
 
     @Bean
     public JPAQueryFactory jpaQueryFactory() {
         return new JPAQueryFactory(entityManager);
     }
 }
src/main/java/team/wego/wegobackend/user/application/FollowService.java (1)

75-86: 페이지네이션 로직 개선 고려

현재 구현은 리스트가 비어있지 않으면 항상 마지막 아이템의 followIdnextCursor로 반환합니다. 이는 실제로 더 많은 데이터가 있는지 확인하지 않아, 클라이언트가 빈 결과를 반환받는 불필요한 추가 요청을 할 수 있습니다.

더 나은 사용자 경험을 위해 size+1개의 아이템을 조회하고, (size+1)번째 아이템이 존재하는지 확인한 후 size개로 자르는 방식을 고려해보세요.

다음과 같이 개선할 수 있습니다:

 public FollowListResponse followList(Long userId, Long cursor, Integer size) {
 
     if(!userRepository.existsById(userId)) {
         throw new UserNotFoundException();
     }
 
-    List<FollowResponse> list = followRepository.findFollowingList(userId, cursor, size);
+    List<FollowResponse> list = followRepository.findFollowingList(userId, cursor, size + 1);
 
-    Long nextCursor = list.isEmpty() ? null : list.getLast().getFollowId();
+    Long nextCursor = null;
+    if (list.size() > size) {
+        nextCursor = list.get(size - 1).getFollowId();
+        list = list.subList(0, size);
+    }
 
     return new FollowListResponse(list, nextCursor);
 }
src/main/java/team/wego/wegobackend/common/support/LocalDataInitializer.java (2)

4-4: jakarta.transaction.Transactional 대신 Spring의 @Transactional 사용 권장

jakarta.transaction.Transactional은 Spring의 트랜잭션 관리와 완전히 통합되지 않을 수 있습니다. Spring 환경에서는 org.springframework.transaction.annotation.Transactional을 사용하는 것이 더 안전합니다.

-import jakarta.transaction.Transactional;
+import org.springframework.transaction.annotation.Transactional;

16-18: @Configuration 대신 @Component 사용 권장

@Configuration은 주로 @Bean 메서드를 포함하는 설정 클래스에 사용됩니다. ApplicationRunner 구현체는 @Component를 사용하는 것이 의미적으로 더 적합합니다.

-@Configuration
+@Component
 @Profile("local")
 public class LocalDataInitializer implements ApplicationRunner {
src/main/java/team/wego/wegobackend/user/repository/FollowRepositoryImpl.java (1)

46-50: 메서드 이름 컨벤션 수정 권장

Java 메서드 이름은 소문자로 시작해야 합니다. ItCursorltCursor 또는 lessThanCursor로 변경하세요.

-    private BooleanExpression ItCursor(Long cursorFollowId) {
+    private BooleanExpression ltCursor(Long cursorFollowId) {
         return cursorFollowId == null
             ? null
             : QFollow.follow.id.lt(cursorFollowId);
     }

Line 39의 호출부도 함께 수정해야 합니다:

-                ItCursor(cursorFollowId)
+                ltCursor(cursorFollowId)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a13711 and 3fc8f26.

📒 Files selected for processing (13)
  • build.gradle (1 hunks)
  • src/main/java/team/wego/wegobackend/common/config/QuerydslConfig.java (1 hunks)
  • src/main/java/team/wego/wegobackend/common/support/LocalDataInitializer.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/presentation/GroupImageController.java (4 hunks)
  • src/main/java/team/wego/wegobackend/user/application/FollowService.java (2 hunks)
  • src/main/java/team/wego/wegobackend/user/application/dto/response/FollowListResponse.java (1 hunks)
  • src/main/java/team/wego/wegobackend/user/application/dto/response/FollowResponse.java (1 hunks)
  • src/main/java/team/wego/wegobackend/user/presentation/UserController.java (4 hunks)
  • src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java (3 hunks)
  • src/main/java/team/wego/wegobackend/user/repository/FollowRepository.java (1 hunks)
  • src/main/java/team/wego/wegobackend/user/repository/FollowRepositoryCustom.java (1 hunks)
  • src/main/java/team/wego/wegobackend/user/repository/FollowRepositoryImpl.java (1 hunks)
  • src/test/http/user/user-api.http (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
src/main/java/team/wego/wegobackend/user/application/FollowService.java (2)
src/main/java/team/wego/wegobackend/user/repository/FollowRepositoryImpl.java (1)
  • RequiredArgsConstructor (12-51)
src/main/java/team/wego/wegobackend/user/presentation/UserController.java (1)
  • Slf4j (34-184)
src/main/java/team/wego/wegobackend/user/presentation/UserController.java (2)
src/main/java/team/wego/wegobackend/user/repository/FollowRepositoryImpl.java (1)
  • RequiredArgsConstructor (12-51)
src/main/java/team/wego/wegobackend/user/application/FollowService.java (1)
  • Slf4j (20-87)
src/main/java/team/wego/wegobackend/common/config/QuerydslConfig.java (1)
src/main/java/team/wego/wegobackend/common/support/LocalDataInitializer.java (1)
  • Configuration (16-48)
src/main/java/team/wego/wegobackend/common/support/LocalDataInitializer.java (1)
src/main/java/team/wego/wegobackend/common/config/QuerydslConfig.java (1)
  • Configuration (9-19)
🔇 Additional comments (12)
src/main/java/team/wego/wegobackend/group/presentation/GroupImageController.java (1)

34-34: 멀티파트 요청 명시 추가를 승인합니다.

consumes = MediaType.MULTIPART_FORM_DATA_VALUE 속성 추가는 API 계약을 명확히 하고, 잘못된 Content-Type 헤더를 가진 요청을 거부하도록 합니다. 멀티파트 엔드포인트에 대한 모범 사례입니다.

src/main/java/team/wego/wegobackend/user/application/dto/response/FollowResponse.java (1)

1-29: 잘 구현된 DTO입니다

불변 객체로 설계되었고 QueryDSL 프로젝션을 위한 @QueryProjection 어노테이션이 적절히 사용되었습니다. 커서 페이지네이션을 위한 followId 필드도 명확하게 표시되어 있습니다.

src/test/http/user/user-api.http (1)

80-92: 효과적인 테스트 케이스 추가

커서 기반 페이지네이션의 초기 요청과 다음 페이지 요청을 모두 테스트하는 케이스가 잘 작성되었습니다. nextCursor 변수를 활용한 연속 요청 테스트도 적절합니다.

src/main/java/team/wego/wegobackend/user/repository/FollowRepository.java (1)

7-7: 표준 패턴에 따른 확장

FollowRepositoryCustom 인터페이스 확장을 통해 커스텀 쿼리 메서드를 추가하는 표준적인 접근 방식입니다.

src/main/java/team/wego/wegobackend/user/application/dto/response/FollowListResponse.java (1)

1-7: 간결하고 명확한 응답 구조

Java record를 사용한 불변 응답 DTO 설계가 적절합니다. 페이지네이션에 필요한 itemsnextCursor 필드가 명확하게 정의되어 있습니다.

src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java (1)

59-64: 잘 작성된 API 문서

파라미터 설명과 검증 제약조건이 명확하게 문서화되어 있습니다. 크기 제한(1-100)과 기본값(20) 설정도 적절합니다.

src/main/java/team/wego/wegobackend/user/application/FollowService.java (1)

77-79: 사용자 존재 확인은 적절합니다

existsById 체크를 통해 명확한 에러 메시지를 제공하는 것은 좋은 접근입니다. 추가 쿼리 비용이 발생하지만, 사용자 경험 측면에서 가치가 있습니다.

src/main/java/team/wego/wegobackend/user/repository/FollowRepositoryCustom.java (1)

6-13: LGTM!

커서 기반 페이지네이션을 위한 커스텀 레포지토리 인터페이스가 잘 정의되어 있습니다. Spring Data JPA의 Impl 접미사 규칙과 결합하여 사용될 수 있도록 설계되어 있습니다.

src/main/java/team/wego/wegobackend/common/support/LocalDataInitializer.java (1)

30-38: 평문 비밀번호 사용 확인 필요

비밀번호가 평문으로 저장되고 있습니다. 실제 로그인 테스트 시 PasswordEncoder로 인코딩된 비밀번호가 필요하다면, 여기서도 인코딩된 값을 사용해야 합니다. 로컬 테스트에서 인증 기능을 사용할 계획이라면 확인이 필요합니다.

src/main/java/team/wego/wegobackend/user/repository/FollowRepositoryImpl.java (1)

17-44: LGTM!

QueryDSL을 사용한 커서 기반 페이지네이션 구현이 잘 되어 있습니다. where 절에서 null 반환 시 조건이 무시되는 QueryDSL의 동작을 적절히 활용하고 있습니다.

src/main/java/team/wego/wegobackend/user/presentation/UserController.java (2)

60-60: LGTM!

consumes = MediaType.MULTIPART_FORM_DATA_VALUE 추가는 파일 업로드 엔드포인트에 적절한 명시적 선언입니다.


138-153: 팔로우 리스트 조회 API 구현 적절합니다.

커서 기반 페이지네이션 파라미터와 기본값 설정이 잘 되어 있습니다. userId를 PathVariable로 받아 다른 사용자의 팔로우 리스트도 조회할 수 있는 설계가 좋습니다.

Comment on lines +51 to +56
//QueryDSL
implementation 'com.querydsl:querydsl-jpa:5.1.0:jakarta'
annotationProcessor 'com.querydsl:querydsl-apt:5.1.0:jakarta'
annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# QueryDSL 최신 버전 확인
echo "=== QueryDSL 최신 버전 확인 ==="
curl -s "https://search.maven.org/solrsearch/select?q=g:com.querydsl+AND+a:querydsl-jpa&rows=5&wt=json" | jq -r '.response.docs[] | "\(.v)"' | head -5

echo ""
echo "=== Maven Central에서 5.1.0 검색 ==="
curl -s "https://search.maven.org/solrsearch/select?q=g:com.querydsl+AND+a:querydsl-jpa+AND+v:5.1.0&wt=json" | jq -r '.response.docs[] | "Version: \(.v), Timestamp: \(.timestamp)"'

Repository: WeGo-Together/WeGo_BackEnd

Length of output: 175


🏁 Script executed:

#!/bin/bash
# Maven Central에서 QueryDSL 정보 더 자세히 확인
echo "=== Maven Central API로 최신 버전 확인 ==="
curl -s "https://search.maven.org/solrsearch/select?q=g:com.querydsl+AND+a:querydsl-jpa&rows=20&wt=json&sort=timestamp+desc" | jq '.response.docs[0:5] | .[] | {version: .v, timestamp: .timestamp}'

echo ""
echo "=== QueryDSL 보안 정보 확인 ==="
# NVD에서 QueryDSL 취약점 확인
curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=querydsl" | jq '.vulnerabilities[]? | {id: .cve.id, summary: .cve.descriptions[0].value}' | head -20

Repository: WeGo-Together/WeGo_BackEnd

Length of output: 497


🏁 Script executed:

#!/bin/bash
# QueryDSL 5.1.x 및 6.x 버전 확인
echo "=== QueryDSL 5.1.x 패치 버전 확인 ==="
curl -s "https://search.maven.org/solrsearch/select?q=g:com.querydsl+AND+a:querydsl-jpa+AND+v:5.1.*&rows=10&wt=json" | jq '.response.docs[] | {version: .v, timestamp: .timestamp}' | sort

echo ""
echo "=== QueryDSL 최신 안정 버전 (6.x) 확인 ==="
curl -s "https://search.maven.org/solrsearch/select?q=g:com.querydsl+AND+a:querydsl-jpa&rows=30&wt=json" | jq '.response.docs | sort_by(.timestamp) | reverse | .[0:3] | .[] | {version: .v, timestamp: .timestamp}'

echo ""
echo "=== CVE-2024-49203 상세 정보 ==="
curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=CVE-2024-49203" | jq '.vulnerabilities[0] | {id: .cve.id, published: .cve.published, modified: .cve.lastModified, severity: .containers.cna.metrics[0].cvssV3_1.baseScore}'

Repository: WeGo-Together/WeGo_BackEnd

Length of output: 406


QueryDSL 5.1.0에 SQL/HQL 인젝션 취약점(CVE-2024-49203) 발견

현재 사용 중인 QueryDSL 5.1.0에 CVE-2024-49203 취약점이 있습니다(2024년 11월 공개). 이는 JPAQuery의 orderBy에서 SQL/HQL 인젝션을 허용하는 취약점입니다. 신뢰할 수 없는 입력값을 orderBy에 직접 사용하지 않는다면 즉시적인 위험은 낮지만, 5.1.0은 패치 버전이 없으므로 최신 버전으로 업그레이드하는 것을 권장합니다.

🤖 Prompt for AI Agents
In build.gradle around lines 51 to 56, QueryDSL 5.1.0 is used which is
vulnerable to CVE-2024-49203; replace the QueryDSL coordinates (implementation
and both annotationProcessor entries) with a patched QueryDSL release (upgrade
5.1.0 → the latest patched version that addresses CVE-2024-49203), update the
version consistently for all three entries, refresh Gradle dependencies (e.g.,
./gradlew --refresh-dependencies), rebuild and run tests, and audit any use of
JPAQuery.orderBy to ensure untrusted input is not directly passed (sanitize or
whitelist ordering fields if needed).

Comment on lines +141 to +146
@GetMapping("/{userId}/follow")
public ResponseEntity<ApiResponse<FollowListResponse>> followList(
@PathVariable Long userId, //다른 유저 조회를 위한 파라메터
@RequestParam(required = false) Long cursor,
@RequestParam(defaultValue = "20") @Min(1) @Max(100) Integer size
) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n src/main/java/team/wego/wegobackend/user/presentation/UserController.java | head -20

Repository: WeGo-Together/WeGo_BackEnd

Length of output: 1201


🏁 Script executed:

rg -n "@Validated|@RestController|@RequestMapping" src/main/java/team/wego/wegobackend/user/presentation/UserController.java | head -20

Repository: WeGo-Together/WeGo_BackEnd

Length of output: 125


🏁 Script executed:

sed -n '30,45p' src/main/java/team/wego/wegobackend/user/presentation/UserController.java

Repository: WeGo-Together/WeGo_BackEnd

Length of output: 587


클래스에 @Validated 어노테이션 추가 필요

@RequestParam@Min(1)@Max(100) 검증이 작동하려면 컨트롤러 클래스에 @Validated 어노테이션이 필수입니다. 현재 클래스 선언부에 해당 어노테이션이 없습니다.

클래스 선언부에 @Validated 추가:

+import org.springframework.validation.annotation.Validated;
+
 @Slf4j
 @RestController
 @RequiredArgsConstructor
+@Validated
 @RequestMapping("/api/v1/users")
 public class UserController implements UserControllerDocs {

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/team/wego/wegobackend/user/presentation/UserController.java
around lines 141 to 146, the @Min/@Max constraints on the @RequestParam 'size'
won't be enforced because the controller class is missing the Spring Validation
trigger; add the @Validated annotation to the controller class declaration
(importing org.springframework.validation.annotation.Validated if needed) so
that parameter-level JSF validation annotations are activated by Spring MVC.

@Be-HinD Be-HinD merged commit a300d3f into main Dec 13, 2025
1 check passed
@Be-HinD Be-HinD deleted the feat/follow-list branch December 13, 2025 10:25
@github-project-automation github-project-automation bot moved this from Backlog to Done in WeGo-Together Backend Dec 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[FEAT] 팔로우 리스트 조회

1 participant