Gearing up the MSA - TheOpenCloudEngine/uEngine-cloud GitHub Wiki
http://start.spring.io/ ์ฌ์ดํธ์ ๋ค์ด๊ฐ์ ์คํ๋ง ๋ถํธ์ ๊ธฐ๋ณธ ํ๋ก์ ํธ ํ ํ๋ฆฟ์ ์์ฑํ๋ค.
Group๊ณผ Artifact๋ฅผ ์ ๋ ฅํ๋ค. ํ์ดํ๊ณผ ์๋ฌธ์๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑํ๋ ๊ฒ์ด ์ข๋ค. Dependencies ์
- JPA - DB ORM
- Rest Repository - ๊ธฐ๋ณธ Hateoas
- H2 - ๊ธฐ๋ณธ ๋ด์ฅ DB
๋ฅผ ์ ๋ ฅํ๊ณ , Generate Project๋ฅผ ํด๋ฆญํ์ฌ ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ค.
Artifact ์ ์ ๋ ฅํ ํ๋ก์ ํธ ๋ช ์ผ๋ก zipํ์ผ์ด ๋ค์ด๋ก๋ ๋๋ค.
๊ธฐ๋ณธ mavenํ๋ก์ ํธ๋ก ์์ฑ๋ ํด๋ ๊ตฌ์กฐ๋ฅผ ๋ณผ ์ ์๋ค. ์ฌ๊ธฐ์ mvnw ํ์ผ์ maven wrapper ๋ก, ๋ฉ์ด๋ธ์ด ์์ ์๋ ์ฌ๋์ด ์๊ธฐ๋๋ฌธ์ ๋ฉ์ด๋ธ ์ค์น์์ด ์คํํ ์ ์๋ ํ์ผ์ด๋ค. ํด๋น ํ๋ก์ ํธ๋ก ํด๋๋ฅผ ์ด๋ํ์ฌ
mvn spring-boot:run
ํน์
mvnw spring-boot:run
์ ํ๊ฒ๋๋ฉด ๋ฉ์ด๋ธ์ผ๋ก ๋ถํฐ library ๋ฅผ ๋ค์ด ๋ฐ์ ํ ๊ธฐ๋ณธ ํฌํธ 8080์ผ๋ก ์คํ๋ง ๋ถํธ ์ดํ๋ฆฌ์ผ์ด์
์ด ๊ตฌ๋ ๋๋ค.
์์ ์ด 8080ํฌํธ๋ฅผ ์ฌ์ฉ์ค์ด๊ณ , ๋ค๋ฅธ ํฌํธ๋ก ๊ตฌ๋์ ์ํค๊ณ ์ถ๋ค๋ฉด ์๋์ ๊ฐ์ด ์์ํ๋ฉด ๋๋ค.
mvn spring-boot:run -Dserver.port=8081
[Tip Java9 ์ด์์์ ๋น๋ ์ค๋ฅ - JAXB ๊ด๋ จ Class ๋ชป์ฐพ๋ - ๊ฐ ๋๋ ๊ฒฝ์ฐ ์๋ dependency๋ฅผ pom.xml์ ์ถ๊ฐํ๋ค]
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
์ฝ์์ฐฝ์ ํ๋ ๋ ์ฐ ํ์, ํด๋น ๊ฒฝ๋ก๋ก ์ด๋์ ํ์ฌ httpie ๋ก ํ์ธ์ ํด๋ณผ์ ์๋ค. (Httpie-๋๊ตฌ ์ค์นํ๊ธฐ)
$ http localhost:8080
{
"_links": {
"profile": {
"href": "http://localhost:8080/profile"
}
}
}
http localhost:8080 ๋ฅผ ์น๊ฒ๋๋ฉด ์์ ์ฒ๋ผ profile ์ ๋ณด๊ฐ ๋์ค๊ฒ๋๋๋ฐ web์ผ๋ก ์น๋ฉด ๋ฉ์ธ ํ์ด์ง๋ก ์ ๊ทผ์ ํ ๊ฒ์ด๋ค. ์ผ๊ตด์ด ์๋ค ๋ฟ์ด์ง, ๋ฐ์ดํฐ๋ง ๋ค์ด๊ฐ ์๋ค.
๋์์ธ ์์๋ง ๋นผ๊ณ , ๋ฐ์ดํฐ๋ง ๋จ๊ธด๊ฒ์ด REST api ์ด๋ค.
์์ ๋ฉ์ธ์ง๋ profile์ด๋ผ๋ sub page๊ฐ ์๋ค๋ ๋ป์ด๋ค.
@SpringBootApplication
public class SpringBootSampleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootSampleApplication.class, args);
}
}
main Class์ด๋ค.
**TIP: @SpringBootApplication **
์ด๋ ธํ ์ด์ ์ผ๋ก ์คํ๋ง๋ถํธ ์ดํ๋ฆฌ์ผ์ด์ ์ด๋ผ๋ ์๋ฏธ์ด๋ค.
์์ฆ์๋ ์ด๋ฐ์์ผ๋ก java class์์์ descriptive (๊ธฐ์ ์ ์ธ), declarative(์ ์ธ์ ) ๋ฐฉ์์ด ์ ํํ๊ณ ์๋ค. - ์์ ์๋ xml ์์ ์ ์ธํ์๋ค.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
....
</dependencies>
parent ์์ ์คํ๋ง ๋ถํธ๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ธฐ๋ณธ์ ์ธ ์์ฑ๋ค์ ๊ฐ์ ธ์จ๋ค.
์ต์ด ํ๋ก์ ํธ ์์ฑ์ ์ค์ ํ์๋ H2, JPA๋ฑ์ด ์๋๊ฒ์ ํ์ธ ํ ์ ์๋ค.
์ด์ Person ์ด๋ผ๋ Entity ํด๋ ์ค๋ฅผ ์์ฑํ์ฌ ๋ณด์
@Entity
public class Person {
@Id
@GeneratedValue
Long id;
String name;
int age;
String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Id๋ ๋ฐ๋๋ฉด ์๋๋ ๊ฐ์ด๊ธฐ ๋๋ฌธ์ id๋ฅผ ์ ์ธํ ๋๋จธ์ง ๋ณ์์ Get, Set ๋ฉ์๋๋ฅผ ๋ง๋ค์ด ์ค๋ค.
@Entity : ์ํฐํฐ ํด๋์ค์์ ์ง์ ํ๋ฉฐ ํ ์ด๋ธ๊ณผ ๋งคํ๋๋ค
@Id ๋ง ์ฌ์ฉํ๋ฉด ๊ธฐ๋ณธ ํค๋ฅผ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ง์ ํ ๋น ํ๋ ์ ๋ต์ด๊ณ
@GeneratedValue ์ ๊ฐ์ด ์ฌ์ฉํ๊ฒ ๋๋ฉด ์๋ ์์ฑ ์ ๋ต์ด๋ค.
REST ์๋น์ค๋ฅผ ์ด๊ธฐ ์ํ์ฌ ์๋น์ค ์ ํ์ค์ Repository ๋ผ๋ Interface๋ฅผ ์์ฑํ์ฌ ์ค๋ค.
์ด๊ฒ์ DDD(Domain Driven Design) ์์ ํ๋์ ํจํด์ค ํ๋์ธ๋ฐ,
์ด๋ค Entity์ ์ ๊ทผํ๋ crud๋ฅผ ๋ด๊ณ ์๋ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ๊ฐ์ง๋ ์๋น์ค์ ์ ํ์ Repository ์ด๋ฆ์ ๋ถ์ฌ์ ์ฌ์ฉํ๋ค.
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
}
PagingAndSortingRepository ๋ ํ์ด์ง ๊ธฐ๋ฅ์ ๋ด๊ณ ์๋ Repository์ด๋ค
๋ ํ์งํ ๋ฆฌ์ ์๋ก์ด ์ ํ์ ๋ง๋ค๊ณ ์ถ์๋๋ ํด๋น Repository๋ฅผ extendsํด์ ์๋กญ๊ฒ ๋ง๋ค ์ ์๋ค.
์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ ์์ง๋ง Repository ์์ฑ์ ์คํ๋ง ๋ถํธ๊ฐ runtime์ ์ค์ ์ํนํ๋ sql๋ฌธ์ ์์ฑํ๊ณ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๋ ๊ฒ์ ๋ง๋ค์ด์ค๋ค
์ด์ ํ๋ก์ ํธ๋ฅผ ๋ค์ run์ ํ ํ์ ์ฝ์์ฐฝ์์ ์๋์ ๊ฐ์ด profile์ ์กฐํํ์ฌ ๋ณด์ (httpie ๋๊ตฌ ์ค์นํ๊ธฐ)
$ http http://localhost:8080/
{
"_links": {
"persons": {
"href": "http://localhost:8080/persons{?page,size,sort}",
"templated": true
},
"profile": {
"href": "http://localhost:8080/profile"
}
}
}
Person์ด๋ผ๋ ํด๋์ค์ PersonRepository๋ฅผ ์์ฑํ์๋๋
http://localhost:8080/profile/persons{?page,size,sort} ์ด๋ผ๋ link๊ฐ ์๊ธด ๊ฒ์ ํ์ธ ํ ์ ์๋ค.
$ http http://localhost:8080/persons page==1
์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์กฐํํ์์๋ ๋์ค๋ ๊ฐ์ด ์๋๊ฒ์ ํ์ธ ๊ฐ๋ฅํ๋ค. ์กฐํ์ ์ฟผ๋ฆฌ์คํธ๋ง์ == ๊ฐ ๋๊ฒ๋ฅผ ์จ์ผ ํ๋ค.
์ด์ POST๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด๋ณด์
$ http POST http://localhost:8080/persons name="ํ๊ธธ๋" address="์์ธ์ ๊ฐ๋จ๊ตฌ ๋
ผํ๋ 111"
{
"_links": {
"person": {
"href": "http://localhost:8080/persons/1"
},
"self": {
"href": "http://localhost:8080/persons/1"
}
},
"address": "ํ๊ธธ๋",
"age": 0,
"name": "์์ธ์ ๊ฐ๋จ๊ตฌ ๋
ผํ๋ 111"
}
๋ฃ์ด์ง ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝ ํ ์ ์๋ PATCH๋ฅผ ์ฐ๋ฉด ๋๋ค
$ http PATCH "http://localhost:8080/persons/1" age=10
{
"_links": {
"person": {
"href": "http://localhost:8080/persons/1"
},
"self": {
"href": "http://localhost:8080/persons/1"
}
},
"address": "ํ๊ธธ๋",
"age": 10,
"name": "์์ธ์ ๊ฐ๋จ๊ตฌ ๋
ผํ๋ 111"
}
๋ฐ์ดํฐ๋ฅผ ๋ง์ด ๋ฃ์ ํ page์ sort ๋ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ค.
$ http "http://localhost:8080/persons/1" page==1 size==5
$ http "http://localhost:8080/persons/1" page==1 size==5 sort=="name"
$ http "http://localhost:8080/persons/1" page==1 size==5 sort=="name,asc"
์ด๋ ๊ฒ ๊ธฐ๋ณธ์ ์ธ ์์ค๋์ (HATEOAS) RESTful API ๋ฅผ ์๋์์ฑํจ.
์ฐธ๊ณ : https://hackernoon.com/restful-api-designing-guidelines-the-best-practices-60e1d954e7c9