2024. 10. 17. 16:47ㆍWeb Development/SI 프로젝트
이번 프로젝트에서 갑자기 IBatis를 보게되었다.
처음 접하는 iBatis와 그리고 동시에,
여태 까지 사용해왔던 MyBatis에 대해서도 잘 모르는 것 같아서 자세히 정리해보고자 한다.
1. iBatis
MyBatis의 전신으로 2000년대 초반에 등장했다. iBatis는 JDBC를 간편하게 다룰 수 있도록 도와주는 퍼시스턴스 프레임워크로, SQL 쿼리를 XML로 작성하고 Java 객체와 매핑할 수 있게 해준다.
등장 배경) JDBC의 복잡성을 해결하기 위한 필요성
문제점)
JDBC를 사용할 때는 SQL 쿼리를 Java 코드에 직접 작성하고, 리소스 관리도 직접 해야 했음.
예시) 데이터베이스에서 사용자를 조회하는 JDBC 코드는 다음과 같다.
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
String sql = "SELECT * FROM users WHERE id = ?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, userId);
rs = stmt.executeQuery();
while (rs.next()) {
// 결과 처리
}
} finally {
// 리소스 수동으로 닫기
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
}
해결 방법)
iBatis는 SQL을 XML 파일에 작성하고, Java 코드에서 간결하게 매핑할 수 있게 변경함
위의 코드를 iBatis로 바꾸면,
- XML 파일에 SQL 쿼리를 작성
<select id="getUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
- Java 코드에서 SQL을 분리한 덕분에 훨씬 간결해짐
User user = sqlSession.selectOne("getUserById", userId);
=> 복잡한 JDBC 코드를 줄이고, SQL과 비즈니스 로직을 분리하여 유지보수를 더 쉽게 만든다.
예시 코드) iBatis- .xml
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="example">
<select id="selectUser" resultClass="User">
SELECT * FROM users WHERE id = #id#
</select>
<insert id="insertUser" parameterClass="User">
INSERT INTO users (id, username, password) VALUES (#id#, #username#, #password#)
</insert>
</sqlMap>
2. MyBatis
iBatis는 2010년에 MyBatis로 이름이 변경되며 새로운 기능과 함께 재출시되었다.
MyBatis는 SQL 쿼리를 직접 작성할 수 있는 프레임워크로, SQL에 대한 제어권을 유지하면서도 매핑 작업을 간소화했다.
문제점)
iBatis는 SQL에 대한 제어는 좋았지만, 동적 SQL 작성이나 다양한 새로운 요구를 지원하는 데 한계가 있었다.
조건에 따라 쿼리를 다르게 실행하려면 코드 복잡성이 심각해짐.
해결 방법)
MyBatis로 동적 SQL 작성 기능을 추가함.
- 동적 SQL 사용
<select id="getUserByCondition" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">AND name = #{name}</if>
<if test="age != null">AND age = #{age}</if>
</where>
</select>
- Java 코드: 조건에 따라 쿼리를 실행할 수 있게 됨
Map<String, Object> params = new HashMap<>();
params.put("name", "John");
params.put("age", 30);
List<User> users = sqlSession.selectList("getUserByCondition", params);
=> MyBatis는 이렇게 동적 SQL과 다양한 기능을 추가하여 iBatis의 한계를 극복했다.
예시 코드) MyBatis- .xml
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="example">
<select id="selectUser" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
<insert id="insertUser" parameterType="User">
INSERT INTO users (id, username, password) VALUES (#{id}, #{username}, #{password})
</insert>
</mapper>
그 후, 추가된 기술들에 대해서도 알아보자.
3. JPA
JPA는 2006년에 Java EE 5의 표준으로 처음 도입되었으며, ORM(Object-Relational Mapping) 방식으로 관계형 데이터베이스와 상호작용을 자동화하는 데 중점을 둔 API이다. JPA 자체는 인터페이스이고, 실제 구현체로 Hibernate와 같은 ORM 프레임워크가 많이 사용되고 있다.
등장 배경) SQL 중심에서 객체 지향적인 ORM 방식의 필요성
문제점)
MyBatis는 여전히 SQL을 직접 작성해야 했는데, 이는 애플리케이션의 복잡성이 증가하면서 SQL을 직접 관리하는 것이 부담이었다. 특히, 데이터베이스 구조가 복잡할 때 객체와 SQL 간의 매핑을 수동으로 처리하는 것이 매우 번거로움.
JPA 해결 방법)
JPA는 SQL을 직접 작성할 필요 없이, 객체와 데이터베이스를 자동으로 매핑한다.
예시)
- 엔티티 클래스를 정의한다.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer age;
// getter, setter
}
- 데이터베이스에서 객체를 조회한다.
User user = entityManager.find(User.class, userId);
=> JPA는 SQL을 자동으로 생성하고, 데이터베이스와의 상호작용을 간소화하며, 특히 트랜잭션 관리와 캐시 같은 기능도 자동으로 처리한다.
4. Querydsl
Querydsl은 타입 안전한 쿼리 작성을 위해 2008년경에 등장했다. SQL과 유사한 쿼리를 Java 코드 내에서 작성할 수 있으며, JPA와 통합할 수 있어 복잡한 쿼리를 더욱 안전하게 처리할 수 있도록 도와준다.
등장 배경) JPA의 동적 쿼리 및 타입 안전성 문제
문제점)
JPA는 기본적인 CRUD에는 좋지만, 복잡한 동적 쿼리 작성에는 어려움이 있다.
예를 들어, 복잡한 조건에 따라 쿼리를 작성할 때 SQL처럼 유연하지 않음 !!
해결 방법)
Querydsl은 Java 코드로 SQL과 비슷한 쿼리를 작성하고, 컴파일 시점에서 쿼리 오류를 잡아줌으로써, 동적 쿼리를 쉽게 작성할 수 있다.
- Querydsl을 사용한 쿼리 작성
QUser user = QUser.user;
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
List<User> users = queryFactory.selectFrom(user)
.where(user.name.eq("John")
.and(user.age.gt(30)))
.fetch();
=> Querydsl은 JPA가 제공하지 못했던 동적 쿼리 작성의 어려움을 해결하고, 타입 안전성을 제공한다. 즉, 컴파일 시점에 쿼리 오류를 미리 확인할 수 있다는 점이 큰 장점이다.
'Web Development > SI 프로젝트' 카테고리의 다른 글
@resource VS @autowired (0) | 2024.10.16 |
---|---|
휴대폰인증 (0) | 2024.09.11 |
JSP XSS방지 (0) | 2024.09.09 |
임시비밀번호 발급 (0) | 2024.07.07 |
sns 로그인을 위한 정보 yaml 파일에 관리 (0) | 2024.07.07 |