1. SSL 인증서 받기

먼저 AWS로 들어가서 ACM 메뉴로 들어가 줍니다.

 

 

시작하기를 눌러 줍니다.

 

 

 

 

오른쪽 하단의 인증서 요청을 눌러줍니다.

 

 

 

 

아래에 본인의 도메인을 적어줍니다. ex) *.example.com으로 적어두시면 example.com의 하위 도메인까지 모두 포함합니다. 입력 후 다음을 눌러줍니다.

 

 

 

 

검증 방법은 DNS검증을 하겠습니다. 다음을 눌러 줍니다.

 

 

 

 

태그는 딱히 추가하지 않아도 무방합니다 . 검토를 눌러줍니다.

 

 

 

 

 

그다음 오른쪽 하단에 확인 및 요청을 눌러줍니다.

 

 

 

 

그러면 이런화면이 나올텐데 Route 53에서 레코드 생성을 눌러줍니다. 그러면 자동으로 생성이됩니다. 그런다음 계속을 눌러준 후 검증이 될때까지 대기해 줍니다.

 

2. LoadBalancer 만들기

AWS 메뉴에서 EC2 메뉴로 들어가신 뒤 왼쪽 사이드메뉴에서 로드밸런서를 눌러 줍니다. 그런다음 Load Balancer 생성을 눌러 줍니다.

 

 

그 뒤 이런 화면이 나올탠데 맨 왼쪽에 Application Load Balancer를 눌러줍니다.

 

 

 

사용 하실 로드밸런서 이름과 80번 포트와 443 포트를 모두 열어줍니다. 80을 포트를 열어주는 이유는 나중에 80번 포트로 접속시 자동으로 443 포트로 리다이렉트 시키기 위함입니다. 다음을 눌러줍니다.

 

 

 

 

자동으로 방금 만든 인증서로 선택이 됩니다. 그후 다음을 눌러줍니다.

 

 

 

보안그룹을 선택해야 하는데 저는 기존에 만들어 놓은 그룹이 있어서 그것을 사용하였습니다. 만약 없으시다면 보안그룹을 새로 만든뒤 보안 안그룹 정책에서 80포트와 443포트를 열어주세요 그후 다음을 눌러줍니다

 

 

 

이제 이 로드밸런서를 이용하여 라우팅할 그룹을 설정해야 하는데요 저의 경우 그룹이 없어서 새로 만드는 작업도 같이 하겠습니다. 중간에 프로토콜과 포트가 있는데 저는 EC2 인스턴스에서 HTTP 프로토콜과 8888번 포트를 사용하여 Application을 실행하고 있기 때문에 맞춰주었습니다. 그후 다음을 눌러줍니다.

 

 

 

 

이제 방금 만든 그룹에 속할 인스턴스를 등록해야 하는데요 저는 dev 인스턴스 하나만 넣도록 하겠습니다. 그후 다음을 눌러주면 검토화면이 나오는데 확인 후 생성을 눌러줍니다.

 

 

 

 

 

3. HTTP로 들어온 요청을 HTTPS로 리다이렉트 시키기

이제 80번 포트로 들어오는 연결을 443 HTTPS로 리다이렉트 시켜보겠습니다. 로드밸런서 메뉴로 들어오신후 80번 포트 리스너를 선택 후 편집을 눌러줍니다.

 

 

 

 

휴지통을 눌러 삭제해 주신뒤 작업 추가를 누른뒤 리디렉션 대상을 눌러줍니다.

 

 

다 마친 뒤 오른쪽 위에 업데이트를 눌러 작업을 마칩니다.

 

4. ROUTE53에서 LoadBalancer 연결하기

 

 

라우트 53으로 가신다음에 호스팅 영역을 눌러줍니다

 

 

 

레코드 생성을 눌러줍니다.

 

 

 

단순 라우팅을 선택한뒤 다음을 눌러줍니다

 

 

 

그 다음 방금 만든 load balance를 연결시켜줍니다. 그 다음 단순 레코드 정의를 눌러줍니다. 

 

 

 

 

레코드 생성을 눌러주면 본인의 도메인과 loadbalance가 연결되었습니다.

 

작업이 모두 끝났지만 적용되는데까지 시간이 걸리는것 같습니다. 저의 경우 30분정도 걸린듯 싶습니다. 꽤나 오래걸린...

Spring Boot : 2.4.4 버전 입니다.

먼저 CKeditor와 AWS S3 버킷은 만들었다고 가정하겠습니다.

우선 기본적으로 CDN을 통해 CK editor를 붙이면 드래그&드롭기능은 있지만 이미지 업로드가 되지 않을텐데요. 먼저 이미지 업로드부터 활성화 시키겠습니다.

 

 

imageUploadUrl 이라는 키워드를 통해 드래그&드롭으로 이미지를 올릴 시 어떤 API로 보낼지 정할 수 있습니다. 저의 경우 /image/upload 입니다.

그 다음은 컨트롤러 부분을 보겠습니다.

 

 

