반응형

토이 프로젝트로 혼자서 클라우드 서비스를 이용하여 웹 개발부터 배포까지 온 과정을 경험해 보았습니다.

이 과정을 단계별로 나누어서 정리해 보려고 합니다.!

많은 피드백은 감사합니다!

 

목차 

STEP 01) NCP 서버 

STEP 02) AWS RDS, S3

STEP 03) Web Application 개발

STEP 04) Jenkins pipeline 배포

STEP 05) Domain 등록

 

 


 

* Web Application 개발은 앞에서 살펴보았던 AWS 서비스를 사용하는 방법만 소개하도록 하겠습니다.

 

개발 환경

 - SpringBoot 2.6.6

 - Mariadb 2.7.5

 - Gradle 7.4.1

 

1. RDS 연결(yml 설정)

  - 이전 RDS 설정 확인

spring:
  datasource:
    url: jdbc:mariadb://rds end point 주소 + prot + schema name
      예) jdbc:mariadb://rds.amazonaws.com:3306/rdstest
    driver-class-name: org.mariadb.jdbc.Driver
    username: admin
    password: 패스워드

 

2. S3 연결

  - 이전 S3 설정 확인

1.  spring cloud starter 의존성 추가

  - build.gradlew

implementation 'io.awspring.cloud:spring-cloud-starter-aws:2.3.1'

 

2. yml 설정

cloud:
  aws:
    credentials:
      access-key: access key
      secret-key: secret key
    s3:
      region: ap-northeast-2
      endpoint: s3-bucket

 

  - access key, secrey key 새 액세스 키 만들기로 생성

 

 

- region, endpoint 작성

  endpoint는 :::뒤에 복/붙

 

AwsS3Config.java

 

package com.bumblebee.dailyspecial.domain.aws;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author bumblebee
 */
@Configuration
public class AwsS3Config {

    @Value("${cloud.aws.credentials.access-key}")
    private String accessKey;

    @Value("${cloud.aws.credentials.secret-key}")
    private String secretKey;

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

    @Bean
    public AmazonS3Client amazonS3Client() {
        BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                .build();
    }

}

 

AwsS3Service.java

 

package com.bumblebee.dailyspecial.domain.aws;

import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.bumblebee.dailyspecial.domain.comutils.CommonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author bumblebee
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class AwsS3Service {

    private final AmazonS3Client amazonS3Client;

    @Value("${cloud.aws.s3.endpoint}")
    private String bucketName;

    public String uploadFileV1(String category, MultipartFile multipartFile) {
        validateFileExists(multipartFile);

        String fileName = CommonUtils.buildFileName(category, multipartFile.getOriginalFilename());

        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(multipartFile.getContentType());

        try (InputStream inputStream = multipartFile.getInputStream()) {
            amazonS3Client.putObject(new PutObjectRequest(bucketName, fileName, inputStream, objectMetadata)
                    .withCannedAcl(CannedAccessControlList.PublicRead));
        } catch (IOException e) {
//            throw new FileUploadFailedException();
        }

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

    private void validateFileExists(MultipartFile multipartFile) {
        if (multipartFile.isEmpty()) {
//            throw new EmptyFileException();
        }
    }

}

 

AwsS3Config class에 amazonS3Client 메소드를 @Bean으로 등록합니다.

파일을 업로드가 필요한 로직에 AwsS3Service class에서 uploadFIleV1 메소드를 이용해서 S3에 업로드 합니다.

예)

awsS3Service.uploadFileV1("Img", multipartFile);

 

그 외 다운로드 및 다중 업로드 기능도 제공하고 있습니다.

 

참조

  - Springboot로 S3 파일 업로드하기

728x90
반응형
반응형

토이 프로젝트로 혼자서 클라우드 서비스를 이용하여 웹 개발부터 배포까지 온 과정을 경험해 보았습니다.

이 과정을 단계별로 나누어서 정리해 보려고 합니다.!

많은 피드백은 감사합니다!

 

목차 

STEP 01) NCP 서버 

STEP 02) AWS RDS, S3

STEP 03) Web Application 개발

STEP 04) Jenkins pipeline 배포

STEP 05) Domain 등록


1. NCP(Naver CLoud Platform)

  - 네이버 클라우드 서비스로 1년간 Free Tier 서비스를 이용할 수 있습니다.

  - 네이버 클라우드 서비스를 사용해 보고 싶어서 서버는 NCP Sorver를 선택

  - 네이버 클라우드 서비스라서 언어가 매우 친숙함.

 

