JDBC, Spring JDBC, Spring JPA ๊ฐ๋ ๊ณผ ์ฌ์ฉ๋ฒ ์ด์ ๋ฆฌ
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉํ๋ ๋ฐฉ์์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์๋ค. JDBC๋ก ์์ํด, ์ด๋ฅผ ์ถ์ํํ Spring JDBC, ๊ทธ๋ฆฌ๊ณ ORM ๊ธฐ๋ฐ์ Spring JPA(Hibernate)๊น์ง ๋ค์ํ ๊ณ์ธต์ ์ ๊ทผ ๋ฐฉ๋ฒ์ด ์กด์ฌํ๋ค. ์ด๋ฒ ํฌ์คํ ์์๋ ์ด ์ธ ๊ฐ์ง ๊ธฐ์ ์ ํน์ง๊ณผ ์ฌ์ฉ๋ฒ์ ๊ฐ๋ตํ ์ดํด๋ณด๊ณ , ์์ ์ฝ๋๋ฅผ ํตํด ์ฐจ์ด์ ์ ๋น๊ตํด๋ณธ๋ค.
CommandLineRunner์ ApplicationRunner
Spring Boot ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ๋ํ ๋, ํน์ ๋ก์ง์ ์๋์ผ๋ก ์คํํ๊ณ ์ถ๋ค๋ฉด CommandLineRunner ๋๋ ApplicationRunner ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
@Component
public class CourseJdbcCommandLineRunner implements CommandLineRunner {
@Autowired
private CourseJdbcRepository repository;
@Override
public void run(String... args) throws Exception {
repository.insert();
}
}
- CommandLineRunner: ์คํ๋ง ์ ํ๋ฆฌ์ผ์ด์
์ด ๊ฐ๋๋ ์งํ
run(String... args)๋ฉ์๋๋ฅผ ์คํํ๋ค. - ApplicationRunner:
CommandLineRunner์ ์ ์ฌํ์ง๋ง,run(ApplicationArguments args)ํํ๋ก ์ธ์๋ฅผ ์ ๋ฌ๋ฐ๋๋ค.
๋ ์ค ํ๋๋ฅผ ์ ํํด ๊ฐ๋ฐ ํ๊ฒฝ ๋ฐ ํ์์ ๋ฐ๋ผ ์ฌ์ฉํ ์ ์๋ค.
JDBC
**JDBC (Java Database Connectivity)**๋ ์๋ฐ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ๊ณ SQL ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ธฐ ์ํ ํ์ค ์ธํฐํ์ด์ค์ด๋ค. ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ด๋ฉฐ, ๋ชจ๋ DB ์์ ์ ์ง์ ์ฒ๋ฆฌํ๋ค.
์๋ ์์๋ ๋จ์ํ ์ญ์ ์ฟผ๋ฆฌ๋ฅผ ์ง์ ์ํํ๋ ๋ชจ์ต์ด๋ค.
public void deleteTodo(int id) {
PreparedStatement st = null;
try {
st = db.conn.prepareStatement("delete from todo where id=?");
st.setInt(1, id);
st.execute();
} catch (SQLException e) {
logger.fatal("Query Failed : ", e);
} finally {
if (st != null) {
try { st.close(); }
catch (SQLException e) {}
}
}
}
JDBC์ ํน์ง
- ์ง์ ์ ์ธ SQL ์์ฑ: SQL ์ฟผ๋ฆฌ๋ฌธ์ ์ง์ ๊ด๋ฆฌํ๋ค.
- ์์ธํ ์์ธ ์ฒ๋ฆฌ ๋ฐ ์์ ๊ด๋ฆฌ ํ์:
try-catch-finally๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ์ปค๋ฅ์ , ์คํ ์ดํธ๋จผํธ, ๋ฆฌ์์ค ํด์ ๋ฑ์ ์ง์ ์ฒ๋ฆฌํด์ผ ํ๋ค. - ์ ์ฐ์ฑ ๋์: ์ํ๋ ๋๋ก SQL ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ณ ์ปค์คํฐ๋ง์ด์งํ ์ ์๋ค.
Spring JDBC
Spring JDBC๋ JDBC๋ฅผ ๋์ฑ ๊ฐ๋จํ ์ฌ์ฉํ ์ ์๋๋ก ๋์์ฃผ๋ ์ถ์ํ ๊ณ์ธต์ด๋ค. JdbcTemplate ํด๋์ค๋ฅผ ํตํด ๋ฐ๋ณต์ ์ธ ์ฝ๋(์ฐ๊ฒฐ, ์์ธ ์ฒ๋ฆฌ ๋ฑ)๋ฅผ ์ ๊ฑฐํ๊ณ , SQL ์คํ ๋ก์ง์ ๊ฐ๋จํ ์์ฑํ ์ ์๊ฒ ํด์ค๋ค.
@Repository
public class CourseJdbcRepository {
@Autowired
private JdbcTemplate springJdbcTemplate;
private static final String INSERT_QUERY =
"""
insert into course (id,name,author) values(2, 'azure', 'solo');
""";
public void insert() {
springJdbcTemplate.update(INSERT_QUERY);
}
}
- JdbcTemplate: SQL ์คํ(
update,queryForObject๋ฑ)์ ๊ฐ๋จํ ์ํํ ์ ์๋๋ก ํด์ค๋ค. - ์ฝ๋ ๊ฐ๊ฒฐํ: ๊ธฐ์กด JDBC๋ณด๋ค ์์ ๊ด๋ฆฌ์ ์์ธ ์ฒ๋ฆฌ๊ฐ ์๋ํ๋์ด ์๋ค.
JdbcTemplate๊ณผ queryForObject() ํ์ฉ
insert, delete ์์
@Repository
public class CourseJdbcRepository {
private static final String INSERT_QUERY = """
insert into course (id, name, author) values(?, ?, ?);
""";
private static final String DELETE_QUERY = """
delete from course where id = ?
""";
@Autowired
private JdbcTemplate springJdbcTemplate;
public void insert(Course course) {
springJdbcTemplate.update(INSERT_QUERY,
course.getId(), course.getName(), course.getAuthor());
}
public void deleteById(long id) {
springJdbcTemplate.update(DELETE_QUERY, id);
}
}
update(): INSERT, DELETE, UPDATE ๋ฑ ์ฟผ๋ฆฌ๋ฅผ ์คํํ ๋ ์ฌ์ฉํ๋ค. ์คํ๋ ํ(row)์ ๊ฐ์๋ฅผ ๋ฐํํ๋ค.
queryForObject()์ RowMapper
๋จ์ผ ๋ ์ฝ๋๋ฅผ ์กฐํํ ๋ ์ฃผ๋ก ์ฌ์ฉํ๋ ๋ฉ์๋์ด๋ค. ์๋ฅผ ๋ค์ด, ํน์ id๋ก Course ๊ฐ์ฒด๋ฅผ ์กฐํํ๋ค๊ณ ๊ฐ์ ํ์.
public Course findById(long id) {
String sql = "SELECT * FROM course WHERE id = ?";
return springJdbcTemplate.queryForObject(
sql,
new BeanPropertyRowMapper<>(Course.class),
id
);
}
queryForObject(): ์ฒซ ๋ฒ์งธ ์ธ์๋ก SQL ์ฟผ๋ฆฌ, ๋ ๋ฒ์งธ ์ธ์๋กRowMapper, ์ธ ๋ฒ์งธ ์ธ์๋ก ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๋๋ค.- BeanPropertyRowMapper: SQL ๊ฒฐ๊ณผ๋ฅผ Java ๊ฐ์ฒด์ ํ๋กํผํฐ์ ์๋ ๋งคํํด์ค๋ค. ํ๋ ์ด๋ฆ๊ณผ ์ปฌ๋ผ ์ด๋ฆ์ด ์ผ์นํ๋ฉด ์๋์ผ๋ก ํ ๋นํ๋ค.
RowMapper์ ์๋ ์๋ฆฌ
- SQL ์คํ ๊ฒฐ๊ณผ์ธ
ResultSet์ ๋ฐ๋๋ค. RowMapper๊ตฌํ์ฒด๊ฐResultSet์ ๊ฐ ์ปฌ๋ผ์ Java ๊ฐ์ฒด๋ก ๋งคํํ๋ค.- ๋งคํ๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
Spring JPA์ Hibernate
**JPA (Java Persistence API)**๋ ์๋ฐ ์ง์์์ ์ ์ํ ORM(Object-Relational Mapping) ํ์ค ์ธํฐํ์ด์ค์ด๋ค. Hibernate๋ ์ด JPA ํ์ค์ ๋ํ์ ์ธ ๊ตฌํ์ฒด์ด๋ค.
- JPA: ์ด๋ค ๊ธฐ๋ฅ(๋ฉ์๋, API)์ ๊ฐ์ ธ์ผ ํ๋์ง ๋ช ์ธํ ์ธํฐํ์ด์ค(ํ์ค).
- Hibernate: JPA ๊ท๊ฒฉ์ ๊ตฌํํ ์ค์ ๊ตฌํ์ฒด.
์๋ฅผ ๋ค์ด,@Entity,@Table,@Id๋ฑ ์ ๋ํ ์ด์ ๊ธฐ๋ฐ์ผ๋ก DB ํ ์ด๋ธ๊ณผ Java ๊ฐ์ฒด๋ฅผ ๋งคํํด์ค๋ค.
JPA ์ฌ์ฉ ์ ์ฅ์
- ์์ฐ์ฑ: ์ง์ SQL์ ์์ฑํ์ง ์์๋, ๋ฉ์๋ ์ด๋ฆ์ด๋ JPA ์ฟผ๋ฆฌ(
JPQL)๋ก ์ฝ๊ฒ CRUD๋ฅผ ๊ตฌํํ ์ ์๋ค. - ๊ฐ์ฒด ์งํฅ์ ๋ฐ์ดํฐ ์ ๊ทผ: ํด๋์ค์ ํ๋๋ง ์ ์ํด๋๋ฉด, JPA๊ฐ ํ ์ด๋ธ๊ณผ ์๋์ผ๋ก ๋งคํํด์ค๋ค.
- ํธ๋์ญ์ ๋ฐ ์บ์ฑ: ์์์ฑ ์ปจํ ์คํธ, 1์ฐจ ์บ์, ์ง์ฐ ๋ก๋ฉ ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ผ๋ก ๊ฐ๋ฐ ์์ฐ์ฑ๊ณผ ์ฑ๋ฅ์ ๋์ธ๋ค.
์ ์ง์ Hibernate๋ฅผ ์ฌ์ฉํ์ง ์๊ณ JPA ์ฝ๋๋ฅผ ์ฐ๋?
- ๊ตฌํ์ฒด ๊ต์ฒด ์ ์ฐ์ฑ: Hibernate ์ธ์๋ EclipseLink, OpenJPA ๋ฑ์ด ์๋ค. JPA ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ธ์ ๋ ๋ค๋ฅธ ๊ตฌํ์ฒด๋ก ๊ฐ์ํ ์ ์๋ค.
- ํ์คํ: JPA๋ ์๋ฐ ์ง์์์ ํ์ค์ผ๋ก ์ธ์ ๋ฐ์ ์คํ์ด๋ฏ๋ก, ์ผ๊ด๋ ์ฝ๋๋ฅผ ์ ์งํ ์ ์๋ค.
JDBC vs Spring JDBC vs Spring JPA ๋น๊ต
1) JDBC
- ์ง์ SQL ์์ฑ: ์์ ๋๊ฐ ๋งค์ฐ ๋์ง๋ง, ๋ฐ๋ณต ์ฝ๋๊ฐ ๋ง๋ค.
- ์์ธ ์ฒ๋ฆฌ์ ์์ ๊ด๋ฆฌ: ๊ฐ๋ฐ์๊ฐ ์ธ์ธํ๊ฒ ์ ์ดํด์ผ ํจ.
- ํ์ต ๊ณก์ : ์ฝ์ง๋ง, ๋๊ท๋ชจ ํ๋ก์ ํธ์์๋ ์ ์ง๋ณด์์ฑ์ด ๋จ์ด์ง ์ ์๋ค.
2) Spring JDBC
JdbcTemplate: ๋ฐ๋ณต์ ์ธ DB ์ ๊ทผ ๋ก์ง์ ์ถ์ํํด ์ฝ๋ ๊ฐ๊ฒฐํ.- ์์ธ ๋ณํ: SQL ์์ธ๋ฅผ Spring ์์ธ๋ก ๋ณํํด ์ผ๊ด๋ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅ.
- ์ ์ ํ ์ถ์ํ ์์ค: SQL ์ค์ฌ ๊ฐ๋ฐ์ ์ง์ํ๋ฉด์๋ ๋ฐ๋ณต ์ฝ๋๋ฅผ ์ค์ฌ์ค.
3) Spring JPA (Hibernate)
- ORM ๊ธฐ๋ฐ: ๊ฐ์ฒด์ ํ ์ด๋ธ ๊ฐ ๋งคํ์ ์ง์ค. SQL ์์ฑ์ด ๋ํญ ์ค์ด๋ฆ.
- ์๋ ์ฟผ๋ฆฌ ์์ฑ: ๋ฉ์๋ ์ด๋ฆ์ ๊ธฐ๋ฐ์ผ๋ก ์๋์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑ(
findById,findByName๋ฑ). - ๋์ ์์ฐ์ฑ: ํ๋ก์ ํธ๊ฐ ์ปค์ง์๋ก ์ ์ง๋ณด์, ํ์ฅ์ฑ์ด ํ์.
| ํญ๋ชฉ | JDBC | Spring JDBC | Spring JPA (Hibernate) |
|---|---|---|---|
| ์ถ์ํ ์์ค | ๋ฎ์ | ์ค๊ฐ | ๋์ |
| ์ฝ๋ ๊ฐ๊ฒฐ์ฑ | ๋ฎ์ | ๋์ | ๋งค์ฐ ๋์ |
| ์์ธ ์ฒ๋ฆฌ | ์ง์ ์ฒ๋ฆฌ | Spring ์์ธ ๋ณํ ์ง์ | Spring ์์ธ ๋ณํ + ORM ์ง์ |
| ์ฟผ๋ฆฌ ์์ฑ | ์ง์ SQL ์์ฑ | ์ง์ SQL ์์ฑ | ๋ฉ์๋ ๊ธฐ๋ฐ ์๋ ์์ฑ + JPQL |
| ์ ์ฐ์ฑ | ๋งค์ฐ ๋์ | ๋์ | ์ค๊ฐ (ORM ๊ท์น์ ๋ฐ๋ฆ) |
| ํ์ต ๊ณก์ | ๋ฎ์ | ๋ฎ์ | ์ค๊ฐ~๋์ |
| ์ ์ง๋ณด์์ฑ | ๋ฎ์ | ์ค๊ฐ~๋์ | ๋์ |
๊ฒฐ๋ก ๐ฏ
ํ๋ก์ ํธ์ ๊ท๋ชจ๋ ์๊ตฌ์ฌํญ์ ๋ฐ๋ผ JDBC, Spring JDBC, Spring JPA๋ฅผ ์ ์ ํ ์ ํํด์ผ ํ๋ค.
- ๋จ์ํ ์ฟผ๋ฆฌ๋ ์ง์ ์ ์ด๊ฐ ํ์ํ ๊ฒฝ์ฐ: JDBC ๋๋ Spring JDBC๊ฐ ๋ ์ ํฉํ๋ค.
- ๋๊ท๋ชจ ์ํฐํ๋ผ์ด์ฆ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ ๊ฐ์ฒด ์งํฅ์ ๊ฐ๋ฐ์ ์ ํธํ๋ ๊ฒฝ์ฐ: Spring JPA(Hibernate)๋ฅผ ์ฌ์ฉํ๋ ํธ์ด ์์ฐ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ ์ธก๋ฉด์์ ์ ๋ฆฌํ๋ค.
๊ฐ๊ฐ์ ์ฅ๋จ์ ์ ์ ์ดํดํ๊ณ , ์ํฉ์ ๋ง์ถฐ ์ ์ ํ ํ์ฉํ๋ ๊ฒ์ด ์ค์ํ๋ค.