🤍 전 강의 25% 할인 중 🤍

2024년 상반기를 돌아보고 하반기에도 함께 성장해요!
인프런이 준비한 25% 할인 받으러 가기 >>

[인프런 워밍업 클럽 1기 BE] 세번째 발자국

[인프런 워밍업 클럽 1기 BE] 세번째 발자국

이번 주도 강의를 많이 듣지는 못했지만, 미니프로젝트 1단계를 개발하고, 중간점검에 참여하면서 많은 것을 느낄 수 있었습니다.

강의는 26강부터 30강까지 들었습니다.

 

학습 내용 요약:

26강: Spring Data JPA를 이용해 다양한 쿼리 작성하기

  1. 25강에서 Spring Data JPA가 무엇인지에 대해 배웠습니다. 복잡한 JPA코드를 스프링과 쉽게 사용할 수 있도록 도와주는 라이브러리였는데요. 26강에서는 실제로 Spring Data JPA를 활용해 다양한 쿼리를 작성해보았습니다.

    1. Spring Data JPA의 가장 편리한 점은, 메서드 이름만 작성하면 필요한 SQL을 자동으로 조립해 준다는 점이었습니다.

    2. 따라서, 메서드 이름을 어떻게 짓는지 규칙을 정확하게 알아야 합니다.

      1. find: 1개의 데이터만 가져옵니다.

      2. By 뒤에 오는 필드 이름을 기준으로 Where문을 작성합니다.

      3. By 앞에 올 수 있는 구절

        1. find: 해당 조건을 만족하는 객체 하나를 가져옵니다. 반환 타입은 객체가 될 수도 있고, Optional<타입>이 될 수도 있습니다.

          1. Optional 객체는 Java8 이후로 등장한, null을 감싸는 Wrapper 객체로, 값이 없을 수 있는 경우를 표현하기 위해 사용합니다.

            null로부터 안전성을 보장받을 수 있어 좋지만, 결국 Unboxing하고, Boxing 하는 과정이 오버헤드로 작용할 수 있습니다.

            1. 따라서 null이 아님이 확실하다면 굳이 사용할 필요가 없습니다.

            2. 제한된 경우에 null 대신 반환형으로서 사용하도록 설계되었다고 합니다.

            3. orElseThrow() 메서드를 사용해, 값이 없는 경우 예외처리를 할 수 있습니다.

              1. ex.orElseThrow(IllegalArgumentException::new)

            4. reference: https://mangkyu.tistory.com/70

          2. 조회 연산에서는 값이 없는 경우가 자주 발생할 수 있기 때문에, null을 리턴하도록 하면 에러가 너무 많이 발생할 것입니다. 따라서 Optional<타입> 형태로 값을 리턴하는 것 같습니다.

             

        2. findAll: 쿼리의 결과물이 N개인 경우 사용합니다. List<타입>을 반환합니다.

        3. exists: 쿼리 결과가 존재하는지 확인합니다. 반환 타입은 boolean입니다.

        4. count: SQL의 결과 개수를 셉니다. 반환 타입은 long입니다.

        5. 각 구절은 And나 Or로 조합할 수도 있습니다.

          1. ex. findAllByPriceLessThanEqualAndSold

      4. By 뒤에 들어갈 수 있는 구절:

        1. GreaterThan: 초과

        2. GreaterThanEqual: 이상

        3. LessThan: 미만

        4. LessThanEqual: 이하

        5. Between: 사이에

        6. StartsWith: ~로 시작하는

        7. EndsWith: ~로 끝나는

           

  2. SQL을 자동으로 생성해주므로, 매우 편리하지만, 조건이 복잡해질수록 메서드 이름이 길고 복잡해져 조건을 간략하게 쓰는 것이 필요해 보였습니다.

27강: 트랜잭션 이론편

  • 트랜잭션: 쪼갤 수 없는 업무의 최소 단위(All or Nothing)

    • ex. 쇼핑몰에서 결제 실패가 발생하면, 주문 전체가 취소되는데 이는 트랜잭션으로 묶여있기 때문이다.

  • start transaction(트랜잭션 시작) / commit(반영) / rollback(미반영)

 

