본문 바로가기
Spring/공부 & 트러블 슈팅

일정 관리 프로그램 프로젝트 트러블슈팅 (Ambiguous handler methods 이슈 등)

by 정구정구 2026. 6. 26.

결과물 : https://github.com/wjdals0508/ScheduleProject

 

GitHub - wjdals0508/ScheduleProject

Contribute to wjdals0508/ScheduleProject development by creating an account on GitHub.

github.com

 

 

JpaAuditing 이슈

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {

    // Jpa Auditing

    @CreatedDate
    @Column(updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime modifiedAt;

}

 

작성일/수정일 처리를 위해, JpaAuditing 기능을 포함한 BaseEntity를 만들어 다른 모든 Entity에 상속시켰다. 

@Getter
@Entity
@Table(name = "comments")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Comment extends BaseEntity { // 상속됨

    ...
}

 

하지만 테스트 결과 CreatedAt과 modifiedAt에 내용이 들어있지 않았다. 원인을 찾아보니, 실행 메서드에 어노테이션 추가를 깜빡했었다.

@EnableJpaAuditing // JpaAuditing 활성화
@SpringBootApplication
public class ScheduleProjectApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScheduleProjectApplication.class, args);
    }

}

 

위 코드를 추가하니 아래와 같이 정상적으로 작동한다.

 

 

Ambiguous handler methods 이슈

GET http://localhost:8080/schedules/7

 

Get 메서드 테스트를 위해 위와 같이 url을 쐈는데 아래와 같은 에러가 발생했다.

Ambiguous handler methods mapped for '/schedules/7'

 

에러에 대해 찾아보니, GET /schedules/7 요청을 처리할 메서드가 2개라서 스프링이 어떤 메서드를 호출해야 할지 몰라서 발생한 에러였다. 

    // 일정 단건 조회
    @GetMapping("/schedules/{id}")
    public ResponseEntity<GetScheduleResponse> getOne(
            @PathVariable Long id) {
        GetScheduleResponse result = scheduleService.getOne(id);
        return ResponseEntity.status(HttpStatus.OK).body(result);
    }
    
    // 일정 다수 조회 (작성자명 입력 가능)
    @GetMapping("/schedules/{authorName}")
    public ResponseEntity<List<GetScheduleResponse>> getAll(
            @PathVariable String authorName) {
        List<GetScheduleResponse> result = scheduleService.getAll(authorName);
        return ResponseEntity.status(HttpStatus.OK).body(result);
    }

 

 getAll 함수에 작성자명 변수를 추가하다가 getOne 메서드와 처리가 중복되게 만들어져 버린게 원인이었다.

    // 일정 단건 조회
    @GetMapping("/schedules/{id}")
    public ResponseEntity<GetScheduleResponse> getOne(
            @PathVariable Long id) {
        GetScheduleResponse result = scheduleService.getOne(id);
        return ResponseEntity.status(HttpStatus.OK).body(result);
    }

    // 일정 다수 조회 (작성자명 입력 가능)
    @GetMapping("/schedules")
    public ResponseEntity<List<GetScheduleResponse>> getAll(
            @RequestParam(required = false) String authorName) {
        List<GetScheduleResponse> result = scheduleService.getAll(authorName);
        return ResponseEntity.status(HttpStatus.OK).body(result);
    }

 

getAll 메서드의 URL 설계를 getOne 메서드와 다르게 하여 수정하면

GET http://localhost:8080/schedules/7

 

getOne 메서드는 위와 같이 요청 해야하고,

GET http://localhost:8080/schedules?authorName=

 

getAll 메서드는 위와 같이 요청 해야해서 스프링이 이 둘을 구분 할 수 있게된다.

(겸사겸사 작성자명이 비어 있을 경우, 모든 일정을 검색해야 한다는 요구사항도 챙길 수 있게 required = false도 선언했다.)