Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions Java/DTO & VO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# DTO & VO

Created: September 26, 2021 3:38 PM
Last Edited Time: January 21, 2022 9:52 AM

## Data Transfer Object

DTO는 본래 프로세스간 Remote 함수 호출의 비용을 줄이기 위해 만들어진 기법이다.

![출처 : P of EAA : Data Transfer Object](./imgs/dtovo1.png)

출처 : P of EAA : Data Transfer Object

위 이미지를 살펴보면 앨범은 제목을 갖고, 아티스트와 연관이 있다. 원격 함수 호출 방식으로 간다면 앨범의 제목을 요청하고, 아티스트의 이름을 각각 요청을 해야한다. 하지만 DTO를 이용해 두 정보를 한번에 전송하면 호출 비용이 1회로 줄일 수 있는 장점이 있다.

많은 사람들이 Sun 커뮤니티의 **Value Ojbect**와 같다고 말하지만 다르다. 무엇이 다른지 아래에서 살펴보자.

## Value Object

Value Object는 Immuatble Object (불변 객체)다. 객체 내 모든 필드들을 final로 선언을 해 생성할 때만 초기화 가능하게해, 추가적인 값 변동 없이 값 그자체로 사용하는 객체들을 말한다.

VO를 사용했을 때 얻는 이점은 아래와 같다.

1. VO객체를 합쳐서 계산적인 이점을 얻을 수 있다.
2. 엔티티가 논리적인 복잡성에서 벗어날 수 있다.
3. 올바르게 사용만 한다면 테스트 가능성 및 **동시성 문제를 해결**할 수 있다.

## DTO & VO

![Untitled](./imgs/dtovo2.png)

참고한 사이트에서는 DTO와 VO를 동일하게 보는 개발자가 많음을 지적하였다. 겉 보기에는 비슷해 보이지만 큰 차이점을 가지고 있기 때문이다.

첫번째로 VO는 Immutable한 객체이다. 이는 동시성 문제를 해결하는 중요한 포인트가 된다.
두번째로 DTO와 달리 VO는 로직을 포함할 수 있다. DTO는 단순히 정보를 전달하기만 하는 객체이기 때문에 추가적인 로직함수를 포함할 수 없다.

**DTO는 값을 전달하기 위한 Wrapper**라고 생각하는 것이 편하다.

### 참고

