Spring 입문 2주차
3Layer Architecture(3계층) - Controller, Service, Repository / MVC 패턴에서 controller의 역할을 분리
컨트롤러: 입구이자 출구, 클라이언트의 요청을 받아 서비스에게 로직 처리 맡김 -> 완료된 결과를 클라이언트에게 응답
서비스: 요구사항을 실질적으로 처리(비즈니스 로직: 사용자의 요구 사항), 점점 비대해짐, DB 저장 및 조회가 필요할 경우 리포지토리에 요청
리포지토리: 데이터베이스를 관리 함, DB CRUD 작업 처리
Ioc & DI: 설계 원칙 및 디자인 패턴, 좋은 코드를 위해 스프링이 제공
Ioc: 설계 원칙
DI: 디자인 패턴(요리의 레시피에 비유), DI패턴을 사용하여 Ioc 설계 원칙을 구현
좋은 코드:
- 논리가 간단
- 중복 제거, 표현 명확
- 코드를 처음 보는 사람도 쉽게 이해하고 수정
- 의존성을 최소화
- 새로운 기능을 추가하더라도 크게 구조의 변경이 없어야 함
의존
- 강한 결합 -> 자바 인터페이스로 해결(다형성) -> 변화에 유연해짐(약한 결합, 약한 의존성)
- 주입
- 코드의 주입: 필요로 하는 객체를 해당 객체에 전달 / 어떤 방식이 유연한지, 변경에 영향을 많이 받는지에 차이가 있음
- 필드에 직접 주입
- 메서드를 통한 주입
- 생성자를 통한 주입 -> 가장 많이 사용/ 객체의 불변성
- 코드의 주입: 필요로 하는 객체를 해당 객체에 전달 / 어떤 방식이 유연한지, 변경에 영향을 많이 받는지에 차이가 있음
- 제어의 역전
- 주입
객체 생성은 한 번만 -> 필요한 곳에서 가져다 사용 (약한 결합)
스프링 프레임워크 - 객체 생성, 관리하는 역할 해줌
bean: 스프링이 관리하는 객체
Ioc container: bean들을 모아둔 하나의 컨테이너, 공간
@Component: 클래스를 bean 객체로 등록(클래스이름 맨 앞의 대문자를 소문자로 변경) -> @ComponentScan이 찾음
jdbc Templete같은 기본적으로 사용되는 것들은 스프링부트가 기본적으로 bean으로 등록해 둠
@Autowired: 생성자가 한개일 때만 생략 가능 / 필드 위에 붙일 경우 private에서도 다른 클래스에서 사용 가능 / Ioc에 있는 bean 객체를 스프링이 주입해주고 있음
@RequiredArgsConstructor: Lombok을 사용하고 싶을 때 사용 / final이 있는 필드의 생성자를 만들어 줌
수동 주입
- 직접 Ioc에 접근해서 주입 - ApplicationContext 이용
- Bean 이름으로 가져오기
- Bean 클래스 형식으로 가져오기
jpa
DB를 직접 다룰 때의 문제 - 변경해야 하는 코드 많음 -> ORM 등장
ORM: 객체와 데이터베이스를 맵핑하는 도구
JPA: ORM 기술의 대표적인 표준 명세
Entity: jpa에서 관리되고 있는 클래스
@Entity(name = "Entity명 지정 가능") - 기본은 클래스명
@Table(name = "DB에서 매핑할 테이블 이름 지정 가능") - 기본은 엔티티명
@Column(name = "컬럼명", 조건): 필드와 컬럼 맵핑, 컬럼명의 기본은 필드명
@Id: 테이블의 기본키 지정
JPA에서 테이블과 맵핑할 때
테이블이 없는 상태에서 맵핑
테이블이 있는 상태에서 맵핑 -> 주의!
영속성(persistence) 컨테스트
객체가 생명이나 공간을 자유롭게 유지하고 이동할 수 있는 객체의 성질
EntityManager : 영속성 컨텍스트에 접근하여 엔티티 객체들을 조작하기 위해 필요
(글 날아간 부분)
- application.properties : Hibernate 설정
- show_sql, format_sql, use_sql_comments 옵션
- Hibernate가 DB에 요청하는 모든 SQL을 보기좋게 출력 해줍니다.
- ddl-auto
- create : 기존 테이블 삭제 후 다시 생성합니다. (DROP + CREATE)
- create-drop : create와 같으나 종료시점에 테이블을 DROP 합니다.
- update : 변경된 부분만 반영합니다.
- validate : Entity와 테이블이 정상 매핑되었는지만 확인합니다.
- none: 아무것도 하지 않습니다.
- show_sql, format_sql, use_sql_comments 옵션
spring boot 환경에서는 EntityManager와 EntityManagerFactory를 자동으로 생성해줌
spring boot 환경 - 트랜잭션 환경을 손쉽게 만들 수 있음: @Transactional사용 (shift 두 번 -> simpleJpaRepository로 확인)
@Transactional(readOnly = true): 읽기 전용으로 최적화, 이 안에서 특정 메소드만 쓰기가 가능하게 하려면 @Transactional을 한번 더 사용해서 덮어 씌워야 함
스프링 컨테이너 환경 - 영속성 컨텍스트와 트랜잭션 생명주기가 일치 -> 트랜잭션이 유지되는 동안은 영속성 컨텍스트도 유지
트랜젝션 전파 기능: 서비스부터 리포지토리까지 트랜젝션을 유지
Spring Data JPA (Repository)
jpa 리포지토리 등록: JpaRepository<"@Entity 클래스", "@Id 의 데이터 타입">를 상속받는 interface 로 선언
optional <- 추가학습 하기
JPA Auditing: 자동으로 시간을 넣어주는 기능
@MappedSuperclass: (추상)클래스에 선언한 멤버 변수를 컬럼으로 인식
@EntityListeners(AuditingEntityListener.class): 클래스에 auditing 기능을 넣어줌, 자동으로 시간을 넣기 위해 필요
@CreatedDate: 생성시간 저장
@Colume(updatable = false): 생성 시간이 업데이트 되지 않도록 막아 줌
@LastModifiedDate: 조회한 객체 값을 변경할 때 변경된 시간 저장
@Temporal: 날짜 데이터를 맵핑할 때 사용
JpaApplication클래스에 @EnableJpaAuditing을 달아줘야 JPA Auditing을 사용하겠다고 알릴 수 있음
query Method: 메소드 이름으로 sql 생성
2주차 퀴즈
다른 부분은 힌트를 통해 풀 수 있었지만 쿼리 스트링을 어떻게 해결해야 하는지만 다소 어려움이 있었다.
@GetMapping("/memos/contents")
public List<MemoResponseDto> getMemosByKeyword(String keyword){
return memoService.getMemosByKeyword(keyword);
}
위의 코드에서 String keyword 부분이 "?keyword=검색어"로 쿼리스트링 부분에 해당한다.