JAVA SPRING/SpringBoot

SpringBootBoard) 점프 투 스프링부트 게시판 만들기 -1

오동순이 2023. 3. 30. 18:09

스프링부트는 웹 프로그램을 쉽고 빠르게 만들어 주는 웹 프레임워크.

스프링부트는 WAS가 따로 필요없다.

스프링부트 대신 스프링만 사용하여 웹 애플리케이션을 개발한다면 웹 애플리케이션을 실행할 수 있는 톰캣과 같은 WAS(Web Application Server)가 필요하다. WAS의 종류(Tomcat, Weblogic, WebSphere, JBoss, Jeus 등)는 매우 다양하며 설정 방식도 제각각이어서 WAS에 대해 공부해야할 내용도 상당하다. 하지만 스프링부트에는 톰캣 서버가 내장되어 있고 설정도 자동 적용되기 때문에 여러분은 WAS에 대해서 전혀 신경쓸 필요가 없다. 심지어 배포되는 jar 파일에도 톰캣서버가 내장되어 실행되므로 서로 다른 WAS들로 인해 발생되는 문제들도 사라진다.

java를 사용하여 구현한 프로그램을 알맞은 형태로 변환하여 환경에 맞게 설정해야 만든 프로젝트를 실행시킬 수 있는데, 이 일을 배포라고 한다. 이 배포를 통해서 소중한 프로그램을 세상에 알릴 수 있다. 그렇다면 배포는어떻게 하는 것일까?
 
1. 프로젝트 추출 방법(Export)
 jar는 java archive의 줄임말이며, war는 web Application archive의 줄임말이다. archive는 압축일을 의미하므로 jar는 자바 압축파일, war는 웹 어플리케이션 압축파일이라고 할 수 있다.
 
자바 어플리케이션 추출
자바 어플리케이션은 java만 설치되어 있다면 실행할 수 있는 프로그램이다. 독립적으로 실행될 수 있으며, 데몬(백그라운드에서 자동 수행되는 작업을 수행하는 프로그램)이 이에 해당한다. 이러한 프로그램은 jar로 추출한다.
 
.jar파일은 class파일, 속성 및 설정파일, 라이브러리 등 java어플리케이션을 실행하기 위해 필요한 파일들을 모아둔 파일이다.
 
웹사이트 추출
네이버, 다음, 구글과 같은 포털사이트나, 은행, 쇼핑몰과 같이 우리가 브라우저와 인터넷을 통하여 접근할 수 있는 웹페이지를 웹사이트라고 한다. 웹사이트를 보여주기 위해 필요한 모든 요소들을 추출하는 방식으로 war가 있다. 웹문서, 자바스크립트, JSP, 이미지 등등 웹자원들을 포함하고 있으며, 사이트를 구동하기위한 class파일, 속성파일과 같은 소스파일도 포함되어 있다.
 
2. 반영
반영은 정해진 규칙은 없다. 회사나 단체에서의 배포방식이 다 다를 뿐이다. 내가 알고 있는 배포방식을 한 번 늘어놓아 보겠다. 
 
1. tomcat을 설정하여, war파일을 올리면 자동적으로 배포되도록 한다.
  - 서버 설정파일에서 별도로 설정해주고, 웹프로젝트를 war로 추출한다.
2. 소스파일 경로에 수정한 파일만을 반영하고, 서버를 재실행한다.
  - war로 추출하고 수정된 파일만을 서버에 반영한다. 이후 서버를 재실행한다.
3. 자동 배포 프로그램을 사용한다.
  - war로 추출할 필요 없이, git과 같은 소스코드 버전관리 시스템과 젠킨스와 연동하여 자동 배포한다.

참조블로그
https://joalog.tistory.com/100 
 

java) 배포란 무엇이고 어떻게 할까? jar? war?

java를 사용하여 구현한 프로그램을 알맞은 형태로 변환하여 환경에 맞게 설정해야 만든 프로젝트를 실행시킬 수 있는데, 이 일을 배포라고 한다. 이 배포를 통해서 소중한 프로그램을 세상에 알

