본문 바로가기

Programming/Spring

[Spring] @PathVariable을 통한 URI 설정 시 점(.) 이후의 값이 생략되는 현상

반응형
이메일 입력값에서 점(.) 이후의 값이 잘려서 넘어온다?

 

이메일 중복 확인 테스트가 계속 실패했다. 

먼저 코드를 확인해보자. 아래 코드는 Controller 클래스의 메소드 그리고 해당 메소드의 테스트 코드이다.

 

구현 코드

@GetMapping("/email/{userEmail}")
public ResponseEntity<Void> checkUserEmail(@PathVariable("userEmail") String userEmail) {
	try {
		service.isExistUserEmail(userEmail);
	} catch (EmailAlreadyExistsException e) {
		return new ResponseEntity<Void>(HttpStatus.CONFLICT);
	}
	return new ResponseEntity<Void>(HttpStatus.OK);
}

 

테스트 코드

@Test
public void C_이메일_중복_확인_테스트() throws Exception {
	mockMvc.perform(get("/users/email/tomato@naver.com")
			.contentType(MediaType.APPLICATION_JSON)
			.accept(MediaType.APPLICATION_JSON))
			.andDo(print())
			.andExpect(status().isConflict());
	}

 

tomato@naver.com이 DB에 저장되어 있는지 중복 여부를 확인하는 테스트. 이미 해당 이메일 주소는 DB에 삽입되어 있으므로 409 상태 코드를 반환해야 한다. 그런데 계속 200 상태 코드를 반환했다. 즉 해당 이메일 주소가 DB에 없다는 것이다. 

 

로그에 출력된 SQL 구문은 다음과 같다.

이상하다. .com 없이 tomato@naver만 출력되었다. 점(.)과 함께 점(.) 뒤의 글자가 인식되지 않은 것이다.

 

SELECT COUNT(user_email) FROM site_user WHERE user_email = 'tomato@naver'

 

스프링은 점(.) 뒤의 문자는 파일 확장자로 인식한다. ( .json / .xml)
따라서 이메일 주소 뒤의 .com을 파일 확장자로 인식해서 .com을 잘라버린 것이다. tomato@naver를 파라미터 값으로 사용하기 위해서.

 

이렇게 해결했습니다.

 

첫 번째 방법은 점(.)이 삽입되는 @PathVariable 변수에 :.* 를 추가하는 것.

{userEmail:.+}로 입력해도 작동한다.

 

@GetMapping("/email/{userEmail:.*}")
public ResponseEntity<Void> checkUserEmail(@PathVariable("userEmail") String userEmail) {
	try {
		service.isExistUserEmail(userEmail);
	} catch (EmailAlreadyExistsException e) {
		return new ResponseEntity<Void>(HttpStatus.CONFLICT);
	}
	return new ResponseEntity<Void>(HttpStatus.OK);
}

 

두 번째 방법은 슬래시(/) 기호를 통해 해당 값은 URI 값으로 사용되는 것이라고 스프링에 알리는 것이다. 

이 방법으로 테스트 해보니 404 상태값을 반환한다. 슬래시를 통해 다음 자원으로 이동하도록 URI를 수정했지만, 더 이상 추가 경로를 입력하지 않았기 때문이다. userEmail 값 이후로 더이상 추가될 값이 없기 때문에 본인의 경우 이 방법을 사용할 수 없다. 따라서 URI의 마지막이 아닌 중간에 값이 삽입되는 경우 유용하게 사용할 수 있겠다.

 

@GetMapping("/email/{userEmail}/")
public ResponseEntity<Void> checkUserEmail(@PathVariable("userEmail") String userEmail) {
	try {
		service.isExistUserEmail(userEmail);
	} catch (EmailAlreadyExistsException e) {
		return new ResponseEntity<Void>(HttpStatus.CONFLICT);
	}
	return new ResponseEntity<Void>(HttpStatus.OK);
}

 

세 번째 방법은 @Configuration 어노테이션을 사용해 스프링 설정 클래스를 생성하여 프로젝트 전역에 걸쳐 영향을 받도록 설정하는 것이다. 해당 코드는 아래 참고 링크를 통해 얻을 수 있다.

 

참고

https://www.baeldung.com/spring-mvc-pathvariable-dot

반응형