# 2022-07-25
# 계획
1. 스프링 핵심 원리 미리보기 들어보기
2. 과제 MYSQL Repository 변경
3. 배포 공부(가능하다면)
4. + alpha
# 공부
## Entity vs DAO
### Entity란?
Spring JPA에서 `Entity` 클래스는 ORM을 통해 DB의 테이블과 1:1 매칭되는 칼럼을 필드로 가지는 객체이다.
JPA를 사용할 때 이 클래스가 Entity임을 알려주기 위해 `@Entity` 어노테이션을 사용한다. 필드에는 `@Id`, `@Column`과 같은 어노테이션을 사용하여 명시한다.
Entity는 **Domain 로직만 구현하고 Presentation로직은 구현하지 않는다.**

Entity에서는 최대한 Setter로 인한 문제가 발생하지 않도록(일관성을 해치지 않도록) 사용을 지양한다.(자바빈 패턴)
- 그럼 생성자를 통해 초기화를 진행해야 하나?(점층적 생성자 패턴)
- > 이 또한 좋은 방법이 아니라고 한다. 생성장에 현재 넣는 값이 어떤 필드인지 명확히 알 수 없고, 매개변수끼리 순서가 바뀌더라도 코드가 모두 실행되기 전까지는 알 수 없기 때문이라고 함.
- 그럼 어떻게 초기화를 해야하나?
- > `Builder` 패턴을 사용한다. 맴버 변수가 많아지더라도 어떤 값을 어떤 필드에 넣는지 코드를 통해 확인할 수 있고, 필요한 값만 집어넣는 것이 가능하기 때문. -> 가독성이 올라감.
- 단점으로는 인스턴스 생성 전 빌더가 생성되어야 하므로 여느 디자인 패턴들이 가지듯 절차가 늘어나고 관리해야할 클래스가 많아지며 구조가 복잡해진다.
### DAO란?
`DAO`는 Data Access Object의 약자로, 실제로 DB에 접근하는 객체를 말한다. DAO는 프로젝트의 서비스 모델과 실제 데이터베이스를 연결하는 역할을 하며, JPA에서는 DB에 데이터를 CRUD하는 `Repository`객체들이 DAO를 대체한다고 볼 수 있다.
-> Spring JPA 강의 듣다보면 정리된 자료로 효율적으로 이해할 수 있을 것 같아서 구글링 중단.
## DAO와 Repository
> DAO와 REPOSITORY 모두 퍼시스턴스 로직에 대한 객체-지향적인 인터페이스를 제공하고 도메인 로직과 퍼시스턴스 로직을 분리하여 관심의 분리(separation of concerns) 원리를 만족시키는데 목적이 있다. 그러나 비록 의도와 인터페이스의 메소드 시그니처에 유사성이 존재한다고 해서 DAO와 REPOSITORY를 동일한 패턴으로 취급하는 것은 성급한 일반화의 오류를 범하는 것이다.
>
> DAO는 퍼시스턴스 로직인 Entity Bean을 대체하기 위해 만들어진 개념이다. DAO가 비록 객체-지향적인 인터페이스를 제공하려는 의도를 가지고 있다고 하더라도 실제 개발 시에는 하부의 퍼시스턴스 메커니즘이 데이터베이스라는 사실을 숨기려고 하지 않는다. DAO의 인터페이스는 데이터베이스의 CRUD 쿼리와 1:1 매칭되는 세밀한 단위의 오퍼레이션을 제공한다. 반면 REPOSITORY는 메모리에 로드된 객체 컬렉션에 대한 집합 처리를 위한 인터페이스를 제공한다. DAO가 제공하는 오퍼레이션이 REPOSITORY 가 제공하는 오퍼레이션보다 더 세밀하며, 결과적으로 REPOSITORY에서 제공하는 하나의 오퍼레이션이 DAO의 여러 오퍼레이션에 매핑되는 것이 일반적이다. 따라서 하나의 REPOSITORY 내부에서 다수의 DAO를 호출하는 방식으로 REPOSITORY를 구현할 수 있다.
> - 출처 : [DAO와 REPOSITORY 논쟁](http://egloos.zum.com/aeternum/v/1160846)
글을 읽고 맥락적으로 이해한 바를 정리하자면.
EJB(Enterprise Java Beans) Sun의 주도로 시작되었다. 개발자가 비즈니스 로직에 집중하도록 분산, 트랜잭션, 퍼시스턴스, 보안 등의 인프라스트럭쳐 서비스는 WAS에서 제공하도록 돕기 위한 목적으로 시작되었다.
DAO는 Entity Bean의 퍼시스턴스 지원 기능을 대체하는 동시에 비즈니스 로직과 퍼시스턴스 로직의 명확한 분리를 위해 퍼시스턴스 로직을 캡슐화하고 도메인 레이어에 객체-지향적인 인터페이스를 제공하는 객체이다.
Repository 개념은 DDD(Domain-Driven Design)의 기본 빌딩 블록중 하나로 관련이 깊다.
이 둘은 기술적으로는 아주 유사하나 동일하게 취급할 수는 없다.
EJB에서 통용되던 개념과 용어들이 Spring과 Hibernate와 같은 경량 프레임워크의 발전과 POJO(Plain Old Java Object) 기술의 성장에 따라서 퍼지게 되고 비슷한 역할을 하는 개념으로 자리잡은 것 같다. 하지만, 디테일하게보면 다르다.
## JPA를 왜 사용하는가?
- 생산성이 뛰어나고 유지보수가 용이.
- 객체지향적인 코드로 인해 더 직관적인 코드 생성 가능
- 객체지향적으로 데이터를 관리하기 때문에, 전체 프로그램 구조를 일관되게 유지할 수 있음.
- SQL을 직접적으로 사용하지 않고 객체를 사용하여 동작하기 때문에, 재사용성이 증가하고 유지보수가 편해짐.
- DB 스키마가 변경될 때, 테이블 수정이나 SQL 수정 등과 같은 과정이 많이 줄어듬.
- DBMS에 대한 종속성이 줄어듬.
- DBMS가 변경되더라도 소스, 쿼리, 구현 방법, 자료형 타입 등을 변경할 필요가 없음.
- 즉, 개발자는 객체에만 집중하면되고, DBMS 교체 작업에 리스크과 시간이 덜 소요됨.
JPA도 단점이 존재
- JPA를 잘 사용하려면 학습비용이 높음. 잘못 사용하면 성능이 오히려 떨어질 수 있음.
- 복잡한 쿼리 사용이 힘듬
- QueryDSL을 이용하여 극복.(지혜님 출처)
-> ORM만 고집하는 것이 아니라 자신 프로젝트에 맞게 Mybatis와 같은 Sql Mapper도 다룰 수 있는 것이 좋다.
## 위 두 내용을 잘 정리한 blog글

- [JPA 기본 개념 - 우리가 JPA 를 사용하는 이유](https://truehong.tistory.com/99)
## DB or 객체에 null로 비워둬도 괜찮은가?
-> 괜찮음.(장현준 기술 매니져님께 여쭤보니 회사 정책상으로도 문제 없다고는 하셨다.)
## AutoWired 생략 조건
- Spring 4.3 버젼 부터 @Autowired 생략가능
- 생성자 선언이 1개 일 때만 생략 가능
## Entity를 위한 `@Column` 어노테이션 옵션
지혜님의 게시글 작성시 update 날짜의 default 값에 대한 피드백 이후 각 Column의 옵션 대해서 공부차 정리하려고 한다.
Entity 작성시 각 필드는 `@Column` 어노테이션을 가지고 있는 것이므로 별다른 설정이 없다면 생략 가능하다.
naming : DB는 대소문자를 가리지 않으므로 만약 2개 이상의 단어라면 스네이크 형식으로 name 속성을 통해 명시한다.
| 옵션 이름 | 사용 예시 | 기본값 | 뜻 |
|-|-|-|-|
|name|`@Column(name = "컬럼명")`|필드명|DB 테이블의 컬럼 명을 지정함.|
|insertable|`@Column(insertable = true/false)` |true|Repository.save시 필드 값을 삽입을 수행할지 결정|
|updatable|`@Column(updatable = true/false)`|true|영속성 Entity 변경시 필드 값 수정을 수행할지 결정|
|nullable|`@Column(nullable = true/false)`|true|DB DDL 제약 조건 : null 허용 여부 결정|
|unique|`@Column(unique = true/false)`|false|DB DDL 제약 조건 : unique 설정<br>단, 제약조건명이 랜덤으로 설정되어 잘 사용하지 않는다고 함.|
|columnDefinition|`@Column(columnDefinition = "varchar(100) default 'EMPTY'")`<br>기본값 EMPTY, varchar타입 100바이트로 설정|x|DB DDL 옵션 : 컬럼 정보 설정 가능.|
|length`@Column(length = 10)`|255|DB DDL 옵션 : 문자(String) 길이 조건 설정 가능.|
|precision, scale|`@Column(precision=8, scale=2) `||precision : 소숫점 포함 전체 자릿수<br>scale=소수의 자리수|
이외에도 `@Temporal`, `@Enumerated`, `@Lob`, `@Transient` 등이 있다.
## @Lob Large Object
Large Object 준말로 사용해본 경험으로는 post의 Content 부분을 저장할 때 사용해봤다. 당시 공부한 내용으로는 html태그와 같은 내용도 함께 저장할 수 있고 최대 4기가까지의 내용을 저장할 수 있는 이점이 있다고 했던 것 같다.
오늘 다시 추가로 찾아보니 사진을 byte array로 변환하여 저장할 수도 있는 것 같다.
- [Mapping LOB Data in Hibernate - 3. LOB Data Model](https://www.baeldung.com/hibernate-lob#lob-data-model)
Lob은 CLOB과 BLOB 나누어지고 각각 문자와 나머지를 매핑한다.
> CLOB : 문자 대형 객체
> BLOB : 이진 대형 객체 (이미지, 동영상 등등)
국내 포스팅된 글을 보면 대부분 김영한님의 `[자바 ORM 표준 JPA 프로그래밍 - 김영한]` 책을 통해 소개하고 있는 듯하다.
## DDD 구글링해서 읽어보다 어려워서 중단~!
## MVC와 Service
간단히 말해 Service는 model에 속한다.
MVC의 핵심은 View는 자신이 요청할 Controller만 알고 있으면 되고, Controller는 화면에서 넘어오는 매개변수를 이용해 Service 객체를 호출하는 역할을 한다. 따라서 Service는 HttpServlet을 상속 받을 필요 없는 순수한 자바 객체로 구성된다.
Service 모델은 추후 view단이 바뀌어도 view단에 종속적이지 않으며 비즈니스 로직으로서 변경이 없고 재사용이 가능해야 한다.
OCP 원칙을 준수하여 변화에는 닫혀있고 확장에는 열려있는 구조여야하고, 단순히 파라미터로는 비즈니스에 사용되어야 하는 DTO만 받아야 한다.
기억상으로 Transaction이 일어나는 범위가 get, post, put, delete에 따라 역사적으로 변화가 생긴 것으로 안다.
# 회고
오늘 배운 내용들 중 어렵고 난해한 내용도 많았던 것 같다.
일단 큰 수확으로는 SOLID 원칙의 재정리 Spring의 탄생 배경을 통한 기존 내가 했던 프로젝트와 구성들이 객체 지향 5원칙에 위배되고 있었다는 것, 그렇기 때문에 DI 컨테이너를 통해 해결해야 한다는 것을 배운 것이 큰 수확이 아닌가 싶다.