skip to content
Q

[Spring๐ŸŒฑ] JDBC,Spring JDBC,Spring JPA ๊ฐœ๋…๊ณผ ์‚ฌ์šฉ๋ฒ• ์ด์ •๋ฆฌ

/ 9 min read

Table of Contents

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์˜ ์ž‘๋™ ์›๋ฆฌ

  1. SQL ์‹คํ–‰ ๊ฒฐ๊ณผ์ธ ResultSet์„ ๋ฐ›๋Š”๋‹ค.
  2. RowMapper ๊ตฌํ˜„์ฒด๊ฐ€ ResultSet์˜ ๊ฐ ์ปฌ๋Ÿผ์„ Java ๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•œ๋‹ค.
  3. ๋งคํ•‘๋œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

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 ๋“ฑ).
  • ๋†’์€ ์ƒ์‚ฐ์„ฑ: ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ์œ ์ง€๋ณด์ˆ˜, ํ™•์žฅ์„ฑ์ด ํƒ์›”.
ํ•ญ๋ชฉJDBCSpring JDBCSpring JPA (Hibernate)
์ถ”์ƒํ™” ์ˆ˜์ค€๋‚ฎ์Œ์ค‘๊ฐ„๋†’์Œ
์ฝ”๋“œ ๊ฐ„๊ฒฐ์„ฑ๋‚ฎ์Œ๋†’์Œ๋งค์šฐ ๋†’์Œ
์˜ˆ์™ธ ์ฒ˜๋ฆฌ์ง์ ‘ ์ฒ˜๋ฆฌSpring ์˜ˆ์™ธ ๋ณ€ํ™˜ ์ง€์›Spring ์˜ˆ์™ธ ๋ณ€ํ™˜ + ORM ์ง€์›
์ฟผ๋ฆฌ ์ž‘์„ฑ์ง์ ‘ SQL ์ž‘์„ฑ์ง์ ‘ SQL ์ž‘์„ฑ๋ฉ”์„œ๋“œ ๊ธฐ๋ฐ˜ ์ž๋™ ์ƒ์„ฑ + JPQL
์œ ์—ฐ์„ฑ๋งค์šฐ ๋†’์Œ๋†’์Œ์ค‘๊ฐ„ (ORM ๊ทœ์น™์— ๋”ฐ๋ฆ„)
ํ•™์Šต ๊ณก์„ ๋‚ฎ์Œ๋‚ฎ์Œ์ค‘๊ฐ„~๋†’์Œ
์œ ์ง€๋ณด์ˆ˜์„ฑ๋‚ฎ์Œ์ค‘๊ฐ„~๋†’์Œ๋†’์Œ

๊ฒฐ๋ก  ๐ŸŽฏ

ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ๋‚˜ ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ JDBC, Spring JDBC, Spring JPA๋ฅผ ์ ์ ˆํžˆ ์„ ํƒํ•ด์•ผ ํ•œ๋‹ค.

  • ๋‹จ์ˆœํ•œ ์ฟผ๋ฆฌ๋‚˜ ์ง์ ‘ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ: JDBC ๋˜๋Š” Spring JDBC๊ฐ€ ๋” ์ ํ•ฉํ•˜๋‹ค.
  • ๋Œ€๊ทœ๋ชจ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋‚˜ ๊ฐ์ฒด ์ง€ํ–ฅ์  ๊ฐœ๋ฐœ์„ ์„ ํ˜ธํ•˜๋Š” ๊ฒฝ์šฐ: Spring JPA(Hibernate)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ์ƒ์‚ฐ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ ์ธก๋ฉด์—์„œ ์œ ๋ฆฌํ•˜๋‹ค.

๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ ์„ ์ž˜ ์ดํ•ดํ•˜๊ณ , ์ƒํ™ฉ์— ๋งž์ถฐ ์ ์ ˆํžˆ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.


์ฐธ๊ณ ์ž๋ฃŒ ๐Ÿ“š