[토비의 스프링 3.1 vol.1] 3. 템플릿

60jong·2022년 9월 4일
0
post-thumbnail

3장에서는 스프링에 적용된 다양한 템플릿을 살펴본다.

템플릿이란 바뀌는 성질이 다른 코드 중에서 변경이 거의 일어나지 않으며 일정한 패턴으로 유지되는 특성을 가진 부분을 자유롭게 변경되는 성질을 가진 부분으로부터 독립시켜서 효과적으로 활용할 수 있도록 하는 방법이다.

예외처리

코드에서 발생하는 예외를 따로 처리해주지 않는다면 프로그램은 종료하게된다. 다중 사용자를 위한 서버라면 큰 문제를 발생시킬 수도 있다. 따라서 try/catch/finally를 통해 예외처리를 해주어야한다.

특히 JDBC에서는 제한된 개수의 DB 커넥션을 만들어 재사용 가능한 풀(pool)로 관리한다. Connection과 PreparedStatement 등 공유 리소스를 사용하는 경우, close() 메소드를 통해 사용이 끝난 리소스를 빠르게 반환해주어야 하는데 그렇지 않으면 풀에 있는 리소스가 고갈되게 되고, 에러를 발생하게 된다.

전략 패턴의 사용

더 효율적으로 관리하기 위해서는 변하는 부분과 변하지 않는 부분을 구분하는 것이다. 변하는 부분을 전략 패턴을 통해 의존관계를 주입해보자.

JDBC의 메소드에서 변하는 부분 중 하나로 PreparedStatement가 있다. 이러한 변하는 부분에 대한 인터페이스를 선언하고 생성 전략을 생성해 의존관계를 주입해줄 수 있다.


StatementStrategy 인터페이스

public interface StatementStrategy {
	PreparedStatement makePreparedStatement(Connection C) throws SQLException;
}

DeleteAllStrategy.java

public class DeleteAllStrategy implements StatementStrategy {
	public PreparedStatement makePreparedStatement(Connection C) 
    	throws SQLException {
    	PreparedStatement ps = c.preparedStatement("delete from users");
        return ps
    }
}

deleteAll() 메소드

public void deleteAll(StatementStrategy stsg) throws SQLException {
	```
    try {
    	c = dataSource.getConnection();
       
        ps = stsg.makeConnection(c);
    } catch (SQLException e) {
    	```
    }
    ```
}

UserDaoClient.java

public class UserDaoClient {
	private UserDao userDao;
    private StatementStrategy stsg;
    
    public UserDaoClient(UserDao userDao) {
    	this.userDao = userDao;
    }
    
    stsg = new DeleteAllStrategy();
    
    userDao.deleteAll(stsg);

}

내가 이해한 방식으로 만든 전략 패턴이다.

전략과 클라이언트의 동거

이 방식에서는 두 가지 개선할 점이 있다.

  • Dao의 메소드만큼 전략 클래스를 생성해줘야한다.
  • 새로운 매개변수가 등장할 경우, 해당 인스턴스 변수와 생성자를 입력해주어야한다.

이럴 경우에는 로컬 클래스를 통해 개선할 수 있다.

중첩 클래스 (nested class),
클래스 내부에 정의되는 클래스를 중첩 클래스라고 부른다. 그리고 중첩 클래스는

  • 스태틱 클래스, 독립적인 오브젝트를 생성가능
  • 내부 클래스, 선언된 클래스 내부에서만 사용할 수 있음

    두 가지로 나뉘고, 내부 클래스는
  • 오브젝트 레벨에서 정의되는 멤버 내부 클래스
  • 메소드 레벨에서 정의되는 로컬 클래스
  • 이름을 갖지 않는 익명 내부 클래스

    로 구분된다.

익명 내부 클래스로의 전환

일정한 작업 패턴이 존재하고 그중 일부만 자주 바꿔서 사용해야하는 경우에는
익명 내부 클래스를 구현하는 인터페이스를 생성자처럼 이용하는 오브젝트를 만들면 된다.

UserDaoClient.java

public class UserDaoClient {
	private UserDao userDao;
    private StatementStrategy stsg;
    
    public UserDaoClient(UserDao userDao) {
    	this.userDao = userDao;
    }
    
    stsg = new DeleteAllStrategy();
    
    userDao.deleteAll(new StatementStrategy(
    	public PreparedStatement makePreparedStatement(Connection C) throws SQLException {
    		PreparedStatement ps = c.preparedStatement("delete from users");
        	return ps;
    	})
    );

}

이러헥 메소드 파라미터로서 익명 내부 클래스를 구현할 수 있다.



DI를 해야하는 조건은 무엇일까?
두 가지로 말할 수 있다.

1. 싱글톤으로 관리될 필요가 있는 경우
2. 다른 빈에 의존하고 있는 경우

두 가지를 포괄하는 말로는 "스프링의 제어권에 의해 IoC의 대상이 될 경우"이다.

템플릿과 콜백

위처럼 바뀌지 않는 일정한 패턴을 갖는 작업의 흐름이 존재하고 그중 일부분만 자주 바꿔서 사용해야 하는 경우에는 전략 패턴의 기본 구조에 익명 내부 클래스를 활용하는 방식을 사용하는게 좋다. 이런 방식을 스프링에서는
템플릿/콜백 패턴 이라고 부른다.

템플릿

어떤 목적을 위해 미리 만들어둔 모양이 있는 틀. 프로그래밍에서는 고정된 틀 안에 바꿀 수 있는 부분을 넣어서 사용하는 경우를 템플릿이라고 부른다.

콜백

콜백은 실행되는 것을 목적으로 다른 오브젝트의 메소드에 전달되는 오브젝트. 특정 로직을 담은 메소드를 실행시키기 위해 사용. 자바에서는 메소드 자체를 파라미터로 전달할 수는 없기 때문에 메소드가 담긴 오브젝트를 전달한다. 그래서 Functional object 라고 부르기도 한다.


콜백은 템플릿 안에서 호출되기 위한 목적으로 만들어진 오브젝트이다.

profile
울릉도에 별장 짓고 싶다

0개의 댓글