🤍 전 강의 25% 할인 중 🤍

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

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

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

2주차 발자국을 찍으며..

생각보다 시간을 잘 활용하지 못한 것 같다.
이 강의를 들으며, 잊었던 자바8 이후 문법들에 대해서도 익숙해지도록 공부하려고 마음 먹었으나 급한 일이 겹치고 오늘만은 늦더라도 강의 듣고 공부 더 하고 자야지 했던 다짐이 조금 무너졌었다.
다음주는 꼭 강의와 과제는 일찍 챙겨 듣고 추가 공부를 더 해서 많이 남겨보는 게 목표이다.
아 그리고 월요일(한 주의 시작)에 그 주의 계획을 세워보고 그대로 살아보기 또한 목표이다.


섹션4. 생애 최초 JPA 사용하기

Spring Data JPA를 사용한 데이터베이스 조작. 23~26강

  • SQL 사람이 직접 작성하면 아쉬운 점

    • 에러가 컴파일 시점(서버를 실행하는 그 순간. .java → .class로 변환시켜서 jvm에서 동작시키는 과정)에 발견되지 않고, 런타임 시점(실제 서버가 동작하고 나서)에 발견된다.

    • 특정 데이터베이스에 종속적이게 된다

    • 반복 작업이 많아진다. 테이블 하나 만들 때마다 CRUD 쿼리가 필요.

    • DB의 테이블과 객체는 패러다임이 다르다.

      • 객체에선 교실과 학생은 서로를 가리킬 수 있다.

      • DB에선 학생만 교실을 가리킨다.

      • 상속관계는 DB 테이블로 표현하기 어렵다

  • 요즘은 어플리케이션을 객체지향적인 설계를 지향. DB 테이블을 직접 쓰기가 애매함

  • 그래서 등장하게 된 것이 JPA(Java Persistence API)

    • 자바 진영의 ORM(Object-Relational Mapping)

    • 영속성 : 서버가 재시작되어도 데이터는 영구적으로 저장되는 속성

    • 객체와 관계형 DB의 테이블을 짝지어 데이터를 영구적으로 저장할 수 있도록 정해진 JAVA 진영의 규칙

  • 말로 되어 있는 규칙을 코드로 구현 → 그 코드가 HIBERNATE(JPA를 구현하는 구현체)

  • Hibernate는 내부적으로 JDBC를 사용한다.

     

    image

  • Java 객체와 MySQL 테이블 매핑

    • @Entity : 스프링이 User객체와 user 테이블을 같은 것으로 바라본다.
      Entity의 의미는 저장되고, 관리되어야 하는 데이터

    • 객체엔 없었던 id 필드를 추가해준다.
      @Id : 이 필드를 primary key로 간주한다.
      @GeneratedValue(strategy = GenerationType.*IDENTITY*)
      (MySQL의 Auto_Increment와 동일. primary key는 자동생성되는 값이다.)
      ※ DB마다 자동 생성 전략이 다르다고 함

    • JPA를 사용하려면 Entity 객체에는 기본생성자(매개변수가 없는)가 필수임. protected로 해도 됨

    • @Column : 객체의 필드와 Table의 필드를 매핑한다. 여러 DB의 설정을 연결함

      • ex) @Column(nullable = false, length = 20, name = "name")

      • 필드의 이름도 name이고 DB의 컬럼 이름도 name이므로 생략가능. 필드의 이름이 다를 때 연결시켜줄 때 사용하기도 함

    • 필드가 컬럼과 동일할 경우 @Column 어노테이션을 생략할 수 있다.

    • JPA를 사용하려면 application.yml 파일에 아래와 같이 추가가 필요하다

    image

    • ddl-auto : 스프링이 시작할 때 DB에 있는 테이블을 어떻게 처리할지

      • DB와 객체가 서로 다르게 생겼으면 검증할 수도 있고, 무시할 수도 있고, 테이블을 바꿀 수도 있음

      • create : 기존 테이블이 있다면 삭제 후 다시 생성(들어있는 데이터 삭제됨)

      • create-drop : 스프링이 종료될 때 테이블을 모두 제거(들어있는 데이터 삭제됨)

      • update : 객체와 테이블이 다른 부분만 변경

      • validate : 객체와 테이블이 동일한지 확인(실패하면 서버를 종료시킴)

      • none : 별다른 조치를 하지 않는다.

    • show_sql : JPA를 사용해 DB에 SQL을 날릴 때 SQL을 보여줄 것인가

    • format_sql : SQL을 보여줄 때 예쁘게 포맷팅할 것인가

    • dialect(방언,사투리) : 이 옵션으로 DB를 특정하면 조금씩 다른 SQL을 수정해준다.

