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

Feature/chung step5 #12

Merged
merged 24 commits into from
May 29, 2024
Merged

Feature/chung step5 #12

merged 24 commits into from
May 29, 2024

Conversation

kochungcheon
Copy link

@kochungcheon kochungcheon commented May 17, 2024

구현 기능

  • 파일 공유 링크 생성 / 다운로드
  • 링크 일괄 삭제

파일 공유 링크 생성

  • UUID.randomUUID 기반 링크 생성
  • 링크 중복 검사

파일 공유 다운로드

  • 링크 유효 기간은 3시간
  • 유효 기간 내 요청만 다운로드 가능
  • 파일 공유 이후 원본 파일 삭제 발생 시 다운 불가능
  • 스케줄러를 통해 유효하지 않은 링크 삭제 ( 5분 단위)

MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 맴버를 찾지 못했습니다"),
EXCEEDED_CAPACITY(HttpStatus.INSUFFICIENT_STORAGE, "더 이상 업로드 할 수 없습니다"),
INVALID_OPERATION(HttpStatus.BAD_REQUEST, "사용 중인 공간보다 많은 공간은 해제할 수 없습니다"),
VALIDATION_ERROR(HttpStatus.BAD_REQUEST, "유효하지 않은 요청입니다."),

Copy link
Author

Choose a reason for hiding this comment

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

공유된 이슈로 개행 문제가 있습니다.
아래 세 개가 이번 수정 사항에 반영된 것입니다.

  • DUPLICATE_SHARE_LINK
  • NOT_FOUND_SHARE_LINK
  • NOT_FRESH_LINK

public void deleteAll(List<FileMetadata> fileMetadataList) {
fileRepository.deleteAll(fileMetadataList);
}

Copy link
Author

Choose a reason for hiding this comment

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

공유된 이슈로 개행 문제가 있습니다.
아래 findBy가 이번에 추가된 사항입니다.

@@ -5,23 +5,22 @@

import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

Copy link
Author

Choose a reason for hiding this comment

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

개행 수정했습니다. 로직 상 수정 사항은 없습니다.

Copy link

@kariskan kariskan left a comment

Choose a reason for hiding this comment

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

수고하셨습니다~ 많이 배웠네요.
근데 이제 봤는데
https://github.com/C4-ComeTrue/c4-cometrue-assignment/blob/main/assignments/my-storage.md
이거랑
https://github.com/C4-ComeTrue/my-storage/tree/main/assignment
이거랑 요구사항이 약간 다르네요. 폴더 공유에 대한 로직도 작성해보시면 좋을 것 같기도..?

List<Long> expirationLinkIds;

do {
expirationLinkIds = fileShareRepository.findExpirations(expirationTime, PageRequest.of(0, DELETE_SIZE));

Choose a reason for hiding this comment

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

전 native query로 limit 사용했는데 이런 방법도 있군요. 신기..

Copy link
Author

Choose a reason for hiding this comment

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

전 native query로 limit 사용했는데 이런 방법도 있군요. 신기..

아 ! limit 거는 형식으로 가야겠네요. 기존 방법대로 하면 불필요하게 정렬되니.. 수정했습니다.

Optional<FileShare> findByShareLink(String shareLink);

@Query("SELECT fs.id FROM FileShare fs WHERE fs.createdAt < :expirationTime")
List<Long> findExpirations(@Param("expirationTime") ZonedDateTime expirationTime, Pageable pageable);

Choose a reason for hiding this comment

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

createdAt에 index는 필요 없나요?

Copy link
Author

Choose a reason for hiding this comment

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

createdAt에 index는 필요 없나요?

인덱스 추가하였습니다 감사합니다~!

}