joalog.tistory.com

 

  • Name - Name은 프로젝트의 이름에 해당된다. 여기서는 "Spring Boot Board"의 이니셜인 sbb를 사용했다.
  • Type - Type은 프로젝트를 관리하는 도구를 선택하는 항목이다. 디폴트로 Maven이 설정되어 있지만 이 책에서는 Gradle을 사용할 것이다. Gradle은 Maven 보다 나중에 개발되었고 Maven보다 성능이 좋고 설정도 편리하다. 이 책은 Gradle 기반으로 설명되어 있으므로 여러분도 꼭 "Gradle - Groovy"를 선택하자.
  • Java Version - 17 버전을 선택한다.
  • Group, Artifact, ... 등은 다르게 설정해도 되지만 이후 예제를 수월하게 진행하기 위해 위와 동일하게 설정하는것을 추천한다.

 

InteliJ 얼티밋 버젼은 스프링이니셜라이저 기능이 제공된다!

하지만 난 없으므로 https://start.spring.io/ 로 스프링설정을 해줌!

 


잠깐 깃 타임!

 

git에 repository생성후 (생성할때 레포지토리이름과 파일이름을 똑같이해준다?)

git repository에 있는 HTTPS의 주소  https://github.com/DifficultWoo/spring_boot_board.git 를 복사해둔다.

git 을 연동해준 파일로 가서 git bash here 하고 

git clone https://github.com/DifficultWoo/spring_boot_board.git 주소 넣으면

.git이 생기면 터미널로 가서 (나는 vscode에서 git bash터미널을 열어서 함)

git add .

git commit -m 'firstTest' 하면 create 되는것을 확일할수있따.

git push 해서 git master에 파일을 올려줌!

혼자 하는 프로젝트지만 git branch hyeonju 브랜치를 하나 더 만들어서 작업하고 최종을 master에 올릴예정


 

스프링 이니셜라이즈 생성 디렉터리 설명!

src/main/resources 디렉터리

src/main/resources 디렉터리는 자바 파일을 제외한 HTML, CSS, Javascript, 환경파일 등을 작성하는 공간이다.
templates 디렉터리
src/main/resources 디렉터리의 하위 디렉터리인 templates 디렉터리에는 템플릿 파일을 저장한다. 템플릿 파일은 HTML 파일 형태로 자바 객체와 연동되는 파일이다. templates 디렉터리에는 SBB의 질문 목록, 질문 상세 등의 HTML 파일을 저장한다.
static 디렉터리
static 디렉터리는 SBB 프로젝트의 스타일시트(.css), 자바스크립트(.js) 그리고 이미지 파일(.jpg, .png) 등을 저장하는 공간이다.
application.properties 파일
application.properties 파일은 SBB 프로젝트의 환경을 설정한다. SBB 프로젝트의 환경, 데이터베이스 등의 설정을 이 파일에 저장한다.
src/test/java 디렉터리
src/test/java 디렉터리는 SBB 프로젝트에서 작성한 파일을 테스트하기 위한 테스트 코드를 작성하는 공간이다. JUnit과 스프링부트의 테스팅 도구를 사용하여 서버를 실행하지 않은 상태에서 src/main/java 디렉터리에 작성한 코드를 테스트할 수 있다.
build.gradle 파일
그레이들(Gradle)이 사용하는 환경 파일이다. 그레이들은 그루비(Groovy)를 기반으로 한 빌드 도구로 Ant, Maven과 같은 이전 세대 빌드 도구의 단점을 보완하고 장점을 취합하여 만든 빌드 도구이다. build.gradle 파일에는 프로젝트를 위해 필요한 플러그인과 라이브러리 등을 기술한다.

ORM

SQL 쿼리와 ORM을 비교해 보자. 다음과 같은 형태로 구성된 질문 테이블에 데이터를 입력한다고 가정해 보자.

[question 테이블 구성 예]