CK Editor를 사용했다면서 왜 RestController있냐고 생각하실수도 있으신 분들을 위해 설명하겠습니다.

이미지 업로드를 하고 나면 정해진 형태의 json 양식으로 response를 보내주어야 CK Editor가 인식 할 수 있습니다.

 

 

response의 양식을 위와 같습니다.

그 다음은 Service 부분입니다.

코드가 길어 이미지 대신 코드블럭으로 대신하였습니다.

@Service
@RequiredArgsConstructor
@Slf4j
public class FileService {

    private final AmazonS3Client amazonS3Client;
    
    @Value("${cloud.aws.s3.bucket}")
    private String bucket;

    public FileUploadDTO fileUpload(MultipartFile upload, Principal principal) throws IOException {
        File uploadFile = convert(upload).orElseThrow(() -> new IllegalArgumentException("MultipartFile -> File 전환실패."));

        return upload(uploadFile, "static");
    }

    private FileUploadDTO upload(File uploadFile, String dir) {
        String sourceName = uploadFile.getName();
        String sourceExt = FilenameUtils.getExtension(sourceName).toLowerCase();

        String fileName = dir + "/" + LocalDateTime.now().toString().concat(".").concat(sourceExt);
        String uploadImageUrl = putS3(uploadFile, fileName);
        removeNewFile(uploadFile);

        return FileUploadDTO.builder()
                .uploaded(true)
                .fileName(fileName)
                .url(uploadImageUrl)
                .build();
    }

    private void removeNewFile(File targetFile) {
        if (targetFile.delete()) {
            log.info("파일이 삭제되었습니다.");
        } else {
            log.info("파일이 삭제되지 못했습니다.");
        }
    }

    private String putS3(File uploadFile, String fileName) {
        try {
            amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, uploadFile)
                    .withCannedAcl(CannedAccessControlList.PublicRead));
        } catch (Exception e) {
            log.error("이미지 s3 업로드 실패");
            log.error(e.getMessage());
            removeNewFile(uploadFile);
            throw new RuntimeException();
        }

        return amazonS3Client.getUrl(bucket, fileName).toString();
    }

    private Optional<File> convert(MultipartFile file) throws IOException {
        File convertFile = new File(Objects.requireNonNull(file.getOriginalFilename()));
        if (convertFile.createNewFile()) {
            try (FileOutputStream fos = new FileOutputStream(convertFile)) {
                fos.write(file.getBytes());
            }

            return Optional.of(convertFile);
        }

        return Optional.empty();
    }
}

코드에 대해 자세한 설명이 필요하신 분들은 https://jojoldu.tistory.com/300 이 글을 보시면 자세히 알 수 있습니다.

저는 위의 글과는 조금 다르게 환경설정을 했습니다. 위의 글에서는 aws.yml 파일을 따로 만들어서 accessKey와 secretKey를 등록을 해줬는데요 저같은 경우에는 로컬, develop 서버, product 서버의 환경이 다르다보니 각 서버별로 RDS를 연결시켜주어야 했습니다. 그러기 때문에 yml파일을 환경별로 세팅하여서 위의 글과는 다른 점이 있습니다. 물론 하나의 yml 파일에 ---로 구분지어 환경을 나눌수 있다고 하는데 아직 해보지 않아서 모르겠습니다. 추후 해본다음에 포스트하도록 하겠습니다.

다른점은 yml파일과 main 함수 부분입니다.

 

 

spring:
  config:
    activate:
      on-profile: dev

  mvc:
    hiddenmethod:
      filter:
        enabled: false

  datasource:
    url: jdbc:mysql://${rds}:3306/board?autoReconnect=true&useUnicode=true&serverTimezone=UTC&characterEncoding=UTF8
    username: ${username}
    password: ${password}
    driver-class-name: com.mysql.cj.jdbc.Driver

  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        show_sql: true
        format_sql: true
        use_sql_comments: true

  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    cache: false

  loggin.level:
    org.hibernate.SQL: debug

server:
  port: 8888

cloud:
  aws:
    s3:
      bucket: hese-board
    region:
      static: ap-northeast-2
    credentials:
      accessKey: ${accessKey}
      secretKey: ${secretKey}
      use-default-aws-credentials-chain: false
      instance-profile: true
    stack:
      auto: false

accessKey와 secretKey 부분에 ${} 이렇게 되어있는걸 볼 수 있는데요 이렇게 해줌으로써 jar 파일을 실행할때 변수를 넘겨주어 acessKey와 secretKey를 설정해줄 수 있습니다.

제가 사용하는 명령어를 적어놓겠습니다.

java -Dspring.profiles.active=dev -jar /home/ubuntu/application/deploy/*.jar --rds=rds주소 --username=계정명 --password=비밀번호 --accessKey=액세스키 --secretKey=시크릿키

-Dspring.profiles.active로 사용할 application.yml 파일을 정해주고 뒤에 추가 변수로 전부 매핑시켜 줍니다.

+ Recent posts