๐ŸŒผSpring JPA ์‹ฌํ™” โถ - H2 ์—”์ง„, DB ๋“œ๋ผ์ด๋ฒ„

ํ•˜๋ฆฌ๋น„ยท2025๋…„ 5์›” 14์ผ
0

๐ŸŒผ Spring

๋ชฉ๋ก ๋ณด๊ธฐ
10/11
post-thumbnail

๐Ÿ“˜ DB ์ƒ์„ฑํ•˜๊ธฐ

๐Ÿ’ก ์˜์กด์„ฑ ์˜ต์…˜ (build.gradle > dependencies)

  • implemenataionย ์˜ต์…˜
    • ์ง์ ‘์ ์ธ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉ
    • ํ”„๋กœ์ ํŠธ ์ปดํŒŒ์ผ ์‹œ ํ•„์š”ํ•˜์ง€๋งŒ, ์™ธ๋ถ€๋กœ ๊ณต๊ฐœ โŒ
  • runtimeOnlyย ์˜ต์…˜
    • ๋Ÿฐํƒ€์ž„ ์‹œ์ ์— ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • testImplementationย ์˜ต์…˜
    • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ ์ ์šฉํ•  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๐Ÿ“– H2

๐Ÿ’กJava ๊ธฐ๋ฐ˜์˜ RDBMS(Database Engine) ์ฆ‰, DB ์—”์ง„
SQL์„ ์‚ฌ์šฉํ•˜๊ณ , JDBC๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ

๐Ÿ“Œ DB ์‚ฌ์šฉ๋ฐฉ์‹ ( H2 )

1๏ธโƒฃ Server Mode

2๏ธโƒฃ In memory Mode

  • ์—”์ง„ ๋ณ„๋„ ์„ค์น˜ โŒ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด๋ถ€ ์—”์ง„ ์‚ฌ์šฉ
    ( build.gradle or application.properties ์„ค์ •)
  • ๋ฐ์ดํ„ฐ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด๋ถ€ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ!
    โž ์•ฑ ์ข…๋ฃŒ์‹œ DB ๋‚ ์•„๊ฐ

3๏ธโƒฃ Embedded Mode

  • ์—”์ง„ ๋ณ„๋„ ์„ค์น˜ โŒ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด๋ถ€ ์—”์ง„ ์‚ฌ์šฉ
    ( build.gradle or application.properties ์„ค์ •)
  • ๋ฐ์ดํ„ฐ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์™ธ๋ถ€์— ์ €์žฅ!
    โž ์•ฑ ์ข…๋ฃŒํ•ด๋„ DB ์•ˆ๋‚ ์•„๊ฐ

ModeH2 ๋‹ค์šด๋กœ๋“œ ์—ฌ๋ถ€์‹คํ–‰ ์ฃผ์ฒดDB ์ €์žฅ ์œ„์น˜์‚ฌ์šฉ ์šฉ๋„
โœ… Server ModeO์™ธ๋ถ€๋กœ์ปฌ
(ํŒŒ์ผ ์‹œ์Šคํ…œ)
๋ฐฐํฌ ์šฉ๋„
โœ… In-Memory ModeX์Šคํ”„๋ง๋ฉ”๋ชจ๋ฆฌํ…Œ์ŠคํŠธ ์šฉ๋„
โœ… Embedded ModeX์Šคํ”„๋ง๋กœ์ปฌ
(ํŒŒ์ผ ์‹œ์Šคํ…œ)
๊ฐœ๋ฐœ ์šฉ๋„

๐Ÿ“Œ ์‹ค์Šตํ•˜๊ธฐ - Embedded Mode

โถ ํŒŒ์ผ ์„ค์ •ํ•˜๊ธฐ

๐Ÿ’ก jbbc:h2:~/test : ~ ์€ ํ™ˆ๋””๋ ‰ํ† ๋ฆฌ, ํ™ˆ๋””๋ ‰ํ† ๋ฆฌ์˜ test์— ์ €์žฅ๋œ๋‹ค

โœ”๏ธ application.yml

spring:  
    datasource:    
        driver-class-name: org.h2.Driver
        โœ… url: jdbc:h2:mem:{DB ์ด๋ฆ„} ----> 2๏ธโƒฃ In-Memory Mode
        โœ… url: jdbc:h2:{DB๊ฐ€ ์ €์žฅ๋  ๊ฒฝ๋กœ} ----> 3๏ธโƒฃ Embedded Mode
        username: sa
        password:  

โœ”๏ธ application.properties

