7 분 소요

인프런 워밍업 클럽 회고 3

서론

벌써 강의를 들은지 2주차가 지나간다. 강의와 스터디를 하면서 배운 내용을 잊지 않도록 주마다 블로그에 정리하려고 한다.

섹션 5 : 책 요구사항 구현하기

조금 더 객체지향적으로 개발할 수 없을까?

  • BookService에서 User와 UserLoanHistory를 연결시켜 대출 기능과 반납 기능을 개선할 수 있다.
  • User와 UserLoanHistory가 서로를 알도록 코드를 수정한다.
  • 연관 관계 설정
    • @ManyToOne : (대출 기록) N : (대출 기록 소유자) 1 일 때 사용한다.
    • @OneToMany : (대출 기록 소유자) 1 : (대출 기록) N 일 때 사용한다.
    • 연관 관계의 주인 설정하기 mappedBy = 주인 필드 이름 : 연관 관계의 주인의 값이 설정되어야만 진정한 데이터가 저장된다.

JPA 연관관계에 대한 추가적인 기능들

  • Person과 Address에서 1:1 관게 일시 @OneToOne을 사용한다.
  • 연관 관계의 주인이 아닌 쪽에 mappedBy를 사용하여 주인을 설정한다.
  • 연관 관계의 주인 효과 : 객체가 연결되는 기준이 된다.
    • 상대 테이블을 참고하고 있으면 연관관계의 주인
    • 연관관계의 주인이 아니면 mappedBy를 사용
    • 연관관계의 주인의 setter가 사용되어야만 테이블 연결
  • 연관관계 사용시 주의해야 할 점
    @Transactionnal
    public void savePerson(){
    Person person = personRepository.save(new Person());
    Address address = addressRepository.save(new Address());
    person.setAddress(address);
    System.out.println(address.getPerson()); // null이 됨.
    }
    
  • 위 코드에서 아직 트랜잭션이 끝나지 않아, 객체 끼리는 한쪽만 연결된 상태, 반대 쪽을 알 수 없어 null 반환하게 된다.
  • setter를 한 번에 둘을 같이 이어주도록 처리하면 된다.
  • 즉, 양쪽 모두 연관관계를 가지고 있을 때는 양쪽 모두 한번에 맺어주는게 좋다.
    @Transactionnal
    public void savePerson(){
    Person person = personRepository.save(new Person());
    Address address = addressRepository.save(new Address());
    person.setAddress(address);
    address.getPerson();
    }
    ...
    public void setAddress(Address address){
    this.address = address;
    this.address.setPerson(this);
    }
    ...
    public Person getPerson(){
    return this.person;
    }
    
  • User와 UserLoanHistory 관계에선 @ManyToOne, @OneToMany를 사용한다.
  • @ManyToOne은 단방향으로만 사용할 수도 있다.
  • @JoinColumn : 연관관계의 주인이 활용할 수 있는 어노테이션으로 필드의 이름이나 null 여부, 유일성 여부, 업데이트 여부 등을 지정한다.

  • @ManyToMany는 구조가 복잡하고, 테이블이 직관적으로 매핑되지 않아 사용을 추천하지 않는다.
  • cascade 옵션 : 저장이나 삭제를 할 때 연관관계에 놓인 테이블까지 함께 저장 또는 삭제해준다.
  • orphanRemoval 옵션 : 연관관계가 끊어진 데이터를 자동으로 제거해준다.