[https://martinfowler.com/eaaCatalog/dataTransferObject.html](https://martinfowler.com/eaaCatalog/dataTransferObject.html)

[https://martinfowler.com/bliki/ValueObject.html](https://martinfowler.com/bliki/ValueObject.html)

[https://multifrontgarden.tistory.com/182](https://multifrontgarden.tistory.com/182)

[https://dzone.com/articles/ddd-part-ii-ddd-building-blocks](https://dzone.com/articles/ddd-part-ii-ddd-building-blocks)
Binary file added Java/imgs/dtovo1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Java/imgs/dtovo2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
126 changes: 126 additions & 0 deletions Network/CORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# CORS (Cross-Origin Resource Sharing)

## 들어가면서
웹 어플리케이션을 개발하다보면 CORS문제와 마주하는 경우가 있다. 쉽게는 로컬에서 작업할 때 뷰나 리액트 같은 Single Page Applicagion(SPA)로 프론트를 구성할 때 맞이할 수 있다.
서버가 JAVA-Spring로 만들었다고 가정할 때 가장 단순한 해결법에는 2가지가 있다. (참고로 스프링 프레임워크 4.2부터 CORS를 지원했다.)
[코드 출처 : [Spring Blog - CORS support in Spring Framework](https://spring.io/blog/2015/06/08/cors-support-in-spring-framework)]
1. @CrossOrigin 어노테이션 사용하기
- Method level
```java
@RestController
@RequestMapping("/account")
public class AccountController {

@CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}

@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
```
- Class Level
``` java
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}

@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
```
2. Global configuration
- Java config
``` java
// Spring framework
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}

// Spring boot
@Configuration
public class MyConfiguration {

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}

// CORS Configuration override
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
```
- XML
```xml
<mvc:cors>
<mvc:mapping path="/api/**"
allowed-origins="http://domain1.com, http://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="false"
max-age="123" />

<mvc:mapping path="/resources/**"
allowed-origins="http://domain1.com" />
</mvc:cors>
```
스프링 시큐리티를 사용할경우에는 방법이 좀 다르다.

## 정의
추가 HTTP 헤더를 사용하여 실행 중인 어플리케이션이 다른 출처의 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 시스템. 웹 어플리케이션은 자원이 **자신의 출처(도메인, 프로토콜, 포트)**와 다를 때 CORS HTTP 요청을 실행합니다.
[[출처](https://developer.mozilla.org/ko/docs/Web/HTTP/CORS)]

## 작동
![cors_principle](./assets/cors_principle.png)
CORS는 웹 브라우저에서 특정 자원에 대한 접근을 허가 받기 위해 본인의 출처를 서버에 설명하는 HTTP 헤더(OPTIONS)를 통해 작동합니다. 브라우저는 서버에 요청을 보내기전에 preflight(사전 전달) 패킷을 전송하고 서버에서 **허가** 응답을 보냈을 때 실제 요청을 전송합니다.

대부분 CORS 문제가 발생한 경우 아래와 같이 콘솔에 출력될 것 입니다.
~~ 스터디 끝나고 재현해서 추가할게요 ㅠㅠ~~

## Simple request
**simple request**로 분류되는 요청은 preflight을 전송하지 않습니다. (Fetch API 명세에서는 이 용어를 사용하지는 않지만 많은 사이트에서 해당 용어를 사용했기에 사용하도록 하겠습니다.)
Simple request은 아래 조건을 모두 충족한 경우에 해당됩니다.
- Method
- GET
- POST
- HEAD
- HEADER
- Accept
- Accept-Language
- Content-Language
- Content-Type
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- [ReadableStream](https://developer.mozilla.org/ko/docs/Web/API/ReadableStream) 객체 미사용
Binary file added Network/assets/cors_principle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
* 더 있었으면 하는 내용이나 파생되어 나올 수 있는 개념에 대한 내용 작성 제안하기
* 정리한 내용이 어느정도 쌓이면
* 팀원들이 뽑은 Best 정리내용을 `main` branch에 올리기
* 다대다 면접형식으로 문답하기
* 4주마다 이전 자료 조사 내용 바탕으로 각자 15분씩 면접진행
* 일대다 면접형식으로 문답하기

## ✔ 커밋 컨벤션
* 커밋 메세지는 한글 또는 영어 둘 다 사용 가능합니다.
Expand All @@ -28,21 +29,27 @@
<th>KJY97</th>
<th>ChaerinYu</th>
<th>leeejuhyeong</th>
<th>Kodo92</th>
</tr>
<tr>
<td>
<a href="https://github.com/KJY97">
<img alt="KJY97" width="200" src="https://avatars.githubusercontent.com/u/47266337?v=4">
<img alt="KJY97" width="150" src="https://avatars.githubusercontent.com/u/47266337?v=4">
</a>
</td>
<td>
<a href="https://github.com/ChaerinYu">
<img alt="ChaerinYu" width="200" src="https://avatars.githubusercontent.com/u/17977857?v=4">
<img alt="ChaerinYu" width="150" src="https://avatars.githubusercontent.com/u/17977857?v=4">
</a>
</td>
<td>
<a href="https://github.com/leeejuhyeong">
<img alt="leeejuhyeong" width="200" src="https://avatars.githubusercontent.com/u/83570399?v=4">
<img alt="leeejuhyeong" width="150" src="https://avatars.githubusercontent.com/u/83570399?v=4">
</a>
</td>
<td>
<a href="https://github.com/Kodo92">
<img alt="Kodo92" width="150" src="https://avatars.githubusercontent.com/u/18136160?v=4">
</a>
</td>
</tr>
Expand Down
41 changes: 41 additions & 0 deletions Spring/RequestBody_vs_ModelAttribute.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# RequestBody & ModelAttribute
|작성자|작성일|
|:--:|:--:|
|KODO|2022.04.10.|


Spring에서 Http 프로토콜의 body를 가져오는 두가지 방법에 대해서 이해하고 차이를 알아보자.

---
## @RequestBody
`Annotation indicating a method parameter should be bound to the body of the web request. The body of the request is passed through an HttpMessageConverter to resolve the method argument depending on the content type of the request. Optionally, automatic validation can be applied by annotating the argument with @Valid.` [출처](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestBody.html)

위 문장에 따르면 **`@RequestBody`** 은 Http request의 json타입 body를 **`HttpMessageConverter`** 를 이용해 DTO로 변환해준다(HTTP 요청의 바디 영역을 전부 DTO로 변환한다.).

![HttpMessageConverter](./assets/HttpMessageConverter.JPG)
이때 `MappingJackson2HttpMessageConverter.readJavaType()`에서 ObjectMapper를 사용해 Body를 DTO 타입으로 변환하는 것을 볼 수 있다. OpjectMapper는 reflection을 사용하기 때문에 `default constructor`가 **강제**된다.
![readJavaType](./assets/readJavaType.JPG)

**정리**
ObjectMapper는 리플렉션을 사용해 객체를 구성하는 특징이 있다. 하지만 Json데이터를 Java 객체로 바인딩 할 때 getter나 setter를 사용해 맵핑할 필드명을 사용한다고 한다.
실제로 getter, setter를 모두 사용하지 않는 경우 필드의 값이 모두 `null`인 객체가 반환된다.
- JSON, XML, TEXT등의 HTTP Body를 HttpMessageConverte이용해 Java 객체로 바인딩
- Refelection을 사용하기 때문에 기본 생성자 필수
- Getter, Setter 중 1개는 필수

## @ModelAttribute
`Annotation that binds a method parameter or method return value to a named model attribute, exposed to a web view. Supported for controller classes with @RequestMapping methods.`
`Can be used to expose command objects to a web view, using specific attribute names, through annotating corresponding parameters of an @RequestMapping method.`
`Can also be used to expose reference data to a web view through annotating accessor methods in a controller class with @RequestMapping methods. Such accessor methods are allowed to have any arguments that @RequestMapping methods support, returning the model attribute value to expose.`
`Note however that reference data and all other model content is not available to web views when request processing results in an Exception since the exception could be raised at any time making the content of the model unreliable. For this reason @ExceptionHandler methods do not provide access to a Model argument.` [출처](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ModelAttribute.html)

위 문장에 따르면 `@ModelAttribute`는 클라이언트로부터 전송 받은 HTTP 파라미터나 웹 뷰 반환값을 Java 객체로 바인딩합니다.

GET, POST 메소드 타입 모두 바인딩이 가능합니다.
필수 조건으로는 요청으로 보낸 GET 파라미터, FORM 데이터가 모두 존재해야합니다. 하나라도 누락될 경우 400 오류가 뜹니다.

**정리**
- HTTP 파라미터 데이터를 Java 객체에 매핑한다.
- 생성자 혹은 Setter가 필요하다. (기본 생성자 제외)
- Query string, form 데이터 외에는 바인딩이 불가능하다.

Binary file added Spring/assets/HttpMessageConverter.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Spring/assets/createUsingDefault.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Spring/assets/deserializeAndSet.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Spring/assets/deserializeFromObject.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Spring/assets/readJavaType.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Spring/assets/readMapAndClose.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.