idsubjectcontent

1 안녕하세요 가입 인사드립니다 ^^
2 질문 있습니다 ORM이 궁금합니다
... ... ...

표에서 id는 각 데이터를 구분하는 고윳값이다. 데이터베이스의 설정을 통해 값이 자동으로 증가되어 저장되도록 할수 있다.

이렇게 구성된 question 테이블에 새로운 데이터를 삽입하는 쿼리는 보통 다음처럼 작성한다.

insert into question (subject, content) values ('안녕하세요', '가입 인사드립니다 ^^');
insert into question (subject, content) values ('질문 있습니다', 'ORM이 궁금합니다');

하지만 ORM을 사용하면 쿼리 대신 자바 코드로 다음처럼 작성할 수 있다.

다음코드는 작성할 필요없이 눈으로만 확인하자.

Question q1 = new Question();
q1.setSubject("안녕하세요");
q1.setContent("가입 인사드립니다 ^^");
this.questionRepository.save(q1);

Question q2 = new Question();
q2.setSubject("질문 있습니다");
q2.setContent("ORM이 궁금합니다");
this.questionRepository.save(q2);

위와 같이 ORM을 이용한 데이터의 삽입 예제는 코드 자체만 놓고 보면 양이 많아 보이지만 별도의 SQL 문법을 배우지 않아도 된다는 장점이 있다.

코드에서 Question은 자바 클래스이며, 이처럼 데이터를 관리하는 데 사용하는 ORM 클래스를 엔티티(Entity)라고 한다. ORM을 사용하면 내부에서 SQL 쿼리를 자동으로 생성해 주므로 직접 작성하지 않아도 된다. 즉, 자바만 알아도 데이터베이스에 질의할 수 있다.

 

JPA 란?

스프링부트는 JPA(Java Persistence API)를 사용하여 데이터베이스를 처리한다. JPA는 자바 진영에서 ORM(Object-Relational Mapping)의 기술 표준으로 사용하는 인터페이스의 모음이다.

JPA는 인터페이스이다. 따라서 인터페이스를 구현하는 실제 클래스가 필요하다. JPA를 구현한 대표적인 실제 클래스에는 하이버네이트(Hibernate)가 있다. SBB도 JPA + 하이버네이트 조합을 사용한다.

 

H2 데이터베이스

JPA를 사용하기 전에 데이터를 저장할 데이터베이스를 설치해 보자. 개발시에는 Oracle, MSSQL 등의 굵직한 데이터베이스 보다는 설치도 쉽고 사용도 편리한 H2 데이터베이스를 많이 사용한다.

점프 투 스프링부트H2 데이터베이스

H2 데이터베이스는 주로 개발용이나 소규모 프로젝트에서 사용되는 파일 기반의 경량 데이터베이스이다. 개발시에는 H2를 사용하여 빠르게 개발하고 실제 운영시스템은 좀 더 규모있는 DB를 사용하는 것이 일반적인 개발 패턴이다.

다음과 같이 H2 데이터베이스를 설치하자.

[파일명: /sbb/build.gradle]

(... 생략 ...)

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
}

(... 생략 ...)

그리고 "Refresh Gradle Project"를 실행하여 필요한 라이브러리를 설치하자.

점프 투 스프링부트runtimeOnly

build.gradle 파일의 runtimeOnly는 해당 라이브러리가 런타임(Runtime)시에만 필요한 경우에 사용한다. 컴파일(Compile)시에만 필요한 경우에는 runtimeOnly 대신 compileOnly를 사용한다.

설치한 H2 데이터베이스를 사용하기 위해서는 설정을 해야 한다. 다음과 같이 application.properties 파일을 수정하자.

현재 application.properties 파일에는 아무런 내용이 없을 것이다.

[파일명: /sbb/src/main/resources/application.properties]

# DATABASE
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.url=jdbc:h2:~/local
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

각각의 항목에 대해서 알아보자.

  • spring.h2.console.enabled - H2 콘솔의 접속을 허용할지의 여부이다. true로 설정한다.
  • spring.h2.console.path - 콘솔 접속을 위한 URL 경로이다.
  • spring.datasource.url - 데이터베이스 접속을 위한 경로이다.
  • spring.datasource.driverClassName - 데이터베이스 접속시 사용하는 드라이버이다.
  • spring.datasource.username - 데이터베이스의 사용자명이다. (사용자명은 기본 값인 sa로 설정한다.)
  • spring.datasource.password - 데이터베이스의 패스워드이다. 로컬 개발 용도로만 사용하기 때문에 패스워드를 설정하지 않았다.

그리고 spring.datasource.url에 설정한 경로에 해당하는 데이터베이스 파일을 만들어야 한다. 위에서 spring.datasource.url을 jdbc:h2:~/local 로 설정했기 때문에 사용자의 홈디렉터리(~ 에 해당하는 경로) 밑에 local.mv.db 라는 파일을 생성해야 한다. 만약 jdbc:h2:~/test라고 설정했다면 test.mv.db 라는 파일을 생성해야 한다.

사용자의 홈디렉터리는 윈도우의 경우에는 C:\Users\(사용자명) 이고 맥OS의 경우에는 /Users/(사용자명) 이다. 본인이 사용하는 OS에 맞는 홈디렉터리에 local.mv.db 파일을 생성하자. 파일은 내용 없이 빈파일로 생성한다.

 

spring.datasource.url=jdbc:h2:~/local 이부분에 대한 경로를 이렇게 만들어줘야 생성됨.

spring.datasource.url=jdbc:h2:file:D:/home/test
나는 D드라이버에 있는 것으로 했음.
 

일단은 이렇게 생성을 했음!

URL 주소로 H2 콘솔에 접속하니 오류가 났음 (H2설정 하고 다시 접속하니되어따.)

  • http://localhost:8080/h2-console 

이유는 not found가 계속해서 떳기때문에 URL접속 말고 다른 방법을 찾아봄

* 점프 투 스프링 전에 점프 투 자바는 강의를 들어본적이 없으므로

H2 설치하고 실행하니 됬다.ㅠㅠ

 

http://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

h2database.com

H2 윈도우 다운

 

h2.bat ot h2w.bat  실행
이제는 요렇게 바로 뜨고,
화면이 뜨기 시작함... 힘들었따 1시간 넘게 삽질했다.

여기까지 완성 한 후 JPA 환경 설정도 추가함.

JPA 환경설정

다음처럼 build.gradle 파일을 수정하자.

[파일명: /sbb/build.gradle]

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

추가 하라고 되있지만 옛날꺼라 그런지 버전 오류

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
}

(... 생략 ...)

아래와 같이 dependencies 를 해주면 Entity 오류났던게  import jakarta가 제대로 됨

(처음부터 Initializr를 제대로 만드는게 더 좋음 롬복 웹 JDBC JPA다 추가하는게 좋음;;

  왜 이러는지 의존성 추가는 가능하지만 버전 맞춰줘야함)

* plugins도 버전을 맞춰줘야 함. entity적용이 h2에서 안되기 때문에_이건 누가 댓글로 적어주셨으ㅠ

plugins {
	id 'org.springframework.boot' version '3.0.0'
	id 'io.spring.dependency-management' version '1.1.0'
	id 'java'
}

 

최종적으로 다 맞춰주셔야 함

plugins {
	id 'org.springframework.boot' version '2.6.5'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web:2.6.2'

	developmentOnly 'org.springframework.boot:spring-boot-devtools'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

	runtimeOnly 'com.h2database:h2'

	testImplementation 'org.springframework.boot:spring-boot-starter-test:2.6.2'
}

 

그리고 "Refresh Gradle Project"로 변경사항을 적용하면 JPA 라이브러리가 설치된다.

 

application.properties 파일을 수정하자.

[파일명: /sbb/src/main/resources/application.properties]

# JPA

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect

spring.jpa.hibernate.ddl-auto=update

추가

# DATABASE
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.url=jdbc:h2:~/local
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

# JPA
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update

추가한 항목을 간단하게 살펴보자.

  • spring.jpa.properties.hibernate.dialect - 데이터베이스 엔진 종류를 설정한다.
  • spring.jpa.hibernate.ddl-auto - 엔티티를 기준으로 테이블을 생성하는 규칙을 정의한다.

* 점프 투 스프링부트 spring.jpa.hibernate.ddl-auto

위 설정에서 spring.jpa.hibernate.ddl-auto를 update로 설정했다. update와 같은 설정값에 대해서 간단히 알아보자.

  • none - 엔티티가 변경되더라도 데이터베이스를 변경하지 않는다.
  • update - 엔티티의 변경된 부분만 적용한다.
  • validate - 변경사항이 있는지 검사만 한다.
  • create - 스프링부트 서버가 시작될때 모두 drop하고 다시 생성한다.
  • create-drop - create와 동일하다. 하지만 종료시에도 모두 drop 한다.

개발 환경에서는 보통 update 모드를 사용하고 운영환경에서는 none 또는 validate 모드를 사용한다.

 

엔티티의 속성 구상하기

- code 만들기 전에 DB설계와 구조도 erd를 먼저 하고 난 후 하는게 좋지만 , 명세서나 구조도가 먼저 나와야 함! 

  점프 투 스프링은 가볍게 만들기 때문에 이렇게 하는거 같음.

질문(Question) 엔티티

속성명 설명
id 질문의 고유 번호
subject 질문의 제목
content 질문의 내용
create_date 질문을 작성한 일시

답변(Answer) 엔티티

속성명 설명
id 답변의 고유 번호
question 질문 (어떤 질문의 답변인지 알아야하므로 질문 속성이 필요하다)
content 답변의 내용
create_date 답변을 작성한 일시

 

mysite / entity 폴더(생성해줌_파일관리차원에서)에 Question 클래스 생성

@Getter
@Setter
@Entity
public class Question {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(length = 200)
    private String subject;
    
    @Column(columnDefinition = "TEXT")
    private String content;

    private LocalDateTime createDate;

    @OneToMany(mappedBy = "question", cascade = CascadeType.REMOVE)
    private List<Answer> answerList;
}

@Id

고유 번호 id 속성에 적용한 @Id 애너테이션은 id 속성을 기본 키로 지정한다. 기본 키로 지정하면 이제 id 속성의 값은 데이터베이스에 저장할 때 동일한 값으로 저장할 수 없다. 고유 번호를 기본 키로 한 이유는 고유 번호는 엔티티에서 각 데이터를 구분하는 유효한 값으로 중복되면 안 되기 때문이다.

데이터베이스에서는 id와 같은 특징을 가진 속성을 기본 키(primary key)라고 한다.

@GeneratedValue

@GeneratedValue 애너테이션을 적용하면 데이터를 저장할 때 해당 속성에 값을 따로 세팅하지 않아도 1씩 자동으로 증가하여 저장된다. strategy는 고유번호를 생성하는 옵션으로 GenerationType.IDENTITY는 해당 컬럼만의 독립적인 시퀀스를 생성하여 번호를 증가시킬 때 사용한다.

strategy 옵션을 생략할 경우에 @GeneratedValue 애너테이션이 지정된 컬럼들이 모두 동일한 시퀀스로 번호를 생성하기 때문에 일정한 순서의 고유번호를 가질수 없게 된다. 이러한 이유로 보통 GenerationType.IDENTITY를 많이 사용한다.

@Column

엔티티의 속성은 테이블의 컬럼명과 일치하는데 컬럼의 세부 설정을 위해 @Column 애너테이션을 사용한다. length는 컬럼의 길이를 설정할때 사용하고 columnDefinition은 컬럼의 속성을 정의할 때 사용한다. columnDefinition = "TEXT"은 "내용"처럼 글자 수를 제한할 수 없는 경우에 사용한다.

