Programming/Spring

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

Cafe_Caramelo 2022. 2. 12. 21:33
반응형
이메일 입력값에서 점(.) 이후의 값이 잘려서 넘어온다?

 

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

먼저 코드를 확인해보자. 아래 코드는 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

반응형