Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[✨3주차 실습 과제 제출✨] #8

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

[✨3주차 실습 과제 제출✨] #8

wants to merge 7 commits into from

Conversation

JungYoonShin
Copy link
Member

@JungYoonShin JungYoonShin commented May 1, 2024

1️⃣ 글 작성 API (PostController, PostService 쪽 봐주시면 됩니다!)

Request Header로 memberId와 blogId를 전달 받아 저장하도록 했습니다!

블로그를 소유하지 않은 사용자가 해당 블로그에 글을 작성할 경우, 아래와 같이 CustomException을 발생시키도록 했습니다!
CustomExceptionRuntimeException을 상속받는 커스텀 예외 클래스입니다.

Blog blog = blogRepository.findById(blogId).orElseThrow(
()-> new NotFoundException(ErrorCode.BLOG_NOT_FOUND)
);
if (!memberId.equals(blog.getMember().getId())) {
throw new CustomException(ErrorCode.NOT_BLOG_OWNER);
}


2️⃣ 글 단건 조회 API (PostController, PostService 쪽 봐주시면 됩니다!)

Path Variable로 postId 전달받아서 상세 내용(dto)을 반환하도록 했습니다!

@Transactional(readOnly = true)
public PostDetailResponse getSinglePost(final Long postId) {
return PostDetailResponse.of(findPostById(postId));
}


🌊 새롭게 적용한 것들

1️⃣ GlobalExceptionHandler - Validation 예외처리 리팩토링

DTO 여러 필드에서 Vallidation Exception이 발생했을 경우을 위해 ErrorResponse를 다음과 같이 수정해보았습니다!

public record ErrorResponse(
int httpStatus,
String message,
@JsonInclude(JsonInclude.Include.NON_NULL)
List<ValidationError> errors
) {
public static ErrorResponse of(int httpStatus, String message){
return ErrorResponse.builder()
.httpStatus(httpStatus)
.message(message)
.build();
}
public static ErrorResponse of(int httpStatus, String message, BindingResult bindingResult){
return ErrorResponse.builder()
.httpStatus(httpStatus)
.message(message)
.errors(ValidationError.of(bindingResult))
.build();
}
@Getter
public static class ValidationError {
private final String field;
private final String message;
private ValidationError(FieldError fieldError){
this.field = fieldError.getField();
this.message = fieldError.getDefaultMessage();
}
public static List<ValidationError> of(final BindingResult bindingResult){
return bindingResult.getFieldErrors().stream()
.map(ValidationError::new)
.toList();
}
}
}

  • postman 실행 화면
image

2️⃣ Swagger를 통한 API 명세 자동화 적용 (SwaggerConfig, PostControllerConfig 및 DTO에 Data Schema 적용해주었습니다!)

처음 시도해보는 건데, 민재님의 아티클을 참고해서 적용해보았습니다! (민재님께 무한한 감사를...🙇‍♀️)
아직 제대로 잘하지는 못했고,,,(시간부족이슈...) 추후 보완해나가겠습니다..!!



📄 API 명세서 (사진으로 첨부하겠습니다!)

  • 글 작성 API
image

  • 글 단건 조회 API
image

🙋‍♀️ 질문 있습니다!

1️⃣ 세미나에서 멤버의 식별자의 경우는 중요한 정보라고 하셔서 PathVariable이 아니라, 헤더를 통해 memberId를 받았었는데, 이번 과제하면서 글 작성의 경우 blogId값을 받고 있는데, 이것도 Request Header로 받아오는 게 적합한지, Path Variable로 받아오는 게 적합할지 궁금합니다!

@softmoca
Copy link
Member

softmoca commented May 3, 2024

정윤님 과제 하시느라 너무너무 고생 많으셨습니다 !

스웨거 까지 적용하셨다니 !! 처음 작성해보신 스웨거 문서 너무 멋집니다 !
새로운 방법을 학습하셔서 적용하시는 모습이 너무 좋은것 같아요 !

질문 있습니다 부분에서 질문에 대해 blogId 또한 PathVariable 보단 header를 통해 통신 하는것이 좋다는 주장이 조금 더 많은 것 같습니다.
식별자(PK, ID)와 같은 내용들은 이왕이면 잘 보이는 url보다는 요청의 헤더에 숨겨서 보내는것이 보안에 더 좋다는 이유 때문 인것 같습니다 !

하지만 서비스 요구사항과 시스템 특성상 헤더 보다 PathVariable을 사용하는것이 나을 때가 있어 정해진 정답은 없는것 같습니다 !
저 또한 사용자 혹은 관리자 등등 과 같은 보안적으로 신경을 써야 하는 엔티티가 아닌 이상 대부분의 id를 PathVariable를 사용하긴 합니다 !
또한 티스토리 혹은 벨로그 에브리타임 같은 경우에도 PathVariable을 사용하는것 같더라구요 !

저도 다른 분들의 의견이 궁금하네요 !
다른 분들의 좋은 의견 있으면 공유 부탁드릴게요 ~

과제 하시느라 너무 고생 많으셨습니다 !

Copy link
Contributor

@sohyundoh sohyundoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정윤이 과제하느라 고생했습니다!

현재 클론코딩 과제와 한번에 올라왔으니 확인해보면 좋을 것 같아요!
헤더 통신과 관련하여.. 우선 저희가 JWT 토큰 방식의 인증을 사용할 때 헤더통신을 사용하죠! 그래서 멤버 식별자도 이처럼 중요한 정보인 것을 가정하며 헤더로 통신한 것입니다! 이 외는 헤더로 통신할 필요(!?)는 없을 수 있습니다! 정윤님이 적절한 것을 생각해보면 좋을 것 같아요!

화이팅입니다-!

import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import할 때 이렇게 종종 5개 정도 같은 라이브러리에서 불러오다 보면 *로 변환되게 되는데요!(인텔리제이에서 자동으로 해줍니다)
그런데 간혹가다 클래스의 이름이 동일해 라이브러리를 많이 참조할 경우 혼란이 될 수 있습니다!
와일드카드 import를 방지하는 방법이 담긴 블로그를 공유드립니다 -!

https://dev-kani.tistory.com/39


// 블로그 관련 에러 200번대
BLOG_NOT_FOUND(HttpStatus.NO_CONTENT.value(), 2001, "ID에 해당하는 블로그가 존재하지 않습니다."),
NOT_BLOG_OWNER(HttpStatus.BAD_REQUEST.value(), 2002, "해당 블로그의 소유자가 아니므로 작성 권한이 없습니다."),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

권한 에러를 BAD_REQUEST 로 보내는 것에 대한 의견을 받아보고 싶네요!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FEAT 기능 추가
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants