TIL ] 토비의 스프링 스터디 -1 리팩토링/ 템플릿 메소드 패턴

BRINCE·2022년 11월 9일
1

스프링 스터디

목록 보기
7/10

스프링?

스프링은 자바를 기반으로 한 기술이다.

스프링이 자바에서 가자 중요하게 가치를 두는 것은 객체지향 프로그래밍이 가능한 언어 라는 점이다.

스프링이 가장 관심을 많이 두는 대상은 오브젝트이다.
-> 오브젝트에 대한 관심은 다양한 목적을 위해 재활용 가능한 설계 방법인 디자인패턴 (MVC패턴도 디자인 패턴중에 하나이다.)
좀더 깔끔한 구조가 되도록 지속적으로 개선해나가는 작업인 리팩토링
오브젝트가 기대한 대로 동작하고 있는지를 효과적으로 검증하는데 쓰이는 단위 테스트와 같은 오브젝트 설계와 구현에 관한 여러가지 응용 기술과 지식이 요구된다.

DAO 를 작성하면서 공부해보자.

자바빈 클래스 생성

DAO란?
Data Access Object는 DB를 사용해 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 오브젝트를 말한다.

자바빈 규약을 따르는 오브젝트를 이용해 클래스를 만들자.

자바빈이란?
비주얼 툴에서 조작 가능한 컴포넌트를 말한다.
특정 관례를 따라 만들어진 오브젝트를 가리킨다.

public class User{
private String id;
private String name;
private String password;

... getter/setter
}

그리고 해당 값들을 저장할 데이터베이스 테이블을 생성해준다.

create table users(
id varchar(10) primary key,
...)

UserDao 클래스 생성

public class UserDao {
    public void add(org.example.User user) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection(
                "jdbc:mysql://localhost/tobiSpring","brince","1234");

        PreparedStatement ps = c.prepareStatement(
                "insert into users(id, name, password) valuse(?,?,?)");
        ps.setString(1, user.getId());
        ps.setString(2,user.getName());
        ps.setString(3,user.getPassword());

        ps.executeUpdate();
        ps.close();
        c.close();
    }
    ...

jdbc 드라이버를 활용해 생성한 테이블에 user 객체의 정보를 저장해주는 메소드를 선언한다.

관심사의 분리

해당 UserDao 의 add 메소드의 내용은 해당 메소드가 호출될 때마다, 매번 db서버에 접속하고 명령문을 실행한다.

하지만 이렇게 add 메소드와 같은 구조를 가진 메소드가 수백개 수천개가 된다면 ?

이러한 상황을 대비하기 위해서 관심사를 분리해야 한다.

개발자가 객체를 설계할 때 가장 염두에 둬야 할 사항은 미래의 변화를 어떻게 대비할 것인가 이다.

지혜로운 개발자는 미래를 위해 설계하고 개발한다.

관심사의 분리라는 것은 관심이 같은 것 끼리는 모으고, 관심이 다른 것은 따로 떨어져 있게 하는것이다.
-> 예를 든다면 노래를 부르는 가창단이 있다고 치자, 가수 한명한명에게 악보를 쥐어주지 않고 노래를 가르쳐주고 있는 상황에서 악보를 만들어 공연의 수정사항이 생겼을때는 단순히 악보만 수정해서 해결이 된다면 이것이 관심사의 분리라는 개념과 같지 않을까? 라는 생각이 든다. 🐋

리팩토링과 테스트

위에 만들었던 UserDao 속 저런식으로 구현된 메소드가 한두개가 아니라면, 메소드 하나만으로도 여러 관심사항을 발견할 수 있다

  • DB와 연결을 위한 커넥션을 어떻게 간단하게 가져올까
  • 매번 어떠한 행동을 하기위해 SQL문장을 담을 Statement 를 만들고 실행해야 하는걸까?
  • 작업이 끝나면 매번 사용한 리소스인 Statement 와 Connection 오브젝트를 닫아줘야 한다.

이렇게 하나의 관심사가 방만하게 중복되어 있고, 여기저기 흩어져 있어서 코드가 이래저래 얽혀있다면, 변경이 일어날 때 엄청난 고통을 일으키는 원인이 되고 이걸 스파게티 코드라고 한다.

중복 코드의 메소드 추출

가장 먼저 할 것은 중복된 코드를 분리하는 것이다.

        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection(
                "jdbc:mysql://localhost/tobiSpring","brince","1234");

이 부분이 매 메소드마다 존재하고, 비밀번호나 타겟이 되는 스키마의 이름을 변경을 해야할 일이 생겨 복잡한 일이 발생하는걸 예방하기 위해 코드를 분리할 수 있다.

private Connection getConnection() throws ClassNotFOundException, SQLException{
        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection(
                "jdbc:mysql://localhost/tobiSpring","brince","1234");
return c;
}

이렇게 코드를 분리한다면, 수정할일이 생겼을때 해당 메소드만 수정하면 된다.

앞에서 한 작업은 기능에 영향을 주지 않으면서 코드의 구조만 변경이 가능하다.

이런 작업을 리팩토링 이라고 한다.

또한 위에서 사용한 공통의 기능을 담당하는 메소드로 중복된 코드를 뽑아내는 것을 메소드 추출 기법이라고 부른다.

템플릿 메소드 패턴

또한 해당 DAO 를 각각의 다른 서비스에서 사용할 일이 생긴다면 ,
한단계 더 분리해 사용할 수 있다.
getConnection() 메소드를 추상 메소드로 만들어 각각의 서비스에서 메소드를 원하는 방식대로 구현하게 하면 된다.

이렇게 구현한다면, 따로 내가 코드 자체를 배포하지 않아도 각각의 서비스에서 메소드를 원하는 방식대로 구현할 수 있다.

해당 방법을 이용해 UserDao 의 코드는 한줄도 수정할 필요 없이 DB연결 기능을 새롭게 정의한 클래스를 만들 수 있다.

이렇게 기본적인 로직의 흐름을 만들고, 그 기능의 일부를 오버라이딩이 가능한 메소드 등으로 만든 뒤 이런 메소드를 필요에 맞게 구현해서 사용하도록 하는 방법을 디자인 패턴에서 템플릿 메소드 패턴 이라고 한다 . -> 템플릿 메소드 패턴은 스프링에서 애용되는 디자인 패턴이다.

스프링 개발자들 사이에 자주 언급되는 몇가지 주요한 디자인 패턴에 대해서 숙지한다면,

패턴을 잘 아는 개발자라면 앞의 설명들을 단순히 UserDao 에 팩토리 메소드 패턴을 적용해서 getConnection 을 분리합시다 라는 말 한마디에 담아낼 수 있을만큼 경제적이다.

단점

템플릿 메소드 패턴은 상속을 사용한다는 단점이 있다.

  • 상속 자체는 간단해 보이지만 많은 한계점이 있다.
  • 자바는 클래스의 다중상속을 허용하지 않는다.
  • 단지 커넥션 개체를 가져오는 방법을 분리하기 위해 상속 구조로 만들어버리면 다른 목적으로 UserDao에 상속을 적용하기 힘들다.

다음 글에서 이어짐

profile
자스코드훔쳐보는변태

0개의 댓글