본문 바로가기
Project/DelFood

[이슈 #3] 아이디 중복 체크시 Http Status값을 어떻게 설정해야 할까?

by EricJeong 2019. 10. 6.

 

 

아이디 중복 체크를 했을 때 HttpStatus값을 어떻게 설정해서 넘겨줘야 할지 고민입니다.

HttpStatus Enum을 하나하나 읽어보며 어떤 것을 적용할 지 고민해보았습니다.


 

ID 중복체크 소스코드

/**
	 * 회원가입 시 아이디의 중복체크를 진행한다.
	 * 아이디 중복체크는 회원가입 아이디 입력 후, 회원가입 요청시 두번 진행한다.
	 * 아이디 중복체크를 한 후 회원가입 버튼을 누를 때 까지 동일한 아이디로 누군가 가입한다면 PK Error가 발생되고
	 * 실제로 회원가입이 진행되지 않을 수 있기 때문에 회원가입을 눌렀을 때 한번 더 실행하는 것이 좋다.
	 * @param id
	 * @return
	 */
	@GetMapping("idCheck/{id}")
	public ResponseEntity<MemberIdDuplResponse> idCheck(@PathVariable String id) {
		ResponseEntity<MemberIdDuplResponse> responseEntity = null;
		MemberIdDuplResponse duplResponse;
		boolean idDuplicated = memberService.isDuplicatedId(id);
		if(idDuplicated) {
			// 아이디가 중복되어있을 때
			duplResponse = MemberIdDuplResponse.DUPLICATED;
			responseEntity = new ResponseEntity<>(duplResponse, HttpStatus.~~~~~);
		}else {
			// 아이디가 중복되어있지 않을 때
			duplResponse = MemberIdDuplResponse.SUCCESS;
			responseEntity = new ResponseEntity<>(duplResponse, HttpStatus.OK);
		}
		return responseEntity;
	}

 

 

423 Locked

HttpStatus Enum에는 다양한 HttpStatus를 제공하고 참고할 수 있는 도큐먼트를 제공하고 있습니다. 일단 상태 이름만 보고 제일 처음 눈에 들어온 것은 Locked(423) 입니다.

/**
	 * {@code 423 Locked}.
	 * @see <a href="https://tools.ietf.org/html/rfc4918#section-11.3">WebDAV</a>
	 */
	LOCKED(423, "Locked"),

Id 리소스가 이미 있으니 더 이상 이 Id를 사용할 수 없다고 판당하여 잠금 상태를 주면 되지 않을까? 라고 생각을 하였지만 웹 API에서는 423 코드가 생소했기에 @see에 있는 링크를 참고해 보았습니다.

11.3. 423 Locked

The 423 (Locked) status code means the source or destination resource of a method is locked. This response SHOULD contain an appropriate precondition or postcondition code, such as 'lock-token-submitted' or 'no-conflicting-lock'.

 

423 Locked

423 상태값은 소스 메서드의 자원이 잠겼음을 의미합니다. 'lock-token-submitted' 또는 'no-conflicting-lock'와같은

전제조건, 사후조건을 포함해야 합니다.

 

423 코드는 자원의 잠금이 아닌 메서드의 잠금을 의미하고 있었습니다. 이러한 상태값은 제가 원하는 ID 리소스에 대한 응답 방식이 아니었기 때문에 사용하기엔 적합하지 않다고 판단하고 다른 값을 더 찾아보았습니다.

 

 


403 Forbidden

다음으로 고려해본 상태 코드는 403 Forbidden입니다.

Id 접근을 금지하는 상태코드로 사용할 수 있다고 생각하였고 도큐먼트를 읽어보았습니다.

/**
	 * {@code 403 Forbidden}.
	 * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.3">HTTP/1.1: Semantics and Content, section 6.5.3</a>
	 */
	FORBIDDEN(403, "Forbidden"),

10.4.4 403 Forbidden

The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.

403 Forbidden

서버에서 요청을 정상적으로 이해하였지만 요청을 이행하는 것을 거부하였습니다. 권한 부여는 도움이 되지 않으며 반복적인 요청이 지양됩니다. 서버가 이 정보를 클라이언트에게 제공하는 것을 원하지 않는다면 404 Not Found 상태코드를 대신 사용할 수 있습니다.

 

403 상태코드에 대해 찾아보니 인가(Authorization) 실패 상태 코드라고 합니다. 비밀번호 등의 유효성 검사에 대한 응답으로 많이 쓰인다고 하여 403 코드를 사용하는 것은 문제가 없을 것이라고 생각합니다.

 


409 Conflict

403과 비교할만한 상태코드는 409 Conflict 입니다.

 

 

/**
	 * {@code 409 Conflict}.
	 * @see <a href="https://tools.ietf.org/html/rfc7231#section-6.5.8">HTTP/1.1: Semantics and Content, section 6.5.8</a>
	 */
	CONFLICT(409, "Conflict")

 

6.5.8. 409 Conflict The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request. The server SHOULD generate a payload that includes enough information for a user to recognize the source of the conflict. Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the representation being PUT included changes to a resource that conflict with those made by an earlier (third-party) request, the origin server might use a 409 response to indicate that it can't complete the request. In this case, the response representation would likely contain information useful for merging the differences based on the revision history.

409 Conflick

대상 리소스의 현재 상태와 충돌하여 요청을 완료할 수 없음을 뜻합니다. 이 코드는 사용자가 충돌을 해결하고 다시 요청을 보낼 수 있을 때 적합합니다. 서버는 사용자가 충돌을 해결할 수 있도록 적합한 페이로드를 생성해야 합니다. PUT 요청에 대해 충돌할 가능성이 가장 높습니다.  예를 들어, 버전 지정이 사용 중이고 PUT인 표현에 이전(제3자) 요청에 의해 수행된 것과 상충되는 자원에 대한 변경사항이 포함된 경우, 원본 서버는 요청을 완료할 수 없음을 나타내기 위해 409 응답을 사용할 수 있습니다.

 

409 Conflict 코드는 리소스가 충돌이 발생하였고 사용자가 이를 반영할 수 있을 때 발생하는 상태 코드입니다. 아이디 중복 체크에서는 사용자가 충돌되지 않는 다른 아이디를 사용하여 충돌을 해결해야 하기 때문에 이 상태 코드도 적합하다고 생각하였습니다. 409 코드에 대하여 조사해보니 다른 웹 사이트에서도 ID 중복 발생 시 409 코드를 많이 쓴다고 현업자 분들의 의견이 달려있는 것을 확인하였습니다.

 


결론

423 Locked는 ID 중복체크와는 관계가 없는 상태코드입니다. 사용할 수 없습니다.

403 Forbidden은 Id 중복체크 보다는 데이터의 유효성이나 인가 실패에 사용하는 코드입니다. Id 중복체크에 사용이 가능할 것이라고 생각하지만 ID가 중복되었다는 상태에 대한 명확한 처리는 아니라고 생각합니다.

409 Conflict는 리소스의 충돌을 의미하는 상태코드입니다. ID 중복이라는 것은 결국 ID라는 PK 자원을 점유한 것에 대한 충돌이기 때문에 이 상태코드가 가장 적합하다고 생각하여 409 상태코드를 반영하기로 했습니다.

 

409 상태코드를 반영하여 변경된 소스코드는 아래와 같습니다.

	/**
	 * 회원가입 시 아이디의 중복체크를 진행한다.
	 * 아이디 중복체크는 회원가입 아이디 입력 후, 회원가입 요청시 두번 진행한다.
	 * 아이디 중복체크를 한 후 회원가입 버튼을 누를 때 까지 동일한 아이디로 누군가 가입한다면 PK Error가 발생되고
	 * 실제로 회원가입이 진행되지 않을 수 있기 때문에 회원가입을 눌렀을 때 한번 더 실행하는 것이 좋다.
	 * @param id
	 * @return
	 */
	@GetMapping("idCheck/{id}")
	public ResponseEntity<MemberIdDuplResponse> idCheck(@PathVariable String id) {
		ResponseEntity<MemberIdDuplResponse> responseEntity = null;
		MemberIdDuplResponse duplResponse;
		boolean idDuplicated = memberService.isDuplicatedId(id);
		if(idDuplicated) {
			// 아이디가 중복되어있을 때
			duplResponse = MemberIdDuplResponse.DUPLICATED;
			responseEntity = new ResponseEntity<>(duplResponse, HttpStatus.CONFLICT);
		}else {
			// 아이디가 중복되어있지 않을 때
			duplResponse = MemberIdDuplResponse.SUCCESS;
			responseEntity = new ResponseEntity<>(duplResponse, HttpStatus.OK);
		}
		return responseEntity;
	}

 

댓글