엔티티의 속성은 @Column 애너테이션을 사용하지 않더라도 테이블 컬럼으로 인식한다. 테이블 컬럼으로 인식하고 싶지 않은 경우에만 @Transient 애너테이션을 사용한다.

 

*테이블 컬럼명 주의사항*

테이블의 컬럼명
DB 테이블 에서는 컬럼명은 create_date  스네이크 케이스(Snake Case)로 작성되었고,
Java Entity에서는 createDate로 대소문자 형태의 카멜케이스(Camel Case)  _대신D대문자표현
엔티티와 Setter
일반적으로 엔티티에는 Setter 메서드를 구현하지 않고 사용하기를 권한다. 엔티티는 데이터베이스와 바로 연결되어 있으므로 데이터를 자유롭게 변경할 수 있는 Setter 메서드를 허용하는 것이 안전하지 않다. 
데이터베이스 직접 수정 금지!

그렇다면 Setter 메서드 없이 어떻게 엔티티에 값을 저장할 수 있을까?
엔티티를 생성할 경우에는 롬복의 @Builder 어노테이션을 통한 빌드패턴을 사용하고, 데이터를 변경해야 할 경우에는 그에 해당되는 메서드를 엔티티에 추가하여 데이터를 변경하면 된다.
다만, 이 책은 복잡도를 낮추고 원활한 설명을 위해 엔티티에 Setter 메서드를 추가하여 진행하려 한다.

 

답변 엔티티 생성하기

@Getter
@Setter
@Entity
public class Answer {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(columnDefinition = "TEXT")
    private String content;
    
    @CreatedDate
    private LocalDateTime createDate;
    
    @ManyToOne
    private Question question;
}

답변은 하나의 질문에 여러개가 달릴 수 있는 구조이다. 따라서 답변은 Many(많은 것)가 되고 질문은 One(하나)이 된다. 따라서 @ManyToOne은 N:1 관계라고 할 수 있다. 이렇게 @ManyToOne 애너테이션을 설정하면 Answer 엔티티의 question 속성과 Question 엔티티가 서로 연결된다. (실제 데이터베이스에서는 ForeignKey 관계가 생성된다.)

@ManyToOne은 질문(부모)이 답변(자식)을 가지는 구조 . 여기서 부모는 Question, 자식은 Answer라고 할 수 있다.
헤즈 어 관계

그렇다면 반대방향, 즉 Question 엔티티에서 Answer 엔티티를 참조할수는 없을까?

가능하다. 답변과 질문이 N:1의 관계라면 질문과 답변은 1:N의 관계라고 할 수 있다. 이런경우에는 @ManyToOne이 아닌 @OneToMany애너테이션을 사용한다. Question 하나에 Answer는 여러개이므로 Question 엔티티에 추가할 답변의 속성은 List 형태로 구성해야 한다.

* 이 부분 헷갈리는 주의할 것  @OneToMany 질문과 답변은 1:N,  @ManyToOne 답변에 질문은 N:1

 

CascadeType.REMOVE

질문 하나에는 여러개의 답변이 작성될 수 있다. 이때 질문을 삭제하면 그에 달린 답변들도 모두 함께 삭제하기 위해서 @OneToMany의 속성으로 cascade = CascadeType.REMOVE를 사용했다.
참고: https://www.baeldung.com/jpa-cascade-types

점프 투 스프링부트 소스

https://github.com/pahkey/sbb3

 

GitHub - pahkey/sbb3: 점프 투 스프링부트 (3.0.0)

점프 투 스프링부트 (3.0.0). Contribute to pahkey/sbb3 development by creating an account on GitHub.

github.com


 

https://wikidocs.net/book/7601

 

점프 투 스프링부트

점프 투 스프링부트는 Spring Boot Board(SBB)라는 이름의 게시판 서비스를 만들어가는 과정을 설명한 스프링부트 입문서이다. 자바 설치부터 시작하여 서비스 운…

wikidocs.net