28강: 트랜잭션 적용과 영속성 컨텍스트

  • @Transactional 어노테이션으로 트랜잭션을 적용할 수 있습니다.

  • 이때, 조회(SELECT) 쿼리만 사용한다면, readOnly 옵션을 통해 성능을 향상시킬 수 있습니다.

    • readOnly 옵션을 사용하면 dirty-read(트랜잭션 중에, 나중에 시작한 다른 트랜잭션이 먼저 완료되어, 결과가 다르게 보이는 것) 처리를 해줄 필요가 없으므로 성능이 향상되고, 영속성 컨텍스트도 readOnly 객체의 변경을 저장해줄 필요가 없으므로, 부담이 줄어듭니다.

      • 태현님께서도, readOnly 옵션을 true로 설정하는 경우, CRUD를 모두 제공하는 DB가 아니라 Read만 가능한 DB에 바로 접근하므로, 성능 향상이 있다고 말씀하셨습니다.

    • 하지만, 서비스 레이어에서 무분별하게 readOnly를 사용할 경우 성능이 저하될 수 있다는 실험도 있었습니다.

    • 영속성 컨텍스트의 능력 4가지

      • 1. 변경 감지(Dirty Check)

        • 영속성 컨텍스트 안에서 불러온 Entity는 명시적으로 save하지 않더라도, 변경을 감지해 자동으로 저장됩니다.

          • ex. 강의에서 update() 메서드의 경우 save() 메서드를 호출하지 않아도 영속성 컨텍스트를 통해 자동으로 저장되었습니다.

        • 2. 쓰기 지연

          • INSERT, UPDATE, DELETE를 바로 날리는 것이 아니라, commit될 때 모아서 한 번에 날림 -> DB와 통신 횟수가 줄어듦

             

            • DB야 미안해... 상황이 덜 발생할 수 있습니다!

               

        • 3. 1차 캐싱

          • ID를 기준으로 Entity를 기억하기 때문에, 캐싱된 객체는 완전히 동일합니다.(인스턴스의 주소도 동일)

        • 4. 지연 로딩

    30강 책 생성 API 개발하기

    • 기존에 배운 내용을 바탕으로 Book 객체를 생성하고, 테이블 설계 -> 도메인, 리포지토리 -> 서비스 -> 컨트롤러, DTO를 작성해보았습니다.

      • 혼자 작성하는 과정에 테이블 필드 이름과 DTO의 필드 이름이 달라서, Spring Data JPA가 필드를 인식하지 못하는 문제가 있었습니다.

      • 책 이름을 255자나 할당하는지 궁금했는데, 문자열을 타이트하게 잡았을 때, 나중에 조건에 변화가 생기면 테이블을 수정해야 하는데, 그게 쉽지가 않다고 하셨습니다.

      • 또, @Column의 length가 기본 255자기 때문에, 255로 설정하면, 옵션에서 length 조건을 지울 수 있습니다.

 

## 스터디에 임하는 자세:

다른 일로 바쁠때는 스프링 공부에 소홀해지기도 하는데, 스터디 과제 마감이 있기 때문에 다시 스프링 공부를 하게 됩니다. 또, Domain / Repository / Service / Controller / DTO 로 구분하여 개발하는 과정이 번거로울 때도 있지만, 과제를 해나갈수록 익숙해지고 있습니다.

중간 점검 시간에 태현님께서 코드 리뷰를 해주셨는데, 코드를 그 자리에서 보시면서 어떤 선택지가 있고, 각 선택지의 장단점은 무엇이며, 본인은 어떤 선택지를 선호하고, 그 이유가 무엇인지에 대해 설명해주셨습니다. 사실 너무 잘하셔서 충격이었고, 저게 현직자구나... 저런 사항들을 고려하면서 코드를 작성한다면, AI에 쉽게 대체되지 않겠다는 생각도 함께 들었습니다. 코드 리뷰에 참여하신 찬영님도 정말 열심히 고민해서 코드를 작성해주셨고, 덕분에 깊이 있는 코드리뷰가 되었던 것 같습니다.

요즘 테스트에 관심이 많이 생겼는데, 중간점검 때 알려주신 테스팅 방법을 좀 더 찾아보고, 미니 프로젝트에도 녹여봐야겠습니다.

댓글을 작성해보세요.

채널톡 아이콘