책 대출/반납 기능 리팩토링과 지연 로딩

  • 대출 기능 리팩토링
      public void loanBook(String bookName){
          this.userLoanHistories.add(new UserLoanHistory(this, bookName));
      }
    
  • 반납 기능 리팩토링
      public void returnBook(String bookName){
          UserLoanHistory targetHistory = this.userLoanHistories.stream()
                  .filter(history -> history.getBookName().equals(bookName))
                  .findFirst()
                  .orElseThrow(IllegalArgumentException::new);
          targetHistory.doReturn();
      }
    
  • User를 가져오는 부분과, 도메인 로직 실행 중간에 출력문을 넣어보면,
      @Transactional
      public void returnBook(BookReturnRequest request){
          // 유저 정보를 가져온다
          User user = userRepository.findByName(request.getUserName())
                  .orElseThrow(IllegalArgumentException::new);
          System.out.println("Hello");
          user.returnBook(request.getBookName());
      }
    
  • User를 가져오고, Hello 가 출력되고, UserLoanHistory를 가져온다.
  • 즉, 영속성 컨텍스트는 지연 로딩이 가능하며, 지연 로딩을 사용하게 되면, 연결되어 있는 객체를 꼭 필요한 순간에만 가져올 수 있다.

  • 연관관계 사용의 장점
    • 각자의 역할에 집중하게 된다.
    • 새로운 개발자가 코드를 읽을 때 이해하기 쉬워진다.
    • 테스트 코드 작성이 쉬워진다.
  • 연관관계 사용의 단점
    • 지나친 사용시, 성능상의 문제가 발생할 수 있다.
    • 도메인 간의 복잡한 연결로 인해 시스템 파악이 어려워질 수 있다.
    • 복잡한 연결로, 하나의 수정이 연관된 다른 요소에 영향을 미칠 수 있다.
  • 즉, 비즈니스 요구사항, 기술적인 요구사항, 도메인 아키텍처 등 여러 부분을 고민해서 연관관계 사용을 선택해야 한다.

Section 5 정리.

  • 객체지향적으로 설계하기 위한 연관관계를 이해하고, 연관관계의 다양한 옵션에 대해 이해했다.
  • JPA에서 연관관계를 매핑하기 위한 방법을 이해하고, 연관관계를 사용해 개발할 때와 사용하지 않고 개발할 때의 차이점을 이해했다.

섹션 6 : 생애 최초 배포 준비하기

배포란 무엇인가?

  • 배포 : 최종 사용자에게 SW를 전달하는 과정. 즉, 전용 컴퓨터에 우리의 서버를 옮겨 실행시키는 것

profile과 H2 DB

  • profile : 똑같은 서버 코드를 실행시키지만, 실행될 때 설정을 다르게 하고 싶을 때 사용한다.
  • profile 적용, profile로 local을 입력시, H2 DB를 사용하게 하고, dev를 입력시, MySQL DB를 사용하도록 설정하기.
  • H2 DB : 경량 Database, 개발 단계에서 많이 사용하며 디스크가 아닌 메모리에 데이터를 저장할 수 있다. (휘발성이라 개발 단계에서만 사용한다.)
  • H2 DB 사용시 ddl-auto 옵션을 create로 사용하면 테이블을 신경쓰지 않고 코드에만 집중할 수 있다.

  • application.yml
    spring:
    config:
      activate:
        on-profile: local
    datasource:
      url: "jdbc:h2:mem:library;MODE=MYSQL;NON_KEYWORDS=USER"
      username: "sa"
      password: //패스워드
      driver-class-name: org.h2.Driver
    jpa:
      hibernate:
        ddl-auto: create
      properties:
        hibernate:
          show_sql: true
          format_sql: true
          dialect: org.hibernate.dialect.H2Dialect
    h2:
      console:
        enabled: true
        path: /h2-console
    ---
    spring:
    config:
      activate:
        on-profile: dev
    datasource:
      url: "jdbc:mysql://localhost/library"
      username: "root"
      password: //패스 워드
      driver-class-name: com.mysql.cj.jdbc.Driver
    
    jpa:
      hibernate:
        ddl-auto: none
      properties:
        hibernate:
          show_sql: true
          format_sql: true
          dialect: org.hibernate.dialect.MySQL8Dialect
    

    [image] [image]

git과 github이란 무엇인가?

  • git : 코드를 쉽게 관리할 수 있도록 해주는 버전 관리 프로그램
  • github : git으로 관리되는 프로젝트의 코드가 저장되는 저장소
  • github에 코드를 저장하는 이유.
    • 코드 소실 방지을 위해
    • 배포 할 떄 활용 가능 하다.

git 기초 사용법

  • git repository 주소 :
  • 강의 초반부터 intellij에서 git을 연결하여 사용 중이였다.

  • git add.
  • git commit -m “커밋 메시지”
  • git push

AWS의 EC2 사용하기

Section 6 정리.

  • 배포가 무엇인지 이해하고, 배포를 하기 위해 어떤 준비를 해야하는지 알아 봤다.
  • 스프링 서버를 실행할 때 DB와 같은 설정들을 코드 변경 없이 제어할 수 있는 방법을 알아봤다.
  • git과 github의 차이를 이해하고 git에 대한 기초적인 사용법을 알아봤다.
  • AWS의 EC2가 무엇인지 이해하고, AWS를 통해 클라우드 컴퓨터를 빌려봤다.