@GetMapping("/download")
public ResponseEntity<DownloadShareFileRes> downloadShareFile(@Valid @RequestBody DownloadShareFileReq req) {

Choose a reason for hiding this comment

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

GetMapping에서는 RequestBody 보다는 PathVariable이나 RequestParam을 이용하는 것은 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

GetMapping에서는 RequestBody 보다는 PathVariable이나 RequestParam을 이용하는 것은 어떨까요?

아 맞네요 ModelAttribute 로 수정하였습니다!

Duration duration = Duration.between(createTimeInLink, now);
Duration maxTime = Duration.ofHours(3);

if (duration.compareTo(maxTime) > 0) {

Choose a reason for hiding this comment

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

duration.toHours() >= 3
이렇게 해도 될 거 같아요

Copy link
Author

Choose a reason for hiding this comment

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

duration.toHours() >= 3 이렇게 해도 될 거 같아요

오 그게 더 깔끔하네요 duration.toHours() 형태로 수정했습니다!
3 을 int maxTime = 3; 처리하는 것과 상수로 나두는 것 둘 중 어떤 걸 선호하시나요

Choose a reason for hiding this comment

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

저는 상수는 스페이스바 이런거 말고는 다 나누긴 해요.
하나의 클래스에서만 사용되면 그냥 전역 변수로 분리하고 여러개에서 사용되면 따로 constant 클래스로 분리해서 사용합니다

Copy link
Author

Choose a reason for hiding this comment

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

의 클래스에서만 사용되면 그냥 전역 변수로 분리하고 여러개에서 사용되면 따로 constant 클래스로 분리해서 사용합니다

오호 그렇군요 배우고 갑니다! 감사합니다!

@kochungcheon kochungcheon added the enhancement New feature or request label May 18, 2024
Copy link

@pear96 pear96 left a comment

Choose a reason for hiding this comment

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

코드 보고 많이 배우고 갑니다!!
수정사항을 찾아낼게 없어서 조금이나마 남기고 갑니다.


private void checkDuplicate(String sharedLink) {
if (fileShareRepository.existsByShareLink(sharedLink)) {
throw ErrorCode.DUPLICATE_SHARE_LINK.serviceException();
Copy link

Choose a reason for hiding this comment

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

공유 링크 중복을 검사를 하는 이유를 혼자서 생각해봤습니다.

  1. 다른 사람끼리의 파일들의 공유 링크가 겹칠까봐
  2. 한 파일의 공유 링크가 중복되면 만료 시간이 달라야 하는데 원래보다 늦게 혹은 일찍 만료될까봐

1번과 같은 경우를 생각해본다면 error를 발생시킨다기보단 파일 id와 같은 파일의 고유한 정보도 shareLink에 추가해줘야하지 않을까 싶습니다.
2번과 같은 경우라면 애초에 LocalDateTime이 달랐을 테니 발생하지 않을 상황 같습니다.

그래서 저라면 shareLink에 파일의 고유한 정보를 넣고, 중복 처리는 딱히 필요 없을 것 같습니다.
(..그냥 저의 생각일 뿐이므로 그렇구나 하고 넘기시면 됩니다. 너무 잘해서 쓸게 없어서 이런 얘기라도 써봤습니다.)

Copy link
Author

Choose a reason for hiding this comment

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

공유 링크 중복을 검사를 하는 이유를 혼자서 생각해봤습니다.

  1. 다른 사람끼리의 파일들의 공유 링크가 겹칠까봐
  2. 한 파일의 공유 링크가 중복되면 만료 시간이 달라야 하는데 원래보다 늦게 혹은 일찍 만료될까봐

1번과 같은 경우를 생각해본다면 error를 발생시킨다기보단 파일 id와 같은 파일의 고유한 정보도 shareLink에 추가해줘야하지 않을까 싶습니다. 2번과 같은 경우라면 애초에 LocalDateTime이 달랐을 테니 발생하지 않을 상황 같습니다.

그래서 저라면 shareLink에 파일의 고유한 정보를 넣고, 중복 처리는 딱히 필요 없을 것 같습니다. (..그냥 저의 생각일 뿐이므로 그렇구나 하고 넘기시면 됩니다. 너무 잘해서 쓸게 없어서 이런 얘기라도 써봤습니다.)

자세히 의견 이야기 해주셔서 다른 관점도 많이 배우고 갑요 감사합니다!
확실히 이야기 하신 것처럼 고유 정보 + 시간 + UUID 와 같은 형태로 구성하면 중복 체크를 방지할 수 있겠네요!! 오호 배우고 갑니다.

공유 링크 중복을 검사를 하는 이유는 중복 링크 생성 가능성을 방지하기 위함이였습니다. 또한 외부 사용자에게는 (공유 파일을 이용하는) 파일 고유 정보 노출을 하지 않기 위해 시간 + UUID 조합을 이용했습니다!

package com.c4cometrue.mystorage.fileshare.dto;

public record CreateShareFileRes(
String fileName,
Copy link

Choose a reason for hiding this comment

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

혹시 Req에는 @NotBlank를 검사하고, Res들에는 검사하지 않는 이유가 있을까요?
Res를 반환해주는 것은 앞선 유효검사 로직을 다 통과한걸텐데, 비어있는 링크가 가도 되는 상황은 무엇인지 궁금합니다.

Copy link
Author

Choose a reason for hiding this comment

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

혹시 Req에는 @NotBlank를 검사하고, Res들에는 검사하지 않는 이유가 있을까요?
Res를 반환해주는 것은 앞선 유효검사 로직을 다 통과한걸텐데, 비어있는 링크가 가도 되는 상황은 무엇인지 궁금합니다.

오호 생각해보니 붙이는 게 좋겠네요..! 감사합니다!

Copy link
Member

@VSFe VSFe left a comment

Choose a reason for hiding this comment

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

작업량이 많지 않아서 짧게 리뷰 남기고 갑니다 ㅎㅎ~~

private final FileShareService fileShareService;

@PostMapping
public ResponseEntity<CreateShareFileRes> createShareFile(@Valid @RequestBody CreateShareFileReq req) {
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

넵 수정하였습니다

List<Long> expirationLinkIds;

do {
expirationLinkIds = fileShareRepository.findExpirations(expirationTime, DELETE_SIZE);
Copy link
Member

Choose a reason for hiding this comment

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

혹시 바로 삭제하지 않는 의도가 있을까요?
(delete 계열은 long을 반환할 수 있습니다.)

Copy link
Author

Choose a reason for hiding this comment

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

혹시 바로 삭제하지 않는 의도가 있을까요? (delete 계열은 long을 반환할 수 있습니다.)

앗...!!!!! 덕분에 하나 배워 갑니다 감사합니다! 수정했습니다 💯

FileMetadata file = fileDataHandlerService.findBy(fileId, userId);

// shareLink 생성
String shareLink = LocalDateTime.now() + UUID.randomUUID().toString();
Copy link
Member

Choose a reason for hiding this comment

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

UUID는 일반적으로 timeStamp를 활용해서 만들어집니다.
UUID와 LocalDateTime이 만들 데이터는 유사할 확률이 높아요.

Copy link
Author

Choose a reason for hiding this comment

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

UUID는 일반적으로 timeStamp를 활용해서 만들어집니다. UUID와 LocalDateTime이 만들 데이터는 유사할 확률이 높아요.

앗 그러네요 UUID 를 통해서만 만드는 것으로 수정하겠습니다.

ZonedDateTime now = ZonedDateTime.now();
Duration duration = Duration.between(createTimeInLink, now);

int maxTime = 3;
Copy link
Member

Choose a reason for hiding this comment

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

이게 Lazy하게 데이터를 Validation 하는게 좋을 수도 있긴 하지만... 여기서는 그렇지가 않아요.
링크 목록을 가져올 때 (특히 FE 관점에서는 목록을 구하는 API 를 호출할 가능성이 있을텐데) Valid 한 것 처럼 보일 가능성이 있고, 이걸 접근하려고 할 때 비로소 isValid가 호출될 것 같거든요.

차라리 Schedule의 Term을 좀 더 짧게 가져가는게 나을 것 같습니다.

Copy link
Author

@kochungcheon kochungcheon May 22, 2024

Choose a reason for hiding this comment

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

이게 Lazy하게 데이터를 Validation 하는게 좋을 수도 있긴 하지만... 여기서는 그렇지가 않아요. 링크 목록을 가져올 때 (특히 FE 관점에서는 목록을 구하는 API 를 호출할 가능성이 있을텐데) Valid 한 것 처럼 보일 가능성이 있고, 이걸 접근하려고 할 때 비로소 isValid가 호출될 것 같거든요.

차라리 Schedule의 Term을 좀 더 짧게 가져가는게 나을 것 같습니다.

5분 주기로 삭제 되도록 수정했습니다!
확실히 짧게 가져가니 삭제 테스크 당 서버 부하가 줄겠네요

@kochungcheon kochungcheon requested a review from VSFe May 22, 2024 14:45
Copy link

sonarcloud bot commented May 22, 2024

@kochungcheon kochungcheon merged commit 9919fac into base/chung May 29, 2024
2 checks passed
kochungcheon added a commit that referenced this pull request Jun 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants