[AWS 무료 서버구축-17/18] 메모앱 만들기 - backend 서비스 만들기
메모앱 만들기
지금까지 구축한 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"
}
]
전체소스 다운로드
지금까지 만든 소스는 아래 링크를 통해서 다운로드 가능합니다.
'Setup > aws' 카테고리의 다른 글
[AWS 무료 서버구축-18/18] 메모앱 만들기 - frontend vue.js (0) | 2021.07.25 |
---|---|
[AWS 무료 서버구축-16/18] SpringBoot 백그라운드에서 실행하기 (0) | 2021.07.25 |
[AWS 무료 서버구축-15/18] SSL 사이트 점검하기 (0) | 2021.07.25 |
[AWS 무료 서버구축-14/18] 무료로 SSL 인증 받기 (0) | 2021.07.25 |
[AWS 무료 서버구축-13/18] Nginx Springboot 연동 (0) | 2021.07.25 |