초난감 DAO

SeungJoo
|2024. 3. 26. 01:03
728x90

DAO

Data Access Object의 초보적인 형태를 가리키는 용어이며 DAO는 소프트웨어 개발에서 데이터베이스나 다른 영속성 메커니즘에 접근하는 객체를 추상화하는 패턴입니다. DAO 패턴은 데이터 액세스 로직을 비즈니스 로직과 분리하여 코드의 유지 보수성을 높이고 확장성을 개선하는 데 사용됩니다.

DAO 특징

  • 간단한 인터페이스로 데이터 액세스를 위한 메서드들을 정의한 간단한 인터페이스를 가지고 있습니다. 주로 CRUD 연산을 수행하기 위한 메서드들이 포함됩니다.
  • 단순한 구현 클래스로 DAO 인터페이스의 메서드들을 구현하는 단순한 구현 클래스가 있으며 이 클래스는 주로 JDBC를 사용하여 데이터베이스와 통신하고 SQL 쿼리를 실행합니다.
  • DAO 인터페이스를 구현한 DAO 클래스들은 일반적으로 모의 객체 또는 테스트용 DB와 연결하여 Unit Test 하기 적합합니다.
package com.example.spring.DAO;

public class user {
    String id;
    String name;
    String password;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Java Bean

자바 언어로 작성된 소프트웨어 컴포넌트를 말합니다. 재사용 가능한 소프트웨어 컴포넌트로, 다양한 환경에서 사용할 수 있도록 일련의 규약을 따릅니다.

규약은 간단하게 보면 Property, Event, Method 등으로 구성되며 비주얼 프로그래밍 환경에서의 사용을 목적으로 하며 시각적으로 조작할 수 있도록 디자인되었습니다.

디폴트 생성자

자바 빈은 파라미터가 없는 디폴트 생성자를 갖고 있어야 한다. 툴이나 프레임 워크에서 리플렉션을 이용해 오프젝트를 생성하기에 필요

프로퍼티

자바빈이 노출하는 이름을 가진 속성을 프로퍼티라고 하며 set으로 시작하는 수정자 메서드와 get으로 시작하는 접근자 메서드를 이용해 수정 또는 조회할 수 있다.

JavaBean의 특징

캡슐화

Java Bean은 여러 속성과 그 속성에 대한 getter/setter 메서드를 포함하며 이를 통해 객체의 상태를 캡슐화하고, 외부에서 쉽게 접근하여 사용 가능합니다.

재사용성

만들어진 Bean은 여러 애플리케이션에서 재사용할 수 있기에 개발 시간과 비용이 절약됩니다.

이벤트 처리

이벤트 리스너와 이벤트 객체를 통해 이벤트를 처리할 수 있습니다. 이를 통해 사용자 인터페이스와의 상호작용이다 다른 Bean의 통신이 가능

지속성

Java Bean은 자신의 상태를 저장하고 복구할 수 있는 메커니즘을 제공하며 Bean은 애플리케이션이 종료된 후에도 그 상태를 유지할 수 있습니다.

UserDao

package com.example.spring.DAO;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.DriverManager;

public class UserDao {
    public void add(User user) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection(
                "jdbc:mysql://localhost/springbook", "spring", "book"
        );

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

        ps.executeUpdate();

        ps.close();
        c.close();

    }

    public User get(String id) throws ClassNotFoundException,SQLException{
        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection(
                "jdbc:mysql://localhost/springbook", "spring", "book"
        );
        PreparedStatement ps = c.prepareStatement(
                "select *  from users where id = ?"
        );
        ps.setString(1,id);

        ResultSet rs = ps.executeQuery();
        rs.next();
        User user = new User();
        user.setId(rs.getString("id"));
        user.setName(rs.getString("name"));
        user.setPassword(rs.getString("password"));

        rs.close();
        ps.close();
        c.close();

        return user;
    }
}

JDBC 작업의 순서

  1. DB 연결을 위한 Connection을 가져온다.
  2. SQL 담은 statement를 만든다.
  3. statement 실행
  4. 조회의 경우 SQL 쿼리의 실행 결과를 ResultSet으로 받아서 정보를 저장할 오브젝트에 옮겨준다.
  5. 작업 중 생성된 Connecton, statement, resultset 같은 리소스는 작업을 마친 후 무조건 닫아준다.
  6. JDBC API가 만들어내는 예외를 잡아서 처리하거나, 메서드 throws를 선언해서 예외가 발생하면 메서드 밖으로 던지게 한다.

DAO 분리

  1. DAO는 DB와의 상호작용을 담당하므로, DB 연결, 쿼리 실행, 결과 처리 등의 역할을 분리해야 합니다. 예를 들어 DB 연결을 담당하는 클래스와 쿼리 실행, 결과 처리 등의 역할을 분리해야 합니다.
  2. DAO에서 사용되는 SQL은 별도 리소스 파일이나 상수로 분리하며 SQL 쿼리를 수정하거나 변경할 때 DAO를 수정하지 않고 쉽게 관리할 수 있습니다.
  3. 트랜잭션을 시작하고 종료하는 책임을 가지지 않아야 합니다. 대신에 서비스 레이어나 트랜잭션 관리자를 사용하여 트랜잭션 관리를 분리합니다.
  4. 데이터 모델과 비즈니스 로직 모델을 분리하며, DAO 클래스는 DB와의 상호작용을 위한 모델을 사용하고 비즈니스 로직은 별도의 모델이나 서비스 클래스에서 처리합니다.

관심사 분리

프로그래밍의 기초 개념 중에 관심사 분리라는 것이 있습니다. 이를 객체지향에 적용해 보면, 관심이 같은 것끼리는 하나의 객체 안으로 또는 친한 객체로 모이게 하고 관심이 다른 것은 가능한 한 따로 떨어져서 서로 영향을 주지 않도록 분리하는 것이라고 생각할 수 있습니다.

Factory Method Pattern

서브 클래스의 getConnection()을 통해 만들어진 Connection 오브젝트의 종류가 달라질 수 있게 하는 것을 목적으로 하는 디자인 패턴인 팩토리 메서드 패턴을 나타내며 NUserDao와 DUserDao가 같은 종류의 Connecton 구현 클래스의 오브젝트를 리턴할 수도 있습니다. 오브젝트를 생성하는 방식이 다르다면, 이는 팩토리 메서드 패턴으로 이해할 수 있습니다.

디자인 패턴

소프트웨어 설계 시 특정 상황에서 자주 만나는 문제를 해결하기 위해 사용할 수 있는 재사용 가능한 솔루션을 말합니다.

디자인 패턴을 사용하는 이유는 패턴을 사용하면 문제에 대한 해결책을 재사용할 수 있어 개발 시간과 비용을 절약할 수 있으며 패턴을 적용하면 코드의 유연성이 높아지고, 변경에 대한 영향을 최소화하여 시스템의 확장성 또한 높일 수 있습니다.

구성요소

생성 패턴

객체 생성에 관련된 패턴으로, 객체의 생성과정을 캡슐화하며 객체 생성에 유연성을 높입니다.

ex ) Singleton, Factory, AbstractFactory, Builder, ProtoType 등이 있습니다.

구조 패턴

클래스나 객체의 구조를 설계하는 패턴으로, 클래스 간의 관계를 조직화하고 확장성을 높입니다.

ex) Adapter, Composite, Bridge, Proxy, Decorator 등이 있습니다.

행동 패턴

객체나 클래스 간의 상호작용을 설계하는 패턴으로, 시스템의 동작과 역할을 분리하고 효율적인 커뮤니케이션을 지원합니다.

ex) Observer, Strategy, Template Method, Command, Iterator

템플릿 메서드 패턴

상속을 통해 슈퍼클래스의 기능을 확장할 때 사용하는 대표적인 방법이며 변하지 않는 기능은 슈퍼클래스에 만들어두고 자주 변경되며 확장할 기능을 서브클래스에서 만들도록 합니다.

구성 요소

템플릿 메서드

슈퍼클래스에서 알고리즘의 전체적인 구조를 정의한 메서드입니다. 이 메서드는 여러 단계의 작업을 포함하고 있으며, 이 중 일부 단계는 추상 메서드나 구현된 메서드로 이루어집니다.

추상 메서드

템플릿 메서드에서 정의된 일부 단계 중 서브 클래스에서 구현해야 하는 메서드입니다. 추상 메서드는 선언만 되며 구현은 서브 클래스에서 이루어집니다.

훅 메서드

템플릿 메서드에서 사용되는데 기본적으로 아무 동작도 하지 않거나 비어있는 메서드입니다. 서브클래스에서 필요에 따라 오버라이딩하여 사용할 수 있습니다.

팩토리 메서드 패턴

객체 생성을 처리하기 위한 디자인 패턴 중 하나이며 객체 생성을 슈퍼클래스에서 분리하여 서브 클래스에서 해당 객체를 생성하도록 하는 방식을 사용합니다. 이를 통해 클라이언트 코드는 구체적인 클래스를 명시적으로 참조하지 않고도 객체를 생성할 수 있습니다.

구성요소

추상 팩토리

객체 생성을 위한 추상 메서드를 선언하는 인터페이스나 추상클래스입니다. 추상 메서드는 객체 생성을 위한 메서드를 정의하고, 서브 클래스에서 구현해야 합니다.

구체적 팩토리

추상 팩토리를 구현한 클래스로, 실제로 객체를 생성하는 책임을 갖습니다. 각각의 구체적인 팩토리라는 특정 타입의 객체를 생성할 수 있는 메서드를 구현합니다.

DAO의 확장

관심사 분리 : User DAO클래스

데이터 액세스 로직과 DB 연결 로직의 분리로 UserDao는 사용자 정보를 데이터베이스에 저장하고 조회하는 역할을 담당하는 클래스이며 이 클래스는 주로 어떤 SQL문을 사용할지, 어떤 테이블과 필드를 다룰지와 같은 데이터 액세스에 관한 관심사를 가지고 있습니다.

변화의 성격이 다른 두 관심사

데이터 액세스 로직의 변화

데이터베이스의 구조나 사용하는 SQL문, 처리하는 데이터의 종류에 따라 변할 수 있습니다. 예를 들어, 사용자 정보에 새로운 필드가 추가되거나, 데이터베이스 스키마가 변경되는 경우 해당 로직을 수정해야 합니다

DB 연결 로직의 변화

데이버베이스에 연결하는 방식이나 사용하는 데이터베이스 드라이버에 따라 달리질 수 있습니다. 예를 들어 다른 데이터베이스 시스템으로 전환하거나, 연결관리 방식을 변경하는 경우 이에 대한 코드를 수정해야 합니다.

상속을 사용한 분리

UserDao에서 데이터 액세스 로직을 담당하고 이를 상속받는 NUserDao나 DUserDao와 같은 하위 클래스에서 DB 연결 방식을 다르게 구현할 수 있습니다. 이렇게 하면, 한쪽의 변화가 다른 쪽에 영향을 미치지 않도록 할 수 있습니다. 예를 들어 DB 연결 방식이 바뀌더라도 UserDao클래스의 코드를 변경할 필요가 없습니다.

이러한 설계 방식은 각각의 관심사를 명확히 분리하여, 시스템의 한 부분이 변경될 때 다른 부분에 미치는 영향을 최소화하고, 코드의 재사용성을 높이며, 유지보수를 용이하게 만듭니다. 따라서 소프트웨어 개발에서는 이러한 원칙을 따르는 것이 중요합니다

// 토비의 스프링 - 이일민

728x90

'Spring(Boot & FrameWork)' 카테고리의 다른 글

클래스 분리  (1) 2024.03.27
CRON 표현식  (0) 2024.02.08
STOMP  (0) 2024.01.23