관리 메뉴

효습

스터디 2주차 본문

스터디/Spring

스터디 2주차

효효효효 2023. 4. 15. 21:48

 

회원 관리 예제 - 웹 MVC 개발

  • [localhost](http://localhost) 8080 요청이 오면 먼저 controller에서 찾음 → 맵핑된 게 있으면 이 controller 호출되고 끝나는거, 그래서 기존에 만들었던 index.html은 무시
    • controller 가 정적파일보다 우선순위가 높음
  • 기본적으로 url 창에 치는 건 @GetMapping , 조회할 때 주로 사용
  • @PostMapping 은 보통 data를 form 같은데다가 넣어서 전달할 때 사용
public class MemberForm {
    //private이라 막 접근을 못
    private String name;

    public String getName() {
        return name;
    }

    // 그래서 저장할 이름이 setName을 통해서 들어가게 
    public void setName(String name) {
        this.name = name;
    }
}
  • html 파일에서 ${members} 는 모델 안에 값을 꺼내는 거임
  • 단축키 : ctrl + E 는 최근에 봤던 파일

스프링 DB 접근 기술

  • JDBC URL : jdbc:h2:tcp://localhost/~/test
    • 파일에 직접 접근하는게 아니라 소켓을 통해서 접근함
    • 이렇게 해야 여러 곳에서 접근할 수 있음
  • generated by default as identity
    • DB가 null 값 , 값을 세팅하지 않고 insert 하면 자동으로 값을 채워줌
  • spring에서는 id가 Long이었는데 sql에서는 bigint
  • 스프링을 왜 쓰냐? 객체지향적인 설계가 좋다고 하는 이유는 ,,,,
    • 다형성을 활용(인터페이스를 두고 구현체를 바꿔끼우기를 할 수 있음)
    • 스프링 편리하게 되도록 스프링 컨테이너가 이걸 지원을 해줌
    • DI(dependency injection) 덕분에
    • 기존의 코드는 하나도 손대지 않고 오직 applicatopn을 설정하는 코드, 이 코드만 손대면 나머지 실제 application에 관련된 코드는 하나도 손댈게 없음
  • 개방-폐쇄 원칙(OCP, Open-Closed Principle)
    • 확장에는 열려있고 수정, 변경에는 닫혀있음
    • 객체지향에서 다형성이라는 개념을 잘 활용을 하면 이렇게 기능을 완전히 변경을 해도 애플리케이션 전체를 수정할 필요가 없음 물론 조립하는 코드는 변경을 해야하지만 애플리케이션이 동작하는데 필요한 코드들은 수정할 필요가 없는거
  • 스프링의 DI (Dependencies Injection)을 사용하면 기존 코드를 전혀 손대지 않고, 설정만으로 구현 클래스를 변경할 수 있다.
  • 회원을 등록하고 DB에 결과가 잘 입력되는지 확인하자.
  • 데이터를 DB에 저장하므로 스프링 서버를 다시 실행해도 데이터가 안전하게 저장된다.

스프링 통합 테스트

  • @Transactional 이라는 어노테이션을 테스트에다가 달면 테스트를 실행할 때 테스트를 먼저 실행하고 DB에 데이터를 insert 쿼리하고 다 넣은 다음에 테스트가 끝나면 rollback을 해줌 →DB에 넣었던 데이터가 반영이 안되고 다 지워짐 (테스트에 붙었을 때만 이렇게 실행됨)
  • @SpringBootTest : 스프링 컨테이너와 테스트를 함께 실행한다.
  • 순수한 단위테스트가 훨씬 더 좋은 테스트일 확률이 더 높음

JDBC 템플릿

  • 생성자가 하나만 있으면 , 스프링 빈으로 등록이 되면 @Autowired 생략할 수 있음
//스프링이 자동으로 datasource injection 해줌 
@Autowired
    public JdbcTemplateMemberRepository(DataSource datasource) {
        jdbcTemplate = new JdbcTemplate(datasource);
    }

jpa

  • JPA는 기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해준다.
  • JPA를 사용하면, SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환을 할 수 있다.
  • JPA를 사용하면 개발 생산성을 크게 높일 수 있다
  • jpa는 회원 객체를 보고 테이블도 다 만들수 있음 - 근데 이미 만들어져있기 때문에 자동으로 만들어지는 건 끄자
spring.jpa.hibernate.ddl-auto=create
//위와 같으면 테이블도 자동으로 생성해
  • jpa는 인터페이스만 제공이 되는거임 , 객체랑 ORM(Object Relational Mapping)이라는 기술
  • @Entity 는 jpa가 관리하는 엔티티라는 의미임
  • DB에 값을 넣으면 DB가 ID를 자동으로 생성해주는 것을 IDENTITY 전략이라고 함
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;//시스템이 저장하는 아이디
  • 만약 DB에서 Column명이 username이면 다음과 같이 한다
@Column(name ="username")
    private String name;

이 어노테이션을 가지고 데이터베이스와 매핑을 하는 거

  • jpa는 엔티티매니저라는 걸로 모든 걸 동작함
  • jpa 라이브러리를 받으면 스프링 부트가 엔티티 매니저라는 것을 생성해줌
  • 현재 데이터 베이스랑 다 연결해가지고 만들어주고 만들어진 걸 injection 받으면 됨
  • findByName 같은 경우에는 JPQL이라는 객체지향쿼리를 써야함, 거의 sql이랑 똑같은데 좀 다르다.
@Override
    public Optional<Member> findByName(String name) {
        List<Member> result = em.createQuery("select m from Member m where m.name=name",Member.class)
        .setParameter("name",name)
                .getResultList();
          return result.stream().findAny();
    }
  • Refector this 단축키: ctrl+alt+shift+t
  • 저장,조회할 때 sql 짤 필요 없음 , 다 자동으로 되는데 pk 기반이 아닌 나머지는 JPQL을 작성해줘야함
  • jpa기술을 스프링에 감싸서 제공하는 스프링 데이터 jpa가 있음 → 그럼 jpql을 안짜도 됨
  • 주의할 점
    • 항상 transaction이라는 게 있어야 함 → service 계층에 @Transactional
    • 데이터를 저장하거나 변경할 때 항상 transaction이 있어야함

스프링 데이터 JPA

  • 스프링 데이터 JPA는 JPA를 편리하게 사용하도록 도와주는 기술
  • 인터페이스가 인터페이스를 받을 때에는 extends
  • 인터페이스만 만들어놓으면 스프링 데이터 jpa가 인터페이스에 대한 구현체를 만들어냄 → 스프링 빈에 등록을 해놓음 그래서 injection을 받을 수 있음
  • SpringDataJpaMemberRepository
package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface SpringDataJpaMemberRepository extends JpaRepository<Member,Long> ,MemberRepository {

    @Override
    Optional<Member> findByName(String name);
}
  • SpringConfig
package hello.hellospring;

import hello.hellospring.repository.MemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    private final MemberRepository memberRepository;
    @Autowired
    public SpringConfig(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository);
    }
}
  • 스프링 데이터 jpa가 SpringDataJpaMemberRepository 를 보고 스프링 빈을 자동으로 만들어서 프록시라는 기술을 가지고 객체를 생성해서 스프링 빈으로 올림

  • 스프링 데이터 JPA 제공 기능
    • 인터페이스를 통한 기본적인 CRUD
    • findByName() , findByEmail() 처럼 메서드 이름 만으로 조회 기능 제공
    • 페이징 기능 자동 제공
  • 복잡한 동적 쿼리는 Querydsl이라는 라이브러리를 사용

