ºÝºÝߣ

ºÝºÝߣShare a Scribd company logo
??? ?? REST API ??
inspired by ¡®??? REST API? ?????¡¯
??? ?¡°?????? ????.¡±
¡ñ ??? ??? ? ????
¡ñ ???? Web API?? ????, REST API? ???? ?? ??? ????
???.. (?????????)
¡ñ ???? REST API?? ??????????!
REST? ???? ??? (??? ?? ?11?)
¡ñ Client-Server
¡ñ Stateless
¡ñ Cache
¡ñ Uniform Interface
¡ñ Layered System
¡ñ Code-On-Demand (optional)
Uniform Interface (???? ???? 11?? 40??)
¡ñ Identification of resources
¡ñ manipulation of resources through represenations
¡ñ self-descrive messages
¡ñ hypermisa as the engine of appliaction state (HATEOAS)
? ??? ? ? ??? ????. (?? ?? 37? 50?)
¡ñ Self-descriptive message
¡ñ HATEOAS
Self-descriptive message ?? ??
¡ñ ?? 1: ??? ??? ???? IANA? ???? ? ??? ??? ??? ??? ?
Content-Type?? ????.
¡ñ ???? 2: profile ???? ?????? ????????. (???? ???? 41?? 50??)
¡ð ?????? ?? ?? ??? ? ??
¡ð ???? ?HAL?? ?? ???? ?profile ??? ??
HATEOAS ?? ??
¡ñ ??1: ???? ?? ??
¡ð ?????? ?????? ?????? ??????? HAL
¡ñ ??2: ?? ??? Location? ??
1. ¡°Event¡± REST API
??? ??, ?? ? ?? API
GET /api/events
??? ?? ?? REST API (??? ? ? ??)
¡ñ ??? ???? ? ???
¡ð ??? ??
¡ð ??
¡ö self
¡ö profile: ??? ?? ?? API ???????? ??
¡ö get-an-event: ??? ?? ???? API ??
¡ö next: ?? ??? (optional)
¡ö prev: ?? ??? (optional)
¡ñ ???
¡ð ??? REST Docs? ?? ??
??? ?? ?? REST API (??? ? ??)
¡ñ ??? ???? ? ???
¡ð ??? ??
¡ð ??
¡ö self
¡ö profile: ??? ?? ?? API ???????? ??
¡ö get-an-event: ??? ?? ???? API ??
¡ö create-new-event: ???????? ?????? ?? ???? API ????
¡ö next: ?? ??? (optional)
¡ö prev: ?? ??? (optional)
¡ñ ??? ? ?????? (stateless??..)
¡ð ??, ??? Bearer ??? ??? AccessToken? ???? ??!
POST /api/events
¡ñ ??? ??
GET /api/events/{id}
¡ñ ??? ?? ??
PUT /api/events/{id}
¡ñ ??? ??
2. Events API ?? ??
1. (?? ??) ??? ?? ??
a. create ? ??
2. access token ?? ?? (A ??? ???)
3. (??? A ?? ???) ??? ?? ??
a. create event ??
4. (??? A ?? ???) ??? ???
5. (?? ??) ??? ??
a. update ?? ? ??
6. (??? A ?? ???) ??? ??
a. update ?? ??
7. access token ?? ?? (B ??? ???)
8. (??? B ?? ???) ??? ??
a. update ? ??
3. ??? ?? ???? ???
??? ???
¡ñ Web
¡ñ JPA
¡ñ HATEOAS
¡ñ REST Docs
¡ñ H2
?? ?? 8? ??
¡ñ ??? ??? ???.
¡ñ ??? 11? ??? ?? (??? ?? 8? ??)
??? ?? ?? ??
¡ñ ??? ?? (pom.xml)
¡ñ ?? ?? (@EnableAutoConfiguration)
¡ñ ?? ? ?? (???? ?? ??? ??)
¡ñ ????? ?? ??? JAR (pom.xml? ????)
4. Event ?? API ??: ???? ??
Event ?? API
¡ñ ??? ?? ?? ???.
¡ð name
¡ð description
¡ð beginEnrollmentDateTime
¡ð closeEnrollmentDateTime
¡ð beginEventDateTime
¡ð endEventDateTime
¡ð location (optional) ?? ??? ??? ??
¡ð basePrice (optional)
¡ð maxPrice (optional)
¡ð limitOfEnrollment
basePrice? maxPrice ??? ?? ??? ??
basePrice maxPrice
0 or null 100 ??? ??
0 or null 0 or null ??
100 0 or null ??? ?? (?? ?? ? ??? ??)
100 200 ??? ??? ??
?? ?? 200? ? ??? ? ??.
100? ?? ??? ? ??? ? ??
? ??? ?? ??? ? ??.
¡ñ ???
¡ð id
¡ð name
¡ð ...
¡ð eventStatus: DRAFT, PUBLISHED, ENROLLMENT_STARTED, ...
¡ð offline
¡ð free
¡ð _links
¡ö profile (for the self-descriptive message)
¡ö self
¡ö publish
¡ö ...
5. Event ?? API ??: Event ??? ??
public class Event {
private String name;
private String description;
private LocalDateTime beginEnrollmentDateTime;
private LocalDateTime closeEnrollmentDateTime;
private LocalDateTime beginEventDateTime;
private LocalDateTime endEventDateTime;
private String location; // (optional) ?? ??? ??? ??
private int basePrice; // (optional)
private int maxPrice; // (optional)
private int x`;
}
?? ??
private Integer id;
private boolean offline;
private boolean free;
private EventStatus eventStatus = EventStatus.DRAFT;
EventStatus ?? ??
public enum EventStatus {
DRAFT, PUBLISHED, BEGAN_ENROLLMEND, CLOSED_ENROLLMENT, STARTED, ENDED
}
?? ??????? ??, ??, ??, ??? ?? (pom.xml)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
¡ñ ??? ?? ??? ?? ?? ??
?? ????? ??
@Getter @Setter @EqualsAndHashCode(of = "id")
@Builder @NoArgsConstructor @AllArgsConstructor
public class Event {
¡ñ ? @EqualsAndHasCode?? of? ?????
¡ñ ? @Builder? ??? ? @AllArgsConstructor? ????
¡ñ @Data? ?? ?? ??
¡ñ ????? ?? ? ??
6. Event ?? API ??: ??? ???
??? ?? ???? ???
¡ñ @WebMvcTest
¡ð MockMvc ?? ?? ?? ???. ??? ?? ???? ?? ?.
¡ð ? ?? ?? ??? ??. (????)
MockMvc
¡ñ ??? MVC ??? ?? ???
¡ñ ? ??? ??? ??? ??? MVC (DispatcherServlet)? ??? ???? ???
??? ? ?? ??? ???? ?????? ?? ??.
??? ? ?
¡ñ ????? ???? JSON ???? 201? ???? ??.
¡ð Location ??? ??? ???? ??? ? ?? URI ?? ??? ??.
¡ð id? DB? ??? ? ????? ??? ???? ??
¡ñ ????? ?? id? eventStatus, offline, free ?? ????? ?? ???
¡ð Bad_Request? ?? vs ??????? ?? ?? ?????? ????
¡ñ ?? ???? ??? ?? Bad_Request? ??
¡ð ???? ??? ?? ??
¡ð ???? ???? ??? ? ?? ??
¡ð ?? ?? ???? ??? ?? ??? ??? ??.
¡ñ ???? ?? ?? ??? ?? ??? ??
¡ð offline? free ? ??
¡ñ ??? HATEOA? profile ?? ??? ??? ??.
¡ð self (view)
¡ð update (?? ??? ??? ? ????)
¡ð events (???? ?? ??)
¡ñ API ?? ???
¡ð ?? ???
¡ð ?? ???
¡ð ?? ???
¡ð profile ?? ??
7. Event ?? API ??: EventController.createEvent() ??
@RestController
¡ñ @ResponseBody? ?? ???? ??? ?? ????.
ResponseEntity? ???? ??
¡ñ ?? ??, ??, ?? ?? ??? ?? API
??? ??
¡ñ id ?? ?? ?? ???? ???? ?? ??? ??? ?? ??? ??.
¡ñ EventDto ??
DTO -> ??? ??? ? ??
¡ñ ModelMapper
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.0</version>
</dependency>
Location URI ???
¡ñ HATEOS? ???? linkTo(), methodOn() ??
??? JSON?? ??
¡ñ ObjectMapper ??
??? ??? JPA
¡ñ JpaRepository ?? ?? ???
Enum? JPA ??? ??? ?
¡ñ @Enumerated(EnumType.STRING)
@Valid? BindingResult (?? Errors)
¡ñ BindingResult? ?? @Valid ?? ?? ??? ???? ?. (??? MVC)
¡ñ @NotNull, @NotEmpty, @Min, @Max, ... ???? ??? ???? ? ?? ???
? ??
??? Validator ???
¡ñ Validator ????? ????
¡ñ ?? ???? ????
??? ?? ? ????? ???
¡ñ @Target, @Retention
??? JSON Serializer ???
¡ñ extends JsonSerializer<T> (Jackson JSON ??)
¡ñ @JsonComponent (??? ?? ??)
BindingError
¡ñ FieldError ? GlobalError (ObjectError)? ??
¡ñ objectName
¡ñ defaultMessage
¡ñ code
¡ñ field
¡ñ rejectedValue
?? ???? ??
¡ñ @WebMvcTest ?? ?? ????? ??
¡ð @SpringBootTest
¡ð @AutoConfigureMockMvc
¡ñ Repository @MockBean ?? ??
8. ??? HATEOAS ??
??? HATEOAS
¡ñ https://docs.spring.io/spring-hateoas/docs/current/reference/html/
¡ñ ?? ??? ??
¡ð ??? ??? ???
¡ð ????? ???? ???
¡ñ ??? ??? ??
¡ð ???: ??? + ??
EvnetResource ???
¡ñ extends ResourceSupport? ??
¡ð @JsonUnwrapped? ??
¡ð extends Resource<T>? ??
9. ??? REST Docs ??
??? REST Docs
¡ñ https://docs.spring.io/spring-restdocs/docs/2.0.2.RELEASE/reference/html5/
¡ñ pom.xml? ??? ???? ??
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
<doctype>book</doctype>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-asciidoctor</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.outputDirectory}/static/docs
</outputDirectory>
<resources>
<resource>
<directory>
${project.build.directory}/generated-docs
</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
¡ñ ??? ?? ??
¡ð src/main/asciidoc/index.adoc
10. ??? REST Docs: ??
https://docs.spring.io/spring-restdocs/docs/2.0.2.RELEASE/reference/html5/
REST Docs ?? ??
¡ñ @AutoConfigureRestDocs
REST Docs ??
¡ñ andDo(document(¡°doc-name¡±, snippets))
¡ñ snippets
¡ð links?()
¡ð requestParameters() + parameterWithName()
¡ð pathParameters() + parametersWithName()
¡ð requestParts() + partWithname()
¡ð requestPartBody()
¡ð requestPartFields()
¡ð requestHeaders() + headerWithName()
¡ð requestFields?() + fieldWithPath()
¡ð responseHeaders() + headerWithName()
¡ð responseFields?() + fieldWithPath()
¡ð ...
¡ñ Relaxed*
¡ñ Processor
¡ð preprocessRequest(prettyPrint())
¡ð preprocessResponse(prettyPrint())
¡ð ...
?? ????
¡ñ mvn package
¡ð test
¡ð prepare-package :: process-asciidoc
¡ð prepare-package :: copy-resources
¡ñ ?? ??
¡ð /docs/index.html
Constraint
¡ñ https://github.com/spring-projects/spring-restdocs/blob/v2.0.2.RELEASE/samples/res
t-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java
RestDocMockMvc ??????
¡ñ RestDocsMockMvcConfigurationCustomizer ??? ? ??
¡ñ @TestConfiguration
11. ?? 11? ?????
??? ?? 2.1? ???
¡ñ ??? ????? 5.1 ??
¡ñ Mockito 2.22 ??
¡ñ https://docs.spring.io/spring-boot/docs/2.1.0.RC1/reference/htmlsingle/#getting-starte
d-first-application-pom
JAXB ?? ??? ??? ??
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0.1</version>
</dependency>
¡ñ 8?? 11? ????? ??? ????? ???..
¡ð ??? ? ? ????
¡ö var (?? ???? ?? 10, ?? ??? ?? 11)
¡ö List.of() (?? 9)
¡ö Files.readString(), Files.writeString() (?? 11)
¡ö HttpClient (?? 11)
¡ð ??? ????? ??? ????
¡ö Flow (?? 9)
¡ð JVM? ??
¡ö ??? GC
¡ö Nested ?? Acess Control (?? 11)
¡ö ??? (?? 9)
12. PostgreSQL ??
??? ? ?? ?? H2? ???? ??? ?????? ??? ??? ? PostgreSQL?
????? ????.
/scripts.md ??
1. PostgreSQL ???? ??? ??
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
2. ??? PostgreSQL ???? ??
docker run --name ndb -p 5432:5432 -e POSTGRES_PASSWORD=pass -d postgres
3. ?? ????? ?????
docker exec -i -t ndb bash
su - postgres
psql -d postgres -U postgres
l
dt
4. ????? ??
application.properties
spring.datasource.username=postgres
spring.datasource.password=pass
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.driver-class-name=org.postgresql.Driver
5. ?????? ??
application.properties
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
?????? ??? ??? ?? ?? ??? ?? ????
¡ñ ????? @ActiveProfiles ??
application-test.properties
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.hikari.jdbc-url=jdbc:h2:mem:testdb
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
13. ?? ???
?? ?? ???
¡ñ document(¡°error¡±, snippets)
?? ???
¡ñ ???? ?? ?? ??
14. ??? ???
??? ???
¡ñ ?? ???? ?? ?? ??
¡ñ ???
@GetMapping("/api")
public ResourceSupport root() {
ResourceSupport index = new ResourceSupport();
index.add(linkTo(EventController.class).withRel("events"));
return index;
}
??? ???? ????
15. Event ?? ?? API: ???
??? ? ?
¡ñ Event ?? Page ??? ?? ??
¡ð content[0].id ??
¡ð pageable ?? ??
¡ñ Event? EventResource? ???? ??
¡ð ? ??? ?? self
¡ñ Sort? Paging ??
¡ð 30?? ???, 10? ???? ??? ??? ???? ??, ?? ????
?? ??? ??? ??.
¡ð ??? ????? ????
¡ð page ?? ??
¡ñ ?? ??
¡ð self
¡ð profile
¡ð (create)
¡ñ ???
16. Event ?? ?? API: ??
???, ?? ??? ???
¡ñ ??? ??? JPA? ???? Pageable
Page<Event>? ?? ???? Event ?? ???? ??? ?????
¡ñ ??? ????? ?? EventResource? ??? ???..
¡ñ PagedResourceAssembler<T> ????
??? ? ? Pageable ???? ???? ??
¡ñ page: 0?? ??
¡ñ size: ??? 20
¡ñ sort: property,property(,ASC|DESC)
17. Event ?? API: ???
???? ???? ?? ?? ??? ??? ??
¡ñ ??
¡ð self
¡ð profile
¡ð (update)
¡ñ ??? ???
???? ???? ?? ?? 404 ?? ??
18. Event ?? API: ??
?? ?? ??
19. Events ?? API: ???
????? ???? ?? ?? 404 NOT_FOUND
?? ??? (??? ???)? ??? ??? 400 BAD_REQUEST
??? ???? ??? ?? ???? 400 BAD_REQUEST
(??? ???? ?? ??? 403 FORBIDDEN)
????? ??? ??? ??? ??? ??
¡ñ 200 OK
¡ñ ??
¡ñ ??? ??? ???
20. Events ?? API: ??
?? ?? ??.
???? ??? ?? ?? ??.
21. Account ??? ??
OAuth2? ??? ??? ?? Account ??
¡ñ id
¡ñ email
¡ñ password
¡ñ roels
AccountRoles
¡ñ ADMIN, USER
JPA ??
¡ñ @Table
JPA enumeration collection mapping
@ElementCollection(fetch = FetchType.EAGER)
@Enumerated(EnumType.STRING)
private Set<AccountRole> roles;
Event? owner ??
@ManyToOne
Account manager;
22. ??? ???? ??
??? ??
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
¡ñ ??? ? ?? (401 Unauthorized)
UserDetailsService ??
¡ñ ?? ?????
¡ð expected
¡ð @Rule ExpectedException
¡ð try-catch
¡ñ assertThat(collection).extracting(GrantedAuthority::getAuthority).contains(¡°ROLE_US
ER¡±)
??? ????
¡ñ ? ???? (Filter ?? ????)
¡ñ ??? ????
¡ñ ? ? ? Security Interceptor? ?????.
¡ð ???? ??? ??? ??? ????? ???? ??? ????.
23. ??? ???? ?? ??
???? ??? ???? ??...
¡ñ /docs/index.html
??? ?? ?? ??
¡ñ GET /api/events
¡ñ GET /api/events/{id}
??? ?? ?? ??
¡ñ ??? ?...
¡ñ POST /api/events
¡ñ PUT /api/events/{id{
¡ñ ...
??? ???? OAuth 2.0
¡ñ AuthorizationServer: OAuth2 ?? ??(/oauth/token) ? ?? ??(/oauth/authorize)
¡ð Oder 0 (??? ?? ?? ?? ??? ??.)
¡ñ ResourceServer: ??? ?? ?? ?? (OAuth 2 ?? ??)
¡ð Oder 3 (? ?? ?? ?? ? ??)
??? ???? ??
¡ñ @EnableWebSecurity
¡ñ @EnableGlobalMethodSecurity
¡ñ extends WebSecurityConfigurerAdapter
¡ñ PasswordEncoder: PasswordEncoderFactories.createDelegatingPassworkEncoder()
¡ñ TokenStore: InMemoryTokenStore
¡ñ AuthenticationManagerBean
¡ñ configure(AuthenticationManagerBuidler auth)
¡ð userDetailsService
¡ð passwordEncoder
¡ñ configure(HttpSecurity http)
¡ð /docs/**: permitAll
¡ñ configure(WebSecurty web)
¡ð ignore
¡ö /docs/**
¡ö /favicon1.ico
¡ñ PathRequest.toStatucResource() ????
24. ??? ???? OAuth 2 ??: ?? ?? ??
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>${spring-security.version}</version>
<scope>test</scope>
</dependency>
?? ?? ???
¡ñ User
¡ñ Client
¡ñ POST /oauth/token
¡ð HTTP Basic ?? ?? (????? ??? + ????? ???)
¡ð ?? ???? (MultiValuMap<String, String>)
¡ö grant_type: password
¡ö username
¡ö password
¡ð ??? access_token ???? ??
Grant Type: Password
¡ñ Granty Type: ?? ???? ?? (
¡ñ ??? ??? ?? ??????? ???? Grant Type
¡ñ https://developer.okta.com/blog/2018/06/29/what-is-the-oauth2-password-grant
AuthorizationServer ??
¡ñ @EnableAuthorizationServer
¡ñ extends AuthorizationServerConfigurerAdapter
¡ñ configure(AuthorizationServerSecurityConfigurer security)
¡ð PassswordEncode ??
¡ñ configure(ClientDetailsServiceConfigurer clients)
¡ð ????? ??
¡ð grantTypes
¡ö password
¡ö refresh_token
¡ð scopes
¡ð secret / name
¡ð accessTokenValiditySeconds
¡ð refreshTokenValiditySeconds
¡ñ AuthorizationServerEndpointsConfigurer
¡ð tokenStore
¡ð authenticationMaanger
¡ð userDetailsService
?? ?? ???
¡ñ ApplicationRunner
¡ð Admin
¡ð User
?? ???? ?? ??? ????? ?? ???
¡ñ @ConfigurationProperties
25. ??? ???? OAuth 2 ??: ??? ?? ??
??? ??
¡ñ GET? ???? ?? ??? ??? ??? ?? ??? ??? ??
ResourceServer ??
¡ñ @EnableResourceServer
¡ñ extends ResourceServerConfigurerAdapter
¡ñ configure(ResourceServerSecurityConfigurer resources)
¡ð ??? ID
¡ñ configure(HttpSecurity http)
¡ð anonymous
¡ð GET /api/** : permit all
¡ð POST /api/**: authenticated
¡ð PUT /api/**: authenticated
¡ð ?? ??
¡ö accessDeniedHandler(OAuth2AccessDeniedHandler())
26. ??? ???? ?? ???
SecurityContext
¡ñ ?? ThreadLocal ?? ???? ?? ??? ?? ??.
¡ñ ?? ?? ??? ??:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
@AuthenticationPrincipal spring.security.User user
¡ñ ?? ?? ??? null
¡ñ ?? ? ???? username? authorities ?? ??
spring.security.User? ???? ???? ????
¡ñ ??? User? ?? ? ??.
¡ñ @AuthenticationPrincipa ?me.whiteship.user.UserAdapter
¡ñ Adatepr.getUser().getId()
SpEL? ????
¡ñ @AuthenticationPrincipa(expression=¡±account¡±) ?me.whiteship.user.Account
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@AuthenticationPrincipal(expression = "user")
public @interface CurrentUser {
}
??? ?????? ???
¡ñ @CurrentUser Account account
¡ñ ?? ?? ?? ??? ????..?
expression = "#this == 'anonymousUser' ? null : account"
¡ñ ?? ?? ??? anonymousUse ? ???? null? ??? ??? ¡°account¡±?
????.
27. Events API ??: ?? ??? ??
?? API ??
¡ñ Event owner ??
¡ñ ???? owner? id? ?? ? ?.
{
"id" : 4,
"name" : "test 3PISM1Ju",
"description" : "test event",
...
"free" : false,
"eventStatus" : "DRAFT",
"owner" : {
"id" : 3,
"email" : "keesun@email.com",
"password" :
"{bcrypt}$2a$10$3z/rHmeYsKpoOQR3aUq38OmZjZNsrGfRZxSnmpLfL3lpLxjD5/JZ6",
"roles" : [ "USER", "ADMIN" ]
},
¡ñ JsonSerializer<User> ??
¡ñ @JsonSerialize(using) ??
?? API ??
¡ñ ?? ???? ???? owner? ??? update ?? ?? (HATEOAS)
?? API ??
¡ñ ?? ???? ??? owner? ?? ??? 403 ?? ??
???? HATEOAS? Self-Descriptive Message? ???? REST API? ??? ? ??
?? ?? ????? ??? ??????.
?????.

More Related Content

What's hot (20)

??????? ???? ??????? ??????
??????? ???? ??????? ????????????? ???? ??????? ??????
??????? ???? ??????? ??????
Young-Ho Cho
?
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
Dinesh U
?
?? ??? ? ???? ???? ?? ?? (????? KUCC, 2022? 4?)
?? ??? ? ???? ???? ?? ?? (????? KUCC, 2022? 4?)?? ??? ? ???? ???? ?? ?? (????? KUCC, 2022? 4?)
?? ??? ? ???? ???? ?? ?? (????? KUCC, 2022? 4?)
Suhyun Park
?
???? ??: 1?? ???, ??? ??????? ??: 1?? ???, ??? ???
???? ??: 1?? ???, ??? ???
Yurim Jin
?
How to build massive service for advance
How to build massive service for advanceHow to build massive service for advance
How to build massive service for advance
DaeMyung Kang
?
?????? ??????? ??????????? [???]
?????? ??????? ??????????? [???]?????? ??????? ??????????? [???]
?????? ??????? ??????????? [???]
Yurim Jin
?
????????? ????????? ??????????
????????? ????????? ??????????????????? ????????? ??????????
????????? ????????? ??????????
Changyol BAEK
?
React Context API
React Context APIReact Context API
React Context API
NodeXperts
?
Redis
RedisRedis
Redis
DaeMyung Kang
?
Testing of React JS app
Testing of React JS appTesting of React JS app
Testing of React JS app
Aleks Zinevych
?
Java ¤Ç¤Ä¤¯¤ë µÍ¥ì¥¤¥Æ¥ó¥·Œg×°¤Î¼¼ÇÉ
Java ¤Ç¤Ä¤¯¤ëµÍ¥ì¥¤¥Æ¥ó¥·Œg×°¤Î¼¼ÇÉJava ¤Ç¤Ä¤¯¤ëµÍ¥ì¥¤¥Æ¥ó¥·Œg×°¤Î¼¼ÇÉ
Java ¤Ç¤Ä¤¯¤ë µÍ¥ì¥¤¥Æ¥ó¥·Œg×°¤Î¼¼ÇÉ
Ryosuke Yamazaki
?
React Architecture & Best Practices.pptx
React Architecture & Best Practices.pptxReact Architecture & Best Practices.pptx
React Architecture & Best Practices.pptx
AleksandarKondov
?
Introduction to jest
Introduction to jestIntroduction to jest
Introduction to jest
pksjce
?
???????????????? ??????? ?????? ?????????
???????????????? ??????? ?????? ????????????????????????? ??????? ?????? ?????????
???????????????? ??????? ?????? ?????????
Young-Ho Cho
?
³§±Ê´¡¤Î¥ë©`¥Æ¥£¥ó¥°¤Î»°
³§±Ê´¡¤Î¥ë©`¥Æ¥£¥ó¥°¤Î»°³§±Ê´¡¤Î¥ë©`¥Æ¥£¥ó¥°¤Î»°
³§±Ê´¡¤Î¥ë©`¥Æ¥£¥ó¥°¤Î»°
ushiboy
?
Introduction to gRPC
Introduction to gRPCIntroduction to gRPC
Introduction to gRPC
Prakash Divy
?
??????????????????????-????? ????
??????????????????????-????? ??????????????????????????-????? ????
??????????????????????-????? ????
NAVER D2
?
Power-up services with gRPC
Power-up services with gRPCPower-up services with gRPC
Power-up services with gRPC
The Software House
?
WebdriverIO: the Swiss Army Knife of testing
WebdriverIO: the Swiss Army Knife of testingWebdriverIO: the Swiss Army Knife of testing
WebdriverIO: the Swiss Army Knife of testing
Daniel Chivescu
?
¤è¤êËÙ¤¯ ¤è¤êß\Ó䷤䤹¤¯ ßM»¯¤·¾A¤±¤ëJVM£¨Java Developers Summit Online 2023 °k±íÙYÁÏ£©
¤è¤êËÙ¤¯ ¤è¤êß\Ó䷤䤹¤¯ ßM»¯¤·¾A¤±¤ëJVM£¨Java Developers Summit Online 2023 °k±íÙYÁÏ£©¤è¤êËÙ¤¯ ¤è¤êß\Ó䷤䤹¤¯ ßM»¯¤·¾A¤±¤ëJVM£¨Java Developers Summit Online 2023 °k±íÙYÁÏ£©
¤è¤êËÙ¤¯ ¤è¤êß\Ó䷤䤹¤¯ ßM»¯¤·¾A¤±¤ëJVM£¨Java Developers Summit Online 2023 °k±íÙYÁÏ£©
NTT DATA Technology & Innovation
?
??????? ???? ??????? ??????
??????? ???? ??????? ????????????? ???? ??????? ??????
??????? ???? ??????? ??????
Young-Ho Cho
?
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
Dinesh U
?
?? ??? ? ???? ???? ?? ?? (????? KUCC, 2022? 4?)
?? ??? ? ???? ???? ?? ?? (????? KUCC, 2022? 4?)?? ??? ? ???? ???? ?? ?? (????? KUCC, 2022? 4?)
?? ??? ? ???? ???? ?? ?? (????? KUCC, 2022? 4?)
Suhyun Park
?
???? ??: 1?? ???, ??? ??????? ??: 1?? ???, ??? ???
???? ??: 1?? ???, ??? ???
Yurim Jin
?
How to build massive service for advance
How to build massive service for advanceHow to build massive service for advance
How to build massive service for advance
DaeMyung Kang
?
?????? ??????? ??????????? [???]
?????? ??????? ??????????? [???]?????? ??????? ??????????? [???]
?????? ??????? ??????????? [???]
Yurim Jin
?
????????? ????????? ??????????
????????? ????????? ??????????????????? ????????? ??????????
????????? ????????? ??????????
Changyol BAEK
?
React Context API
React Context APIReact Context API
React Context API
NodeXperts
?
Java ¤Ç¤Ä¤¯¤ë µÍ¥ì¥¤¥Æ¥ó¥·Œg×°¤Î¼¼ÇÉ
Java ¤Ç¤Ä¤¯¤ëµÍ¥ì¥¤¥Æ¥ó¥·Œg×°¤Î¼¼ÇÉJava ¤Ç¤Ä¤¯¤ëµÍ¥ì¥¤¥Æ¥ó¥·Œg×°¤Î¼¼ÇÉ
Java ¤Ç¤Ä¤¯¤ë µÍ¥ì¥¤¥Æ¥ó¥·Œg×°¤Î¼¼ÇÉ
Ryosuke Yamazaki
?
React Architecture & Best Practices.pptx
React Architecture & Best Practices.pptxReact Architecture & Best Practices.pptx
React Architecture & Best Practices.pptx
AleksandarKondov
?
Introduction to jest
Introduction to jestIntroduction to jest
Introduction to jest
pksjce
?
???????????????? ??????? ?????? ?????????
???????????????? ??????? ?????? ????????????????????????? ??????? ?????? ?????????
???????????????? ??????? ?????? ?????????
Young-Ho Cho
?
³§±Ê´¡¤Î¥ë©`¥Æ¥£¥ó¥°¤Î»°
³§±Ê´¡¤Î¥ë©`¥Æ¥£¥ó¥°¤Î»°³§±Ê´¡¤Î¥ë©`¥Æ¥£¥ó¥°¤Î»°
³§±Ê´¡¤Î¥ë©`¥Æ¥£¥ó¥°¤Î»°
ushiboy
?
??????????????????????-????? ????
??????????????????????-????? ??????????????????????????-????? ????
??????????????????????-????? ????
NAVER D2
?
WebdriverIO: the Swiss Army Knife of testing
WebdriverIO: the Swiss Army Knife of testingWebdriverIO: the Swiss Army Knife of testing
WebdriverIO: the Swiss Army Knife of testing
Daniel Chivescu
?
¤è¤êËÙ¤¯ ¤è¤êß\Ó䷤䤹¤¯ ßM»¯¤·¾A¤±¤ëJVM£¨Java Developers Summit Online 2023 °k±íÙYÁÏ£©
¤è¤êËÙ¤¯ ¤è¤êß\Ó䷤䤹¤¯ ßM»¯¤·¾A¤±¤ëJVM£¨Java Developers Summit Online 2023 °k±íÙYÁÏ£©¤è¤êËÙ¤¯ ¤è¤êß\Ó䷤䤹¤¯ ßM»¯¤·¾A¤±¤ëJVM£¨Java Developers Summit Online 2023 °k±íÙYÁÏ£©
¤è¤êËÙ¤¯ ¤è¤êß\Ó䷤䤹¤¯ ßM»¯¤·¾A¤±¤ëJVM£¨Java Developers Summit Online 2023 °k±íÙYÁÏ£©
NTT DATA Technology & Innovation
?

Similar to REST API Development with Spring (20)

?? ??? ??? ??? ???? ?????? ??
 ?? ??? ??? ??? ???? ?????? ?? ?? ??? ??? ??? ???? ?????? ??
?? ??? ??? ??? ???? ?????? ??
LGU+
?
7. html5 api
7. html5 api7. html5 api
7. html5 api
?? ?
?
F3 ?????api??????
F3 ?????api??????F3 ?????api??????
F3 ?????api??????
NAVER D2
?
??????? ????????? ???????? ????
??????? ????????? ????????   ??????????? ????????? ????????   ????
??????? ????????? ???????? ????
Kwangyoun Jung
?
???? ??? ??
???? ??? ?????? ??? ??
???? ??? ??
Keesun Baik
?
Do IoT Yourself 3rd : Open API - revision 3
Do IoT Yourself 3rd : Open API - revision 3Do IoT Yourself 3rd : Open API - revision 3
Do IoT Yourself 3rd : Open API - revision 3
Hyunghun Cho
?
Meetup tools for-cloud_native_apps_meetup20180510-vs
Meetup tools for-cloud_native_apps_meetup20180510-vsMeetup tools for-cloud_native_apps_meetup20180510-vs
Meetup tools for-cloud_native_apps_meetup20180510-vs
minseok kim
?
RESTful API ??
RESTful API ??RESTful API ??
RESTful API ??
Jinho Yoo
?
PHP Slim Framework with Angular
PHP Slim Framework with AngularPHP Slim Framework with Angular
PHP Slim Framework with Angular
JT Jintae Jung
?
??????? ????????? ????????
??????? ????????? ???????? ??????? ????????? ????????
??????? ????????? ????????
Yong Joon Moon
?
(???????? ??)??????? ? HelloWorld ????
(???????? ??)??????? ? HelloWorld ????(???????? ??)??????? ? HelloWorld ????
(???????? ??)??????? ? HelloWorld ????
?????(????????3??? 2???)
?
1.Create Project Sunshine - ?????? ????? ???
1.Create Project Sunshine - ?????? ????? ???1.Create Project Sunshine - ?????? ????? ???
1.Create Project Sunshine - ?????? ????? ???
Youngbin Han
?
2Naver Open Android API Translation At DCamp
2Naver Open Android API Translation At DCamp2Naver Open Android API Translation At DCamp
2Naver Open Android API Translation At DCamp
Jeikei Park
?
???? ??? ?? ????? ?????
???? ??? ?? ????? ????????? ??? ?? ????? ?????
???? ??? ?? ????? ?????
Sungju Jin
?
Portfolio
PortfolioPortfolio
Portfolio
MyeongSeokKim2
?
Java script ????_ed13
Java script ????_ed13Java script ????_ed13
Java script ????_ed13
hungrok
?
Do IoT Yourself! - ?? ?? ??? ?? Open API
Do IoT Yourself! - ?? ?? ??? ?? Open APIDo IoT Yourself! - ?? ?? ??? ?? Open API
Do IoT Yourself! - ?? ?? ??? ?? Open API
Hyunghun Cho
?
Klaytn Developer Meetup_20191022
Klaytn Developer Meetup_20191022Klaytn Developer Meetup_20191022
Klaytn Developer Meetup_20191022
Klaytn
?
Dependency Injection ??
Dependency Injection ??Dependency Injection ??
Dependency Injection ??
beom kyun choi
?
PHP Log Tracking with ELK & Filebeat part#2
PHP Log Tracking with ELK & Filebeat part#2PHP Log Tracking with ELK & Filebeat part#2
PHP Log Tracking with ELK & Filebeat part#2
Juwon Kim
?
?? ??? ??? ??? ???? ?????? ??
 ?? ??? ??? ??? ???? ?????? ?? ?? ??? ??? ??? ???? ?????? ??
?? ??? ??? ??? ???? ?????? ??
LGU+
?
7. html5 api
7. html5 api7. html5 api
7. html5 api
?? ?
?
F3 ?????api??????
F3 ?????api??????F3 ?????api??????
F3 ?????api??????
NAVER D2
?
??????? ????????? ???????? ????
??????? ????????? ????????   ??????????? ????????? ????????   ????
??????? ????????? ???????? ????
Kwangyoun Jung
?
Do IoT Yourself 3rd : Open API - revision 3
Do IoT Yourself 3rd : Open API - revision 3Do IoT Yourself 3rd : Open API - revision 3
Do IoT Yourself 3rd : Open API - revision 3
Hyunghun Cho
?
Meetup tools for-cloud_native_apps_meetup20180510-vs
Meetup tools for-cloud_native_apps_meetup20180510-vsMeetup tools for-cloud_native_apps_meetup20180510-vs
Meetup tools for-cloud_native_apps_meetup20180510-vs
minseok kim
?
PHP Slim Framework with Angular
PHP Slim Framework with AngularPHP Slim Framework with Angular
PHP Slim Framework with Angular
JT Jintae Jung
?
??????? ????????? ????????
??????? ????????? ???????? ??????? ????????? ????????
??????? ????????? ????????
Yong Joon Moon
?
1.Create Project Sunshine - ?????? ????? ???
1.Create Project Sunshine - ?????? ????? ???1.Create Project Sunshine - ?????? ????? ???
1.Create Project Sunshine - ?????? ????? ???
Youngbin Han
?
2Naver Open Android API Translation At DCamp
2Naver Open Android API Translation At DCamp2Naver Open Android API Translation At DCamp
2Naver Open Android API Translation At DCamp
Jeikei Park
?
???? ??? ?? ????? ?????
???? ??? ?? ????? ????????? ??? ?? ????? ?????
???? ??? ?? ????? ?????
Sungju Jin
?
Java script ????_ed13
Java script ????_ed13Java script ????_ed13
Java script ????_ed13
hungrok
?
Do IoT Yourself! - ?? ?? ??? ?? Open API
Do IoT Yourself! - ?? ?? ??? ?? Open APIDo IoT Yourself! - ?? ?? ??? ?? Open API
Do IoT Yourself! - ?? ?? ??? ?? Open API
Hyunghun Cho
?
Klaytn Developer Meetup_20191022
Klaytn Developer Meetup_20191022Klaytn Developer Meetup_20191022
Klaytn Developer Meetup_20191022
Klaytn
?
PHP Log Tracking with ELK & Filebeat part#2
PHP Log Tracking with ELK & Filebeat part#2PHP Log Tracking with ELK & Filebeat part#2
PHP Log Tracking with ELK & Filebeat part#2
Juwon Kim
?

REST API Development with Spring

  • 1. ??? ?? REST API ?? inspired by ¡®??? REST API? ?????¡¯ ??? ?¡°?????? ????.¡± ¡ñ ??? ??? ? ???? ¡ñ ???? Web API?? ????, REST API? ???? ?? ??? ???? ???.. (?????????) ¡ñ ???? REST API?? ??????????! REST? ???? ??? (??? ?? ?11?) ¡ñ Client-Server ¡ñ Stateless ¡ñ Cache ¡ñ Uniform Interface ¡ñ Layered System ¡ñ Code-On-Demand (optional) Uniform Interface (???? ???? 11?? 40??) ¡ñ Identification of resources ¡ñ manipulation of resources through represenations ¡ñ self-descrive messages ¡ñ hypermisa as the engine of appliaction state (HATEOAS) ? ??? ? ? ??? ????. (?? ?? 37? 50?) ¡ñ Self-descriptive message ¡ñ HATEOAS Self-descriptive message ?? ?? ¡ñ ?? 1: ??? ??? ???? IANA? ???? ? ??? ??? ??? ??? ? Content-Type?? ????. ¡ñ ???? 2: profile ???? ?????? ????????. (???? ???? 41?? 50??) ¡ð ?????? ?? ?? ??? ? ?? ¡ð ???? ?HAL?? ?? ???? ?profile ??? ?? HATEOAS ?? ?? ¡ñ ??1: ???? ?? ?? ¡ð ?????? ?????? ?????? ??????? HAL ¡ñ ??2: ?? ??? Location? ??
  • 2. 1. ¡°Event¡± REST API ??? ??, ?? ? ?? API GET /api/events ??? ?? ?? REST API (??? ? ? ??) ¡ñ ??? ???? ? ??? ¡ð ??? ?? ¡ð ?? ¡ö self ¡ö profile: ??? ?? ?? API ???????? ?? ¡ö get-an-event: ??? ?? ???? API ?? ¡ö next: ?? ??? (optional) ¡ö prev: ?? ??? (optional) ¡ñ ??? ¡ð ??? REST Docs? ?? ?? ??? ?? ?? REST API (??? ? ??) ¡ñ ??? ???? ? ??? ¡ð ??? ?? ¡ð ?? ¡ö self ¡ö profile: ??? ?? ?? API ???????? ?? ¡ö get-an-event: ??? ?? ???? API ?? ¡ö create-new-event: ???????? ?????? ?? ???? API ???? ¡ö next: ?? ??? (optional) ¡ö prev: ?? ??? (optional) ¡ñ ??? ? ?????? (stateless??..) ¡ð ??, ??? Bearer ??? ??? AccessToken? ???? ??! POST /api/events ¡ñ ??? ?? GET /api/events/{id} ¡ñ ??? ?? ?? PUT /api/events/{id} ¡ñ ??? ??
  • 3. 2. Events API ?? ?? 1. (?? ??) ??? ?? ?? a. create ? ?? 2. access token ?? ?? (A ??? ???) 3. (??? A ?? ???) ??? ?? ?? a. create event ?? 4. (??? A ?? ???) ??? ??? 5. (?? ??) ??? ?? a. update ?? ? ?? 6. (??? A ?? ???) ??? ?? a. update ?? ?? 7. access token ?? ?? (B ??? ???) 8. (??? B ?? ???) ??? ?? a. update ? ??
  • 4. 3. ??? ?? ???? ??? ??? ??? ¡ñ Web ¡ñ JPA ¡ñ HATEOAS ¡ñ REST Docs ¡ñ H2 ?? ?? 8? ?? ¡ñ ??? ??? ???. ¡ñ ??? 11? ??? ?? (??? ?? 8? ??) ??? ?? ?? ?? ¡ñ ??? ?? (pom.xml) ¡ñ ?? ?? (@EnableAutoConfiguration) ¡ñ ?? ? ?? (???? ?? ??? ??) ¡ñ ????? ?? ??? JAR (pom.xml? ????)
  • 5. 4. Event ?? API ??: ???? ?? Event ?? API ¡ñ ??? ?? ?? ???. ¡ð name ¡ð description ¡ð beginEnrollmentDateTime ¡ð closeEnrollmentDateTime ¡ð beginEventDateTime ¡ð endEventDateTime ¡ð location (optional) ?? ??? ??? ?? ¡ð basePrice (optional) ¡ð maxPrice (optional) ¡ð limitOfEnrollment basePrice? maxPrice ??? ?? ??? ?? basePrice maxPrice 0 or null 100 ??? ?? 0 or null 0 or null ?? 100 0 or null ??? ?? (?? ?? ? ??? ??) 100 200 ??? ??? ?? ?? ?? 200? ? ??? ? ??. 100? ?? ??? ? ??? ? ?? ? ??? ?? ??? ? ??. ¡ñ ??? ¡ð id ¡ð name ¡ð ... ¡ð eventStatus: DRAFT, PUBLISHED, ENROLLMENT_STARTED, ... ¡ð offline ¡ð free ¡ð _links ¡ö profile (for the self-descriptive message) ¡ö self ¡ö publish ¡ö ...
  • 6. 5. Event ?? API ??: Event ??? ?? public class Event { private String name; private String description; private LocalDateTime beginEnrollmentDateTime; private LocalDateTime closeEnrollmentDateTime; private LocalDateTime beginEventDateTime; private LocalDateTime endEventDateTime; private String location; // (optional) ?? ??? ??? ?? private int basePrice; // (optional) private int maxPrice; // (optional) private int x`; } ?? ?? private Integer id; private boolean offline; private boolean free; private EventStatus eventStatus = EventStatus.DRAFT; EventStatus ?? ?? public enum EventStatus { DRAFT, PUBLISHED, BEGAN_ENROLLMEND, CLOSED_ENROLLMENT, STARTED, ENDED } ?? ??????? ??, ??, ??, ??? ?? (pom.xml) <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> ¡ñ ??? ?? ??? ?? ?? ?? ?? ????? ?? @Getter @Setter @EqualsAndHashCode(of = "id") @Builder @NoArgsConstructor @AllArgsConstructor public class Event { ¡ñ ? @EqualsAndHasCode?? of? ????? ¡ñ ? @Builder? ??? ? @AllArgsConstructor? ???? ¡ñ @Data? ?? ?? ?? ¡ñ ????? ?? ? ??
  • 7. 6. Event ?? API ??: ??? ??? ??? ?? ???? ??? ¡ñ @WebMvcTest ¡ð MockMvc ?? ?? ?? ???. ??? ?? ???? ?? ?. ¡ð ? ?? ?? ??? ??. (????) MockMvc ¡ñ ??? MVC ??? ?? ??? ¡ñ ? ??? ??? ??? ??? MVC (DispatcherServlet)? ??? ???? ??? ??? ? ?? ??? ???? ?????? ?? ??. ??? ? ? ¡ñ ????? ???? JSON ???? 201? ???? ??. ¡ð Location ??? ??? ???? ??? ? ?? URI ?? ??? ??. ¡ð id? DB? ??? ? ????? ??? ???? ?? ¡ñ ????? ?? id? eventStatus, offline, free ?? ????? ?? ??? ¡ð Bad_Request? ?? vs ??????? ?? ?? ?????? ???? ¡ñ ?? ???? ??? ?? Bad_Request? ?? ¡ð ???? ??? ?? ?? ¡ð ???? ???? ??? ? ?? ?? ¡ð ?? ?? ???? ??? ?? ??? ??? ??. ¡ñ ???? ?? ?? ??? ?? ??? ?? ¡ð offline? free ? ?? ¡ñ ??? HATEOA? profile ?? ??? ??? ??. ¡ð self (view) ¡ð update (?? ??? ??? ? ????) ¡ð events (???? ?? ??) ¡ñ API ?? ??? ¡ð ?? ??? ¡ð ?? ??? ¡ð ?? ??? ¡ð profile ?? ??
  • 8. 7. Event ?? API ??: EventController.createEvent() ?? @RestController ¡ñ @ResponseBody? ?? ???? ??? ?? ????. ResponseEntity? ???? ?? ¡ñ ?? ??, ??, ?? ?? ??? ?? API ??? ?? ¡ñ id ?? ?? ?? ???? ???? ?? ??? ??? ?? ??? ??. ¡ñ EventDto ?? DTO -> ??? ??? ? ?? ¡ñ ModelMapper <dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>2.3.0</version> </dependency> Location URI ??? ¡ñ HATEOS? ???? linkTo(), methodOn() ?? ??? JSON?? ?? ¡ñ ObjectMapper ?? ??? ??? JPA ¡ñ JpaRepository ?? ?? ??? Enum? JPA ??? ??? ? ¡ñ @Enumerated(EnumType.STRING) @Valid? BindingResult (?? Errors) ¡ñ BindingResult? ?? @Valid ?? ?? ??? ???? ?. (??? MVC) ¡ñ @NotNull, @NotEmpty, @Min, @Max, ... ???? ??? ???? ? ?? ??? ? ?? ??? Validator ??? ¡ñ Validator ????? ???? ¡ñ ?? ???? ???? ??? ?? ? ????? ??? ¡ñ @Target, @Retention
  • 9. ??? JSON Serializer ??? ¡ñ extends JsonSerializer<T> (Jackson JSON ??) ¡ñ @JsonComponent (??? ?? ??) BindingError ¡ñ FieldError ? GlobalError (ObjectError)? ?? ¡ñ objectName ¡ñ defaultMessage ¡ñ code ¡ñ field ¡ñ rejectedValue ?? ???? ?? ¡ñ @WebMvcTest ?? ?? ????? ?? ¡ð @SpringBootTest ¡ð @AutoConfigureMockMvc ¡ñ Repository @MockBean ?? ??
  • 10. 8. ??? HATEOAS ?? ??? HATEOAS ¡ñ https://docs.spring.io/spring-hateoas/docs/current/reference/html/ ¡ñ ?? ??? ?? ¡ð ??? ??? ??? ¡ð ????? ???? ??? ¡ñ ??? ??? ?? ¡ð ???: ??? + ?? EvnetResource ??? ¡ñ extends ResourceSupport? ?? ¡ð @JsonUnwrapped? ?? ¡ð extends Resource<T>? ??
  • 11. 9. ??? REST Docs ?? ??? REST Docs ¡ñ https://docs.spring.io/spring-restdocs/docs/2.0.2.RELEASE/reference/html5/ ¡ñ pom.xml? ??? ???? ?? <plugin> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <version>1.5.3</version> <executions> <execution> <id>generate-docs</id> <phase>prepare-package</phase> <goals> <goal>process-asciidoc</goal> </goals> <configuration> <backend>html</backend> <doctype>book</doctype> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-asciidoctor</artifactId> <version>2.0.2.RELEASE</version> </dependency> </dependencies> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>2.7</version> <executions> <execution> <id>copy-resources</id> <phase>prepare-package</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory> ${project.build.outputDirectory}/static/docs </outputDirectory> <resources> <resource>
  • 13. 10. ??? REST Docs: ?? https://docs.spring.io/spring-restdocs/docs/2.0.2.RELEASE/reference/html5/ REST Docs ?? ?? ¡ñ @AutoConfigureRestDocs REST Docs ?? ¡ñ andDo(document(¡°doc-name¡±, snippets)) ¡ñ snippets ¡ð links?() ¡ð requestParameters() + parameterWithName() ¡ð pathParameters() + parametersWithName() ¡ð requestParts() + partWithname() ¡ð requestPartBody() ¡ð requestPartFields() ¡ð requestHeaders() + headerWithName() ¡ð requestFields?() + fieldWithPath() ¡ð responseHeaders() + headerWithName() ¡ð responseFields?() + fieldWithPath() ¡ð ... ¡ñ Relaxed* ¡ñ Processor ¡ð preprocessRequest(prettyPrint()) ¡ð preprocessResponse(prettyPrint()) ¡ð ... ?? ???? ¡ñ mvn package ¡ð test ¡ð prepare-package :: process-asciidoc ¡ð prepare-package :: copy-resources ¡ñ ?? ?? ¡ð /docs/index.html Constraint ¡ñ https://github.com/spring-projects/spring-restdocs/blob/v2.0.2.RELEASE/samples/res t-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java RestDocMockMvc ?????? ¡ñ RestDocsMockMvcConfigurationCustomizer ??? ? ?? ¡ñ @TestConfiguration
  • 14. 11. ?? 11? ????? ??? ?? 2.1? ??? ¡ñ ??? ????? 5.1 ?? ¡ñ Mockito 2.22 ?? ¡ñ https://docs.spring.io/spring-boot/docs/2.1.0.RC1/reference/htmlsingle/#getting-starte d-first-application-pom JAXB ?? ??? ??? ?? <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.3.0.1</version> </dependency> ¡ñ 8?? 11? ????? ??? ????? ???.. ¡ð ??? ? ? ???? ¡ö var (?? ???? ?? 10, ?? ??? ?? 11) ¡ö List.of() (?? 9) ¡ö Files.readString(), Files.writeString() (?? 11) ¡ö HttpClient (?? 11) ¡ð ??? ????? ??? ???? ¡ö Flow (?? 9) ¡ð JVM? ?? ¡ö ??? GC ¡ö Nested ?? Acess Control (?? 11) ¡ö ??? (?? 9)
  • 15. 12. PostgreSQL ?? ??? ? ?? ?? H2? ???? ??? ?????? ??? ??? ? PostgreSQL? ????? ????. /scripts.md ?? 1. PostgreSQL ???? ??? ?? <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> 2. ??? PostgreSQL ???? ?? docker run --name ndb -p 5432:5432 -e POSTGRES_PASSWORD=pass -d postgres 3. ?? ????? ????? docker exec -i -t ndb bash su - postgres psql -d postgres -U postgres l dt 4. ????? ?? application.properties spring.datasource.username=postgres spring.datasource.password=pass spring.datasource.url=jdbc:postgresql://localhost:5432/postgres spring.datasource.driver-class-name=org.postgresql.Driver 5. ?????? ?? application.properties spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true spring.jpa.properties.hibernate.format_sql=true
  • 16. logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE ?????? ??? ??? ?? ?? ??? ?? ???? ¡ñ ????? @ActiveProfiles ?? application-test.properties spring.datasource.username=sa spring.datasource.password= spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.hikari.jdbc-url=jdbc:h2:mem:testdb spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
  • 17. 13. ?? ??? ?? ?? ??? ¡ñ document(¡°error¡±, snippets) ?? ??? ¡ñ ???? ?? ?? ?? 14. ??? ??? ??? ??? ¡ñ ?? ???? ?? ?? ?? ¡ñ ??? @GetMapping("/api") public ResourceSupport root() { ResourceSupport index = new ResourceSupport(); index.add(linkTo(EventController.class).withRel("events")); return index; } ??? ???? ????
  • 18. 15. Event ?? ?? API: ??? ??? ? ? ¡ñ Event ?? Page ??? ?? ?? ¡ð content[0].id ?? ¡ð pageable ?? ?? ¡ñ Event? EventResource? ???? ?? ¡ð ? ??? ?? self ¡ñ Sort? Paging ?? ¡ð 30?? ???, 10? ???? ??? ??? ???? ??, ?? ???? ?? ??? ??? ??. ¡ð ??? ????? ???? ¡ð page ?? ?? ¡ñ ?? ?? ¡ð self ¡ð profile ¡ð (create) ¡ñ ??? 16. Event ?? ?? API: ?? ???, ?? ??? ??? ¡ñ ??? ??? JPA? ???? Pageable Page<Event>? ?? ???? Event ?? ???? ??? ????? ¡ñ ??? ????? ?? EventResource? ??? ???.. ¡ñ PagedResourceAssembler<T> ???? ??? ? ? Pageable ???? ???? ?? ¡ñ page: 0?? ?? ¡ñ size: ??? 20 ¡ñ sort: property,property(,ASC|DESC)
  • 19. 17. Event ?? API: ??? ???? ???? ?? ?? ??? ??? ?? ¡ñ ?? ¡ð self ¡ð profile ¡ð (update) ¡ñ ??? ??? ???? ???? ?? ?? 404 ?? ?? 18. Event ?? API: ?? ?? ?? ??
  • 20. 19. Events ?? API: ??? ????? ???? ?? ?? 404 NOT_FOUND ?? ??? (??? ???)? ??? ??? 400 BAD_REQUEST ??? ???? ??? ?? ???? 400 BAD_REQUEST (??? ???? ?? ??? 403 FORBIDDEN) ????? ??? ??? ??? ??? ?? ¡ñ 200 OK ¡ñ ?? ¡ñ ??? ??? ??? 20. Events ?? API: ?? ?? ?? ??. ???? ??? ?? ?? ??.
  • 21. 21. Account ??? ?? OAuth2? ??? ??? ?? Account ?? ¡ñ id ¡ñ email ¡ñ password ¡ñ roels AccountRoles ¡ñ ADMIN, USER JPA ?? ¡ñ @Table JPA enumeration collection mapping @ElementCollection(fetch = FetchType.EAGER) @Enumerated(EnumType.STRING) private Set<AccountRole> roles; Event? owner ?? @ManyToOne Account manager;
  • 22. 22. ??? ???? ?? ??? ?? <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.1.0.RELEASE</version> </dependency> ¡ñ ??? ? ?? (401 Unauthorized) UserDetailsService ?? ¡ñ ?? ????? ¡ð expected ¡ð @Rule ExpectedException ¡ð try-catch ¡ñ assertThat(collection).extracting(GrantedAuthority::getAuthority).contains(¡°ROLE_US ER¡±) ??? ???? ¡ñ ? ???? (Filter ?? ????) ¡ñ ??? ???? ¡ñ ? ? ? Security Interceptor? ?????. ¡ð ???? ??? ??? ??? ????? ???? ??? ????.
  • 23. 23. ??? ???? ?? ?? ???? ??? ???? ??... ¡ñ /docs/index.html ??? ?? ?? ?? ¡ñ GET /api/events ¡ñ GET /api/events/{id} ??? ?? ?? ?? ¡ñ ??? ?... ¡ñ POST /api/events ¡ñ PUT /api/events/{id{ ¡ñ ... ??? ???? OAuth 2.0 ¡ñ AuthorizationServer: OAuth2 ?? ??(/oauth/token) ? ?? ??(/oauth/authorize) ¡ð Oder 0 (??? ?? ?? ?? ??? ??.) ¡ñ ResourceServer: ??? ?? ?? ?? (OAuth 2 ?? ??) ¡ð Oder 3 (? ?? ?? ?? ? ??) ??? ???? ?? ¡ñ @EnableWebSecurity ¡ñ @EnableGlobalMethodSecurity ¡ñ extends WebSecurityConfigurerAdapter ¡ñ PasswordEncoder: PasswordEncoderFactories.createDelegatingPassworkEncoder() ¡ñ TokenStore: InMemoryTokenStore ¡ñ AuthenticationManagerBean ¡ñ configure(AuthenticationManagerBuidler auth) ¡ð userDetailsService ¡ð passwordEncoder ¡ñ configure(HttpSecurity http) ¡ð /docs/**: permitAll ¡ñ configure(WebSecurty web) ¡ð ignore ¡ö /docs/** ¡ö /favicon1.ico ¡ñ PathRequest.toStatucResource() ????
  • 24. 24. ??? ???? OAuth 2 ??: ?? ?? ?? <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <version>${spring-security.version}</version> <scope>test</scope> </dependency> ?? ?? ??? ¡ñ User ¡ñ Client ¡ñ POST /oauth/token ¡ð HTTP Basic ?? ?? (????? ??? + ????? ???) ¡ð ?? ???? (MultiValuMap<String, String>) ¡ö grant_type: password ¡ö username ¡ö password ¡ð ??? access_token ???? ?? Grant Type: Password ¡ñ Granty Type: ?? ???? ?? ( ¡ñ ??? ??? ?? ??????? ???? Grant Type ¡ñ https://developer.okta.com/blog/2018/06/29/what-is-the-oauth2-password-grant AuthorizationServer ?? ¡ñ @EnableAuthorizationServer ¡ñ extends AuthorizationServerConfigurerAdapter ¡ñ configure(AuthorizationServerSecurityConfigurer security) ¡ð PassswordEncode ?? ¡ñ configure(ClientDetailsServiceConfigurer clients) ¡ð ????? ?? ¡ð grantTypes ¡ö password ¡ö refresh_token ¡ð scopes ¡ð secret / name ¡ð accessTokenValiditySeconds ¡ð refreshTokenValiditySeconds ¡ñ AuthorizationServerEndpointsConfigurer ¡ð tokenStore ¡ð authenticationMaanger ¡ð userDetailsService
  • 25. ?? ?? ??? ¡ñ ApplicationRunner ¡ð Admin ¡ð User ?? ???? ?? ??? ????? ?? ??? ¡ñ @ConfigurationProperties
  • 26. 25. ??? ???? OAuth 2 ??: ??? ?? ?? ??? ?? ¡ñ GET? ???? ?? ??? ??? ??? ?? ??? ??? ?? ResourceServer ?? ¡ñ @EnableResourceServer ¡ñ extends ResourceServerConfigurerAdapter ¡ñ configure(ResourceServerSecurityConfigurer resources) ¡ð ??? ID ¡ñ configure(HttpSecurity http) ¡ð anonymous ¡ð GET /api/** : permit all ¡ð POST /api/**: authenticated ¡ð PUT /api/**: authenticated ¡ð ?? ?? ¡ö accessDeniedHandler(OAuth2AccessDeniedHandler())
  • 27. 26. ??? ???? ?? ??? SecurityContext ¡ñ ?? ThreadLocal ?? ???? ?? ??? ?? ??. ¡ñ ?? ?? ??? ??: Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); @AuthenticationPrincipal spring.security.User user ¡ñ ?? ?? ??? null ¡ñ ?? ? ???? username? authorities ?? ?? spring.security.User? ???? ???? ???? ¡ñ ??? User? ?? ? ??. ¡ñ @AuthenticationPrincipa ?me.whiteship.user.UserAdapter ¡ñ Adatepr.getUser().getId() SpEL? ???? ¡ñ @AuthenticationPrincipa(expression=¡±account¡±) ?me.whiteship.user.Account @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @AuthenticationPrincipal(expression = "user") public @interface CurrentUser { } ??? ?????? ??? ¡ñ @CurrentUser Account account ¡ñ ?? ?? ?? ??? ????..? expression = "#this == 'anonymousUser' ? null : account" ¡ñ ?? ?? ??? anonymousUse ? ???? null? ??? ??? ¡°account¡±? ????.
  • 28. 27. Events API ??: ?? ??? ?? ?? API ?? ¡ñ Event owner ?? ¡ñ ???? owner? id? ?? ? ?. { "id" : 4, "name" : "test 3PISM1Ju", "description" : "test event", ... "free" : false, "eventStatus" : "DRAFT", "owner" : { "id" : 3, "email" : "keesun@email.com", "password" : "{bcrypt}$2a$10$3z/rHmeYsKpoOQR3aUq38OmZjZNsrGfRZxSnmpLfL3lpLxjD5/JZ6", "roles" : [ "USER", "ADMIN" ] }, ¡ñ JsonSerializer<User> ?? ¡ñ @JsonSerialize(using) ?? ?? API ?? ¡ñ ?? ???? ???? owner? ??? update ?? ?? (HATEOAS) ?? API ?? ¡ñ ?? ???? ??? owner? ?? ??? 403 ?? ?? ???? HATEOAS? Self-Descriptive Message? ???? REST API? ??? ? ?? ?? ?? ????? ??? ??????. ?????.