Spring 심화 주차 8.26(금) ~ 9.1(목)
1. 개인 과제: Spring 핵심 키워드 정리 2. 팀 과제: 요구사항에 맞추어 API 구성 및 Git을 활용한 협업 |
진행 계획
- 26일(금) API 명세서 작성, ERD 만들기
- 27일(토) 팀 과제에 필요한 강의 수강 및 공부
- 28일(일) 팀 과제 내가 맡은 이미지 업로드 기능 코드 작성
- 29일(월) 개인 과제 Spring 핵심 키워드 정리
- 30일(화) 팀 과제 코드 수정 및 검토
- 31일(수) 팀 과제 코드 취합 및 요구사항 충족 확인
- 1일(목) 팀 과제 코드 최종 취합 및 AWS 배포
1. 개발 진행 상황
1) 인텔리제이(IntelliJ IDEA)-AWS 연결 하기
👉🏻 인텔리제이 공식 블로그 보고 따라함
2) 이미지 업로드 코드 구현
- S3 configuration
@Configuration
public class S3Config {
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;
@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Bean
public AmazonS3 amazonS3Client() {
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
return AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(region)
.build();
}
}
- S3Uploader(Service)
MultipartFile을 받아서 File 전환 후 S3에 업로드
@Slf4j
@RequiredArgsConstructor // final 멤버변수가 있으면 생성자 항목에 포함시킴
@Component
@Service
public class S3Uploader {
private final AmazonS3Client amazonS3Client;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
// MultipartFile을 전달받아 File로 전환한 후 S3에 업로드
public String upload(MultipartFile multipartFile, String dirName) throws IOException {
File uploadFile = convert(multipartFile)
.orElseThrow(() -> new IllegalArgumentException("fail convert multipart to file"));
return upload(uploadFile, dirName);
}
private String upload(File uploadFile, String dirName) {
String fileName = dirName + "/" + uploadFile.getName();
String uploadImageUrl = putS3(uploadFile, fileName);
removeNewFile(uploadFile); // 로컬에 생성된 File 삭제 (MultipartFile -> File 전환 하며 로컬에 파일 생성됨)
return uploadImageUrl; // 컨트롤러로 S3 URL 주소 반환
}
private String putS3(File uploadFile, String fileName) {
amazonS3Client.putObject(
new PutObjectRequest(bucket, fileName, uploadFile)
.withCannedAcl(CannedAccessControlList.PublicRead) // PublicRead 권한으로 업로드 됨
);
return amazonS3Client.getUrl(bucket, fileName).toString(); // 업로드된 파일의 S3 URL 주소 반환
}
private void removeNewFile(File targetFile) {
if(targetFile.delete()) {
log.info("파일이 삭제되었습니다.");
}else {
log.info("파일이 삭제되지 못했습니다.");
}
}
private Optional<File> convert(@NotNull MultipartFile file) throws IOException {
File convertFile = new File(file.getOriginalFilename());
if(convertFile.createNewFile()) {
try (FileOutputStream fos = new FileOutputStream(convertFile)) {
fos.write(file.getBytes());
}
return Optional.of(convertFile);
}
return Optional.empty();
}
}
- ImageController
MultipartFile을 받아서 S3Uploader를 통해 업로드 및 이미지URL을 반환 받고 그 주소를 요구사항에 맞게 응답해주기 위해서 imageService를 이용함
@RestController
@RequiredArgsConstructor
public class ImageController {
private final S3Uploader s3Uploader;
private final ImageService imageService;
@RequestMapping(value = "/api/upload/image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, method = RequestMethod.POST)
public ResponseDto<?> upload(HttpServletRequest request, @RequestParam(value="image", required = false) MultipartFile multipartFile) throws IOException {
String imgUrl = s3Uploader.upload(multipartFile, "static");
return imageService.upload(request, imgUrl);
}
}
- ImageService
@Service
@RequiredArgsConstructor
public class ImageService {
private final PostRepository postRepository;
private final ImageRepository imageRepository;
private final TokenProvider tokenProvider;
@Transactional
public ResponseDto<?> upload(HttpServletRequest request, String imgUrl) {
if (null == request.getHeader("Refresh-Token")) {
return ResponseDto.fail("MEMBER_NOT_FOUND",
"로그인이 필요합니다.");
}
if (null == request.getHeader("Authorization")) {
return ResponseDto.fail("MEMBER_NOT_FOUND",
"로그인이 필요합니다.");
}
Member member = validateMember(request);
if (null == member) {
return ResponseDto.fail("INVALID_TOKEN", "Token이 유효하지 않습니다.");
}
if (null == imgUrl) {
return ResponseDto.fail("EMPTY", "multipart file is empty");
}
Image image = Image.builder()
.imgUrl(imgUrl)
.build();
imageRepository.save(image);
return ResponseDto.success(
ImageResponseDto.builder()
.data(image.getImgUrl())
.build()
);
}
@Transactional
public Member validateMember(HttpServletRequest request) {
if (!tokenProvider.validateToken(request.getHeader("Refresh-Token"))) {
return null;
}
return tokenProvider.getMemberFromAuthentication();
}
}
2. 오늘 한 일 / 회고
- 팀 과제: 이미지 업로드 기능 구현
- 강의 수강
3. TO-DO LIST
- 개인 과제: 스프링 키워드 작성
- 강의 수강
4. 레퍼런스
https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html
'개발 일지' 카테고리의 다른 글
[TIL]이노베이션 캠프 29일차 (0) | 2022.08.30 |
---|---|
[WIL]이노베이션 캠프 4주차 (0) | 2022.08.29 |
[TIL]이노베이션 캠프 27일차 (0) | 2022.08.28 |
[TIL]이노베이션 캠프 26일차 (0) | 2022.08.27 |
[TIL]이노베이션 캠프 25일차 (0) | 2022.08.25 |