섹션 7 : 생애 최초 배포하기

EC2에 접속해 리눅스 명령어 다뤄보기

  • 다운로드 받은 키 페어를 이용하는 방법
    • 접속하려는 EC2의 IP주소
    • 다운로드 받았던 키 페어
    • 접속하기 위한 프로그램 (git CLI)

    • ssh -i 경로/키페어이름.pem ec2-user@IP
    • EC2컴퓨터가 많아 졌을 경우 간편하게 접근 가능하다.
  • AWS 콘솔을 활용하는 방법
    • AWS 화면에서 인스턴스에 연결에서 연결하면 된다.
    • 복잡한 명령어를 작성할 필요가 없다.
  • 가장 기본적인 리눅스 명령어
    • mkdir folder1 : folder1 폴더 생성
    • cd folder1 : folder1 폴더로 이동
    • pwd : 현재 경로 출력
    • cd.. : 상위 폴더로 이동
    • ls 또는 ls -l : 현재 위치의 폴더 및 파일 목록 출력
    • rmdir folder1 : folder1 폴더 제거

배포를 위한 프로그램 설치하기

  • 설치해야 할 프로그램 목록
    • git : 코드를 가져오기 위함
    • java : 서버를 구동
    • mysql : 데이터베이스 역할
  • 설치 과정
    sudo yum update
    sudo yum install git -y
    ALTER user'root'@'localhost' IDENTIFIED WITH mysql_native_password BY "패스워드";
    
  • 설정 후 profile에서도 변경해주어야 한다.
  • git으로 원격 저장소를 최신화 해주면 완료.

빌드와 실행, 그리고 접속

종료되지 않는 실행

가비아를 이용한 도메인 구입, DNS 적용

Section 7 정리.

  • EC2에 접속하는 방법을 알아보고, EC2에 접속해 리눅스 명령어를 다뤄봤다.
  • 개발한 서버의 배포를 위해 환경 설정을 리눅스에서 진행하고, 실제 배포를 진행해봤다.
  • foreground와 background의 차이를 이해하고 background 서버를 제어해봤다.
  • 도메인 이름을 사용해 사용자가 IP대신 이름으로 접속할 수 있도록 했다.

섹션 8 : Spring Boot의 이모저모

build.gradle 이해하기

  • build.gradle : 빌드 스크립트라고도 불리며, gradle을 이용해 프로젝트를 빌드하고 의존성을 관리하기 위해 작성되었으며, groovy언어를 사용해 작성되었고, kotlin언어를 사용할 수도 있다.
  • plugins 블락 : 다양한 플러그인을 적용하도록 작성할 수 있다.
    • org.springframework.boot 플러그인 역할
      • 스프링을 빌드했을때 실행가능한 jar파일이 나오도록 도와준다.
      • 스프링 애플리케이션을 실행할 수 있게 도와준다.
      • 다른 플러그인들이 잘 적용되도록 도와준다.
    • io.spring.dependency-management
      • 외부 라이브러리, 프레임워크의 버전관리에 도움을 주고 서로 얽혀 있는 의존성을 처리하는데 도와준다.
    • java
      • java 프로젝트를 개발하는데 필요한 기능들을 추가해주고, 다른 JVM언어 Gradle 플러그인을 사용할 수 있는 기반을 마련한다.
  • group : 프로젝트의 그룹
  • version : 프로젝트의 버전
  • sourceCompatibility : 프로젝트가 사용하고 있는 JDK 버전
  • repositories 블락 : 외부 라이브러리/프레임워크를 가져오는 장소 결정
  • dependencies 블락 : 사용하는 라이브러리/프레임워크를 표시하는 곳
  • tests : 테스트 수행시 사용하는 버전 명시.

Spring과 Spring Boot

  • Spring과 Spring Boot의 차이점
    • 간편한 설정
    • 간단한 의존성 관리
    • 강력한 확장성
    • MSA에 적합한 모니터링

application.yml과 application.properties, lombok

  • lombok : getter, setter, 생성자와 같은 반복되는 보일러 플레이트 코드를 제거할 수 있다.
    • lombok 의존성 추가
    • IntelliJ lombok 플러그인 추가
    • IntelliJ Annotation Processor 설정

