[Spring] 숙련 강의 복습(1부)

조성현·2022년 12월 19일
1

이번 글의 취지

  • 스프링[숙련]강의를 복습하면서 "이 부분은 앞으로도 꺼내보겠다" 싶은 부분들만 추려 적어보자 입니다.
  • 글 우측에 뜨는 소제목들을 보시며 필요한 부분들만 보시는 방식이 효율적이지 싶습니다.
  • 정확히 그 개념들의 총정리라기보다는 제가 이해한 방식들을 기술한 느낌이 강합니다. 이해가 잘 안되시는 부분은 해당 키워드로 구글링하셔서 더 좋은 글들을 읽어보시는걸 추천드립니다.
    (역시 구글이 최곱니다. 공부할 키워드를 얻어가는 용도로 이 글을 활용하시면 좋겠습니다.)

JPA, 스프링 공부는 어떻게 해야 하는가

라이브러리, 프레임워크를 잘 배우려면 목적에 따라 초점을 달리 공부해보자.

  • [WHY] 이 친구들이 왜 우리를 편하게 해주는지에 초점을 맞춘다. (이걸 왜 써야하는지?)
  • [HOW] 이 친구들이 어떻게 우리를 편하게 해주는지(어떤 방식으로 동작하는지)

영속성 컨텍스트

EM(Entity Manager)마다 '영속성 컨텍스트'라는 개별적인 공간을 가진다고 생각하자.

  • 영속화한다. -> EM의 '영속성 컨텍스트'라는 공간에 넣어준다.
  • 공부 키워드: 비영속(New), 영속(Managed), 준영속(Detached) , 삭제(Removed)

1차 캐시

  • 영속성 컨텍스트는 '1차 캐시'라는 것을 가진다.
  • DB access는 비용이 큰 작업이다. 한번 쿼리를 보내 조회한 내용은 1차 캐시에 저장한다.
  • 어떠한 값을 찾을 때 정확한 순서로는
    (1차 캐시를 조회한다. -> 1차 캐시에 있으면 그걸 반환한다. -> 없으면 DB access해서 가져온다. -> 찾아온 값을 1차 캐시에 저장하고 반환한다.) 라고 생각하면 이해하기 편하다.

쓰기지연 SQL저장소

  • 동일한 이유로 존재한다.(DB로 매번 쿼리를 날리는 비용을 절약하고자)
  • Flush()로 저장소에 쌓인 SQL문들을 Commit()을 통해 한번에 전송하는 것
  • 깃허브 커밋푸쉬를 생각해보면 이해가 쉽다.
    (Flush를 커밋으로/Commit을 푸쉬로 생각해보자)

Dirty Checking

  • 사실 1차 캐시에는 DB의 엔티티의 정보만 저장하는것이 아님
  • 해당 엔티티를 조회한 시점의 데이터의 정보를 같이 저장해둠(스냅샷 개념).
  • 현재 엔티티객체와 조회 시점의 데이터가 다르다면 변경이 발생했다고 판단
  • 해당 변경 부문을 반영 할 수 있는 UPDATE 쿼리를 작성해서 SQL저장소에 슬쩍 넣어둔다.
  • Commit()을 통해 쓰기지연 SQL저장소에서 DB로 쿼리들이 날아갈 때! 업데이트도 자동으로 되는 마법이 일어난다.

데이터의 어플리케이션 단의 동일성을 보장해준다.

  • 이 부분은 아직 이르다고 하시면서 키워드만 던져주고 사라지신 부분.


객체 중복 생성 문제

아래와 같이 매번 new ProductRepository()를 해버리면, 서로 다른 repository에 일을 하고 있는 상황이 벌어진다.

@Service
public class ProductService {

    public ProductResponseDto createProduct(ProductRequestDto requestDto) throws SQLException {
        ProductRepository productRepository = new ProductRepository();
        // ...
    }

    public List<ProductResponseDto> getProducts() throws SQLException {
        ProductRepository productRepository = new ProductRepository();
				// ...
    }

    public Long updateProduct(Long id, ProductMypriceRequestDto requestDto) throws SQLException {
        ProductRepository productRepository = new ProductRepository();
				// ...
    }
}		

아래의 코드로 객체의 중복생성 문제는 해결했지만 '강한 결합'상태라는 문제점은 유지中

@Service
public class ProductService {
    
    // 멤버 변수 선언
    private final ProductRepository productRepository;

		public ProductService() {
        this.productRepository = new ProductRepository();
    }
    
public ProductResponseDto createProduct(ProductRequestDto requestDto) throws SQLException {
        // 요청받은 DTO 로 DB에 저장할 객체 만들기
        Product product = new Product(requestDto);

        return  productRepository.createProduct(product);
    }
		...
}

'강한 결합' -> '느슨한 결합' 으로 바꿔줘야함.

느슨한 결합으로 바꿔주는 법 ( parameter로 넘겨주세요~ )

Class Service1 {
	private final Repository1 repitory1;
	// repository1 객체 사용
	public Service1(Repository1 repository1) {
		// this.repository1 = new Repository1();
		this.repository1 = repository1;
	}
}

// 객체 생성
Service1 service1 = new Service1(repository1);


DI(Dependency Injection) & IoC(Inversion of Control)

👉 "제어의 역전 (IoC: Inversion of Control)"

  • 프로그램의 제어 흐름이 뒤바뀜

일반적인 제어흐름: 사용자가 자신이 필요한 객체를 생성해서 사용

IoC (제어의 역전)

  • 용도에 맞게 필요한 객체를 그냥 가져다 사용

    • "DI (Dependency Injection)" 혹은 한국말로 "의존성 주입"
  • 사용할 객체가 어떻게 만들어졌는지는 알 필요 없음(사실 알아야 되긴 하지만, 사용할 객체의 수정내용을 일일이 반영하는 리소스를 아낄 수 있다는 의미)

    실생활 예제) 가위의 용도별 사용
    음식을 자를 때 필요한 가위는? → 부엌가위 (생성되어 있는 객체 kitchenScissors)
    무늬를 내며 자를 때 필요한 가위는? → 핑킹가위 (생성되어 있는 객체 pinkingShears)
    정원의 나무를 다듬을 때 필요한 가위는? → 전지가위 (생성되어 있는 객체 pruningShears)


예외처리
테코블-전역예외처리
ResponseEntity는 왜 사용하는 것이며 @RestControllerAdvice는 무엇일까.
exceptionHandling
@ExceptionHandler를 통한 예외처리


JPA - 양방향 연관관계 ( mappedBy)

ID Generate전략


트랜잭션 ACID
IBM- Transaction ACID

Stream 정렬(sorted)

영속성 전이(cascade)
How to Set a Header on a Response

profile
맛있는 음식과 여행을 좋아하는 당당한 뚱땡이

2개의 댓글

comment-user-thumbnail
2022년 12월 23일

당뚱님... 레베루를 어프 하고 정독시간 갖겠습니다. 멋진 글 감사드려요 ~!

1개의 답글