[AWS 무료 서버구축-17/18] 메모앱 만들기 - backend 서비스 만들기

Setup/aws|2021. 7. 25. 17:31

메모앱 만들기

지금까지 구축한 aws 서버위에 간단한 메모 application을 만들어서 배포 하겠습니다

 

테이블 생성 및 초기데이터 적재

테이블을 생성하고 초기 데이터를 인서트 합니다.

아래 스크립트는 aws 의 mariadb 에서 실행합니다.

먼저 메모 테이블을 생성합니다.

CREATE TABLE `memo` ( ​​`id` bigint(20) NOT NULL, ​​`contents` varchar(4000) NOT NULL, ​​`title` varchar(200) NOT NULL, ​​PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

자동증가 시퀀스 테이블을 만듭니다.

CREATE TABLE `hibernate_sequence` ( ​​`next_val` bigint(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

초기 데이터를 생성합니다.

INSERT INTO memo (id, contents, title) VALUES(1, '내용1', '제목1'); INSERT INTO memo (id, contents, title) VALUES(2, '내용2', '제목2'); INSERT INTO memo (id, contents, title) VALUES(3, '내용3', '제목3'); INSERT INTO hibernate_sequence (next_val) VALUES(4);

 

앱구조

springboot application 구조는 아래와 같습니다.

. ├── build.gradle └── src ​​​​└── main ​​​​​​​​├── java ​​​​​​​​│ └── io ​​​​​​​​│ └── github ​​​​​​​​│ └── goodsaem ​​​​​​​​│ └── api ​​​​​​​​│ ├── ApiApplication.java ​​​​​​​​│ ├── config ​​​​​​​​│ │ └── WebConfig.java ​​​​​​​​│ ├── controller ​​​​​​​​│ │ └── v1 ​​​​​​​​│ │ └── MemoController.java ​​​​​​​​│ ├── entity ​​​​​​​​│ │ └── Memo.java ​​​​​​​​│ ├── repo ​​​​​​​​│ │ └── MemoJpaRepo.java ​​​​​​​​│ └── service ​​​​​​​​│ ├── IMemoService.java ​​​​​​​​│ └── MemoService.java ​​​​​​​​└── resources ​​​​​​​​​​​​├── application.yml ​​​​​​​​​​​​├── banner.txt ​​​​​​​​​​​​└── templates

 

build.gradle

특별한 내용은 없고 springboot 2.4.4 버전 사용 및 mariadb 와 jpa 라이브러리 추가및 lombok 플러그인을 추가했습니다.

buildscript { ‌ext { ‌‌springBootVersion = '2.4.4' } ‌repositories { ‌‌mavenCentral() } ‌dependencies { ‌‌classpath( ‌‌‌‌"org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'org.springframework.boot' apply plugin: 'war' apply plugin: 'io.spring.dependency-management' sourceCompatibility = '1.8' targetCompatibility = '1.8' group = 'io.github.goodsaem' version = '1.1' configurations { ‌compileOnly { ‌‌extendsFrom annotationProcessor } } repositories { ‌mavenCentral() } dependencies { ‌implementation 'org.springframework.boot:spring-boot-starter-data-jpa' ‌implementation 'org.springframework.boot:spring-boot-starter-web' ‌implementation 'org.springframework.boot:spring-boot-autoconfigure' ‌implementation("org.mariadb.jdbc:mariadb-java-client") ‌compileOnly 'org.projectlombok:lombok' ‌annotationProcessor 'org.projectlombok:lombok' ‌testImplementation 'org.springframework.boot:spring-boot-starter-test' } test { ‌useJUnitPlatform() }

 

ApiApplication.java

springboot 시작 파일 입니다.

package io.github.goodsaem.api; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ApiApplication { public static void main(String[] args) { ‌‌SpringApplication.run(ApiApplication.class, args); } }

 

WebConfig.java

CORS 설정 파일입니다. 허용할 도메인에 대해서 아래와 같이 정의 합니다.

package io.github.goodsaem.api.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { ​​​​@Override ​​​​public void addCorsMappings(CorsRegistry registry) { ​​​​​​​​registry.addMapping("/**") ​​​​​​​​​​​​​​​​.allowedOrigins("https://goodsaem.github.io","http://localhost:8080") ​​​​​​​​​​​​​​​​.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE","OPTIONS"); ​​​​} }

 

MemoController.java

restapi controller 입니다. 메모의 crud url 을 호출하면 해당 요청에 맞는 서비스를 호출하여 db 작업을 수행합니다

package io.github.goodsaem.api.controller.v1; import io.github.goodsaem.api.entity.Memo; import io.github.goodsaem.api.service.IMemoService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; @RequiredArgsConstructor @RestController @RequestMapping(value = "/v1") public class MemoController { ​​​​private final IMemoService iMemoService; ​​​​@GetMapping(value = "/memos") ​​​​public List<Memo> readMemos() { ​​​​​​​​return iMemoService.readMemos(); ​​​​} ​​​​@GetMapping(value = "/memo/{id}") ​​​​public Memo readMemo( @PathVariable long id) { ​​​​​​​​return iMemoService.readMemo(id); ​​​​} ​​​​@PostMapping(value = "/memo") ​​​​public Memo createMemo(@RequestParam String title,String contents) { ​​​​​​​​return iMemoService.createMemo(title,contents); ​​​​} ​​​​@PutMapping(value = "/memo") ​​​​public Memo updateMemo(@RequestParam long id, @RequestParam String title,String contents) { ​​​​​​​​return iMemoService.updateMemo(id,title,contents); ​​​​} ​​​​@DeleteMapping(value="/memo/{id}") ​​​​public void deleteMemo(@PathVariable long id) { ​​​​​​​​iMemoService.deleteMemo(id); ​​​​} ​​​​@DeleteMapping(value="/memos") ​​​​public void deleteMemos() { ​​​​​​​​iMemoService.deleteMemos(); ​​​​} }

 

Memo.java

memo entity 입니다.

package io.github.goodsaem.api.entity; import lombok.*; import javax.persistence.*; @Builder @Entity @Setter @Getter @NoArgsConstructor @AllArgsConstructor @Table(name="memo") public class Memo { ​​​​@Id ​​​​@GeneratedValue(strategy = GenerationType.AUTO) ​​​​private long id; ​​​​@Column(nullable = false, length = 30) ​​​​private String title; ​​​​@Column(nullable = false, length = 4000) ​​​​private String contents; }

 

MemoJpaRepo.java

jpa를 사용하기 위해 jparepository를 상속 받습니다.

package io.github.goodsaem.api.repo; import io.github.goodsaem.api.entity.Memo; import org.springframework.data.jpa.repository.JpaRepository; public interface MemoJpaRepo extends JpaRepository<Memo, Long> { }

 

IMemoService.java

서비스 인터페이스 입니다.

package io.github.goodsaem.api.service; import io.github.goodsaem.api.entity.Memo; import java.util.List; public interface IMemoService { ​​​​List<Memo> readMemos(); ​​​​Memo readMemo(long id); ​​​​Memo createMemo(String title,String contents); ​​​​Memo updateMemo(long id,String title,String contents); ​​​​void deleteMemo(long id); ​​​​void deleteMemos(); }

 

MemoService.java

jpaRepo로 실제 crud 작업을 수행합니다.

package io.github.goodsaem.api.service; import io.github.goodsaem.api.entity.Memo; import io.github.goodsaem.api.repo.MemoJpaRepo; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; @Slf4j @Service @RequiredArgsConstructor public class MemoService implements IMemoService { ​​​​private final MemoJpaRepo memoJpaRepo; ​​​​@Override ​​​​public List<Memo> readMemos() { ​​​​​​​​return memoJpaRepo.findAll(); ​​​​} ​​​​@Override ​​​​public Memo readMemo(long id) { ​​​​​​​​return memoJpaRepo.findById(id).orElse(null); ​​​​} ​​​​@Override ​​​​public Memo createMemo(String title, String contents) { ​​​​​​​​Memo memo = Memo.builder() ​​​​​​​​​​​​​​​​.title(title) ​​​​​​​​​​​​​​​​.contents(contents) ​​​​​​​​​​​​​​​​.build(); ​​​​​​​​return memoJpaRepo.save(memo); ​​​​} ​​​​@Override ​​​​public Memo updateMemo(long id, String title, String contents) { ​​​​​​​​Memo memo = Memo.builder() ​​​​​​​​​​​​​​​​.id(id) ​​​​​​​​​​​​​​​​.title(title) ​​​​​​​​​​​​​​​​.contents(contents) ​​​​​​​​​​​​​​​​.build(); ​​​​​​​​return memoJpaRepo.save(memo); ​​​​} ​​​​@Override ​​​​public void deleteMemo(long id) { ​​​​​​​​memoJpaRepo.deleteById(id); ​​​​} ​​​​@Override ​​​​public void deleteMemos() { ​​​​​​​​memoJpaRepo.deleteAll(); ​​​​} }

 

application.yml

appplication 설정 내용으로 mariadb 연결정보와 서비스 포트 context path 설정정보를 가지고 있습니다.

server: ​​port: 9090 ​​servlet: ​​​​context-path: /spring ​​​​session: ​​​​​​timeout: 60 ​​​​​​tomcat: ​​​​​​​​uri-encoding: UTF-8 spring: ​​datasource: ​​​​driver-class-name: org.mariadb.jdbc.Driver ​​​​url: jdbc:mariadb://localhost:3306/goodsaem?useSSL=false&serverTimezone=KST ​​​​username: goodsaem ​​​​password: xxxxxxxxxx ​​jpa: ​​​​database-platform: org.hibernate.dialect.MariaDBDialect ​​​​properties.hibernate.hbm2ddl.auto: none ​​​​showSql: true

 

banner.txt

spring boot 시작시 사용할 배너 입니다.

※ 배너는 http://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20 여기에서 만들수 있습니다.

​██████╗ ██████╗ ██████╗ ██████╗ ███████╗ █████╗ ███████╗███╗ ███╗ ██╔════╝ ██╔═══██╗██╔═══██╗██╔══██╗██╔════╝██╔══██╗██╔════╝████╗ ████║ ██║ ███╗██║ ██║██║ ██║██║ ██║███████╗███████║█████╗ ██╔████╔██║ ██║ ██║██║ ██║██║ ██║██║ ██║╚════██║██╔══██║██╔══╝ ██║╚██╔╝██║ ╚██████╔╝╚██████╔╝╚██████╔╝██████╔╝███████║██║ ██║███████╗██║ ╚═╝ ██║ ​╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ :: Spring Boot :: ver : ${spring-boot.version}

 

api-1.1.war 파일 만들기

프로젝트 시작 home 디렉토리에서 아래 명령어를 입력하여 war 파일을 만듭니다.

sh gradlew build

 

war file 업로드

aws 서버에 api-1.1.war 파일을 업로드 합니다.

 

springboot 재시작

aws 서버에 접속한후 아래 명령어를 입력합니다.

서비스 중지

ubuntu@goodsaem:~$ ./stop.sh =====spring is running at 5808 Shutdown spring now

 

서비스 시작

ubuntu@goodsaem:~$ ./start.sh;./log.sh

 

시작 로그

​██████╗ ██████╗ ██████╗ ██████╗ ███████╗ █████╗ ███████╗███╗ ███╗ ██╔════╝ ██╔═══██╗██╔═══██╗██╔══██╗██╔════╝██╔══██╗██╔════╝████╗ ████║ ██║ ███╗██║ ██║██║ ██║██║ ██║███████╗███████║█████╗ ██╔████╔██║ ██║ ██║██║ ██║██║ ██║██║ ██║╚════██║██╔══██║██╔══╝ ██║╚██╔╝██║ ╚██████╔╝╚██████╔╝╚██████╔╝██████╔╝███████║██║ ██║███████╗██║ ╚═╝ ██║ ​╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ :: Spring Boot :: ver : 2.4.4 2021-03-27 17:10:46.869 INFO 7734 --- [ main] io.github.goodsaem.api.ApiApplication : Starting ApiApplication using Java 1.8.0_282 on goodsaem with PID 7734 (/home/ubuntu/api-1.1.war started by ubuntu in /home/ubuntu) 2021-03-27 17:10:46.874 INFO 7734 --- [ main] io.github.goodsaem.api.ApiApplication : No active profile set, falling back to default profiles: default 2021-03-27 17:10:48.714 INFO 7734 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2021-03-27 17:10:48.852 INFO 7734 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 121 ms. Found 1 JPA repository interfaces. 2021-03-27 17:10:50.415 INFO 7734 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 9090 (http) 2021-03-27 17:10:50.442 INFO 7734 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2021-03-27 17:10:50.446 INFO 7734 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.44] 2021-03-27 17:10:51.931 INFO 7734 --- [ main] o.a.c.c.C.[.[localhost].[/spring] : Initializing Spring embedded WebApplicationContext 2021-03-27 17:10:51.932 INFO 7734 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 4908 ms 2021-03-27 17:10:52.874 INFO 7734 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2021-03-27 17:10:52.986 INFO 7734 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.29.Final 2021-03-27 17:10:53.296 INFO 7734 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2021-03-27 17:10:53.661 INFO 7734 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2021-03-27 17:10:53.804 INFO 7734 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2021-03-27 17:10:53.848 INFO 7734 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MariaDBDialect 2021-03-27 17:10:54.767 INFO 7734 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2021-03-27 17:10:54.779 INFO 7734 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2021-03-27 17:10:55.548 WARN 7734 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2021-03-27 17:10:55.822 INFO 7734 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2021-03-27 17:10:56.395 INFO 7734 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 9090 (http) with context path '/spring' 2021-03-27 17:10:56.413 INFO 7734 --- [ main] io.github.goodsaem.api.ApiApplication : Started ApiApplication in 10.795 seconds (JVM running for 11.987)

 

웹브라우저에서 확인

https://goodsaem.ml/spring/v1/memosurl 접근했을때 아래와 같은 문자열이 출력되면 정상입니다.

[ ​​{ ​​​​"id": 1, ​​​​"title": "제목1", ​​​​"contents": "내용1" ​​}, ​​{ ​​​​"id": 2, ​​​​"title": "제목2", ​​​​"contents": "내용2" ​​}, ​​{ ​​​​"id": 3, ​​​​"title": "제목3", ​​​​"contents": "내용3" ​​} ]

 

전체소스 다운로드

지금까지 만든 소스는 아래 링크를 통해서 다운로드 가능합니다.

api2.zip
0.13MB

댓글()