# application.properties
spring.datasource.driver-class-name=org.h2.Driver
โœ… spring.datasource.url=jdbc:h2:mem:{DB ์ด๋ฆ„} ----> 2๏ธโƒฃ In-Memory Mode
โœ… spring.datasource.url=jdbc:h2:{DB๊ฐ€ ์ €์žฅ๋  ๊ฒฝ๋กœ} ----> 3๏ธโƒฃ Embedded Mode
spring.datasource.username=sa
spring.datasource.password=

โท ์˜์กด์„ฑ ๋“ฑ๋กํ•˜๊ธฐ

โœ”๏ธ build.gradle

โธ ์ฝ˜์†” ๋„์šฐ๊ธฐ

โž Path ์ฐธ๊ณ ํ•ด์„œ ์ฝ˜์†” url ์ ‘์†

โž properties ์„ค์ •๊ณผ ๋˜‘๊ฐ™์ด ์ž‘์„ฑํ•˜๊ธฐ (url, username, password...)

๐Ÿ’ก In-Memory ๋ชจ๋“œ์—์„œ ์ฝ˜์†” ์กฐํšŒ๊ฐ€ ์•ˆ๋˜๋Š” ๊ฒฝ์šฐ
#url: 'jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE'



SQL

DDL

create table
alter table
drop table
TRUNCATE TABLE orders; -> ๋ฐ์ดํ„ฐ ์ดˆ๊ธฐํ™” ( ํ…Œ์ด๋ธ” ๋‚ด์šฉ ์ง€์šฐ๊ธฐ )
TRUNCATE TABLE products;
TRUNCATE TABLE users;

DML

๋ฐ์ดํ„ฐ ์ฐพ๊ธฐ
select where ๋“ฑ..
order by group by
join

๋ฐ์ดํ„ฐ ์กฐ์ž‘ํ•˜๊ธฐ
insert into
update
delete from

DCL

ํŠธ๋žœ์ ์…˜ ๊ด€๋ฆฌ


DB ๋“œ๋ผ์ด๋ฒ„

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ํ†ต์‹ ์„ ์ค‘๊ฐœํ•˜๋Š” ์—ญํ• 

๋™์ž‘ ๋ฐฉ์‹

  1. ์—ฐ๊ฒฐ ์ดˆ๊ธฐํ™” - ๋“œ๋ผ์ด๋ฒ„ ์—ฐ๊ฒฐ ์š”์ฒญ ์ˆ˜์‹ ํ›„ ์—ฐ๊ฒฐ ์™„๋ฃŒ
  2. SQL ์ „์†ก ๋ฐ ์‹คํ–‰ - SQL ์ฟผ๋ฆฌ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ณ  ์ฒ˜๋ฆฌ
  3. ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ - ๊ฒฐ๊ณผ ์ˆ˜์‹  ํ›„ ๋ณ€ํ™˜๋œ ๊ฒฐ๊ณผ ์ „๋‹ฌ
  4. ์—ฐ๊ฒฐ ์ข…๋ฃŒ - ๋‹ค์Œ ์„ธ์…˜์„ ์œ„ํ•ด ์‹œ์Šคํ…œ ์ดˆ๊ธฐํ™”

JDBC ์‹ค์Šต

Spring Boot๋Š” ๋‹ค์–‘ํ•œ JDBC ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์ง€์›ํ•œ๋‹ค

-spring-boot-starter-jdbc
: ์Šคํƒ€ํ„ฐ ํŒจํ‚ค์ง€, ์ฃผ์š” ์˜์กด์„ฑ, ์ž๋™๊ตฌ์„ฑ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋˜์–ด ์žˆ์Œ
: ์ฝ”๋“œ ๊ฐ„์†Œํ™”, ์ž๋™ ๊ตฌ์„ฑ, ์˜ˆ์™ธ์ฒ˜๋ฆฌ ( JDBC์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ -> Spring ์˜ˆ์™ธ์ฒด๊ณ„๋กœ ๋ณ€ํ™˜)

  • JDBC ๋“œ๋ผ์ด๋ฒ„
    : ์ž๋ฐ” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” API

JDBC Driver

try-with-resources๋ž€?

โœ… ์ž๋™์œผ๋กœ close()๋ฅผ ํ˜ธ์ถœํ•ด์ฃผ๋Š” try ๊ตฌ๋ฌธ์ด์•ผ. (์ž์› ํ•ด์ œ)

JDBC์—์„œ Connection, Statement, ResultSet ๊ฐ™์€ ๊ฐ์ฒด๋Š” ๋ฐ˜๋“œ์‹œ ๋‹ซ์•„์ค˜์•ผ ํ•ด.
๊ทธ๋Ÿฐ๋ฐ ์‹ค์ˆ˜๋กœ connection.close()๋ฅผ ์•ˆ ์“ฐ๊ฑฐ๋‚˜, return ์ „์— ๋น ์ง€๋ฉด ๋ฆฌ์†Œ์Šค ๋ˆ„์ˆ˜๊ฐ€ ๋‚˜์ง€.