AOP

AOP가 필요한 상황

  • 모든 메서드의 호출 시간을 측정하고 싶다면?
  • 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern)
  • 회원 가입 시간, 회원 조회 시간을 측정하고 싶다면?

문제

  • 회원가입, 회원 조회에 시간을 측정하는 기능은 핵심 관심 사항이 아니다.
  • 시간을 측정하는 로직은 공통 관심 사항이다.
  • 시간을 측정하는 로직과 핵심 비즈니스의 로직이 섞여서 유지보수가 어렵다.
  • 시간을 측정하는 로직을 별도의 공통 로직으로 만들기 매우 어렵다.
  • 시간을 측정하는 로직을 변경할 때 모든 로직을 찾아가면서 변경해야 한다

AOP : Aspect Oriented Programming

  • 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern) 분리

  • Inline Variable : ctrl+alt+n

해결

  • 회원가입, 회원 조회등 핵심 관심사항과 시간을 측정하는 공통 관심 사항을 분리한다.
  • 시간을 측정하는 로직을 별도의 공통 로직으로 만들었다.
  • 핵심 관심 사항을 깔끔하게 유지할 수 있다.
  • 변경이 필요하면 이 로직만 변경하면 된다.
  • 원하는 적용 대상을 선택할 수 있다

  • 프록시라고 하는 가짜 스프링 빈을 만들어냄
  • 가짜 스프링 빈이 끝나면 joinPoint.proceed() 해서 진짜를 호출