https://www.ncloud.com/

 

NAVER CLOUD PLATFORM

cloud computing services for corporations, IaaS, PaaS, SaaS, with Global region and Security Technology Certification

www.ncloud.com

 

2. NCP에서는 다양항 클라우드 서비스를 제공합니다.

  - Free Tier에서는 아래 설명과 같이 Micro Server를 1년간 무료로 1대를 제공합니다. 

  - Compute > Server 선택

  - NCP server guide(https://guide.ncloud-docs.com/docs/compute-server-prep)

 

 

3. Server > 서버 생성

 

 

4. 서버 이미지 선택에서 서버 타입 Micro 선택 후 centos-7.8-64 선택  

 

 

5. 서버 설정 탭에서 Free Tier 서버에 맞게 설정 후 다음

  - 본 이미지는 Micro 타입 서버를 이미 1개 생성해서 하나 더 생성할 수 없어서 Compact 타입으로 설정 후 진행하였습니다.

  - SSD 서버는 Micro 타입 서버를 지원하지 않습니다.

 

 

6. 인증키 설정에서 서버에 접속할 관리자 비밀번호를 생성합니다.

  - 항상 인증키는 안전한 곳에 저장!

 

 

7. 네트워크 접근 설정은 생성 할 서버에 대한 방화벽 설정이라고 생각하시면 될 것 같습니다. 

 

 

8. ACG 설정에서 접근 소스는 접속에 허용될 ip 대역을 의미합니다.

  - 웹 서비스를 접근할 8080 포트를 허용합니다.

  - 서버 ssh에 접근되는 22 포트를 허용합니다. (서버 접근은 myip로 하여 보안을 강화하는 게 좋습니다.)

 

 

9. 이제 생성된 서버에 접근해보도록 하겠습니다.

  ssh에 접근에 많이 사용되는 tool인 putty를 이용해 보도록 하겠습니다.

  ncp에 새로 생성된 서버를 클릭해 보시면 포트 포워딩 정보에 서버 접속용 공인 ip와 외부 포트가 있습니다.

  해당 정보를 아래 위치에 작성하고 Open!

  [MacOS putty 참고 블로그]

   - https://velog.io/@wlgus2134/MAC-PUTTY-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0

 

putty

10. 리눅스 관리자 계정은 root이고, password는 위에서 입력한 관리자 비밀번호로 접속이 가능합니다!

 

 

NCP 클라우드 플랫폼을 이용해서 아주 간편하게 Web Server를 구동시킬 수 있는 서버 한 대가 생성되었습니다!

공인 ip를 발급받아야지 저희가 구동시킨 Web Server에 접근할 수 있습니다.

다음 Step에서 Application를 개발하고 진행하도록 하겠습니다.

 

 

728x90
반응형
반응형

로컬에서 정상적으로 작동하는 기능이 리눅스 서버에 배포하니 500 에러가 발생하였다.

에러를 확인하니 아래와 같이 출력되고 있었다..

 

Error resolving template [/index], template might not exist or might not be accessible by any of the configured Template Resolvers

 

Controller에서 return하는 html 파일을 찾을 때 발생하는 문제였다.

"/index"가 문제 발생 원인이다.

 

    @GetMapping("/test")
    public String test( Model model) {
        return "/index"; // 에러 발생
    }

 

/ 를 제거하면 리눅스에서도 정상 작동한다.

 

    @GetMapping("/test")
    public String test( Model model) {
        return "index"; // 정상 작동
    }

 

구글링해서 문제를 해결하였지만, 충분히 에러코드를 읽었으면 쉽게 해결할 문제였던 것 같다.

항상 에러 코드를 상세히 잘 읽어보자..

728x90
반응형
반응형

개발하다 보면 html 파일을 수정할 때마다 서버를 재시작하는 일은 매우 번거롭다.

개발 생산성을 높이기 위해서 Spring Boot에서는 Spring Boot Devtools 모듈을 제공하여 개발 시 유용한 기능들을 제공한다.

Intellij에서 Spring Boot Devtools 의존성을 추가하였지만, 소스코드가 바로 적용이 안되시는 분들을 한 번 따라 해보면 좋을 것 같다.

 

대표적인 기능

  - Automatic Restart : classpath에 있는 파일이 변경될 때마다 감지하여 애플리케이션을 자동으로 재시작해준다.

  - Live Reload : 정적 자원(html, css, js) 수정 시 새로고침 없이 바로 적용할 수 있다.

  - Property Defaults : Thymeleaf는 기본적으로 성능을 향샹시키기 위해서 캐싱 기능을 사용한다. 이 캐싱 기능을 false 값으로 설정하여 수정한 소스가 바로 반영되어지도록 적용할 수 있다.

 

세팅 환경

  - IntelliJ IDEA 2021.3.1 (Ultimate Edition)

  - SpringBoot 2.6.6 

  - gradle

 

Spring Boot Devtools 적용

1. build.gradle에 dependencies 추가

 

developmentOnly 'org.springframework.boot:spring-boot-devtools'

 

2. Preferences > Build, Execution, Deployment > Compiler > Build project automatically 체크

 

 

2. Preferences > Advanced Settings > Compiler > Allow auto-make to start even if developed ... 체크

 

 

3. Edit Configurations...

 

 

4. Modify options

 

 

5. On 'Update' action > Update classes and resources 체크

 

 

6. On frame deactivation > Update classes and resources 체크

 

 

7.  Modify options 확인

 

 

* 설정을 하나씩 추가해 보며 소스코드가 적용이 되는지 확인해 보면 좋을 것 같다. 

  나 같은 경우 브라우저 새로고침을 2번 해야지 html 소스코드가 적용이 되었는데 6번(프레임 비활성 시 클래스 및 리소스 업데이트를 체크)을 적용했더니 새로고침 한 번에 바로 적용이 되었다.

728x90
반응형
반응형

1. h2 Database Engine 다운로드

download에서 본인의 운영체제에 맞게 다운로드

h2 download url

- https://www.h2database.com/html/main.html

 

H2 Database Engine

H2 Database Engine Welcome to H2, the Java SQL database. The main features of H2 are: Very fast, open source, JDBC API Embedded and server modes; in-memory databases Browser based Console application Small footprint: around 2.5 MB jar file size     Supp

www.h2database.com

 

2. SpringBoot 프로젝트 생성 후 yml 파일 작성

spring:
  # DB 연결
  datasource:
    # 설치된 H2 DB와 연결 URL
    url: jdbc:h2:file:./db/H2/data;AUTO_SERVER=true
    # 접속을 위한 드라이버
    driver-class-name: org.h2.Driver
    # springboot 2.4 부터는 username이 꼭 있어야합니다. 없으면 에러가 발생합니다.
    username: sa
    password:
  • jdbc:h2:file : file로 DB를 관리하겠다는 뜻
  • ./db/H2/data : 현재 설정된 경로에 data 라는 이름으로 데이터베이스 파일이 생성된다.  
  • AUTO_SERVER : 다중 접속을 허용하겠다는 의미

 

3. 프로젝트 실행

 

Menu Entity 생성

@Entity
public class Menu {

    @Id
    @GeneratedValue
    private Long id;

    private String menuName;

    private String menuType;



}

 

MenuType Entity 생성

@Entity
public class MenuType {

    @Id
    @GeneratedValue
    private Long id;

    private String typeSeq;

    private String typeName;

}

 

yml 설정에 맞게 생성된 DB file 확인

 

 

4. h2 console 실행

터미널에서 1번에서 다운로드 받은 h2 파일 아래에 bin 파일로 이동 후 ./h2.sh 실행 (mac os 기준)

JDBC URL에 해당 프로젝트 경로에 h2 db 위치를 작성 후 AUTO_SERVE 설정을 넣어준다

ex) jdbc:h2:file:/Users/Desktop/DailySpecial/db/H2/data;AUTO_SERVER=true

 

 

5. 생성된 테이블  확인

 

 

** db file 경로 지정시 h2 console 같은 경우 사용자 디렉터리에서 부터 찾아야 한다.

사용자 디렉터리 경로 파일 접근 같은 경우

h2 console

ex) jdbc:h2:~/testdb

 

yml

ex)

url: jdbc:h2:tcp://localhost/~/testdb

 

728x90
반응형
반응형

 

intellij 상단에 File -> Open -> import할 프로젝트의 build.gradle 선택 후 Open as Project 선택

 

1. Open

 

 

 

2. build.gradle 선택

 

 

3. Open as Project 선택 끝!

 

728x90
반응형

+ Recent posts