๊ทธ๋ž˜์„œ Java7๋ถ€ํ„ฐ๋Š” AutoCloseable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด๋Š” try ๊ด„ํ˜ธ ์•ˆ์— ๋„ฃ์œผ๋ฉด ์ž๋™์œผ๋กœ close()ํ•ด์ค˜!

๊ตฌ๋ถ„try-catchtry-with-resources
๋ชฉ์ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์˜ˆ์™ธ ์ฒ˜๋ฆฌ + ๋ฆฌ์†Œ์Šค ์ž๋™ ๋ฐ˜ํ™˜
๋ฆฌ์†Œ์Šค close์ง์ ‘ ๋ช…์‹œํ•ด์•ผ ํ•จ (finally์—์„œ)์ž๋™ ํ˜ธ์ถœ (close() ํ˜ธ์ถœ๋จ)
์ฝ”๋“œ ๊ธธ์ด๋” ๊ธธ๊ณ  ๋ณต์žกํ•จ์งง๊ณ  ์•ˆ์ •์ ์ž„
์‚ฌ์šฉ ์กฐ๊ฑด์ œํ•œ ์—†์ŒAutoCloseable ๊ตฌํ˜„ ๊ฐ์ฒด ํ•„์š”

์˜ˆ์ œ ์ฝ”๋“œ

@SpringBootApplication
public class JdbcApplication {

	public static void main(String[] args) throws SQLException {
    	// ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ
		SpringApplication.run(JdbcApplication.class, args);

		// โ–ถ๏ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ
		String url = "jdbc:h2:mem:test"; 	// โœ…in-memory ๋ชจ๋“œ H2 DB
		String username = "sa";				// ์‚ฌ์šฉ์ž๋ช…

		// ๐Ÿ”น DriverManager.getConnection()
		// - JDBC ๋“œ๋ผ์ด๋ฒ„๋ฅผ ํ†ตํ•ด DB์™€ ์—ฐ๊ฒฐ
		try (Connection connection = DriverManager.getConnection(url, username, null)) { // โœ… ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์—ฐ๊ฒฐ ์ •๋ณด ๋„ฃ์–ด์ฃผ๊ธฐ

			try {
            	// โ–ถ๏ธ ํ…Œ์ด๋ธ” ์ƒ์„ฑ
				// ๐Ÿ”น connection.prepareStatement(String sql)
				// - SQL ๋ฌธ์„ ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผ๋œ ์ƒํƒœ๋กœ ์ค€๋น„ 
				String creatSql = "CREATE TABLE USERS (id SERIAL, username varchar(255))";
				try (PreparedStatement statement = connection.prepareStatement(creatSql)) {
					// ๐Ÿ”น statement.execute()
					// - ์ปดํŒŒ์ผ ๋œ SQL๋ฌธ์„ ์‹คํ–‰
					statement.execute();
				}

				// โ–ถ๏ธ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€
				String insertSql = "INSERT INTO USERS (username) VALUES ('teasun kim')";
				try (PreparedStatement statement = connection.prepareStatement(insertSql)) {
					statement.execute();  
				}
                
				// โ–ถ๏ธ ๋ฐ์ดํ„ฐ ์กฐํšŒ
				String selectSql = "SELECT * FROM USERS";
				try (PreparedStatement statement = connection.prepareStatement(selectSql)) {
					// ๐Ÿ”น statement.executeQuery()
					// - SELECT ๋ฌธ ์‹คํ–‰
					var rs = statement.executeQuery();

					// ๐Ÿ”น rs.next()
					while (rs.next()) {
						// ๐Ÿ”น rs.getInt("์ปฌ๋Ÿผ๋ช…")
						// ๐Ÿ”น rs.getString("์ปฌ๋Ÿผ๋ช…")
						System.out.printf("%d, %s", rs.getInt("id"), rs.getString("username"));
					}
				}
			} catch (SQLException e) {
				// ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋น„๊ตํ•ด ์˜ˆ์™ธ ์ƒํ™ฉ์„ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ
				if (e.getMessage().equals("ERROR: relation \"account\" already exists")) {
					System.out.println("USERS ํ…Œ์ด๋ธ”์ด ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.");
				} else {
					// ๊ทธ ์™ธ ์˜ˆ์™ธ๋Š” ๋Ÿฐํƒ€์ž„ ์˜ˆ์™ธ๋กœ ๊ฐ์‹ธ์„œ ๋˜์ง
					throw new RuntimeException();
				}
			}
		}
	}
}

0๊ฐœ์˜ ๋Œ“๊ธ€