DAO(Data Access Object)는 데이터베이스나 다른 영구 저장소에 대한 접근을 추상화하여, 비즈니스 로직과 데이터 접근 로직을 분리하는 설계 패턴입니다. DAO 패턴은 애플리케이션의 데이터 저장 및 조회 기능을 담당하는 객체들을 정의하고, 이들을 통해 데이터베이스의 데이터를 조작하는 역할을 합니다.
DAO의 주요 개념
- 데이터 접근 추상화: DAO는 데이터베이스와 같은 영구 저장소에 접근하는 방법을 추상화하여, 데이터 접근 로직을 비즈니스 로직으로부터 분리합니다. 이를 통해 비즈니스 로직은 데이터가 어디에서 어떻게 저장되는지 신경 쓰지 않고, 오직 DAO를 통해서만 데이터를 조작할 수 있습니다.
- CRUD 작업: DAO는 주로 Create, Read, Update, Delete (CRUD) 작업을 수행합니다. 데이터베이스와 상호작용하여 엔티티를 생성, 조회, 수정, 삭제하는 기능을 제공합니다.
- 재사용성: DAO는 데이터 접근 로직을 중앙화하여 코드의 재사용성을 높입니다. 또한, 데이터베이스와 상호작용하는 코드를 한 곳에서 관리할 수 있어 유지보수가 용이합니다.
- 데이터베이스 독립성: DAO 패턴을 사용하면 데이터베이스에 대한 의존성을 줄일 수 있습니다. 데이터베이스를 교체하거나 수정할 때 DAO만 수정하면 되므로, 애플리케이션의 다른 부분에 영향을 주지 않습니다.
DAO 패턴의 구성 요소
- DAO 인터페이스: 데이터 접근 객체가 수행해야 할 메서드를 정의합니다. 예를 들어,
save()
,findById()
,findAll()
,update()
,delete()
등의 메서드가 포함될 수 있습니다.
- DAO 구현 클래스: DAO 인터페이스를 구현하여 실제 데이터베이스 작업을 수행하는 클래스입니다. 예를 들어, JDBC, JPA, Hibernate 등을 사용하여 데이터베이스와 상호작용합니다.
- 엔티티 클래스: 데이터베이스 테이블과 매핑되는 클래스입니다. DAO는 이 엔티티 객체를 사용하여 데이터베이스와 데이터를 주고받습니다.
DAO의 예제 코드 (Java)
간단한 예제로,
User
엔티티를 관리하는 DAO를 만들어 보겠습니다.// User 엔티티 클래스
public class User {
private Long id;
private String name;
private String email;
// getters and setters
}
// DAO 인터페이스
public interface UserDao {
void save(User user);
User findById(Long id);
List<User> findAll();
void update(User user);
void delete(Long id);
}
// DAO 구현 클래스 (JDBC 사용 예)
public class UserDaoImpl implements UserDao {
private Connection connection;
public UserDaoImpl(Connection connection) {
this.connection = connection;
}
@Override
public void save(User user) {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, user.getName());
stmt.setString(2, user.getEmail());
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setLong(1, id);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
return user;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<User> findAll() {
List<User> users = new ArrayList<>();
String sql = "SELECT * FROM users";
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
users.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
}
return users;
}
@Override
public void update(User user) {
String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, user.getName());
stmt.setString(2, user.getEmail());
stmt.setLong(3, user.getId());
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void delete(Long id) {
String sql = "DELETE FROM users WHERE id = ?";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setLong(1, id);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
DAO 패턴의 장점
- 유지보수성: 데이터 접근 로직이 분리되어 있어 변경이 필요할 때 비즈니스 로직에 영향을 주지 않습니다.
- 재사용성: DAO 클래스는 다양한 곳에서 재사용될 수 있습니다.
- 테스트 용이성: DAO 패턴을 사용하면 데이터베이스와의 상호작용을 모의(Mock) 객체로 대체할 수 있어 단위 테스트가 용이합니다.
DAO 패턴의 단점
- 복잡성 증가: 애플리케이션 규모가 커질수록 DAO 클래스가 많아져 복잡성이 증가할 수 있습니다.
- 추상화에 따른 성능 손실: 높은 수준의 추상화는 때때로 성능 손실을 야기할 수 있습니다.
결론
DAO는 데이터 접근 로직을 캡슐화하고, 비즈니스 로직과 분리하여 코드를 더 유지보수하기 쉽게 만드는 유용한 패턴입니다. 특히 데이터베이스와의 상호작용이 많은 애플리케이션에서 DAO 패턴을 사용하면, 코드의 재사용성, 모듈화, 테스트 가능성을 크게 높일 수 있습니다.
Share article