Skip to content

Commit

Permalink
feat: 사진 업로드 및 삭제 S3 적용 (#518)
Browse files Browse the repository at this point in the history
* chore: cloud aws s3 관련 의존성 추가

* feat: S3의 파일 주고 받는 객체 구현

* feat: 긴급 push

* feat: 긴급 저장

* Update backend_dev_merge_workflow.yml

* feat: 긴급 푸시

* feat: 긴급 푸시(삭제 관련 테스트 주석처리)

* Update backend_dev_merge_workflow.yml

* feat: 삭제 관련 api 테스트

* feat: 버전을 가진 객체 삭제 기능 수정

* feat: 버전을 가진 객체 삭제 기능 수정

* feat: 임시 커밋

* fix: 파일 삭제 오류 해결

* chore: 주석 삭제

* refactor: 검수 중 장소 거절 시 이미지 삭제, 장소 등록시 검수중 장소 레코드만 삭제로 코드 수정

* 잠시 머지 dev 머지 워크플로우 수정

* refactor: s3 imageUrl 수정

* chore: 서브모듈 업데이트

* chore: 서브모듈 업데이트

* refactor: 워크 플로우 수정

---------

Co-authored-by: dooboocookie <[email protected]>
  • Loading branch information
zillionme and dooboocookie authored Oct 19, 2023
1 parent 3f23946 commit 6b2f1eb
Show file tree
Hide file tree
Showing 17 changed files with 429 additions and 297 deletions.
76 changes: 38 additions & 38 deletions .github/workflows/backend_rel_merge_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,53 @@ on:
- backend/**

jobs:
deploy:
runs-on: naaga
github_actions_setting:
runs-on: ubuntu-latest

steps:
- name: change permission
run: |
sudo chown -R ubuntu:ubuntu /home/ubuntu/actions-runner/naaga/2023-naaga/2023-naaga
- name: checkout
- name: 📂 프로젝트 파일 가져오는 중... 📂
uses: actions/checkout@v3
with:
submodules: true
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}

- name: project remove
run: |
sudo rm -rf /home/ubuntu/prod/2023-naaga
- name: project copy
run: |
sudo cp -r /home/ubuntu/actions-runner/naaga/2023-naaga/2023-naaga /home/ubuntu/prod

- name: build
- name: ☕️ 깃허브 액션에 JDK 17 적용시키는 중... ☕️
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'corretto'

- name: 🐘 Gradle 세팅 중... 🐘
uses: gradle/[email protected]

- name: ⚙️ Gradle 로 JAR 파일 테스트 및 빌드 중... ⚙️
run: |
cd /home/ubuntu/prod/2023-naaga/backend
sudo chmod +x ./gradlew
sudo ./gradlew clean bootJar
- name: transfer & run
cd backend
./gradlew clean bootJar -Dspring.profiles.active=test
- name: 🐳 도커 세팅 중... 🐳
uses: docker/[email protected]

- name: 🐳 도커 허브에 로그인 중... 🐳
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESSTOKEN }}

- name: 🐳 도커 이미지 빌드 중... 🐳
run: |
cd /home/ubuntu/prod
chmod +x ./deploy_prod.sh
sudo ./deploy_prod.sh
cd backend
docker build --platform linux/arm64/v8 -t ${{ secrets.DOCKERHUB_REPOSITORY }}/${{ secrets.DOCKERHUB_APPNAME }} -f Dockerfile-prod .
sync-dev_backend:
needs: deploy
- name: 🐳 도커 허브에 Push 중... 🐳
run: docker push ${{ secrets.DOCKERHUB_REPOSITORY }}/${{ secrets.DOCKERHUB_APPNAME }}

runs-on: ubuntu-latest
naaga_prod_ec2_deploy:
needs: github_actions_setting
runs-on: naaga

steps:
- name: Checkout
uses: actions/checkout@v2
with:
ref: main

- name: merge release -> dev_backend
uses: devmasx/merge-branch@master
with:
type: now
target_branch: dev_backend
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: 🙏 쉘 스크립트 실행 중 ... 🙏
run: |
cd /home/ubuntu/prod
sudo ./deploy_prod.sh
12 changes: 8 additions & 4 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.rest-assured:rest-assured:5.3.1'

implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
Expand All @@ -30,6 +26,14 @@ dependencies {
implementation 'ch.qos.logback.contrib:logback-jackson:0.1.5'
implementation 'ch.qos.logback.contrib:logback-json-classic:0.1.5'
implementation 'net.logstash.logback:logstash-logback-encoder:6.1'

implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.rest-assured:rest-assured:5.3.1'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
package com.now.naaga.common.config;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.now.naaga.gameresult.domain.gamescore.FailResultScorePolicy;
import com.now.naaga.gameresult.domain.gamescore.ResultScoreCalculator;
import com.now.naaga.gameresult.domain.gamescore.ResultScorePolicy;
import com.now.naaga.gameresult.domain.gamescore.SuccessResultScorePolicy;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@Configuration
public class BeanConfig {

@Value("${cloud.aws.region.static}")
private String clientRegion;

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
Expand Down Expand Up @@ -41,4 +48,11 @@ public ResultScoreCalculator gameScoreCalculator() {
);
return new ResultScoreCalculator(gameScorePolicies);
}

@Bean
public AmazonS3 amazonS3() {
return AmazonS3ClientBuilder.standard()
.withRegion(clientRegion)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ public enum CommonExceptionType implements BaseExceptionType {
HttpStatus.BAD_REQUEST,
"파일 저장하다 문제가 발생했습니다."
),
;

MULTIPART_FILE_NOT_EXIST(
224,
HttpStatus.BAD_REQUEST,
"전송한 파일이 비어있습니다."
);

private final int errorCode;
private final HttpStatus httpStatus;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.now.naaga.common.infrastructure;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.now.naaga.common.exception.CommonException;
import com.now.naaga.common.exception.CommonExceptionType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

@Component
public class AwsS3FileManager {

private static final String FILE_EXTENSION_SEPARATOR = ".";

private final AmazonS3 amazonS3;

private final String bucketName;

public AwsS3FileManager(final AmazonS3 amazonS3,
@Value("${cloud.aws.s3.bucket}") final String bucketName) {
this.amazonS3 = amazonS3;
this.bucketName = bucketName;
}

public String uploadFile(final MultipartFile multipartFile) {
validateFileExists(multipartFile);
final String fileName = buildFileName(multipartFile.getOriginalFilename());
final ObjectMetadata objectMetadata = initializeObjectMetadata(multipartFile);

try (final InputStream inputStream = multipartFile.getInputStream()) {
amazonS3.putObject(new PutObjectRequest(bucketName, fileName, inputStream, objectMetadata));
} catch (IOException e) {
throw new IllegalArgumentException();
}

return amazonS3.getUrl(bucketName, fileName).toString();
}

private void validateFileExists(final MultipartFile multipartFile) {
if (multipartFile.isEmpty()) {
throw new CommonException(CommonExceptionType.MULTIPART_FILE_NOT_EXIST);
}
}

private String buildFileName(final String originalFileName) {
final String extension = originalFileName.substring(originalFileName.lastIndexOf(FILE_EXTENSION_SEPARATOR));
return UUID.randomUUID() + extension;
}

private ObjectMetadata initializeObjectMetadata(final MultipartFile multipartFile) {
final ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(multipartFile.getSize());
objectMetadata.setContentType(multipartFile.getContentType());
return objectMetadata;
}

//버전이 지정된 버킷 객체 삭제
public void deleteFile(String imageUrl) {
String fileName = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
amazonS3.deleteObject(new DeleteObjectRequest(bucketName, fileName));
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ public DeleteTemporaryPlaceWithPlaceCreateEventHandler(final TemporaryPlaceServi
@EventListener
public void handle(final PlaceCreateEvent placeCreateEvent) {
final Long temporaryPlaceId = placeCreateEvent.temporaryPlaceId();
temporaryPlaceService.deleteById(temporaryPlaceId);
temporaryPlaceService.deleteByIdWhenPlaceCreated(temporaryPlaceId);
}
}
Loading

0 comments on commit 6b2f1eb

Please sign in to comment.