코딩공부/Spring

Spring 입문 2주차

정해인3 2023. 6. 16. 22:50

3Layer Architecture(3계층) - Controller, Service, Repository / MVC 패턴에서 controller의 역할을 분리 

컨트롤러: 입구이자 출구, 클라이언트의 요청을 받아 서비스에게 로직 처리 맡김 -> 완료된 결과를 클라이언트에게 응답

서비스: 요구사항을 실질적으로 처리(비즈니스 로직: 사용자의 요구 사항), 점점 비대해짐, DB 저장 및 조회가 필요할 경우 리포지토리에 요청 

리포지토리: 데이터베이스를 관리 함, DB CRUD 작업 처리 

 

Ioc & DI: 설계 원칙 및 디자인 패턴, 좋은 코드를 위해 스프링이 제공 

Ioc: 설계 원칙 

DI: 디자인 패턴(요리의 레시피에 비유), DI패턴을 사용하여 Ioc 설계 원칙을 구현 

좋은 코드: 

  1. 논리가 간단
  2. 중복 제거, 표현 명확
  3. 코드를 처음 보는 사람도 쉽게 이해하고 수정
  4. 의존성을 최소화 
  5. 새로운 기능을 추가하더라도 크게 구조의 변경이 없어야 함 

의존

  • 강한 결합 -> 자바 인터페이스로 해결(다형성) -> 변화에 유연해짐(약한 결합, 약한 의존성)
    • 주입 
      • 코드의 주입: 필요로 하는 객체를 해당 객체에 전달 / 어떤 방식이 유연한지, 변경에 영향을 많이 받는지에 차이가 있음  
        • 필드에 직접 주입 
        • 메서드를 통한 주입 
        • 생성자를 통한 주입 -> 가장 많이 사용/ 객체의 불변성 
    • 제어의 역전 

객체 생성은 한 번만 -> 필요한 곳에서 가져다 사용 (약한 결합)

 

스프링 프레임워크 - 객체 생성, 관리하는 역할 해줌 

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: 아무것도 하지 않습니다.

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=검색어"로 쿼리스트링 부분에 해당한다.