-
Notifications
You must be signed in to change notification settings - Fork 0
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
Carrot/#3 #14
base: main
Are you sure you want to change the base?
Carrot/#3 #14
Conversation
- 고객 등록 API 추가 - 판매 정보에 판매자의 별명과 판매여부 추가 - 판매 정보 중 판매자의 별명은 판매자의 아이디를 이용하여 판매자의 정보를 찾고 별명 저장
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.
안녕하세요 ~ 클론코딩 과제를 리뷰하게 된 명예오비 최윤한이라고 합니다..!
저도 부족하지만 궁금한 점이나 아니면 제 생각에 대해서 리뷰 해봤습니다!! 잘 부탁드립니다 ㅎㅎ
API 테스트 하신 것 PR에 올려두신 부분 너무 좋은 것 같습니다 ~ !
//Multipart file | ||
implementation("software.amazon.awssdk:bom:2.21.0") | ||
implementation("software.amazon.awssdk:s3:2.21.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.
//Multipart file 보다는 s3 혹은 aws 라고 표현해도 좋을 것 같습니다 !
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.
좋은 의견 감사합니다!
int status, | ||
String message, | ||
|
||
List<T> data |
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.
data를 담는 필드의 타입을 List<T>
로 사용하신 이유가 있는지 궁금합니다!
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.
2차시 클론코딩에서 지역별 판매 '리스트'를 반환하는 API를 구현하는 중에 '리스트'를 구현하는 것에 초점을 맞췄던 것 같습니다..! 말씀해주신 것을 생각하면 그냥 제네릭 타입 T를 사용하는 것이 더 적절한 것 같다고 생각하게 되었습니다!
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.
API 명세에 따라 달라지는 부분일 것 같아서 ... API 기본 응답 포맷을 배열로 사용하는 것이 아니라면 T로 바꿔도 좋을 것 같아요 ~
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.
넵 감사합니다~!
|
||
private final HeartService heartService; | ||
|
||
@Transactional |
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.
Service에서 작성하는 로직들이 Transaction 관리에 조금 더 이점이 있기 떄문에, @Transactional
어노테이션은 Controller가 아닌 Service 계층에서 처리해도 좋을 것 같습니다 ...!
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.
엇 이 부분은 잘못 작성했던 것 같은데 미처 발견하지 못했던 것 같습니다! 감사합니다! Controller에 Transactional 어노테이션을 붙이는 것보다 Service에 붙이면 생기는 이점에 대해서 더 찾아보도록 하겠습니다!
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.
넵!! 찾아보니 JPA와 관련되어 있어서 더 공부하면 좋을 것 같습니다. 감사합니다 : )
@RequestHeader("customerId") Long customerId, | ||
@RequestHeader("sellId") Long sellId |
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.
Request Header에서 customerId, sellId를 받아오시는 이유가 있는지 궁금합니다 ..!🤔
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.
Id라는 속성이 중요한 정보라 생각해서 Header에 포함하여 안전하게 넘긴다고 생각했습니다. 하지만 다른 분들의 코드를 보고 jwt를 배우면서, 이러한 Id는 객체를 식별하는 용도로 사용하는 정도고 PathVariable이나 RequestParam을 통해 받아오는 것이 더 적절한 것 같다고 생각하게 되었습니다!
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.
REST API를 사용한다면 URL에 최대한 표현되면 좋을 것 같아요!
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.
아하! 좋은 의견 감사합니다!! 바로 적용해보도록 하겠습니다.
return ResponseEntity.status(HttpStatus.CREATED) | ||
.header("Location", heartService.create(customerId, sellId)) |
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.
ResponseEntity.created()
로 한번에 처리할 수 있을 것 같습니다 ~
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.
엇 그런 방법을 생각치 못했습니다..! 감사합니다 : )
@Bean | ||
public SystemPropertyCredentialsProvider systemPropertyCredentialsProvider() { | ||
System.setProperty(AWS_ACCESS_KEY_ID, accessKey); | ||
System.setProperty(AWS_SECRET_ACCESS_KEY, secretKey); | ||
return SystemPropertyCredentialsProvider.create(); |
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.
AWS에서 credential을 setting하는 방법이 있는데, 해당 방법 말고도 다른 방법이 어떤 방법이 있는지 알아봐도 좋을 것 같습니다 ~
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.
좋은 정보 감사합니다!!
sellRepository.save(sell); | ||
return sell.getId().toString(); | ||
} catch (RuntimeException | IOException e) { | ||
throw new RuntimeException(e.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.
RuntimeException을 던지고 있는데, 해당 예외보다 개발하고 있는 프로젝트에서 사용하는 적절한 커스텀 Exception을 정의하여 그 Exception을 RuntimeException 대신에 사용해도 좋을 것 같아요! RuntimeException은 Java API 에서 정의된 예외이기 때문에, 예외 상황 추적이나 의도하지 않은 예외가 발생할 수도 있기 때문입니다 ~!
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.
아하 그런 문제점이 있을 수 있군요..! 감사합니다!!
private String generateImageFileName() { | ||
return UUID.randomUUID() + ".jpg"; | ||
} |
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.
uploadImage method에서 private method로 image의 사이즈와 확장자를 validation하고 있는데요. 이 때 확장자로 네가지를 제한하고 있는데, 현재 method로 이미지 파일 이름을 생성할 때 jpg만을 붙이고 있습니다. 이렇게 되면 .webp 확장자 파일을 올려도 jpg 이름으로 저장되기 때문에 이후에 조회할 때 문제가 생길수도 있을 것 같아요 ! 어떻게 해결하면 좋을까요 ? 🤔🤔
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.
그러한 생각은 못했던 것 같습니다! 음.. 말씀해주신 것을 통해 생각해 봤을 땐 validateExtension에서 확장자를 반환하여 그 확장자를 붙이는 방법을 생각해보았습니다. 하지만 더 좋은 의견이나 제가 말씀드린 것 중 잘못된 부분이 있으면 수정해 나가도록 하겠습니다!! 감사합니다 : )
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.
아하! 감사합니다!!
.bucket(bucketName) | ||
.key(key) | ||
.contentType(image.getContentType()) | ||
.contentDisposition("inline") |
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.
contentDisposition을 inline으로 해두신 이유가 궁금합니다 ~
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.
큰 이유 없이 세미나를 참고했습니다..! 하지만 말씀하신 것을 듣고 찾아보니 바로 실행과 첨부파일로 인식하여 확인을 하는 차이라는 것을 알게 되었습니다!! 감사합니다 ㅜㅜ
Gwanak, | ||
Gangnam, | ||
Dongjak |
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.
enum 자체는
GWANAK ,GANGNAM, DONGJAK으로 선언하고, 실제 사용하는 값은 필드로 선언하는 방법도 있을 것 같습니다..!
아래는 예시코드 입니다!
public enum Place {
GWANAK("Gwanak"),
GANGNAM("Gangnam"),
DONGJAK("Dongjak"),
private String value;
}
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.
Enum의 상수 자체를 그대로 사용하게 되면, 변경에 취약해집니다.
예를들어 현재는 Gwanak으로 되어있는 값을 gwanak으로 바꿔야한다고 가정했을 때, Enum의 상수 값을 그대로 사용하면 상수 자체를 변경해야합니다. 이렇게 되면 Place라는 Enum을 사용하는 모든 class의 코드가 변경되어야 합니다. 하지만 필드로 따로 선언해주면 필드안에 선언했던
GWANAK("Gwanak") -> GWANAK("gwanak')으로만 바꿔주면 되기 때문에 변경이 적어집니다.
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.
바쁘신 와중에도 자세하게 의견을 말씀해셔서 감사합니다!! 덕분에 디테일한 부분이나 당연하다고 생각했던 부분에 대해서도 다시 한 번 생각해볼 수 있었습니다 : )
//Multipart file | ||
implementation("software.amazon.awssdk:bom:2.21.0") | ||
implementation("software.amazon.awssdk:s3:2.21.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.
좋은 의견 감사합니다!
int status, | ||
String message, | ||
|
||
List<T> data |
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.
2차시 클론코딩에서 지역별 판매 '리스트'를 반환하는 API를 구현하는 중에 '리스트'를 구현하는 것에 초점을 맞췄던 것 같습니다..! 말씀해주신 것을 생각하면 그냥 제네릭 타입 T를 사용하는 것이 더 적절한 것 같다고 생각하게 되었습니다!
|
||
private final HeartService heartService; | ||
|
||
@Transactional |
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.
엇 이 부분은 잘못 작성했던 것 같은데 미처 발견하지 못했던 것 같습니다! 감사합니다! Controller에 Transactional 어노테이션을 붙이는 것보다 Service에 붙이면 생기는 이점에 대해서 더 찾아보도록 하겠습니다!
@RequestHeader("customerId") Long customerId, | ||
@RequestHeader("sellId") Long sellId |
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.
Id라는 속성이 중요한 정보라 생각해서 Header에 포함하여 안전하게 넘긴다고 생각했습니다. 하지만 다른 분들의 코드를 보고 jwt를 배우면서, 이러한 Id는 객체를 식별하는 용도로 사용하는 정도고 PathVariable이나 RequestParam을 통해 받아오는 것이 더 적절한 것 같다고 생각하게 되었습니다!
return ResponseEntity.status(HttpStatus.CREATED) | ||
.header("Location", heartService.create(customerId, sellId)) |
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.
엇 그런 방법을 생각치 못했습니다..! 감사합니다 : )
private long cost; | ||
|
||
private boolean costPropose; | ||
|
||
private String detail; | ||
|
||
@Enumerated(EnumType.STRING) | ||
private Place place; | ||
|
||
private boolean soldOut; | ||
|
||
@ColumnDefault("0") | ||
private long likeCount; |
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.
좋은 의견 감사합니다! 리팩토링하면서, 또 앞으로 코드를 작성하면서 적용해보도록 하겠습니다!
@Bean | ||
public SystemPropertyCredentialsProvider systemPropertyCredentialsProvider() { | ||
System.setProperty(AWS_ACCESS_KEY_ID, accessKey); | ||
System.setProperty(AWS_SECRET_ACCESS_KEY, secretKey); | ||
return SystemPropertyCredentialsProvider.create(); |
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.
좋은 정보 감사합니다!!
.bucket(bucketName) | ||
.key(key) | ||
.contentType(image.getContentType()) | ||
.contentDisposition("inline") |
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.
큰 이유 없이 세미나를 참고했습니다..! 하지만 말씀하신 것을 듣고 찾아보니 바로 실행과 첨부파일로 인식하여 확인을 하는 차이라는 것을 알게 되었습니다!! 감사합니다 ㅜㅜ
private String generateImageFileName() { | ||
return UUID.randomUUID() + ".jpg"; | ||
} |
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.
그러한 생각은 못했던 것 같습니다! 음.. 말씀해주신 것을 통해 생각해 봤을 땐 validateExtension에서 확장자를 반환하여 그 확장자를 붙이는 방법을 생각해보았습니다. 하지만 더 좋은 의견이나 제가 말씀드린 것 중 잘못된 부분이 있으면 수정해 나가도록 하겠습니다!! 감사합니다 : )
sellRepository.save(sell); | ||
return sell.getId().toString(); | ||
} catch (RuntimeException | IOException e) { | ||
throw new RuntimeException(e.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.
아하 그런 문제점이 있을 수 있군요..! 감사합니다!!
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.
시험기간 때문에 리뷰를 지금에서야 보았습니다.. 좋은 말씀 많이 해주셨는데 너무 늦게 봐서 죄송하고, 정성스럽게 써주신 만큼 많이 배울 수 있었습니다! 감사합니다 : )
int status, | ||
String message, | ||
|
||
List<T> data |
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.
넵 감사합니다~!
|
||
private final HeartService heartService; | ||
|
||
@Transactional |
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.
넵!! 찾아보니 JPA와 관련되어 있어서 더 공부하면 좋을 것 같습니다. 감사합니다 : )
@RequestHeader("customerId") Long customerId, | ||
@RequestHeader("sellId") Long sellId |
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.
아하! 좋은 의견 감사합니다!! 바로 적용해보도록 하겠습니다.
|
||
@GetMapping("/list") | ||
public ResponseEntity<SuccessResponse> findSellListByPlace( | ||
@RequestParam("place") Place place |
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.
아 그런 방법이 또 있었군요! 감사합니다!! (Entity대신 객체를 정의해서 받아오면 이점은 개인적으로 질문하는 것으로..)
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor |
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.
아.. NoArgsConstructor에 대해서 자세하게는 알지 못해서 그 안에 access option이 있다는 것을 알게 되었습니다! 감사합니다!! 더 공부해보고 적용해보도록 하겠습니다 : )
Gwanak, | ||
Gangnam, | ||
Dongjak |
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.
자세하게 설명해 주셔서 감사합니다!! 바로 적용해 보도록 하겠습니다 : )
private String generateImageFileName() { | ||
return UUID.randomUUID() + ".jpg"; | ||
} |
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 #13
이 주의 과제 ❗️
image upload 로직✅
sansan20535/carrot/src/main/java/clone/carrot/domain/Sell.java
Line 38 in 88748df
sansan20535/carrot/src/main/java/clone/carrot/dto/SellCreateDto.java
Line 16 in 88748df
sansan20535/carrot/src/main/java/clone/carrot/service/SellService.java
Lines 28 to 48 in 88748df
S3Service : https://github.com/NOW-SOPT-SERVER/sansan20535/blob/88748dfddbb9a056d11511628ab820cdcfaf96bd/carrot/src/main/java/clone/carrot/external/S3Service.java
AwsConfig : https://github.com/NOW-SOPT-SERVER/sansan20535/blob/88748dfddbb9a056d11511628ab820cdcfaf96bd/carrot/src/main/java/clone/carrot/external/AwsConfig.java
image delete 로직✅
API
path : /api/v1/sell/{sellId}
pathvariable : sellId, 판매 물품 Id
sansan20535/carrot/src/main/java/clone/carrot/service/SellService.java
Lines 62 to 71 in 88748df
요구사항 분석 ❗️
image upload 로직✅
image delete 로직✅