IllegalArgumentException
오류 발생REST API를 호출할 때 다음과 같은 오류가 발생했습니다:
java.lang.IllegalArgumentException: Name for argument of type [java.lang.Long] not specified, and parameter name information not available via reflection. Ensure that the compiler uses the '-parameters' flag.
이 오류는 Spring이 런타임에 메서드 인자의 이름을 확인할 수 없어서 발생하였습니다. 더 자세히 말하자면, @PathVariable
또는 @RequestParam
어노테이션이 있는 메서드 인자가 명시적으로 이름이 지정되지 않았을 때 발생합니다. 자바 컴파일러가 기본적으로 메서드 인자 이름을 클래스 파일에 포함하지 않기 때문에, Spring이 해당 정보를 사용할 수 없게 되기 때문에 생긴 문제입니다.
빌드 설정 수정: build.gradle
파일에서 JavaCompile
태스크에 -parameters
플래그를 추가하여 자바 컴파일러가 메서드 인자 이름 정보를 클래스 파일에 포함하도록 설정했습니다.
tasks.withType(JavaCompile).configureEach {
options.compilerArgs += ["-parameters"]
}
컨트롤러 메서드 수정: @PathVariable
및 @RequestParam
어노테이션에 명시적으로 이름을 지정했습니다.
@GetMapping("/cpUsers/{cpUserId}/reviews")
public ResponseEntity<GlobalApiResponse<UserReviewListResponseDTO>> getReviewsWithVisibility(
@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable("cpUserId") Long cpUserId,
@RequestParam("page") int page,
@RequestParam("size") int size) {
// 메서드 구현
}
@PostMapping("/reviews/{reviewId}/view")
public ResponseEntity<GlobalApiResponse<ReviewResponseDTO>> viewReview(
@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable("reviewId") Long reviewId) {
// 메서드 구현
}
이러한 수정 후, IllegalArgumentException
오류가 발생하지 않고, API가 정상적으로 작동했습니다. 이를 통해 컴파일러 플래그와 메서드 인자 이름의 중요성을 이해하게 되었습니다.
복잡한 쿼리를 작성하기 위해 QueryDSL을 사용하려고 했으나, 설정 문제로 인해 제대로 작동하지 않았습니다.
QueryDSL은 JPA와 함께 사용될 때, 적절한 설정과 의존성이 필요합니다. 특히, 컴파일 타임에 QueryDSL 관련 클래스를 생성하기 위해서는 빌드 설정이 올바르게 구성되어 있어야 합니다. 초기 설정에서는 이러한 부분이 누락되어 문제가 발생했습니다.
QueryDSL 의존성 추가: build.gradle
파일에 QueryDSL 관련 의존성을 추가했습니다.
dependencies {
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
}
빌드 설정 수정: QueryDSL의 소스 생성 디렉토리를 설정하고, 컴파일러가 이를 인식하도록 빌드 설정을 수정했습니다.
def generated = 'src/main/generated'
sourceSets {
main {
java {
srcDirs = ['src/main/java', generated]
}
}
}
tasks.named('clean') {
delete generated
}
tasks.withType(JavaCompile).configureEach {
options.annotationProcessorPath = configurations.querydsl
options.generatedSourceOutputDirectory = file(generated)
}
querydsl {
library = "com.querydsl:querydsl-apt"
jpa = true
querydslSourcesDir = generated
}
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}
tasks.withType(JavaCompile).matching { task -> task.name != 'compileQuerydsl' }.configureEach {
dependsOn compileQuerydsl
}
QueryDSL 설정 후, 복잡한 쿼리를 문제없이 작성하고 실행할 수 있었습니다. 이를 통해 빌드 설정의 중요성과 QueryDSL의 유용성을 다시 한 번 확인할 수 있었습니다.
대량의 데이터를 처리할 때, 페이지네이션이 제대로 작동하지 않는 문제를 겪었습니다. 이는 성능 문제로 이어질 수 있었습니다.
페이지네이션을 구현하기 위해 Pageable
및 PageRequest
를 사용하지 않았거나, 잘못 사용하여 문제가 발생했습니다.
페이지네이션 구현: 서비스 레이어에서 Pageable
및 PageRequest
를 사용하여 데이터를 페이징 처리하도록 수정했습니다.
@Service
@RequiredArgsConstructor
public class ReviewService {
private final ReviewRepository reviewRepository;
private final UserReviewStatusRepository userReviewStatusRepository;
private final UserRepository userRepository;
@Transactional(readOnly = true)
public UserReviewListResponseDTO getReviewsWithVisibility(Long cpUserId, Long userId, int page, int size) {
Pageable pageable = PageRequest.of(page, size);
Page<Review> reviews = reviewRepository.findReviewsByCpUser_CpUserId(cpUserId, pageable);
List<UserReviewStatus> statuses = userReviewStatusRepository.findByUserAndReviewIn(userRepository.findById(userId)
.orElseThrow(() -> new ApiException(ErrorCode.USER_NOT_FOUND)), reviews.getContent());
return new UserReviewListResponseDTO(reviews, statuses);
}
}
컨트롤러 수정: 페이지네이션을 지원하도록 컨트롤러 메서드를 수정했습니다.
@GetMapping("/cpUsers/{cpUserId}/reviews")
public ResponseEntity<GlobalApiResponse<UserReviewListResponseDTO>> getReviewsWithVisibility(
@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable("cpUserId") Long cpUserId,
@RequestParam("page") int page,
@RequestParam("size") int size) {
Long userId = userDetails.getUserId();
UserReviewListResponseDTO responseDTO = reviewService.getReviewsWithVisibility(cpUserId, userId, page, size);
return ResponseEntity.status(SUCCESS_CP_USER_REVIEW_READ.getHttpStatus())
.body(
GlobalApiResponse.of(
SUCCESS_CP_USER_REVIEW_READ.getMessage(),
responseDTO
)
);
}
페이지네이션 기능이 정상적으로 작동하여 대량의 데이터를 효율적으로 처리할 수 있었습니다. 이를 통해 페이지네이션의 중요성을 실감할 수 있었으며, 대규모 데이터를 처리할 때 발생할 수 있는 성능 문제를 해결할 수 있었습니다.