Spring Boot 2.7.x에서 3.0.x로 업데이트하기

  • Java 최소 버전이 17로 업그레이드 됨.
  • 많은 스프링 프로젝트, Thrid-party Library가 버전업 됨.
  • AOT 기초 작업이 이루어짐.
  • javax대신 jakarta 패키지를 사용하게 됨.
  • 모니터링 기능들이 강화 됨.

3주차 과제

과제 6번 : https://www.inflearn.com/blogs/7993

  • 4번 과제의 API를 Controller - Service - Repository로 분리하기.
  • FruitRepository를 FruitMemoryRepository와 FruitMySqlRepository로 분리하고, @Primary 어노테이션을 사용해 두 Repository를 교차하며 동작해보기.

과제 7번 : https://www.inflearn.com/blogs/8017

  • 6번 과제의 기능들을 JPA를 이용하여 동작하도록 변경하기.
  • 과일 Entity Class를 이용해 특정 과을을 기준으로 과일 개수를 카운트하는 API 만들기
  • 판매되지 않은 특정 금액 이상 또는 특정 금액 이하의 과일 목록을 반환하는 API 만들기

3주차 후기

지난주 2주차 회고록에 이어서 인프런 워밍업 클럽 과정의 3주차가 마무리됬다. 이번 주차에서는 섹션 5의 일부분 부터 섹션 8까지 강의를 수강할 수 있었다. 간단하게 각 섹션 별로 강의의 주제를 다시 한번 상기하고 어떤걸 배우고 느꼈는지 확인해보려고 한다.

섹션 5의 주제 : 책 요구사항 구현하기

객체지향적으로 설계하기 위한 연관관계를 이해하고, 연관관계의 다양한 옵션에 대해 이해했다. 또한 JPA에서 연관관계를 매핑하기 위한 방법을 이해하고, 연관관계를 사용해 개발할 때와 사용하지 않고 개발할 때의 차이점을 이해했다.

섹션 6의 주제 : 생애 최초 배포 준비하기

배포가 무엇인지 이해하고, 배포를 하기 위해 어떤 준비를 해야하는지 알아 봤으며 스프링 서버를 실행할 때 DB와 같은 설정들을 코드 변경 없이 제어할 수 있는 방법을 알아볼 수 있었다. 또한 git과 github의 차이를 이해하고 git에 대한 기초적인 사용법을 알아보고, AWS의 EC2가 무엇인지 이해하고, AWS를 통해 클라우드 컴퓨터를 빌려볼 수 있었다.

섹션 7의 주제 : 생애 최초 배포하기

EC2에 접속하는 방법을 알아보고, EC2에 접속해 리눅스 명령어를 다뤄봤다. 개발한 서버의 배포를 위해 환경 설정을 리눅스에서 진행하고, 실제 배포를 진행해볼 수 있었다. foreground와 background의 차이를 이해하고 background 서버를 제어해보고, 도메인 이름을 사용해 사용자가 IP대신 이름으로 접속할 수 있도록 했다.

섹션 8의 주제 : Spring Boot의 이모저모

그동안 진행해온 Spring Boot의 build.gradle과 application.yml 등 다양한 설정 파일의 내부를 확인해볼 수 있었다.

2차 중간 점검

2차 중간 점검은 질의 응답보단 코드 리뷰를 진행하는 형식으로 진행됬다. 본인은 아직 미니 프로젝트 1번까지 수행하지 못해 직접 피드백을 받지는 못했지만, 고맙게도 올려주신 분들의 코드의 매커니즘 대체로 깔끔해서 작성한 내 코드와 비교해보며 간접적으로 좋은 피드백을 받을 수 있었다.

마무리

이번 주차는 대체적으로 개발한 코드를 리팩토링 하고 배포하는 부분이 많았다. 특히, 배포하는 부분을 주요 깊게 봤다.

처음으로 AWS 계정을 생성해서 배포하는 과정까지 천천히 진행해봤는데, 확실히 금전적으로 사고가 일어날 수 있는 부분이다 보니 강의 자료 외에도 더 알아보고 신중하게 진행했다.

이제 미니 프로젝트만 마무리 지으면 벌써 워밍업 클럽의 수료가 눈앞에 다가온다.

다음 주차엔 남은 강의도 얼마 없어서 미니 프로젝트에 신경을 많이 쓰게 될것 같다.

댓글남기기