public interface UserRepository extends JpaRepository<User, Long> {

}
  • domain에 user 옆에 UserRepository 인터페이스를 하나 만든다.
    이후 JpaRepository를 상속받고 <> 안에 Entity 객체, User의 id 타입을 적어주면 된다

  • 이 인터페이스는 @Repository를 붙이지 않아도 JpaRepository를 상속받는 것만으로 Spring bean으로 관리된다.

  • 저 인터페이스의 save 메소드에 객체를 넣어주면 INSERT SQL이 자동으로 날아간다.

  • save되고 난 후의 User에는 id가 들어있다.

  • 해당 인터페이스의 findAll 메소드 를 사용하면 모든 데이터를 가져온다.(select * from user)

image

  • 위와 같이 작성해주면(객체를 업데이트 해주고나서 save 메소드를 호출)
    마지막에 save할 때 변경사항이 있으면 자동으로 바뀐 객체정보로 update문이 날아가게 됨

image

  • SQL을 작성하지 않아도 동작하는 이유

    • Spring Data JPA : 복잡한 JPA 코드를 스프링과 함께 쉽게 사용할 수 있도록 도와주는 라이브러리

    • SimpleJpaRepository : 어려운 JPA코드를 감싼 라이브러리(사용자가 쉽게 쓸 수 있게)

    image

  • 다양한 쿼리를 Spring Data JPA로 변경해보자

image

  • userRepository.delete(user); 로 데이터를 DB에서 제거하게 됨

  • 기본 제공되지 않는 메서드 만드는 법

    • 함수 이름이 중요함. 알아서 SQL이 조립됨.

    • find라고 작성하면, 1개의 데이터만 가져온다.

    • By 뒤에 붙는 필드 이름으로 SELECT 쿼리의 WHERE문이 작성된다.

image

  • By 뒤에 올 수 있는 구절

imageimage

트랜잭션과 영속성 컨텍스트(27~29강)

  • 저번시간까지는 Repository 계층이 하는 일 처리,
    이제는 Service 계층이 해야하는 추가적인 역할인 transaction에 대해 알아보자

  • 트랜잭션

    • 쪼갤 수 없는 업무의 최소 단위

    • 모든 SQL을 성공시키거나, 하나라도 실패하면 모두 실패시키자

  • 트랜잭션 명령어

    • 시작 : start transaction;

    • 정상 종료 : commit;

    • 실패처리 : rollback;

  • ※ 트랜잭션을 시작했을 때 commit 전 데이터를 다른 접속에서도 보이게 할 수는 있다(옵션조절로)
    하지만 대부분 그러지 않는 기본값을 사용함

  • 트랜 잭션 적용 방법

    • @Transactional 어노테이션 사용

      • 함수에 붙이면 함수가 시작될 때 트랜잭션이 시작되고 함수가 종료될 때
        commit(정상종료시)/rollback(에러발생시)을 해주도록 적용

      • SELECT 쿼리만 사용한다면, (readOnly = true) 옵션을 붙일 수 있다.

        • 저장, 업데이트, 삭제 등 데이터 변경을 위한 불필요한 기능이 빠져서 약간의 성능적 이점이 있음

  • Service 계층의 중요한 역할 : 비즈니스 로직을 가지고 있는 것, 여러 SQL에 접속해야할 경우 트랜잭션 관리

  • ※ 주의사항 : IOException 같은 Checked Exception은 롤백이 일어나지 않는다.
    (서비스계층에서 날 일은 거의 없긴 하다)

  • 영속성 컨텍스트 : 테이블과 매핑된 Entity 객체를 관리/보관하는 역할

    • 스프링에서는 트랜잭션을 사용하면 영속성 컨텍스트가 생겨나고, 트랜잭션이 종료되면 영속성 컨텍스트가 종료된다.

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

      • 변경 감지(Dirty Check) : 영속성 컨텍스트 안에서 불러와진 Entity는 명시적으로 save하지 않더라도,
        변경을 감지해 자동으로 저장된다. ⇒ updateUser 함수에서 userRepository.save를 지워도 자동으로 저장됨

      • 쓰기 지연 : 영속성 컨텍스트 안에서 DB INSERT/UPDATE/DELETE SQL을 바로 날리는 것이 아니라,
        트랜잭션이 commit될 때 모아서 한 번만 날린다.(통신횟수 줄고 비용이 줄어듬)

      • 1차 캐싱 : ID를 기준으로 Entity를 기억한다(통신횟수 줄고 비용이 줄어듬),
        이렇게 캐싱된 객체는 완전히 동일하다(자바의 같은 객체. 주소가 같은 객체와 같은 의미)

      • 나머지 하나는 다음 섹션에서….!


