SlideShare une entreprise Scribd logo
1  sur  32
템플릿 3장
템플릿이란?
질이 다른 코드 중에서 변경이 거의 일어나지 않으며 일정한
패턴으로 유지되는 특성을 가진 부분을 자유롭게 변경되는 성질
을 가진 부분으로부터 독립시켜서 효과적으로 활용할 수 있도록
하는 방법.
1. JDBC 예외처리
DB Connection과 같은 제한적인 리소스를 공유해서 사용하는
서버에서는 중간에 어떤 이유에서든 예외가 발생해도 사용한 리
소스는 반환해야한다. 그 것을 처리하는 예외처리가 필요하다.
일반적인 서버에서는 제한적인 개수의 DB Connection을 사용하
는데 오류가 날 때마다 Connection을 반환하지 못한다면 풀에 사
용할 Connection 이 없어지고 서버가 작동하지 않거나, 중단될 수 있
다.
try / catch / finally 구문을 이용해서 처리해 줄 수 있다.
하지만 try / catch / finally 구문이 중첩되고, 메소드마다 반복된다.
1. JDBC 예외처리
이 문제를 해결하기 위해서 많은 곳에서 중복되는 코드와 로직에
따라서 자꾸 확장되고 자주 변하는 코드를 분리해야한다.
변하는 부분
메소드로 분리
2. 디자인 패턴 - 템플릿 메소드 적용
템플릿 메소드 패턴 : 변하지 않는 부분은 Super Class에 변하는
부분은 추상 메소드로 정의해서 Sub Class 에서 오버라이드해서
사용하는 패턴이다.
기존의 DAO에 변화가 생기지 않고, 확장하고 싶을 때 상속을 통해서
자유롭게 확장 할 수 있다.
하지만 DAO 로직마다 상속들 통해서 새로운 클래스를 만들어야 한다. 또한
확장구조가 이미 클래스를 설계하는 시점에 고정이 되버린다. UserDao의
try / catch / finally 블록과 변하는 Prepared Statement를 담고있는 서브 클
래스들이 이미 클래스 레벨에서 컴파일 시점에 이미 그 관계가 결정되어 있
다.
2. 디자인 패턴 - 전략패턴 적용
전략패턴 : 확장에 해당하는 변하는 부분을 별도의 클래스로 만
들어 추상화된 인터페이스를 통해 위임하는 방식.
Context의 contextMethod() 에서 일정한 구조를
가지고 동작하다가, 특정 확장 기능은 Strategy
Interface를 이용해서 외부의 독립된 전략 클래스에
위임하는 것이다.
하지만 컨텍스트 안에서 이미 구체적인
전략클래스를 사용하도록 고정되어 있다면 계속
컨텍스트를 수정해야하기 때문에 전략을 바꿔 쓸
수 있다는 전략패턴을 위배한다.
2. 디자인 패턴 - 전략패턴 적용
2. 디자인 패턴 - 전략패턴 적용(DI 적용을 위한 클라이언트 / 컨텍스트 분리)
2. 디자인 패턴 - 전략패턴 적용(DI 적용을 위한 클라이언트 / 컨텍스트 분리)
DI는 전략패턴의 장점을 일반적으로 활용할 수 있도록 만든 구조
이다. DI를 다시 기억해 보면 제 3자의 도움을 통해서 두 오브젝
트 사이의 유연한 관계가 설정되도록 하는 것이다.
하지만 이렇게 하면 계속해서 클래스의 개수가 많아지게된다. DI
를 제외하면 템플릿 메소드 패턴에서의 불만은 해결되지 않았다.
또한, add() 시 입력해야 하는 부가적인 정보인 User와 같은 정보
가 있다면 이를 위해 오브젝트를 전달받는 생성자와
이를 저장해둘 인스턴스 변수를 번거롭게 구성해야한다.
2. 디자인 패턴 - 전략패턴 적용(DI 적용을 위한 클라이언트 / 컨텍스트 분리)
로컬클래스
클래스가 많아지는 경우에는 클래스를 매번 독립된 class가 아닌
내부클래스로 정의해버리는 것이다.
코드의 가독성이 올라갈 수 있다. 또한 가장 큰 장점은
자신이 선언된 곳의 정보에 접근이 가능하다. 그렇기
때문에 여기서는 부가적인 정보인 User를 전달해줄
필요가 없다. 결과적으로 클래스 파일도 줄일 수 있었고,
부가적인 정보를 전달하지 않고 바로 가져다 사용할 수
있었다.
2. 디자인 패턴 - 전략패턴 적용(DI 적용을 위한 클라이언트 / 컨텍스트 분리)
익명클래스
어쩌피 메소드 안에서만 사용될 것이기 때문에 이름이 필요하지는
않다. 이름을 갖지 않는 클래스인 익명 내부 클래스 사용
3. 컨텍스트와 DI
위에서 클라이언트와 컨텍스트를 분리시키기는 했지만, 클라이언
트 클래스 안에 클라이언트(UserDao) 안에 컨텍스트가 공존하고
있었다. 그래서 컨텍스트를 다른 DAO 에서 사용할 수 있음에도
불구하고 사용할 수 없었다.
클래스로 따로 분리하자! jdbcContextWithStatementStrategy()를!
3. 컨텍스트와 DI
클래스 분리
JdbcContext 를 UserDao로부터 분리하고 DI를 통해서 의존관계
를 설정할 수 있도록 구성한모습
3. 컨텍스트와 DI
3. 컨텍스트와 DI
applicationContext.xml 스프링 빈으로 DI
applicationContext 에서 JdbcContext를
bean으로 등록하고 UserDao에 DI를 해줬다.
JdbcContext 클래스를 인터페이스를
사용하지 않고, 클래스 레벨에서 의존관계가
설정되었다.
인터페이스를 사용해서 런타임시에 의존할
오브젝트와의 관계를 다이나믹하게
주입해주지는 않았지만, JdbcContext를
스프링을 이용해서 UserDao로 DI하고 있기
때문에 DI구조를 가지고 있다.
3. 컨텍스트와 DI
왜 DI 구조를 가지는가?
첫째는, JdbcContext가 스프링 컨테이너의 싱글톤 레지스트리에서 관리되는 싱글톤 빈이
되기 때문이다.
dataSource라는 인스턴스가 있지만 읽기 전용이기 때문에 JdbcContext가 싱글톤이 되는데
문제가 없다. JdbcContext는 JDBC 컨텍스트 메소드를 제공해주는 서비스 오브젝트로서 의
미가 있고, 그렇기 때문에 싱글톤으로 등록되어 여러 오브젝트에 공유해서 사용되는 것이 이상적이다.
둘째는, JdbcContext는 dataSource를 주입받도록 되어있다. 하지만 DI를 위해서 dataSource 뿐만 아
니라 jdbcContext도 스프링 빈으로 등록되어있어야지 DI가 가능하다.
왜 인터페이스를 사용하지 않았는가?
인터페이스가 없다는 것은 UserDao 와 JdbcContext가 매우 긴밀한 관계로 결합되어 있다는 것이다.
이 둘은 강한 응집도를 가지고 있고, JdbcContext는 DataSource와 달리 테스트에서도 다른 구현으로
대체해서 사용할 이유가 없기 때문이다.
이런 클래스를 바로 사용하는 코드 구성을 DI 적용하는 것은 가장 마지막 단계에 고려하자! 인터페이
스를 만들기 귀찮을 수 있다. 또한 인터페이스를 만들어도 문제될 것은 없다.
3. 컨텍스트와 DI
코드를 이용하는 수동 DI
JdbcContext를 스프링의 빈으로 등록해서 UserDao에 DI 하는 대신 사
용할 수 있는 방법은 UserDao 내부에서 직접 DI를 적용하는 것이다.
Dao마다 JdbcContext를 인스턴스 변수로 한개씩 가지고 있자는 말이
다. 대형 프로젝트여도 DAO개수만큼 정도면 충분하고, 상태정보가 거
의 없기 때문에 메모리에 주는 부담이 적다. 또한 JdbcContext를 스프
링 빈으로 등록하지 않았기 때문에 생성과 초기화를 책임져야 한다.
이 정도면 구현하는데 크게 문제가 되지 않는다.
하지만 DataSource가 스프링 빈이기 때문에 스프링 빈이여야지 DI를
받을 수 있다고 했다. 이럴 경우에는 UserDao에게 DataSource DI까지 맡기
는 것이다.
UserDao가 DataSource를 주입받아서 jdbcContext에 주입해주면된다
3. 컨텍스트와 DI
3. 컨텍스트와 DI
정리
인터페이스를 사용하지 않고 DAO와 밀접한 관계를 갖는 클래스를 DI
에 적용하는 방법 두가지 였다.
스프링 빈으로 DI
인터페이스를 사용하지 않는 클래스와의 의존관계이지만 스프링의 DI
를 이용하기 위해서 빈으로 등록해서 사용하는 방법은 오브젝트 사이
의 실제 의존관계가 설정파일에 명확하게 드러난다는 장점이 있다. 하지만
DI의 근본적인 원칙에 부합하지 않는 구체적인 클래스와의 관계가 설정에
직접 노출된다.
수동으로 DI
JdbcContext가 UserDao 내부에서 만들어지고 사용되면서 은밀히 DI를 사용
하고 전략을 외부에 숨길 수 있다. 하지만 JdbcContext를 여러 오브젝트가 사용해
도 싱글톤으로 만들 수 없고, DI 작업을 위한 부가적인 코드들이 필요하다.
4. 템플릿과 콜백
템플릿 / 콜백 패턴 : 전략패턴의 컨텍스트를 템플릿이라고 부르고, 익
명 내부 클래스로 만들어지는 오브젝트를 콜백이라고 한다.
템플릿은 고정된 작업 흐름을 가진 코드를 재사용한다는 의미이고, 콜
백은 템플릿 안에서 호출되는 것을 목적으로 만들어진 오브젝트이다.
템플릿 : 어떤 목적을 위해 미리 만들어둔 모양이 있는 틀을 가리킨다.
도형자, 모양자를 생각하면 쉽다. 템플릿 메소드 패턴은 고정된 틀을
가지고 있는 템플릿 메소드를 슈퍼 클래스에 두고, 바뀌는 부분을 서
브 클래스의 메소드에 두는 구조이다.
콜백 : 실행되는 것을 목적으로 다른 오브젝트의 메소드에 전달되는 오브젝
트를 말한다. 파라미터로 전달되지만 값을 참조하기 위한 것이 아니라 특정
로직을 담은 메소드를 실행시키기 위해서 사용한다. 자바에서는 메소드 자
체를 파라미터로 전달할 방법은 없기 때문에 메소드가 담긴 오브젝트를 전
달해야 한다. 그 것을 functional object 라고 한다.
4. 템플릿과 콜백
템플릿 / 콜백의 특징
여러개의 메소드를 가진 일반적인 인터페이스를 사용할 수 있는
전략패턴의 전략과 달리 템플릿 / 콜백 패턴은 보통 단일 메소드
인터페이스를 사용한다.
4. 템플릿과 콜백
DI 방식의 전략 패턴구조하고 생각하면 쉽다.매번 메소드 단위로 사용할 오브젝트를 새롭게 전달 받는
것이 특징이다. 콜백 오브젝트가 내부 클래스로서 자신을 생성한 클라이언트 메소드 내의 정보를 직접
참조하는 것도 특징이다. 클라이언트와 콜백이 강하게 결합된다는 면에서도 일반적인 DI와는 다르다.
4. 템플릿과 콜백
jdbcContext를 사용하기만 해도 클라이언트인 DAO의 메소드는 간결해지고 최소한의 데이터
액세스 로직만 갖고 있게 된다.
하지만 익면 내부 클래스는 복잡하다. 그렇기 때문에 사용을 최소화 해보자. 분리를 통해
재사용한 코드를 찾아보자.
이 중에서 바뀔 수 있는 부분은 delete from users 뿐이고 나머지는 변하지 않는다.
4. 템플릿과 콜백
JDBC 안에 클라이언트와 템플릿, 콜백이 모두 함께 공존하면서 동작하는 구조가 되었다.
일반적으로는 성격이 다른 코드들은 가능한 분리하는 것이 낫지만 이 경우는 하나의 목적을 위해
서로 긴밀하게 연관되러 동작하는 응집력이 강한 코드들이기 때문에 한군데 모여있는 것이 유리하다.
구체적인 구현과 내부의 전략패턴, 코드에의한 DI, 익명 내부 클래스 등의 기술은 최대한 감추고,
외부에는 꼭 필요한 기능을 제공하는 단순한 메소드만 노출한다.
5. JdbcTemplate
스프링이 제공하는 JDBC 코드용 기본 탬플릿 JdbcTemplate
5. JdbcTemplate
update
public void add(final User user) throws SQLException {
jdbcTemplate.update("insert into users(id, name, password)
values(?,?,?)", user.getId(),user.getName(),user.getPassword());
}
5. JdbcTemplate
jdbcTemplate.queryForInt
ResultSetExtractor는 PreparedStatement의 쿼리를 실행해서 얻
은 ResultSet을 전달받는 콜백이다. ResultSetExtractor 콜백은 템
플릿이 제공하는 ResultSet을 이용해 원하는 값을 추출해서 템플
릿에 전달하면, 템플릿은 나머지 작업을 수행한 뒤에 그 값을
query() 메소드 리턴 값으로 돌려준다.
JdbcTemplate이런 기능을 가진 콜백을 내장하고 있는
queryForInt() 라는 메소드를 제공한다
5. JdbcTemplate
jdbcTemplate.queryForInt
public int getCount() throws SQLException {
return this.jdbcTemplate.queryForInt("select count(*) from
users");
}
한줄로 코딩가능
5. JdbcTemplate
jdbcTemplate.queryForObject
public User get(String id) {
return this.jdbcTemplate.queryForObject("select * from users where id = ?",
new Object[] {id},
new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum)
throws SQLException {
User user = new User();
user.setId(rs.getString("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
return user;
}
});
}
첫번째 파라미터는 PreparedStatement를 만들기 위한 SQL 문이고, 두번째는 바인딩 값을 Object 타입 배열로 전달해야 한다.
queryForObject()는 SQL 문을 실행하면 한 개의 로우만 얻을 것이하고 기대한다. 그리고 ResultSet의 next()를 실행해서 첫번째 로우로 이동시킨 후에 RowMapper
콜
백을 호출한다. RowMapper가 호출되는 시점에서 ResultSet는 첫번째 로우를 가리키고 있기 때문에 rs.next()를 해줄필요는 없다.
결과가 없다면 EMptyResultDataAccessException 을 던진다.
5. JdbcTemplate
jdbcTemplate.query
public List<User> getAll() {
return this.jdbcTemplate.query("select * from users order by id",
new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum)
throws SQLException {
User user = new User();
user.setId(rs.getString("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
return user;
}
});
}
바인딩 할 파라미터가 없어서 두번 째를 생략 한 것이다.
5. JdbcTemplate
중복코드 분리
get(), getAll() 메소드에서 사용하는 RowMapper는 동일한 것으
로 중복이 된다.추출한다.
private RowMapper<User> userMapper =
new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getString("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
return user;
}
};
5. JdbcTemplate
public User get(String id) {
return this.jdbcTemplate.queryForObject("select * from users where id = ?",
new Object[] {id}, this.userMapper);
}
public List<User> getAll() {
return this.jdbcTemplate.query("select * from users order by id",this.userMapper);
}
최종 UserDao
UserDao에는 User정보를 DB에 넣거나 가져오거나 조작하는 방법에 관한 핵심적인 로직이 담겨있다. 만약 테이블이 변경되면
UserDao의 코드가 함께 바뀐다. 그러므로 응집도가 높다고 볼 수 있다. 반면 JDBC API를 사용하는 방식, 예외처리, 리소스반납, DB
연결 등 모두 JdbcTemplate에게 있다. jdbcTemplate의 코드가 수정이 되도 UserDao에는 아무런 영향을 주지 않는다. 그런 면에서
는 책임이 다른 코드와는 낮은 결합도를 유지하고 있다.

Contenu connexe

Tendances

Programming java day2
Programming java day2Programming java day2
Programming java day2Jaehoonyam
 
C# 세미나 12회차
C# 세미나 12회차C# 세미나 12회차
C# 세미나 12회차Jeung_mh
 
객체지향 단어가 의미하는 것
객체지향 단어가 의미하는 것객체지향 단어가 의미하는 것
객체지향 단어가 의미하는 것jaypi Ko
 
메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함
메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함 메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함
메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함 uEngine Solutions
 
도메인 주도 설계 - 6장 도메인 객체의 생명주기
도메인 주도 설계 - 6장 도메인 객체의 생명주기도메인 주도 설계 - 6장 도메인 객체의 생명주기
도메인 주도 설계 - 6장 도메인 객체의 생명주기JangHyuk You
 
C언어 들어가기
C언어 들어가기C언어 들어가기
C언어 들어가기jaypi Ko
 
Reflect package 사용하기
Reflect package 사용하기Reflect package 사용하기
Reflect package 사용하기Yong Joon Moon
 
Head first디자인패턴 1~13_희민_호준
Head first디자인패턴 1~13_희민_호준Head first디자인패턴 1~13_희민_호준
Head first디자인패턴 1~13_희민_호준HoJun Sung
 
DDD 그게 뭔데 (개념 찍먹편)
DDD 그게 뭔데 (개념 찍먹편)DDD 그게 뭔데 (개념 찍먹편)
DDD 그게 뭔데 (개념 찍먹편)명석 고
 
파이썬 class 및 인스턴스 생성 이해하기
파이썬 class 및 인스턴스 생성 이해하기파이썬 class 및 인스턴스 생성 이해하기
파이썬 class 및 인스턴스 생성 이해하기Yong Joon Moon
 
The art of readable code _ Part I
The art of readable code _ Part IThe art of readable code _ Part I
The art of readable code _ Part I운용 최
 

Tendances (12)

Programming java day2
Programming java day2Programming java day2
Programming java day2
 
C# 세미나 12회차
C# 세미나 12회차C# 세미나 12회차
C# 세미나 12회차
 
객체지향 단어가 의미하는 것
객체지향 단어가 의미하는 것객체지향 단어가 의미하는 것
객체지향 단어가 의미하는 것
 
메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함
메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함 메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함
메타웍스3 워크숍 - 개념소개 및 예제, 그리고 간단한 API문서포함
 
도메인 주도 설계 - 6장 도메인 객체의 생명주기
도메인 주도 설계 - 6장 도메인 객체의 생명주기도메인 주도 설계 - 6장 도메인 객체의 생명주기
도메인 주도 설계 - 6장 도메인 객체의 생명주기
 
C언어 들어가기
C언어 들어가기C언어 들어가기
C언어 들어가기
 
Uml intro 0
Uml intro 0Uml intro 0
Uml intro 0
 
Reflect package 사용하기
Reflect package 사용하기Reflect package 사용하기
Reflect package 사용하기
 
Head first디자인패턴 1~13_희민_호준
Head first디자인패턴 1~13_희민_호준Head first디자인패턴 1~13_희민_호준
Head first디자인패턴 1~13_희민_호준
 
DDD 그게 뭔데 (개념 찍먹편)
DDD 그게 뭔데 (개념 찍먹편)DDD 그게 뭔데 (개념 찍먹편)
DDD 그게 뭔데 (개념 찍먹편)
 
파이썬 class 및 인스턴스 생성 이해하기
파이썬 class 및 인스턴스 생성 이해하기파이썬 class 및 인스턴스 생성 이해하기
파이썬 class 및 인스턴스 생성 이해하기
 
The art of readable code _ Part I
The art of readable code _ Part IThe art of readable code _ Part I
The art of readable code _ Part I
 

Similaire à [스프링 스터디 1일차] 템플릿

토비의 스프링 - DI
토비의 스프링 - DI토비의 스프링 - DI
토비의 스프링 - DIJU Chae
 
2014-15 Intermediate C++ Study #7
2014-15 Intermediate C++ Study #72014-15 Intermediate C++ Study #7
2014-15 Intermediate C++ Study #7Chris Ohk
 
이펙티브 C++ 789 공부
이펙티브 C++ 789 공부이펙티브 C++ 789 공부
이펙티브 C++ 789 공부quxn6
 
[HaU] 신입 기술 면접 준비 java
[HaU] 신입 기술 면접 준비 java[HaU] 신입 기술 면접 준비 java
[HaU] 신입 기술 면접 준비 java유리 하
 
디자인패턴 1~13
디자인패턴 1~13디자인패턴 1~13
디자인패턴 1~13Shin heemin
 
C Language II
C Language IIC Language II
C Language IISuho Kwon
 
안드로이드 DB, 서버 연동하기
안드로이드 DB, 서버 연동하기안드로이드 DB, 서버 연동하기
안드로이드 DB, 서버 연동하기은아 정
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4성연 김
 
Rails style-guide-2
Rails style-guide-2Rails style-guide-2
Rails style-guide-2Yunho Jo
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Hyosang Hong
 
Sql 중심 코드 탈피 발표자료
Sql 중심 코드 탈피 발표자료Sql 중심 코드 탈피 발표자료
Sql 중심 코드 탈피 발표자료ssuser776e2d
 
[Dev rookie]designpattern
[Dev rookie]designpattern[Dev rookie]designpattern
[Dev rookie]designpattern대영 노
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 Yong Joon Moon
 
이펙티브 C++ (7~9)
이펙티브 C++ (7~9)이펙티브 C++ (7~9)
이펙티브 C++ (7~9)익성 조
 
Sql Server 2005 개요
Sql Server 2005 개요Sql Server 2005 개요
Sql Server 2005 개요beamofhope
 
Ksh portfolio
Ksh portfolioKsh portfolio
Ksh portfolioSunhoKo2
 
LucideWorks Banana 소개
LucideWorks Banana 소개 LucideWorks Banana 소개
LucideWorks Banana 소개 SuHyun Jeon
 
[스프링 스터디 3일차] @MVC
[스프링 스터디 3일차] @MVC[스프링 스터디 3일차] @MVC
[스프링 스터디 3일차] @MVCAnselmKim
 

Similaire à [스프링 스터디 1일차] 템플릿 (20)

토비의 스프링 - DI
토비의 스프링 - DI토비의 스프링 - DI
토비의 스프링 - DI
 
2014-15 Intermediate C++ Study #7
2014-15 Intermediate C++ Study #72014-15 Intermediate C++ Study #7
2014-15 Intermediate C++ Study #7
 
이펙티브 C++ 789 공부
이펙티브 C++ 789 공부이펙티브 C++ 789 공부
이펙티브 C++ 789 공부
 
[HaU] 신입 기술 면접 준비 java
[HaU] 신입 기술 면접 준비 java[HaU] 신입 기술 면접 준비 java
[HaU] 신입 기술 면접 준비 java
 
디자인패턴 1~13
디자인패턴 1~13디자인패턴 1~13
디자인패턴 1~13
 
C Language II
C Language IIC Language II
C Language II
 
Design patterns
Design patternsDesign patterns
Design patterns
 
안드로이드 DB, 서버 연동하기
안드로이드 DB, 서버 연동하기안드로이드 DB, 서버 연동하기
안드로이드 DB, 서버 연동하기
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4
 
Rails style-guide-2
Rails style-guide-2Rails style-guide-2
Rails style-guide-2
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료
 
Sql 중심 코드 탈피 발표자료
Sql 중심 코드 탈피 발표자료Sql 중심 코드 탈피 발표자료
Sql 중심 코드 탈피 발표자료
 
[Dev rookie]designpattern
[Dev rookie]designpattern[Dev rookie]designpattern
[Dev rookie]designpattern
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기
 
이펙티브 C++ (7~9)
이펙티브 C++ (7~9)이펙티브 C++ (7~9)
이펙티브 C++ (7~9)
 
EC 789
EC 789EC 789
EC 789
 
Sql Server 2005 개요
Sql Server 2005 개요Sql Server 2005 개요
Sql Server 2005 개요
 
Ksh portfolio
Ksh portfolioKsh portfolio
Ksh portfolio
 
LucideWorks Banana 소개
LucideWorks Banana 소개 LucideWorks Banana 소개
LucideWorks Banana 소개
 
[스프링 스터디 3일차] @MVC
[스프링 스터디 3일차] @MVC[스프링 스터디 3일차] @MVC
[스프링 스터디 3일차] @MVC
 

Plus de AnselmKim

[스프링 스터디 2일차] 스프링 핵심 기술의 응용
[스프링 스터디 2일차] 스프링 핵심 기술의 응용[스프링 스터디 2일차] 스프링 핵심 기술의 응용
[스프링 스터디 2일차] 스프링 핵심 기술의 응용AnselmKim
 
[스프링 스터디 2일차] AOP
[스프링 스터디 2일차] AOP[스프링 스터디 2일차] AOP
[스프링 스터디 2일차] AOPAnselmKim
 
[스프링 스터디 3일차] AOP와 LTW
[스프링 스터디 3일차] AOP와 LTW[스프링 스터디 3일차] AOP와 LTW
[스프링 스터디 3일차] AOP와 LTWAnselmKim
 
[스프링 스터디 3일차] 스프링 웹 기술 응용과 MVC
[스프링 스터디 3일차] 스프링 웹 기술 응용과 MVC[스프링 스터디 3일차] 스프링 웹 기술 응용과 MVC
[스프링 스터디 3일차] 스프링 웹 기술 응용과 MVCAnselmKim
 
[스프링 스터디 3일차] 데이터엑세스기술
[스프링 스터디 3일차] 데이터엑세스기술[스프링 스터디 3일차] 데이터엑세스기술
[스프링 스터디 3일차] 데이터엑세스기술AnselmKim
 
[스프링 스터디 2일차] IoC 컨테이너와 DI
[스프링 스터디 2일차] IoC 컨테이너와 DI[스프링 스터디 2일차] IoC 컨테이너와 DI
[스프링 스터디 2일차] IoC 컨테이너와 DIAnselmKim
 
[스프링 스터디 1일차] Test
[스프링 스터디 1일차] Test[스프링 스터디 1일차] Test
[스프링 스터디 1일차] TestAnselmKim
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화AnselmKim
 
[스프링 스터디 1일차] 예외 처리
[스프링 스터디 1일차] 예외 처리[스프링 스터디 1일차] 예외 처리
[스프링 스터디 1일차] 예외 처리AnselmKim
 
[스프링 스터디 1일차] 오브젝트와 의존관계
[스프링 스터디 1일차] 오브젝트와 의존관계[스프링 스터디 1일차] 오브젝트와 의존관계
[스프링 스터디 1일차] 오브젝트와 의존관계AnselmKim
 

Plus de AnselmKim (10)

[스프링 스터디 2일차] 스프링 핵심 기술의 응용
[스프링 스터디 2일차] 스프링 핵심 기술의 응용[스프링 스터디 2일차] 스프링 핵심 기술의 응용
[스프링 스터디 2일차] 스프링 핵심 기술의 응용
 
[스프링 스터디 2일차] AOP
[스프링 스터디 2일차] AOP[스프링 스터디 2일차] AOP
[스프링 스터디 2일차] AOP
 
[스프링 스터디 3일차] AOP와 LTW
[스프링 스터디 3일차] AOP와 LTW[스프링 스터디 3일차] AOP와 LTW
[스프링 스터디 3일차] AOP와 LTW
 
[스프링 스터디 3일차] 스프링 웹 기술 응용과 MVC
[스프링 스터디 3일차] 스프링 웹 기술 응용과 MVC[스프링 스터디 3일차] 스프링 웹 기술 응용과 MVC
[스프링 스터디 3일차] 스프링 웹 기술 응용과 MVC
 
[스프링 스터디 3일차] 데이터엑세스기술
[스프링 스터디 3일차] 데이터엑세스기술[스프링 스터디 3일차] 데이터엑세스기술
[스프링 스터디 3일차] 데이터엑세스기술
 
[스프링 스터디 2일차] IoC 컨테이너와 DI
[스프링 스터디 2일차] IoC 컨테이너와 DI[스프링 스터디 2일차] IoC 컨테이너와 DI
[스프링 스터디 2일차] IoC 컨테이너와 DI
 
[스프링 스터디 1일차] Test
[스프링 스터디 1일차] Test[스프링 스터디 1일차] Test
[스프링 스터디 1일차] Test
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화
 
[스프링 스터디 1일차] 예외 처리
[스프링 스터디 1일차] 예외 처리[스프링 스터디 1일차] 예외 처리
[스프링 스터디 1일차] 예외 처리
 
[스프링 스터디 1일차] 오브젝트와 의존관계
[스프링 스터디 1일차] 오브젝트와 의존관계[스프링 스터디 1일차] 오브젝트와 의존관계
[스프링 스터디 1일차] 오브젝트와 의존관계
 

[스프링 스터디 1일차] 템플릿

  • 2. 템플릿이란? 질이 다른 코드 중에서 변경이 거의 일어나지 않으며 일정한 패턴으로 유지되는 특성을 가진 부분을 자유롭게 변경되는 성질 을 가진 부분으로부터 독립시켜서 효과적으로 활용할 수 있도록 하는 방법.
  • 3. 1. JDBC 예외처리 DB Connection과 같은 제한적인 리소스를 공유해서 사용하는 서버에서는 중간에 어떤 이유에서든 예외가 발생해도 사용한 리 소스는 반환해야한다. 그 것을 처리하는 예외처리가 필요하다. 일반적인 서버에서는 제한적인 개수의 DB Connection을 사용하 는데 오류가 날 때마다 Connection을 반환하지 못한다면 풀에 사 용할 Connection 이 없어지고 서버가 작동하지 않거나, 중단될 수 있 다. try / catch / finally 구문을 이용해서 처리해 줄 수 있다. 하지만 try / catch / finally 구문이 중첩되고, 메소드마다 반복된다.
  • 4. 1. JDBC 예외처리 이 문제를 해결하기 위해서 많은 곳에서 중복되는 코드와 로직에 따라서 자꾸 확장되고 자주 변하는 코드를 분리해야한다. 변하는 부분 메소드로 분리
  • 5. 2. 디자인 패턴 - 템플릿 메소드 적용 템플릿 메소드 패턴 : 변하지 않는 부분은 Super Class에 변하는 부분은 추상 메소드로 정의해서 Sub Class 에서 오버라이드해서 사용하는 패턴이다. 기존의 DAO에 변화가 생기지 않고, 확장하고 싶을 때 상속을 통해서 자유롭게 확장 할 수 있다. 하지만 DAO 로직마다 상속들 통해서 새로운 클래스를 만들어야 한다. 또한 확장구조가 이미 클래스를 설계하는 시점에 고정이 되버린다. UserDao의 try / catch / finally 블록과 변하는 Prepared Statement를 담고있는 서브 클 래스들이 이미 클래스 레벨에서 컴파일 시점에 이미 그 관계가 결정되어 있 다.
  • 6. 2. 디자인 패턴 - 전략패턴 적용 전략패턴 : 확장에 해당하는 변하는 부분을 별도의 클래스로 만 들어 추상화된 인터페이스를 통해 위임하는 방식. Context의 contextMethod() 에서 일정한 구조를 가지고 동작하다가, 특정 확장 기능은 Strategy Interface를 이용해서 외부의 독립된 전략 클래스에 위임하는 것이다. 하지만 컨텍스트 안에서 이미 구체적인 전략클래스를 사용하도록 고정되어 있다면 계속 컨텍스트를 수정해야하기 때문에 전략을 바꿔 쓸 수 있다는 전략패턴을 위배한다.
  • 7. 2. 디자인 패턴 - 전략패턴 적용
  • 8. 2. 디자인 패턴 - 전략패턴 적용(DI 적용을 위한 클라이언트 / 컨텍스트 분리)
  • 9. 2. 디자인 패턴 - 전략패턴 적용(DI 적용을 위한 클라이언트 / 컨텍스트 분리) DI는 전략패턴의 장점을 일반적으로 활용할 수 있도록 만든 구조 이다. DI를 다시 기억해 보면 제 3자의 도움을 통해서 두 오브젝 트 사이의 유연한 관계가 설정되도록 하는 것이다. 하지만 이렇게 하면 계속해서 클래스의 개수가 많아지게된다. DI 를 제외하면 템플릿 메소드 패턴에서의 불만은 해결되지 않았다. 또한, add() 시 입력해야 하는 부가적인 정보인 User와 같은 정보 가 있다면 이를 위해 오브젝트를 전달받는 생성자와 이를 저장해둘 인스턴스 변수를 번거롭게 구성해야한다.
  • 10. 2. 디자인 패턴 - 전략패턴 적용(DI 적용을 위한 클라이언트 / 컨텍스트 분리) 로컬클래스 클래스가 많아지는 경우에는 클래스를 매번 독립된 class가 아닌 내부클래스로 정의해버리는 것이다. 코드의 가독성이 올라갈 수 있다. 또한 가장 큰 장점은 자신이 선언된 곳의 정보에 접근이 가능하다. 그렇기 때문에 여기서는 부가적인 정보인 User를 전달해줄 필요가 없다. 결과적으로 클래스 파일도 줄일 수 있었고, 부가적인 정보를 전달하지 않고 바로 가져다 사용할 수 있었다.
  • 11. 2. 디자인 패턴 - 전략패턴 적용(DI 적용을 위한 클라이언트 / 컨텍스트 분리) 익명클래스 어쩌피 메소드 안에서만 사용될 것이기 때문에 이름이 필요하지는 않다. 이름을 갖지 않는 클래스인 익명 내부 클래스 사용
  • 12. 3. 컨텍스트와 DI 위에서 클라이언트와 컨텍스트를 분리시키기는 했지만, 클라이언 트 클래스 안에 클라이언트(UserDao) 안에 컨텍스트가 공존하고 있었다. 그래서 컨텍스트를 다른 DAO 에서 사용할 수 있음에도 불구하고 사용할 수 없었다. 클래스로 따로 분리하자! jdbcContextWithStatementStrategy()를!
  • 13. 3. 컨텍스트와 DI 클래스 분리 JdbcContext 를 UserDao로부터 분리하고 DI를 통해서 의존관계 를 설정할 수 있도록 구성한모습
  • 15. 3. 컨텍스트와 DI applicationContext.xml 스프링 빈으로 DI applicationContext 에서 JdbcContext를 bean으로 등록하고 UserDao에 DI를 해줬다. JdbcContext 클래스를 인터페이스를 사용하지 않고, 클래스 레벨에서 의존관계가 설정되었다. 인터페이스를 사용해서 런타임시에 의존할 오브젝트와의 관계를 다이나믹하게 주입해주지는 않았지만, JdbcContext를 스프링을 이용해서 UserDao로 DI하고 있기 때문에 DI구조를 가지고 있다.
  • 16. 3. 컨텍스트와 DI 왜 DI 구조를 가지는가? 첫째는, JdbcContext가 스프링 컨테이너의 싱글톤 레지스트리에서 관리되는 싱글톤 빈이 되기 때문이다. dataSource라는 인스턴스가 있지만 읽기 전용이기 때문에 JdbcContext가 싱글톤이 되는데 문제가 없다. JdbcContext는 JDBC 컨텍스트 메소드를 제공해주는 서비스 오브젝트로서 의 미가 있고, 그렇기 때문에 싱글톤으로 등록되어 여러 오브젝트에 공유해서 사용되는 것이 이상적이다. 둘째는, JdbcContext는 dataSource를 주입받도록 되어있다. 하지만 DI를 위해서 dataSource 뿐만 아 니라 jdbcContext도 스프링 빈으로 등록되어있어야지 DI가 가능하다. 왜 인터페이스를 사용하지 않았는가? 인터페이스가 없다는 것은 UserDao 와 JdbcContext가 매우 긴밀한 관계로 결합되어 있다는 것이다. 이 둘은 강한 응집도를 가지고 있고, JdbcContext는 DataSource와 달리 테스트에서도 다른 구현으로 대체해서 사용할 이유가 없기 때문이다. 이런 클래스를 바로 사용하는 코드 구성을 DI 적용하는 것은 가장 마지막 단계에 고려하자! 인터페이 스를 만들기 귀찮을 수 있다. 또한 인터페이스를 만들어도 문제될 것은 없다.
  • 17. 3. 컨텍스트와 DI 코드를 이용하는 수동 DI JdbcContext를 스프링의 빈으로 등록해서 UserDao에 DI 하는 대신 사 용할 수 있는 방법은 UserDao 내부에서 직접 DI를 적용하는 것이다. Dao마다 JdbcContext를 인스턴스 변수로 한개씩 가지고 있자는 말이 다. 대형 프로젝트여도 DAO개수만큼 정도면 충분하고, 상태정보가 거 의 없기 때문에 메모리에 주는 부담이 적다. 또한 JdbcContext를 스프 링 빈으로 등록하지 않았기 때문에 생성과 초기화를 책임져야 한다. 이 정도면 구현하는데 크게 문제가 되지 않는다. 하지만 DataSource가 스프링 빈이기 때문에 스프링 빈이여야지 DI를 받을 수 있다고 했다. 이럴 경우에는 UserDao에게 DataSource DI까지 맡기 는 것이다. UserDao가 DataSource를 주입받아서 jdbcContext에 주입해주면된다
  • 19. 3. 컨텍스트와 DI 정리 인터페이스를 사용하지 않고 DAO와 밀접한 관계를 갖는 클래스를 DI 에 적용하는 방법 두가지 였다. 스프링 빈으로 DI 인터페이스를 사용하지 않는 클래스와의 의존관계이지만 스프링의 DI 를 이용하기 위해서 빈으로 등록해서 사용하는 방법은 오브젝트 사이 의 실제 의존관계가 설정파일에 명확하게 드러난다는 장점이 있다. 하지만 DI의 근본적인 원칙에 부합하지 않는 구체적인 클래스와의 관계가 설정에 직접 노출된다. 수동으로 DI JdbcContext가 UserDao 내부에서 만들어지고 사용되면서 은밀히 DI를 사용 하고 전략을 외부에 숨길 수 있다. 하지만 JdbcContext를 여러 오브젝트가 사용해 도 싱글톤으로 만들 수 없고, DI 작업을 위한 부가적인 코드들이 필요하다.
  • 20. 4. 템플릿과 콜백 템플릿 / 콜백 패턴 : 전략패턴의 컨텍스트를 템플릿이라고 부르고, 익 명 내부 클래스로 만들어지는 오브젝트를 콜백이라고 한다. 템플릿은 고정된 작업 흐름을 가진 코드를 재사용한다는 의미이고, 콜 백은 템플릿 안에서 호출되는 것을 목적으로 만들어진 오브젝트이다. 템플릿 : 어떤 목적을 위해 미리 만들어둔 모양이 있는 틀을 가리킨다. 도형자, 모양자를 생각하면 쉽다. 템플릿 메소드 패턴은 고정된 틀을 가지고 있는 템플릿 메소드를 슈퍼 클래스에 두고, 바뀌는 부분을 서 브 클래스의 메소드에 두는 구조이다. 콜백 : 실행되는 것을 목적으로 다른 오브젝트의 메소드에 전달되는 오브젝 트를 말한다. 파라미터로 전달되지만 값을 참조하기 위한 것이 아니라 특정 로직을 담은 메소드를 실행시키기 위해서 사용한다. 자바에서는 메소드 자 체를 파라미터로 전달할 방법은 없기 때문에 메소드가 담긴 오브젝트를 전 달해야 한다. 그 것을 functional object 라고 한다.
  • 21. 4. 템플릿과 콜백 템플릿 / 콜백의 특징 여러개의 메소드를 가진 일반적인 인터페이스를 사용할 수 있는 전략패턴의 전략과 달리 템플릿 / 콜백 패턴은 보통 단일 메소드 인터페이스를 사용한다.
  • 22. 4. 템플릿과 콜백 DI 방식의 전략 패턴구조하고 생각하면 쉽다.매번 메소드 단위로 사용할 오브젝트를 새롭게 전달 받는 것이 특징이다. 콜백 오브젝트가 내부 클래스로서 자신을 생성한 클라이언트 메소드 내의 정보를 직접 참조하는 것도 특징이다. 클라이언트와 콜백이 강하게 결합된다는 면에서도 일반적인 DI와는 다르다.
  • 23. 4. 템플릿과 콜백 jdbcContext를 사용하기만 해도 클라이언트인 DAO의 메소드는 간결해지고 최소한의 데이터 액세스 로직만 갖고 있게 된다. 하지만 익면 내부 클래스는 복잡하다. 그렇기 때문에 사용을 최소화 해보자. 분리를 통해 재사용한 코드를 찾아보자. 이 중에서 바뀔 수 있는 부분은 delete from users 뿐이고 나머지는 변하지 않는다.
  • 24. 4. 템플릿과 콜백 JDBC 안에 클라이언트와 템플릿, 콜백이 모두 함께 공존하면서 동작하는 구조가 되었다. 일반적으로는 성격이 다른 코드들은 가능한 분리하는 것이 낫지만 이 경우는 하나의 목적을 위해 서로 긴밀하게 연관되러 동작하는 응집력이 강한 코드들이기 때문에 한군데 모여있는 것이 유리하다. 구체적인 구현과 내부의 전략패턴, 코드에의한 DI, 익명 내부 클래스 등의 기술은 최대한 감추고, 외부에는 꼭 필요한 기능을 제공하는 단순한 메소드만 노출한다.
  • 25. 5. JdbcTemplate 스프링이 제공하는 JDBC 코드용 기본 탬플릿 JdbcTemplate
  • 26. 5. JdbcTemplate update public void add(final User user) throws SQLException { jdbcTemplate.update("insert into users(id, name, password) values(?,?,?)", user.getId(),user.getName(),user.getPassword()); }
  • 27. 5. JdbcTemplate jdbcTemplate.queryForInt ResultSetExtractor는 PreparedStatement의 쿼리를 실행해서 얻 은 ResultSet을 전달받는 콜백이다. ResultSetExtractor 콜백은 템 플릿이 제공하는 ResultSet을 이용해 원하는 값을 추출해서 템플 릿에 전달하면, 템플릿은 나머지 작업을 수행한 뒤에 그 값을 query() 메소드 리턴 값으로 돌려준다. JdbcTemplate이런 기능을 가진 콜백을 내장하고 있는 queryForInt() 라는 메소드를 제공한다
  • 28. 5. JdbcTemplate jdbcTemplate.queryForInt public int getCount() throws SQLException { return this.jdbcTemplate.queryForInt("select count(*) from users"); } 한줄로 코딩가능
  • 29. 5. JdbcTemplate jdbcTemplate.queryForObject public User get(String id) { return this.jdbcTemplate.queryForObject("select * from users where id = ?", new Object[] {id}, new RowMapper<User>() { public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getString("id")); user.setName(rs.getString("name")); user.setPassword(rs.getString("password")); return user; } }); } 첫번째 파라미터는 PreparedStatement를 만들기 위한 SQL 문이고, 두번째는 바인딩 값을 Object 타입 배열로 전달해야 한다. queryForObject()는 SQL 문을 실행하면 한 개의 로우만 얻을 것이하고 기대한다. 그리고 ResultSet의 next()를 실행해서 첫번째 로우로 이동시킨 후에 RowMapper 콜 백을 호출한다. RowMapper가 호출되는 시점에서 ResultSet는 첫번째 로우를 가리키고 있기 때문에 rs.next()를 해줄필요는 없다. 결과가 없다면 EMptyResultDataAccessException 을 던진다.
  • 30. 5. JdbcTemplate jdbcTemplate.query public List<User> getAll() { return this.jdbcTemplate.query("select * from users order by id", new RowMapper<User>() { public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getString("id")); user.setName(rs.getString("name")); user.setPassword(rs.getString("password")); return user; } }); } 바인딩 할 파라미터가 없어서 두번 째를 생략 한 것이다.
  • 31. 5. JdbcTemplate 중복코드 분리 get(), getAll() 메소드에서 사용하는 RowMapper는 동일한 것으 로 중복이 된다.추출한다. private RowMapper<User> userMapper = new RowMapper<User>() { public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getString("id")); user.setName(rs.getString("name")); user.setPassword(rs.getString("password")); return user; } };
  • 32. 5. JdbcTemplate public User get(String id) { return this.jdbcTemplate.queryForObject("select * from users where id = ?", new Object[] {id}, this.userMapper); } public List<User> getAll() { return this.jdbcTemplate.query("select * from users order by id",this.userMapper); } 최종 UserDao UserDao에는 User정보를 DB에 넣거나 가져오거나 조작하는 방법에 관한 핵심적인 로직이 담겨있다. 만약 테이블이 변경되면 UserDao의 코드가 함께 바뀐다. 그러므로 응집도가 높다고 볼 수 있다. 반면 JDBC API를 사용하는 방식, 예외처리, 리소스반납, DB 연결 등 모두 JdbcTemplate에게 있다. jdbcTemplate의 코드가 수정이 되도 UserDao에는 아무런 영향을 주지 않는다. 그런 면에서 는 책임이 다른 코드와는 낮은 결합도를 유지하고 있다.