-
Notifications
You must be signed in to change notification settings - Fork 8
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
해커톤 작업 내역을 리팩토링 #94
해커톤 작업 내역을 리팩토링 #94
Conversation
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드에서 고민의 흔적이 많이 보입니다👍 수고하셨어요!
리뷰 확인해주시면 감사하겠습니다 🍀
+) 추가로 변경 사항에 잡히지 않는 swagger 클래스들(ex.
SpringDocTemplateController
)도 확인해주시면 좋을 것 같아요!
이번 pr부터 검증 로직이 들어갔는데, 실패 케이스에 대해서도 문서화를 진행해주어야 프론트엔드 개발자가 예외 메시지나 포맷을 확인하고 처리를 수월하게 할 수 있습니다
backend/src/main/java/codezap/global/auditing/JpaAuditingConfiguration.java
Show resolved
Hide resolved
backend/src/main/java/codezap/global/serializing/DateTimeFormatConfiguration.java
Outdated
Show resolved
Hide resolved
backend/src/main/java/codezap/template/controller/TemplateController.java
Outdated
Show resolved
Hide resolved
String content, | ||
@NotNull(message = "스니펫 순서가 null 입니다.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
순서는 0부터 시작인가요?
순서 검증이 필요할 것 같아요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 부분은 공부를 조금 더 해보고 적용해야 할 것 같아 이슈로 열어놓고 추후에 추가하도록 하겠습니다.
backend/src/test/java/codezap/template/service/TemplateServiceTest.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
개발 할 때 열띤 토론을 하시던데, 그 과정이 아깝지 않을 정도로 코드 굿 😊 수고하셨습니다 👍🏻
코멘트로 제 의견을 좀 남겨놨어요 ! 확인해보시고 괜찮다고 생각하는 의견만 수용해주세요. (모두 다 수용하실 필요 없습니다 ~! )
@RestControllerAdvice | ||
public class GlobalExceptionHandler { | ||
|
||
@ExceptionHandler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사소하지만 @ExceptionHandler
를 @ExceptionHandler(CodeZapException.class)
로 해당 메서드가 어떤 exception을 처리하는지 명시해주면 좋을 것 같아요 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
메서드명과 매개변수만으로도 충분히 어떤 exception을 처리하는지 알 수 있다고 생각해서 불필요한 코드라고 판단하였습니다.
backend/src/main/java/codezap/global/exception/GlobalExceptionHandler.java
Outdated
Show resolved
Hide resolved
backend/src/main/java/codezap/global/exception/GlobalExceptionHandler.java
Outdated
Show resolved
Hide resolved
backend/src/main/java/codezap/template/controller/TemplateController.java
Outdated
Show resolved
Hide resolved
@ManyToOne | ||
@JoinColumn(name = "member_id", nullable = false) | ||
private Member member; | ||
|
||
@Column(nullable = false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
join된 컬럼에만 이름 설정을 해줬네요! 그냥 컬럼에는 이름 설정을 하지 않은 이유가 있을까요?
저 같은 경우에는 코드의 일관성, 읽기 편리함, 변수명 변경에 컬럼에 영향을 주지 않음 과 같은 이유로 컬럼이 변수 명과 동일하더라도, 이름 설정을 따로 해주는 편이라 궁금해서 물어봅니당 ~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
원래 의도는 필드 이름과 다르게 저장되는 컬럼 이름만 명시해 주고자 하는 의도였어요.
하지만, 우리가 명시해 준 이름을 그대로 사용하는 경우 굳이 이름을 명시해 주는 것이 불필요하다고 느껴 제거해 주었습니다!
+) 변수 명이 변경이 된다면 컬럼에 영향을 주는 것이 자연스럽다고 생각해요. 영향을 주고 싶지 않을 경우 그 때 이름을 명시해 주는 것이 좋아 보이기도 하고요!
String content, | ||
@NotNull(message = "스니펫 순서가 null 입니다.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null 입니다
라는 문장은 너무 개발자 측면의 문장이라고 생각합니다. 입력되지 않았습니다.
와 같은 문장은 어떤가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거는 프론트엔드와 이야기했었던 내용인데
어차피 프론트 측에서 별도의 메세지로 다시 한 번 래핑해서 내보낸다고 해서 프론트 쪽으로 보내는 의미 정도로만 작성하였습니다!!
|
||
public record FindAllTemplatesResponse( | ||
List<FindTemplateBySummaryResponse> templates | ||
) { | ||
public static FindAllTemplatesResponse from(List<RepresentativeSnippet> representativeSnippets) { | ||
List<FindTemplateBySummaryResponse> templatesBySummaryResponse = representativeSnippets.stream() | ||
public static FindAllTemplatesResponse from(List<ThumbnailSnippet> thumbnailSnippets) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dto 네이밍은 FindAllTemplatesResponse
인데 실제 안에 들어있는 변수는 SummaryResponse
이고, SummaryRespnse
는 ThumbnailSnippet
의 dto 네요.
SummaryRespnse
명이 ThumbnailSnippet
의 dto임을 잘 나타내는 이름으로 네이밍 된다면 좋을 것 같아요😊
그리고 이건 갑자기 든 생각인데, ThumbnailSnippet 보다
ThumbnailTemplate
은 어떤가요?
연속 사진에서 섬네일 사진은 대표 사진인 것처럼, 템플릿에 섬네일 ! ㅎㅎ
이렇게 되면 네이밍이 자연스러울 것 같아서요
(FindAllTemplatesResponse
,ThumbnailTemplateResponse
,ThumbnailTemplate
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FindTemplateBySummaryResponse
클래스는 명확한 네이밍을 차지 못해서 FindAllTemplatesById
의 내부 클래스로 변경하였습니다.
backend/src/main/java/codezap/template/dto/response/FindTemplateByIdResponse.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해커톤 이후 첫 PR이네요 ㅎㅎ 짱수 초롱 정말 고생 많았어요!! 🎉
첫 코드리뷰라 재미있기도, 조심스럽기도 했네요.
같이 얘기해봐요~
@ExceptionHandler | ||
public ResponseEntity<ProblemDetail> handleException(Exception exception) { | ||
return ResponseEntity.internalServerError() | ||
.body(ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, exception.getMessage())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 메서드가 없어도 Exception이 발생하면 스프링에서 500에러를 주지 않나요? 본 메서드가 필요한 이유를 알고 싶습니다~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 메서드는 예기치 못한 오류가 발생했을 때를 구분하기 위해 작성하였습니다.
따라서 message 부분을 조금 더 명시적으로 나타낼 수 있도록 수정하였습니다.
backend/src/main/java/codezap/global/serializing/DateTimeFormatConfiguration.java
Outdated
Show resolved
Hide resolved
@NotNull(message = "템플릿 이름이 null 입니다.") | ||
@Size(max = 255, message = "템플릿 이름은 최대 255자까지 입력 가능합니다.") | ||
String title, | ||
int representative_snippet_ordinal, | ||
@NotNull(message = "스니펫 리스트가 null 입니다.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/woowacourse-teams/2024-code-zap/pull/94/files?diff=split&w=0#r1685259424
켬미가 리뷰해준 내용을 여기서도 생각해보면 좋을 것 같습니당
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 커멘트에 답변 달아두었습니다!!
@NotNull(message = "파일 내용이 null 입니다.") | ||
String content, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filename 처럼 content의 max size도 여기서 검증해주는 건 어떻게 생각하시나요?
MySQL의 TEXT 타입은 65,535byte까지 저장할 수 있습니다! 출처 | MySQL Data Type Storage Requirements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 내용은 이번 PR 이 아닌 다른 이슈 #102 로 등록하여 해결하겠습니다!
backend/src/main/java/codezap/template/service/TemplateService.java
Outdated
Show resolved
Hide resolved
@Test | ||
@DisplayName("템플릿 생성 성공") | ||
void createTemplateSuccess() { | ||
CreateTemplateRequest templateRequest = new CreateTemplateRequest("a".repeat(255), | ||
List.of(new CreateSnippetRequest("a".repeat(255), "content", 1))); | ||
RestAssured.given().log().all() | ||
.contentType(ContentType.JSON) | ||
.body(templateRequest) | ||
.when().post("/templates") | ||
.then().log().all() | ||
.statusCode(201); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 테스트가 템플릿 생성 성공 케이스를 검증하는 게 맞을까요?
만약 컨트롤러에서 201을 반환하고 실제 DB에 반영하지는 않는 경우, 이 테스트에서 검증할 수 있을까요?
서비스 로직을 함께 검증하고 싶다면, 모킹한 DB에서 데이터를 꺼내 확인하는 assert문이 필요할 것 같아요.
서비스 로직과 DB 로직을 함께 검증하고 싶다면, 로컬 DB에서 데이터를 꺼내는 로직이 필요할 것 같구요.
아니면 애초에 컨트롤러가 올바른 응답을 주는지만 검증하고 싶었던 걸까요?
테스트 범위를 알 수 있게 개선하면 좋을 것 같습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
서비스에 대한 테스트를 이미 진행하였으므로, 서비스는 정상 동작한다고 가정하였습니다.
이에 따라 해당 테스트 코드에서는 응답만을 확인하고 있습니다.
backend/src/test/java/codezap/template/TemplateIntegrationTest.java
Outdated
Show resolved
Hide resolved
import codezap.template.dto.response.FindTemplateByIdResponse; | ||
import io.restassured.RestAssured; | ||
|
||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SpringBootTest
는 스프링 컨테이너에 모든 빈을 로드해서 속도가 가장 느린 방법으로 알고 있어요.
서비스의 단위테스트를 의도했다면 @SpringBootTest
를 사용하지 않거나, classes
속성으로 사용할 빈만 등록하는 건 어떨까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
조금 더 찾아보고 추후에 적용하도록 하겠습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 이슈 태그해주세용~!
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
Co-authored-by: hoeseong123 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수고하셨습니다~ 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수고하셨습니다🔥
리뷰가 잘 반영된 것 같아 approve 할게요~!
Co-authored-by: hoeseong123 <[email protected]>
89cafb0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드잽 파이팅~~!! ⚡
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
마지막까지 파이팅.........!
BindingResult bindingResult = exception.getBindingResult(); | ||
return ResponseEntity.status(HttpStatus.BAD_REQUEST) | ||
.body(ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, | ||
bindingResult.getFieldError().getDefaultMessage())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getFieldError()
는 하나의 필드 에러만 가져오네요.
하나의 요청 바디에서 여러 개의 검증 오류가 난다면, 클라이언트는 여러번에 걸쳐서 에러를 해결해야 할 것 같아요.
유효하지 않은 필드가 여러 개라도 한번에 보여주는 게 어떨까요?
( getFieldErrors()
로 수정 후 유효하지 않은 필드를 joining 해서 응답을 줄 수 있을 것 같아요. )
Co-authored-by: hoeseong123 <[email protected]>
8b3de77
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드잽 파이팅 ⚡
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
초롱 짱수 너무 고생 많았어요 !!!
⚡️ 관련 이슈
close #93
📍주요 변경 사항
🎸기타
MethodArgumentNotValidException
에 대한 처리로 구현되어 있습니다.CodeZapException
으로 감싸야 할지 고민입니다 🤔