과제4. 추가적인 API를 만들어 보며 API 개발에 익숙해지기

https://slime-feels-660.notion.site/60da5bdb68b9456cad02df9659fff823?pvs=4

4-1은 강의 때 배운대로 3단계의 layer로 분리하여 코드를 작성하였고 자바의 LocalDate를 MySQL의 date 형식과 맞춰 작업하면 되겠구나 생각한 것 외에는 간단했던 것 같다.
4-2는 테이블을 변경하는 DDL을 검색해서 풀었다. 잠시 까먹었던 문법을 상기시킬 수 있었다.
4-3은 문제가 제시하는 형태로 API 결과값을 만들어야 해서 SQL을 두 번 보내는 방식으로 할 지,
SQL문 자체를 group by / sum 을 사용해서 후처리를 할 지 고민하다가 두번째 방법을 쓰고 최대한 배운대로 작업해보고자 노력해서 조금 시간이 더 걸렸다. 잊었던 SQL들을 공부한 느낌이라 역시 계속 한 번씩이라도 다시 봐야겠다고 생각했다.

<추가> 자바에서 정수를 다루는 가장 대표적인 두 가지 방법은 intlong 입니다.
이 두 가지 방법 중 위 API에서 long 을 사용한 이유는 무엇일까요?

나도 비슷하게 답변을 하였지만, 실제 면접에서 답변하듯이 깔끔한 대답은 잘 못 한 것 같다.
값이 커질 수 있다는 말만 하였고 오버플로우가 발생할 수 있다는 식의 대답은 하지 못한 것 같아 조금 더 이런 질문에
면접에서의 원하는 깔끔한 대답을 할 수 있도록 준비해야 겠다고 생각이 들었다.

+) 4번 과제.. 날짜를 착각해서 제출이 조금 늦어졌지만 새벽에 끝까지 집중해서 과제를 마무리하고 제출 후 잠들어 그나마 마음의 짐이 덜어진 것 같았고, 꼼꼼히 과제 체크 및 강의 듣는 것을 다시 한 번 다짐했다..

과제5. 주어진 코드를 클린 코드로 고쳐보기

https://slime-feels-660.notion.site/ba498281917f439b8f230cb8f87ac29b?pvs=4

인터넷 검색을 해보며 클린 코드에 대해 다시 한 번 생각해보게 되었고, 모듈화 하는 것을 나는 솔직히 코딩작업 시간을 늘리고 굳이 이렇게까지 나눠야 하나 라는 생각이 더 컸었다. 그런데 생각을 해보니, 나만 볼 때야 다 알아볼 수 있으니까 그런거지라는 생각이 들었고 코드를 깔끔하게 작업한다면 함께 일하는 사람들이 볼 때 훨씬 편하겠다는 생각을 하게 되었다.
여태까지 나와 함께 프로젝트를 했던 사람들은 그럼 힘들었을까? 라는 생각을 해보며 최대한 모듈화, 함수명 네이밍, 주석 등을 신경쓰며 과제를 진행하였다.


마무리

2주차가 벌써 지나갔다. 시간이 참 빠른 것 같다. 아직 공부하고 싶은 것도 많고 해야할 것도 많다고 생각한다.
절대 나태해지지 말고 강의 꾸준히, 쉬는 시간 적당히, 적절한 운동으로 건강까지..
모두 챙겨서 3주차엔 행복하게 발자국을 남길 수 있길 바래본다.

댓글을 작성해보세요.

채널톡 아이콘