본문 바로가기
Spring/토비의 스프링 3.1

토비의 스프링 3.1 - 1장

by 성건희 2022. 5. 25.
반응형

토비의 스프링 chap 1

이전에 토비의 스프링 1권을 읽다가 바쁘다는 핑계로 미뤄두었었는데,
한번쯤 정독해볼 시기인 듯 하여 다시 읽어보기로 하였다.
책은 Spring 으로 프로젝트를 구성했지만, 필자는 SpringBoot 를 사용하기로 하였다.

DB

데이터베이스는 학습 목적이기 때문에 간단하게 H2 를 사용했다.
H2 Database Engine

실습 코드

코드는 GitHub - gbeea1004/toby-spring: 토비의 스프링 실습 깃허브에 올려두었다.
chap 별로 브랜치로 나눠두어서 실습하고자 하는 브랜치에서 진행하면 된다.

UserDao

p.56 에서 UserDao 를 만들어서 '회원가입'과 '회원조회' 기능을 만든다.
여기 코드에서 문제가 있는데, Connection 을 연결하는 부분이 매번 중복 이라는 점이다.
이것을 해결하기 위해서는 관심사의 분리 를 해야한다.

참고) Class.forname

JVM 에게 해당 클래스의 정보를 로드한다.
JDBC 4.0 이후로는 해당 메서드를 호출하지 않아도 자동으로 드라이버를 초기화한다.
따라서 각 메서드의 Class.forName(); 을 제거해도 정상 동작한다.
Java 궁금증 Class.forName()은 어떻게 동작할까? :: kyun2world

관심사의 분리

관심이 같은 것끼리는 모으고, 관심이 다른 것은 따로 떨어져 있게 한다.


커넥션에 대한 관심을 getConnection() 이라는 별도의 메서드로 따로 분리하자.
그렇게 되면 추후 커넥션이 변경되더라도 getConnection() 메서드에서만 수정해주면 된다.
이렇게 getConnection() 의 별도의 메서드로 분리하는 작업을 리팩토링에서는 메서드 추출 (extract method) 이라고 한다.

리팩토링

기존의 코드를 외부의 동작방식에는 변화 없이 내부 구조를 변경해서 재구성하는 기술

커넥션 확장

위 getConnection() 의 경우 커넥션 정보가 고정되어 있기 때문에 확장하기가 어렵다.
확장을 하기 위해서는 2가지 방법이 있다.

  1. 상속을 통한 확장
  2. 조합을 통한 확장

상속을 통한 확장

상속을 사용하면 간단하고 사용하기 편하지만 단점이 많다.

  1. 자바는 다중상속을 허용하지 않는다.
  2. 상속을 통한 부모 자식 클래스의 관계가 밀접해진다. (결합도 ↑)
    부모 클래스의 변경이 있을 때 모든 자식 클래스를 수정해야 할 수도 있다.
  3. 확장된 기능의 DB 커넥션을 생성하는 코드를 다른 DAO 클래스에 적용할 수 없다.

조합을 통한 확장

인터페이스를 도입하여 추상화하여 해당 인터페이스를 DAO 클래스의 필드로 주입한다.
이렇게 되면 Connection 을 수정한다고 해도 DAO 를 수정할 일이 없다.
DAO 가 아무리 많아져도 DB 접속 방법에 대한 관심은 오직 한 군데에 집중되게 할 수 있고,
DB 접속 방법을 변경해야 할 때도 오직 한 곳 의 코드만 수정하면 된다.
이는 OCP (Open-Closed Principle) 를 만족한다.

높은 응집도와 낮은 결합도

  • 높은 응집도 : 변화가 일어날 때 해당 모듈에서 변하는 부분이 크다.
  • 낮은 결합도 : 하나의 변경이 발생할 때 다른 것도 변경해야 하는 상황이 발생하지 않는 상태.

애플리케이션 컨텍스트

IoC 컨테이너 또는 스프링 컨테이너 또는 빈 팩토리라고 부른다. (사실은 BeanFactory 를 확장한 형태임)
애플리케이션 컨텍스트는 애플리케이션에서 IoC 를 적용해서 관리할 모든 오브젝트에 대한 생성과 관계설정을 담당한다.

동작 방식

  1. @Configuration 이 붙은 클래스를 설정정보로 등록해두고 @Bean 이 붙은 메서드의 이름을 가져와서 빈 목록을 만든다.
  2. 클라이언트가 애플리케이션 컨텍스트의 getBean() 을 호출하면 자신의 빈 목록에서 요청한 이름이 있는지 찾는다.
  3. 있다면 빈을 생성하는 메서드를 호출해서 오브젝트를 생성시킨 후 클라이언트에 돌려준다.

애플리케이션 컨텍스트 장점

  • 클라이언트는 구체적인 팩토리 클래스를 알 필요가 없다.
  • 애플리케이션 컨텍스트는 종합 IoC 서비스를 제공해준다.
  • 애플리케이션 컨텍스트는 빈을 검색하는 다양한 방법을 제공한다.

싱글톤 레지스트리

애플리케이션 컨텍스트는 IoC 컨테이너 이면서, 동시에 싱글톤을 저장하고 관리하는 싱글톤 레지스트리이기도 하다.
스프링은 기본적으로 별다른 설정을 하지 않으면 빈 오브젝트를 싱글톤으로 만든다.
디자인 패턴의 싱글톤 패턴과 비슷한 개념이지만 구현 방법이 다르다.
싱글톤 레지스트리는 private 생성자를 사용하지 않고 평범한 클래스도 싱글톤으로 활용하게 해준다.
스프링의 싱글톤 레지스트리 덕분에 싱글톤 방식으로 사용될 애플리케이션 클래스도 public 생성자를 가질 수 있다.

싱글톤 패턴의 한계

  • private 생성자를 가지고 있어 상속이 불가능하다.
  • 테스트하기가 힘들다.
  • 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다.
  • 싱글톤의 사용은 전역 상태를 만들 수 있기 때문에 바람직하지 못하다.

스프링 빈의 스코프

스프링 빈의 기본 스코프는 싱글톤이다.
만약 빈을 요청할 때마다 매번 새로운 오브젝트를 만들고 싶다면, 프로토타입 스코프로 설정하면 된다.

DataSource 인터페이스 적용

전에 커넥션 생성을 위해 ConnectionMaker 인터페이스를 만들었었는데,
DB 커넥션을 가져오는 오브젝트의 기능을 추상화해서 사용할 수 있도록 DataSource 인터페이스가 있다.
이것을 사용하도록 빈으로 등록하면 된다.

@Bean
public DataSource dataSource() {
    SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
    dataSource.setDriverClass(org.h2.Driver.class);
    dataSource.setUrl("jdbc:h2:tcp://localhost/~/springbook");
    dataSource.setUsername("sa");
    dataSource.setPassword("");
    return dataSource;
}

dataSource.setDriverClass 설정 시에 컴파일 에러가 발생했었는데,
build.gradle 의 h2 의존을 다음과 같이 runtimeOnly 에서 implementation 로 바꾸면 해결된다.

implementation 'com.h2database:h2'

참고

  • 토비의 스프링 3.1 Vol.1
반응형

'Spring > 토비의 스프링 3.1' 카테고리의 다른 글

토비의 스프링 chap 4 - 예외  (0) 2022.06.30
토비의 스프링 chap 3 - 템플릿  (2) 2022.06.02
토비의 스프링 3.1 - 2장  (0) 2022.05.30
토비의 스프링 - 1장 (p.1 ~ 87)  (0) 2020.06.22
1.1 초난감 DAO  (0) 2019.01.06

댓글