안녕하세요, Brad입니다. 오늘 수업 중에 들었던 내용들을 간략하게 정리해볼게요.
Q&A
Mock Test
Service Layer는 비즈니스 로직을 구현하는 곳이 아닙니다. 객체들의 연결을 담당할 뿐입니다. Domain 상태값을 조절하는 부분은 Domain으로 메시지를 보내서 조절해야합니다.
그래서 Service Layer는 Thin(얇은) Layer로 되어야 한다고 하는 것입니다.
Service Layer가 테스트하기 힘들었던 이유는 Repository에 데이터가 있어야하기 때문입니다. 그래서 등장한 것이 Mock Test입니다. Mock Test는 데이터베이스에 의존하지 않도록 도와줍니다.
테스트의 중요도
- Domain Test가 가장 중요합니다
- 가장 큰 이유 중 하나는 테스트하기 쉽기 때문입니다.
테스트 데이터 관리방안
- 테스트를 위한 데이터 → Fixture
- User라면 UserTest에서
public static final
로 만들어두어 사용합니다. 만약 다른 부분에서 User데이터들이 필요한다면 UserTest에 있는 상수값으로 만들어둔 데이터를 가져오는 것입니다. - 해당 Domain 테스트 내에 Fixture를 상수값으로 만들어두고 그것을 가져와쓰는 것이 좋습니다.
- Fixture데이터가 엄청 많은 경우에는 따로 클래스를 만들 수도 있습니다.
- 만약 Fixture를 만드는게 복잡하다면 클래스 설계가 제대로 되었는지 의심해봐야합니다. 객체가 하는 일이 너무 많을 수 있기 때문입니다.
Validation
사용자들이 값을 제대로 입력했는지 체크하는 부분입니다. 상당히 중요한 부분입니다. 그 이유는 이후에 DB에 잘못된 값이 들어가게 되면 비즈니스 로직을 구현하는데 어려움이 생기기 때문입니다.
'javax.validation.constraints' 패키지의 여러 Annotation을 사용하여 입력값에 대해 제한을 걸 수 있습니다.
- 예를들어
@Size(min = 3, max = 20)
이 있습니다. 이러한 부분도 설계시 모두 고려되어야 합니다.
- 예를들어
매개변수 내
@Valid
를 사용하면 사용자가 유효한 데이터를 입력하지 않았을 때 에러를 발생합니다.프론트엔드, 백엔드 어디서 처리해줘야할까요?
- 둘 다 해줘야 합니다. 하지만 이렇게 하는 것이 좋지만 하나의 이슈가 있다면 설정값을 바꾸었을 때, 즉 아이디 default 길이를 바꾸었을 때 항상 둘 다 동시에 바꾸어줘야한다는 것입니다.
- 하지만 시간이 없어 둘 중 하나만 해야한다면 반드시 백엔드에서는 해줘야합니다. 왜냐하면 프론트는 언제든 우회할 수 있기 때문입니다.
- 이렇게 둘 다 해주기 때문에 실은 백엔드는 에러만 발생시키면 됩니다.
- 만약 사용자 경험을 좋게하기 위해 ajax를 통해 바로바로 유효성 체크 결과를 전달할 수 있습니다.
코드 내
ValidationExceptionControllerAdvice
에서 에러를 통합적으로 관리하여 메시지를 보냅니다.
Spring 내 servlet의 동작(추가 공부필요)
servlet는 자바 진영에서 만든 인터페이스의 조합입니다.
이렇게 조합해서 좋은 점은 뭘까요?
- 다양한 구현체를 받을 수 있습니다.
- Spring은 Tomcat을 쓰는데요. Jetty나 다른 서버들이 많습니다.
SpringMVC는 Servlet없이 사용될 수 없습니다. SpringMVC는 Servlet를 추상화한 것입니다.
DispacherServlet은 Servlet의 구현체입니다.
Tomcat위에 Dispacher servlet, 그리고 그 위에 SpringMVC가 있습니다.
Dispacher가 모든 요청을 다 받습니다. 그리고 컨트롤러 path를 보고 Dispatch합니다.
Tomcat(Servlet Container)이 시작되면 그 위에 Dispacher servlet가 생성되고 초기화가 됩니다. 이 때 초기화될 때 DI Cotainer도 초기화됩니다.
다시 정리하자면, Servlet의 구현체인 Tomcat 안에 SpringMVC가 있구요. 이 안에서 Dispacher Servlet이 DI Container 안에 있는 Bean들을 요청을 보내는 역할을 합니다.
ORM, JPA, Hibernate, JDBC
JDBC는 다양한 데이터베이스 구현체(Oracle, Mysql 등 - JDBC Driver)를 받아주는 인터페이스입니다.
- 현재 h2데이터베이스 구현체 연결을 gradle.build에서 하고 있습니다.
- 만약 mysql로 바꿔주고 싶으면 gradle.build에서 바꾸면 됩니다.
JPA(interface)는 자바진영에서 ORM에 대한 표준을 만든 것입니다.
Hibernate는 JPA를 구현한 구현체입니다. 물론 Hibernate말고 다양한 구현체가 존재하지만 Spring은 Hibernate를 기본으로 합니다. 사실은 Hibernate 밑단에서 JDBC가 자리잡고 있습니다.
현재 qna-atdd에서 사용하고 있는 것은 Spring Data JPA입니다. 가장 추상화된 것입니다.
JDBC에 대해 지금은 공부할 필요가 없지만 query나 table 설계 능력은 중요합니다.
JPA, ORM 그리고 영속성(peter 발표)
Entity 생명주기
준영속 : 영속성 컨텍스트에 저장되었다가 분리된 상태
코드에서
UserService
에서 original이 영속성 상태입니다. 준영속성은 코드 내엔 없습니다.영속성 컨텍스트는 어디에서 만들어질까요?
- Tomcat서버의 메모리의 일정 영역에 만들어집니다
1차 캐시
- 영속성 컨텍스트 내부의 캐쉬를 말합니다.
- 영속성 컨텍스트는 찾을 때 조회할 데이터가 1차 캐쉬에 있는지 찾습니다. 만약 없으면 쿼리를 생성하여 DB에 전송하고 결과값을 영속성 컨텍스트가 받습니다. 전달받은 데이터를 엔티티로 저장한 다음 엔티티 인스턴스를 리턴합니다.
쓰기지연 SQL
- 쿼리를 생성하여 특정 영역에 저장해두었다가 flush 되는순간 한번에 DB에 쿼리를 날립니다.
- 이전에는 코드가 수행될 때마다 DB에 요청을 보냈습니다.
변경 감지
- 코드 내
@Transactional
어노테이션을 통해서 가능합니다. - 스냅샷 상태값을 토대로 변경값들을 감지합니다.
영속성 전이
Cascade
키워드를 사용합니다.- 부모가 영속성이 되면 자식도 영속성을 가지게 됩니다.
- 그렇기 때문에 이번 qna-atdd에서 Question을 통해 Answer CRUD도 가능한 것입니다.
flush나 commit하는 시점은 언제일까요?
@Transaction
메서드가 끝나는 시점 입니다.
flush와 commit이 무엇이 다를까요?
flush가 git에서 commit이라면, commit은 push라고 할 수 있습니다. 지금 단계에서 여기까지만 알아두면 좋을 것 같습니다.
스냅샷은 뭔가요?
영속성 만들어줄 때 딱 그 상태를 말합니다. 이 상태에서 '자동변경감지' 기능을 통해 변경이 가해졌을 때 아는 것이죠.
@Transactional과 AOP
@Transaction도 AOP가 쓰이고 있습니다. @Transaction내 엄청난 코드가 숨어있습니다.
이 부분은 제가 알아야 나가야할 부분인 것 같네요..
좀 더 알아야할 부분
- AOP -
ValidationExceptionControllerAdvice
내 Target, Advice, Pointcut
- AOP -
Peter 발표외 참고한 사이트
'TIL' 카테고리의 다른 글
Today's Dev Notes(2018-12-17) (0) | 2018.12.17 |
---|---|
Today's Dev Notes(2018-12-16) (0) | 2018.12.16 |
Today's Dev Notes(2018-12-12) (0) | 2018.12.12 |
Today's Dev Notes(2018-12-11) (0) | 2018.12.11 |
Today's Dev Notes2(2018-12-10) (0) | 2018.12.10 |