SpringBoot Part3 (4) : ๋จ์ผ ํ์ด์ง ์น ์ดํ๋ฆฌ์ผ์ด์ , CORS
๋จ์ผ ํ์ด์ง ์น ์ดํ๋ฆฌ์ผ์ด์
URL ๋ณ๊ฒฝ์ ๋ชจ๋ ํ์ด์ง๊ฐ ๋ค์ ๋ ๋๋ง ๋๋ ์ผ๋ฐ ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ๋ฌ๋ฆฌ ํน์ ์์ญ๋ง ๋ ๋๋ง๋๋ค.
์ด๋ ์ฃผ๋ก DOM ์กฐ์์ ํตํด ๋ ๋๋ง์ด ์ด๋ฃจ์์ง๋ค. → ๊ณต์ ์์์ธ server์ ์ด์ ์ ๋ณผ ์ ์๋ค.
: ๋ค์ด๋๋ฏนํ ๋ ๋๋ง์ ์๋ฒ๊ฐ ์๋ ๋ธ๋ผ์ฐ์ ์์ ์ฒ๋ฆฌ
: ํ๋ฉด์์ ๊ทธ๋ ค์ ธ์ผํ ๋ถ๋ถ์ DOM ํ๋ก๊ทธ๋จ์ ์ด์ฉํด ๋์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ์์ ๊ทธ๋ฆฐ๋ค.
: ์ ํ๋ฆฌ์ผ์ด์ ๋ก๋๊ฐ ์ฒ์์ ํ๋ฒ๋๋ฉด ๊ทธ ๋ค์๋ถํด AJAX๋ฅผ ์ด์ฉํด url์ด ๋ณ๊ฒฝ๋์ง์๊ณ server์ ์์ฒญ์ ๋ณด๋ธ๋ค. server๊ฐ ๊ทธ ์๋ต์ ๋ฐ์ JSON ์๋ต์ ์ฃผ๊ณ client๊ฐ JSON์ parsingํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ , ํด๋น ๋ฐ์ดํฐ๋ก DOM ํ๋ก๊ทธ๋๋ฐ์ ํ์ฌ ํ๋ฉด์ ์ ๋ก๋ํ๋ค.
: ์ฌ์ฉ์ ์ธ์ ์ด ์ปค์ง๋ฉด server์ ๋ถ๋ด์ด ๋ ์ ์๋ค.(์ฌ์ฉ์ ๋ฉ๋ด ๊ฐ์ ๋ฐ์ดํฐ) SPA ๊ธฐ๋ฐ์ผ ๊ฒฝ์ฐ, ์ฌ์ฉ์ ๋ฐ์ดํฐ ๋ชจ๋ธ์ ์ผ๋ถ๋ฅผ ๋ธ๋ผ์ฐ์ ์ ๋ฉ๋ชจ๋ฆฌ(local storage)์ ๋ด์๋์ด ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ๋ ค ์ฒ๋ฆฌํ ์ ์๋ค.
๋ผ์ฐํ ์ฒ๋ฆฌ
DOM๋ง ๋ณ๊ฒฝํ ๊ฒฝ์ฐ refreshํ๋ฉด url์ด ๊ณ ์ ๋์ด์๊ธฐ ๋๋ฌธ์ ์ด์ ํ๋ฉด์ด ๋ณด์ผ ๊ฒ์ด๋ค.
ํด์ํ๊ทธ๋ HTML5 ํ์คํ ๋ฆฌ๋ฅผ ์ด์ฉํ๋ฉด url ๋ณ๊ฒฝ๋๊ณ ๋์ ์๋ฒ์๊ฒ ์์ฒญ์ ๋ณด๋ด์ง์๊ณ client์ชฝ์์ ๊ทธ url์ ํ์ํ ๋ ๋๋ง์ ํ๊ฒ๋๋ค. → server์๋ view๋ฅผ ๋ ๋๋งํ๋ ์ฝ๋๊ฐ ์์ด์ง๋ค.
react <Router/> ๋ด๋ถ์์ ์๋์ผ๋ก ์ ๊ณตํด์ค.
not found ์ฒ๋ฆฌํ๊ธฐ
- not found error๋ฅผ throwํ๊ณ ์๋ฌ๋ฅผ ๊ณตํต ์ฒ๋ฆฌํ๋ ๋ชจ๋์์ ์ฒ๋ฆฌํ๊ธฐ
- HTTP response์ ๋ํ ํค๋๋ ์ํ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด Spring์์ ์ ๊ณตํ๋ ResponseEntity
@GetMapping( "/api/v1/customers/{customerId}")
@ResponseBody
public ResponseEntity<Customer> findCustomer(@PathVariable("customerId") UUID customerId){
var customer = customerService.getCustomer(customerId);
return customer.map(v -> ResponseEntity.ok(v)).orElse(ResponseEntity.notFound().build());
// ok -> 202, notFound -> 404
}
CORS
web application์ ๋์ผํ ์ถ์ฒ์ ๋ฆฌ์์ค์๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค. (same-origin)
๋ค์ํ ํธ์คํธ์ ์ ๊ทผ(๋ค์ํ ๋ฆฌ์์ค์ ์ถ์ฒ์ ์ ๊ทผ)์ ํ๊ธฐ์ํด ํ์ฉํด ์ฃผ๋๊ฒ์ด CORS๋ค.
๋จ์์์ฒญ์ ๊ฒฝ์ฐ ์๋น ์์ฒญ์ ๋ณด๋ด์ง ์๋๋ค.
https://developer.mozilla.org/ko/docs/Web/HTTP/CORS
post์ ๊ฒฝ์ฐ (๋จ์์์ฒญ์ด ์๋์ผ๋ก) 2๋ฒ์ ์์ฒญ์ด ๊ฐ๊ฒ์ ํ์ธํ ์ ์๋ค.
Proxy์ฒ๋ฆฌ
package.json
"proxy" : "<http://localhost:8080>"
CORS๋ฅผ ์ง์ํ๋ API
Spring MVC configuration ์ค์
1. WebMvcConfigurer์ addCorsMappings ์ค๋ฐ๋ผ์ด๋ฉ
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "org.prgrms.kdt.customer",
includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = CustomerController.class),
useDefaultFilters = false)
static class ServletConfig implements WebMvcConfigurer, ApplicationContextAware {
ApplicationContext applicationContext;
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
...
}
// ์ ์ ๋ฆฌ์์ค
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
...
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
...
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedMethods("GET","POST") // method ์ง์ ๊ฐ๋ฅ
.allowedOrigins("*");
}
}
Jackson์ ์ด์ฉํ๋ ค๋ฉด default ์์ฑ์๊ฐ ์์ด์ผํ๋ค. → domain์ ๋ณ๊ฒฝํ๋ คํ์ง๋ง๊ธฐ!! DTO ๋ง๋ค๊ธฐ
public class CustomerDTO { // DTO๋ ๋ถ๋ณ
private final UUID customerId;
private final String name;
private final String email;
private final LocalDateTime lastLoginAt;
private final LocalDateTime createdAt;
public CustomerDTO(UUID customerId,
String name,
String email,
LocalDateTime lastLoginAt,
LocalDateTime createdAt) {
this.customerId = customerId;
this.name = name;
this.email = email;
this.lastLoginAt = lastLoginAt;
this.createdAt = createdAt;
}
// dto๋ก mapping
static CustomerDTO of(Customer customer){
return new CustomerDTO(customer.getCustomerId(),
customer.getName(),
customer.getEmail(),
customer.getLastLoginAt(),
customer.getCreatedAt());
}
// domain์ผ๋ก mapping -> domain์ ์์ฑํ๋ ๊ฒ์ ๋ณดํต ์๋น์ค์์ ๋ง๋๋๊ฒ ์ข ๋ ๋ซ๋ค.
static Customer to(CustomerDTO dto){
return new Customer(dto.customerId,
dto.name,
dto.email,
dto.lastLoginAt,
dto.createdAt);
}
}public class CustomerDTO { // DTO๋ ๋ถ๋ณ
private final UUID customerId;
private final String name;
private final String email;
private final LocalDateTime lastLoginAt;
private final LocalDateTime createdAt;
public CustomerDTO(UUID customerId,
String name,
String email,
LocalDateTime lastLoginAt,
LocalDateTime createdAt) {
this.customerId = customerId;
this.name = name;
this.email = email;
this.lastLoginAt = lastLoginAt;
this.createdAt = createdAt;
}
// dto๋ก mapping
static CustomerDTO of(Customer customer){
return new CustomerDTO(customer.getCustomerId(),
customer.getName(),
customer.getEmail(),
customer.getLastLoginAt(),
customer.getCreatedAt());
}
// domain์ผ๋ก mapping -> domain์ ์์ฑํ๋ ๊ฒ์ ๋ณดํต ์๋น์ค์์ ๋ง๋๋๊ฒ ์ข ๋ ๋ซ๋ค.
static Customer to(CustomerDTO dto){
return new Customer(dto.customerId,
dto.name,
dto.email,
dto.lastLoginAt,
dto.createdAt);
}
}
validation์ domain entity์ ์กด์ฌ (๋น์ง๋์ค domian์ ๋ํ ๋ฃฐ)
controller ๋ก์ง์์๋ validation ๋ก์ง์ด๋, ์์ธ ํธ๋ค๋ง (DTO ์์ฒญ์ ๋ํ ๋ฃฐ)
2. ํน์ controller์์๋ง origin์ ์ ์ฉํ๊ณ ์ถ์๋, ์ด๋ ธํ ์ด์ ์ฌ์ฉ
@CrossOrigin(origins ="*")
ํน์ controller ํด๋์ค๋ ๋ฉ์๋์ ์ง์ ๊ฐ๋ฅ.
์ถ์ฒ - ํด๋ฆฌ : SpringBoot Part3
'Back-end ๋ฐ๋ธ์ฝ์ค > week 03 - 05 TIL (Spring)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[TIL] 221117 - SpringBoot Part3 : AutoConfiguration (0) | 2022.11.24 |
---|---|
[TIL] 221116 - SpringBoot Part3 : WebApplicationContext, REST API (0) | 2022.11.24 |
[TIL] 221115 - SpringBoot Part3 : Spring MVC - jsp, Thymeleaf (0) | 2022.11.22 |
[TIL] 221114 - SpringBoot Part3 : ์น ๊ธฐ์ Overview, Servelt (0) | 2022.11.22 |
[TIL] 221111 - SpringBoot Part2 : ํธ๋์ญ์ ๊ณผ AoP (1) | 2022.11.22 |
๋๊ธ