๐Ÿ“„ ํ† ๋น„ ์Šคํ”„๋ง 3์žฅ ์ •๋ฆฌ

6 minute read

๐ŸŸข ์˜ˆ์™ธ ์ƒํ™ฉ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ

JDBC ์ˆ˜์ • ๊ธฐ๋Šฅ์˜ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ์ฝ”๋“œ

public void deleteAll() throws SQLException {
  Connection c = dataSource.getConnection();
  
  PreparedStatement ps = c.preparedStatement("delete from users");
  
  ps.close();
  c.close();
}

์œ„ ๋ฉ”์†Œ๋“œ๋Š” Connection๊ณผ PreparedStatement๋ผ๋Š” ๋‘ ๊ฐœ์˜ ๊ณต์œ  ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด close()๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋งŒ์•ฝ์— PreparedStatement๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋„์ค‘์— ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ์ด๋•Œ๋Š” ๋ฉ”์†Œ๋“œ ์‹คํ–‰์ด ์ œ๋Œ€๋กœ ๋๋งˆ์น˜์ง€ ๋ชปํ•œ์ฑ„ ๋ฉ”์†Œ๋“œ๋ฅผ ๋น ์ ธ๋‚˜๊ฐ€๊ฒŒ๋œ๋‹ค. ๋”ฐ๋ผ์„œ close() ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์•„์„œ ์ œ๋Œ€๋กœ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋ฐ˜ํ™˜๋˜์ง€ ์•Š๋Š”๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ์„œ๋ฒ„๋Š” ์ œํ•œ๋œ ๊ฐœ์ˆ˜์˜ DB ์ปค๋„ฅ์…˜์„ ๋งŒ๋“ค์–ด์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ’€๋กœ ๊ด€๋ฆฌํ•œ๋‹ค. DB ํ’€์€ ๋งค๋ฒˆ getConnection()์œผ๋กœ ๊ฐ€์ ธ๊ฐ„ ์ปค๋„ฅ์…˜์„ ๋ช…์‹œ์ ์œผ๋กœ close()ํ•ด์„œ ๋Œ๋ ค์ค˜์•ผ์ง€์ง€๋งŒ ๋‹ค์‹œ ํ’€์— ๋„ฃ์—ˆ๋‹ค๊ฐ€ ๋‹ค์Œ ์ปค๋„ฅ์…˜ ์š”์ฒญ์ด ์žˆ์„ ๋•Œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์•ž์„œ ์ด์•ผ๊ธฐํ•œ Connection๊ณผ PreparedStatement๊ฐ€ ์ œ๋Œ€๋กœ ๋ฐ˜ํ™˜๋˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์„ ์ƒ๊ฐํ•ด๋ณด์ž. ์ด๋Ÿฐ ์ƒํ™ฉ์ด ๊ณ„์† ์Œ€์ด๊ฒŒ ๋˜๋ฉด ์–ด๋А ์ˆœ๊ฐ„์— ์ปค๋„ฅ์…˜ ํ’€์— ์—ฌ์œ ๊ฐ€ ์—†์–ด์ง€๊ณ  ๋ฆฌ์†Œ์Šค๊ฐ€ ๋ชจ์ž๋ž€๋‹ค๋Š” ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜๊ฐ€ ์ผ์–ด๋‚˜๊ณ  ์„œ๋ฒ„๊ฐ€ ์ค‘์ง€๋  ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์œ„ ์ฝ”๋“œ๋Š” ํด๋ผ์ด์–ธํŠธ๋ฅผ ์œ„ํ•œ ์ง€์†์ ์ธ ์„œ๋ฒ„ ์šด์˜์— ์น˜๋ช…์ ์ธ ์•ฝ์ ์„ ๋‚ดํฌํ•˜๊ณ  ์žˆ๋‹ค.


๋ฆฌ์†Œ์Šค ๋ฐ˜ํ™˜๊ณผ close()์— ๋Œ€ํ•ด

connection์ด๋‚˜ PreparedStatement์—๋Š” close() ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ๋‹ค. ์ด๋•Œ close๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ์˜๋ฏธ๋กœ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. Connection ๊ณผ PreparedStatement๋Š” ๋ณดํ†ต ํ’€(pool)๋ฐฉ์‹์œผ๋กœ ์šด์˜๋œ๋‹ค. pool ๋ฐฉ์‹์ด๋ž€ ์ž์ฃผ์“ฐ๋Š” ๊ฐ์ฒด๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋†“๊ณ  ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๋นŒ๋ฆฌ๊ณ  ์‚ฌ์šฉํ•œ ๋‹ค์Œ ๋ฐ˜๋‚ฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋”ฐ๋ผ์„œ ํ’€ ์•ˆ์— ์ œํ•œ๋œ ์ˆ˜์˜ ๋ฆฌ์†Œ์Šค(Connection, Statement)๋ฅผ ๋งŒ๋“ค์–ด ๋‘๊ณ  ํ•„์š”ํ•  ๋•Œ ํ• ๋‹นํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•˜์—ฌ ๋‹ค์‹œ ํ’€์— ๋„ฃ๋Š” ๋ฐฉ์‹์œผ๋กœ ์šด์˜๋œ๋‹ค. ์ฆ‰ ์š”์ฒญ์ด ๋งค์šฐ ๋งŽ์€ ์„œ๋ฒ„ํ™˜๊ฒฝ์—์„œ๋Š” ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ๋ฆฌ์†Œ์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋Œ€์‹  ํ’€์— ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘” ๋ฆฌ์†Œ์Šค๋ฅผ ๋Œ๋ ค๊ฐ€๋ฉฐ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ํ›จ์”ฌ ์œ ๋ฆฌํ•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉํ•œ ๋ฆฌ์†Œ์Šค๋Š” ๋น ๋ฅด๊ฒŒ ๋ฐ˜ํ™˜ํ•ด์•ผํ•œ๋‹ค. ์ด ๋•Œ ๊ทธ๋ ‡์ง€ ๋ชปํ•˜๋ฉด ํ’€์— ์žˆ๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ๊ณ ๊ฐˆ๋˜๊ณ  ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์œ„์—์„œ ๋งํ•œ close()๋Š” ์‚ฌ์šฉํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋Œ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.


๊ทธ๋ž˜์„œ JDBC์ฝ”๋“œ์—์„œ๋Š” ์ด๋Ÿฐ ์˜ˆ์™ธ ์ƒํ™ฉ์—์„œ๋„ ๊ฐ€์ ธ์˜จ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก try/catch/finally ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•œ๋‹ค. ์•„๋ž˜๋Š” deleteAll()๋ฉ”์†Œ๋“œ๋ฅผ ๋ณ€ํ™˜ํ•œ ๊ฒƒ์ด๋‹ค.

public void deleteAll() throws SQLExceptions {
  Connection c = null;
  PrepareStatement ps = null;
  
  try {
    c = dataSource.getConnection();
    ps = c.preparedStatement("delete from users");
    ps.executeUpdate();
  } catch(SQLException e) {
    throw e;
  } finally {
    if (ps != null) {
      try {
        ps.close();
      } catch(SQLException e) {
      }
    }
    if (c != null) {
      try {
        c.close();
      } catch (SQLException e) {
      }
    }
  }
}

์ด์ œ ์˜ˆ์™ธ ์ƒํ™ฉ์—์„œ๋„ ์•ˆ์ „์•ˆ ์ฝ”๋“œ๊ฐ€ ๋˜์—ˆ๋‹ค. finally๋Š” try ๋ธ”๋ก์„ ์ˆ˜ํ–‰ํ•œ ํ›„์— ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋“  ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์—ˆ๋“  ์ƒ๊ด€์—†์ด ๋ฐ˜๋“œ์‹œ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ๋ฅผ ๋„ฃ์—ˆ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์ผ๋‹จ try ๋ธ”๋ก์œผ๋กœ ๋“ค์–ด์„ฐ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ connection์ด๋‚˜ PreparedStatement์˜ close() ํ˜ธ์ถœ์„ ํ†ตํ•ด ๊ฐ€์ ธ์˜จ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค. ์ด์ œ ๋”ฐ๋กœ ๊ณ ๋ คํ•ด์•ผํ•  ์ƒํ™ฉ์€ Connection๊ณผ PreparedStatement์ค‘ ์–ด๋–ค ๊ฒƒ์˜ close() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ• ์ง€๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋งŒ์•ฝ์— getConnection()์—์„œ DB ์ปค๋„ฅ์…˜์„ ๊ฐ€์ ธ์˜ค๋‹ค๊ฐ€ ์ผ์‹œ์ ์ธ DB ์„œ๋ฒ„ ๋ฌธ์ œ๋‚˜, ๋„คํŠธ์›Œํฌ ๋ฌธ์ œ ๋˜๋Š” ๊ทธ ๋ฐ–์˜ ์˜ˆ์™ธ์ƒํ™ฉ ๋•Œ๋ฌธ์— ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด ps๋Š” ๋ฌผ๋ก ์ด๊ณ  ๋ณ€์ˆ˜ c๋„ ์•„์ง null ์ƒํƒœ์ด๋‹ค. null ์ƒํƒœ์˜ ๋ณ€์ˆ˜์— close() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ ๋œ๋‹ค.

PreparedStatement๋ฅผ ์ƒ์„ฑํ•˜๋‹ค๊ฐ€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด ๊ทธ๋–„๋Š” c ๋ณ€์ˆ˜๊ฐ€ ์ปค๋„ฅ์…˜ ๊ฐ์ฒด๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” ์ƒํƒœ์ด๋‹ˆ c๋Š” close()ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•œ ๋ฐ˜๋ฉด ps๋Š” ์•„๋‹ˆ๋‹ค. ๋งŒ์•ฝ ps๋ฅผ ์‹คํ–‰ํ•˜๋‹ค๊ฐ€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ๋ผ๋ฉด, ps์™€ c ๋ชจ๋‘ close()๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์ค˜์•ผ ํ•œ๋‹ค. ์–ด๋А ์‹œ์ ์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€์— ๋”ฐ๋ผ์„œ close()๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— finally์—์„œ๋Š” ๋ฐ˜๋“œ์‹œ c์™€ ps๊ฐ€ null์ด ์•„๋‹Œ์ง€ ๋จผ์ € ํ™•์ธํ•œ ํ›„์— close() ๋ฉ”์†Œ์Šค๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

๋‹ค๋ฅธ ๋ฌธ์ œ๋กœ๋Š” ์ง€๊ธˆ close()๋„ SQLException์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ๋ผ๋Š” ์ ์ด๋‹ค. ๋”ฐ๋ผ์„œ try/catch ๋ฌธ์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค. ๋ฌผ๋ก  close()๊ฐ€ ์‹คํŒจํ–ˆ์„ ๋•Œ๋Š” ํŠน๋ณ„ํžˆ ํ•  ์กฐ์น˜๋Š” ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋น„์›Œ๋‘”๋‹ค. ์ด๋•Œ ์ด๋ฏธ deleteAll()์— SQLException์ด ๋˜์ ธ์ง„๋‹ค๊ณ  ์„ ์–ธ๋˜์–ด ์žˆ์œผ๋‹ˆ close()๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋˜์ง€ ์•Š์„๊นŒ ๋ผ๋Š” ์ƒ๊ฐ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. [ SQLException์— ๋˜์ ธ์ง„๋‹ค.๋Š” ์˜๋ฏธ๊ฐ€ ๋ฌด์—‡์ผ๊นŒ..? ]


SQLException์— ๋˜์ ธ์ง„๋‹ค.๋ฅผ ์•Œ์•„๋ณด์•˜๋‹ค.

์—ฌ๊ธฐ์„œ ๋˜์ง„๋‹ค๋Š” ๊ฒƒ์˜ ์•ฝ๊ฐ„ ๋ฉ”์†Œ๋“œ ์‚ฌ์ด์— ์กด์žฌํ•˜๋Š” ์ฑ…์ž„ ์ „๊ฐ€๋ผ๋Š” ์˜๋ฏธ๋ฅผ ์ง€๋‹ˆ๊ณ  ์žˆ๋Š”๊ฑฐ ๊ฐ™๋‹ค.(๋ฌผ๋ก  ๋‚ด ์ƒ๊ฐ์ด๋‹ค.)

throws: ์˜ˆ์™ธ๋ฅผ ์ „๊ฐ€์‹œํ‚ค๋Š” ๊ฒƒ

throw: ๊ฐ•์ œ๋กœ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ

์ฆ‰ throws๋Š” ์ „๊ฐ€, throw๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ํŒ๋‹จ์— ๋”ฐ๋ฅธ ์ฒ˜๋ฆฌ์ด๋‹ค.

์กฐ๊ธˆ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณด๋ฉด throws๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ณณ์—์„œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•ด์ค˜์•ผ ํ•œ๋‹ค.

throw๋Š” ์˜ˆ์™ธ๋ฅผ ๊ฐ•์ œ๋กœ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์ด๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ํŒ๋‹จ์— ๋”ฐ๋ผ ํ•ด๋‹น ๋ถ€๋ถ„์— ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์— throw๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.


๐ŸŸข ๋ณ€ํ•˜๋Š” ๊ฒƒ๊ณผ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ

์•ž์„œ try/catch/finally๋กœ ๊ณ ์นœ ์ฝ”๋“œ์˜ ๋ฌธ์ œ์ ์€ ๊ณ„์†ํ•ด์„œ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๋ฐ˜๋ณตํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ๋ฐ˜๋ณต๋œ ์ฝ”๋“œ๋ฅผ ๊ณ„์† ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋ฉด, ์‹ค์ˆ˜, ์œ ์ง€๋ณด์ˆ˜ ๋“ฑ ๋งค์šฐ ๋งŽ์€ ๊ฒƒ์ด ๋น ์งˆ ์œ„ํ—˜์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์กฐ์‹ฌํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์œ„์—์„œ ์ž‘์„ฑํ•œ try/catch/finally๋„ ๊ฐ™์€ ์ด์น˜๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

UserDao์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐœ์„ ํ•˜๋Š” ์ž‘์—…์„ ์‹œ์ž‘ํ•ด๋ณด์ž. ๊ฐ€์žฅ ๋จผ์ € ํ•  ์ผ์€ ๋ณ€ํ•˜๋Š” ์„ฑ๊ฒฉ์ด ๋‹ค๋ฅธ ๊ฒƒ์„ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ deleteAll()๋ฉ”์†Œ๋“œ์˜ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ์‚ดํŽด๋ณด์ž.

Connection c = null;
PreparedStatement ps = null;
// ---- ๋ณ€ํ•œ์ง€ ์•Š๋Š” ๋ถ€๋ถ„ ----
try {
  c = dataSource.getConnection();
// ---------------------- 
  ps = c.preparedStatement("delete from users"); // โ†’ ๋ณ€ํ•˜๋Š” ๋ถ€๋ถ„
// ---- ๋ณ€ํ•œ์ง€ ์•Š๋Š” ๋ถ€๋ถ„ ----
  ps.executeUpdate();
} catch (SQLException e) {
  throw e;
} finally {
  if (ps != null) { try {ps.close();} catch (SQLException e) {} }
  if (c != null) { try {c.close();} catch (SQLException e) {} }
 // ---------------------- 
}

1. ๋ฉ”์†Œ๋“œ ์ถ”์ถœ

๋จผ์ € ์ƒ๊ฐํ•ด ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๋ณ€ํ•˜๋Š” ๋ถ€๋ถ„์„ ๋ฉ”์†Œ๋“œ๋กœ ๋นผ๋Š” ๊ฒƒ์ด๋‹ค. ๋ณ€ํ•˜๋Š” ๋ถ€๋ถ„์„ ๋ฉ”์†Œ๋“œ๋กœ ์ถ”์ถœํ•˜๊ณ  ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„์—์„œ ํ˜ธ์ถœํ•˜๋„๋ก ๋งŒ๋“ค๋ฉด, ์–ด๋ ต๋‹ค๊ณ  ์ƒ๊ฐํ•œ ์ž‘์—…์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

public void deleteAll() throws SQLExceptions {
  //...
  try {
    c = dataSource.getConnection();
    
    ps = makeStatement(c);
    
    ps.executeUpdate(c);
  } catch (SQLException e) {
    //...
  }
 //... 
}

private PreparedStatement makeStatement(Connection c) throws SQLException {
  PreparedStatement ps;
  ps = c.prepareStatement("delete from users");
  return ps;
}

์ž์ฃผ ๋ฐ”๋€Œ๋Š” ๋ถ€๋ถ„์„ ๋ฉ”์†Œ๋“œ๋กœ ๋…๋ฆฝ์‹œ์ผฐ๋Š”๋ฐ ๋‹น์žฅ ๋ด์„œ๋Š” ๋ณ„ ์ด๋“์ด ์—†์–ด ๋ณด์ธ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ณดํ†ต ๋ฉ”์†Œ๋“œ ์ถ”์ถœ ๋ฆฌํŽ™ํ† ๋ง์„ ์ ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ถ„๋ฆฌ์‹œํ‚จ ๋ฉ”์†Œ๋“œ๋ฅผ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๋Š”๋ฐ, ์ด๊ฑด ๋ฐ˜๋Œ€๋กœ ๋ถ„๋ฆฌ์‹œํ‚ค๊ณ  ๋‚จ์€ ๋ฉ”์†Œ๋“œ๊ฐ€ ์žฌ์‚ฌ์šฉ์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์ด๊ณ  ๋ถ„๋ฆฌ๋œ ๋ฉ”์†Œ๋“œ๋Š” DAO ๋กœ์ง๋งˆ๋‹ค ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค์–ด์„œ ํ™•์žฅ๋ผ์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ญ”๊ฐ€ ๋ฐ˜๋Œ€๋กœ ๋๋‹ค.

2. ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์˜ ์ ์šฉ

ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์„ ์ด์šฉํ•ด์„œ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์€ ์ƒ์†์„ ํ†ตํ•ด ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค. ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„์€ ์Šˆํผํด๋ž˜์Šค์— ๋‘๊ณ  ๋ณ€ํ•˜๋Š” ๋ถ€๋ถ„์€ ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๋กœ ์ •์˜ํ•ด๋‘ฌ์„œ ์„œ๋ธŒํด๋ž˜์Šค์—์„œ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ์ƒˆ๋กญ๊ฒŒ ์ •์˜ํ•ด ์“ฐ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ถ”์ถœํ•ด์„œ ๋ณ„๋„์˜ ๋ฉ”์†Œ๋“œ๋กœ ๋…๋ฆฝ์‹œํ‚จ makeStatement()๋ฉ”์†Œ๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ”์ƒ ๋ฉ”์†Œ๋“œ ์„ ์–ธ์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค. ๋ฌผ๋ก  UserDao ํด๋ž˜์Šค๋„ ์ถ”์ƒ ํด๋ž˜์Šค๊ฐ€ ๋ผ์•ผ ํ•  ๊ฒƒ์ด๋‹ค.

abstract protected PreparedStatement makeStatement(Connection c) throws SQLException;

๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ์ƒ์†ํ•˜๋Š” ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ฑฐ๊ธฐ์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค. ๊ณ ์ •๋œ JDBC try/catch/finally ๋ธ”๋ก์„ ๊ฐ€์ง„ ์Šˆํผํด๋ž˜์Šค ๋ฉ”์†Œ๋“œ์™€ ํ•„์š”์— ๋”ฐ๋ผ์„œ ์ƒ์†์„ ํ†ตํ•ด ๊ตฌ์ฒด์ ์ธ PreparedStatement๋ฅผ ๋ฐ”๊ฟ”์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“œ๋Š” ์„œ๋ธŒํด๋ž˜์Šค๋กœ ๊น”๋”ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์Œ์€ UserDao๋ฅผ ์ƒ์†ํ•ด์„œ ๋งŒ๋“  ํด๋ž˜์Šค์ด๋‹ค.

public class UserDaoDeleteAll extends UserDao {
  protected PreparedStatement makeStatement(Connection c) throws SQLException {
    PreparedStatement ps = c.prepareStatement("delete from users");
    return ps;
  }
}

์ด๋ ‡๊ฒŒ UserDao ํด๋ž˜์Šค์—์„œ UserDaoDeleteAll์„ ํ™•์žฅํ•˜๋ฏ€๋กœ์จ UserDao ํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋งˆ๋‹ค ์ƒ์†์„ ํ†ตํ•ด ์ž์œ ๋กญ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์ž‡๊ณ , ํ™•์žฅ ๋•Œ๋ฌธ์— ๊ธฐ์กด์˜ ์ƒ์œ„ DAO ํด๋ž˜์Šค์— ๋ถˆํ•„์š”ํ•œ ๋ณ€ํ™”๋Š” ์ƒ๊ธฐ์ง€ ์•Š๋„๋ก ํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„์˜ ํ•ต์‹ฌ ์›๋ฆฌ์ธ ๊ฐœ๋ฐœ ํ์‡„ ์›์น™(OCP)์„ ์ง€ํ‚ค๋Š” ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜๋Š” ์žˆ๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ ํƒฌํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์œผ๋กœ์˜ ์ ‘๊ทผ์€ ์ œํ•œ์ด ๋งŽ๋‹ค. ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋Š” DAO ๋กœ์ง๋งˆ๋‹ค ์ƒ์†์„ ํ†ตํ•ด ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋Š” ์ €์ด๋‹ค. ๋งŒ์•ฝ ์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด UserDao์˜ JDBC ๋ฉ”์†Œ๋“œ๊ฐ€ 4๊ฐœ์ผ ๊ฒฝ์šฐ 4๊ฐœ์˜ ์„œ๋ธŒ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. (๋ญ์ง€โ€ฆ? ์ด๋Ÿด๊ฑฐ๋ฉด ๊ตณ์ด ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์žˆ๋‚˜?)

์ฆ‰ ์ด๋Ÿฌํ•œ ๊ณผ์ •์„ ํ†ตํ•ด ํ™•์žฅ์„ ๊พ€ํ•˜๋Š” ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์˜ ๋‹จ์ ์ด ๊ณ ์Šค๋ž€ํžˆ ๋“œ๋Ÿฌ๋‚œ๋‹ค.

3. ์ „๋žต ํŒจํ„ด์˜ ์ ์šฉ

๊ฐœ๋ฐฉ ํŒจ์‡„ ์›์น™์„ ์ž˜ ์ง€ํ‚ค๋Š” ๊ตฌ์กฐ์ด๋ฉด์„œ๋„ ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด๋ณด๋‹ค ์œ ์—ฐํ•˜๊ณ  ํ™•์žฅ์„ฑ์ด ๋›ฐ์–ด๋‚œ ๊ฒƒ์ด ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์•„์˜ˆ ๋‘˜๋กœ ๋ถ„๋ฆฌํ•˜๊ณ  ํด๋ž˜์Šค ๋ ˆ๋ฒจ์—์„œ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์˜์กดํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ์ „๋žต ํŒจํ„ด์ด๋‹ค.

์ „๋žต ํŒจํ„ด์€ OCP ๊ด€์ ์— ๋ณด๋ฉด ํ™•์žฅ์— ํ•ด๋‹นํ•˜๋Š” ๋ณ€ํ•˜๋Š” ๋ถ€๋ถ„์„ ๋ณ‘๋„์˜ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์–ด ์ถ”์ƒํ™”๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์œ„์ž„ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ์ด๋ ‡๋“ฏ deleteAll()์€ JDBC๋ฅผ ์ด์šฉํ•ด DB๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ์ž‘์—…์ด๋ผ๋Š” ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๋งฅ๋ฝ์„ ๊ฐ–๋Š”๋‹ค. deleteAll()์˜ ์ปจํ…์ŠคํŠธ๋ฅผ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • DB ์ปค๋„ฅ์…˜ ๊ฐ€์ ธ์˜ค๊ธฐ
  • PreparedStatement๋ฅผ ๋งŒ๋“ค์–ด์ค„ ์™ธ๋ถ€ ๊ธฐ๋Šฅ ํ˜ธ์ถœํ•˜๊ธฐ
  • ์ „๋‹ฌ๋ฐ›์€ PreparedStatement ์‹คํ–‰ํ•˜๊ธฐ
  • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ด๋ฅผ ๋‹ค์‹œ ๋ฉ”์†Œ๋“œ ๋ฐ–์œผ๋กœ ๋˜์ง€๊ธฐ
  • ๋ชจ๋“  ๊ฒฝ์šฐ์— ๋งŒ๋“ค์–ด์ง„ PreparedStatement์™€ connection์„ ์ ์ ˆํžˆ ๋‹ซ์•„์ฃผ๊ธฐ

์—ฌ๊ธฐ์„œ 2๋ฒˆ์งธ ์ž‘์—…์—์„œ ์‚ฌ์šฉํ•˜๋Š” PreparedStatement๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์™ธ๋ถ€ ๊ธฐ๋Šฅ์ด ๋ฐ”๋กœ ์ „๋žต ํŒจํ„ด์—์„œ ๋งํ•˜๋Š” ์ „๋žต์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ „๋žต ํŒจํ„ด ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ผ ์ด ๊ธฐ๋Šฅ์„ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋งŒ๋“ค์–ด๋‘๊ณ  ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด PreparedStatement๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ „๋žต์„ ํ˜ธ์ถœํ•  ๋•Œ๋Š” ์ด ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ๋งŒ๋“ค์–ด๋‘” DB ์ปค๋„ฅ์…˜์„ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ์ฆ‰ ์ปค๋„ฅ์…˜์ด ์—†์œผ๋ฉด PreparedStatement๋„ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค.

PreparedStatement๋ฅผ ๋งŒ๋“œ๋Š” ์ „๋žต์˜ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ปจํ…์ŠคํŠธ๊ฐ€ ๋งŒ๋“ค์–ด๋‘” Connection์„ ์ „๋‹ฌ๋ฐ›์•„์„œ PreparedStatement๋ฅผ ๋งŒ๋“ค๊ณ  ๋งŒ๋“ค์–ด์ง„ PreparedStatement ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋Œ๋ ค์ค€๋‹ค. ์ด ๋‚ด์šฉ์„ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ •์˜ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

package springbook.user.dao;

public interface StatementStrategy {
  PreparedStatement makePreparedStatement(Connection c) throws SQLException;
}

์œ„ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†ํ•ด์„œ ์‹ค์ œ ์ „๋žต, ์ฆ‰ ๋ฐ”๋€Œ๋Š” ๋ถ€๋ถ„์ธ PreparedStatement๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž. deleteAll() ๋ฉ”์†Œ๋“œ์˜ ๊ธฐ๋Šฅ์„ ์œ„ํ•ด ๋งŒ๋“  ์ „๋žต ํด๋ž˜์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

package springbook.user.dao;

public class DeleteAllStatement implements StatementStrategy {
  public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
    PreparedStatement ps = c.prepareStatement("delete from users");
    return ps;
  }
}

์ „๋žต ํŒจํ„ด์— ๋”ฐ๋ผ DeleteAllStatement๊ฐ€ deleteAll() ๋ฉ”์†Œ๋“œ์— ์ ์šฉํ•ด๋ณด์ž.

public void deleteAll() throws SQLException {
  
  try {
    c = dataSource.getConnection();
    
    statementStrategy strategy = new DeleteAllStatement();
    ps = strategy.makePreparedStatement(c);
    
    ps.executeUpdate();
  } catch (SQLException e) {
    
  }
}

์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ปจํ…์ŠคํŠธ ์•ˆ์—์„œ ์ด๋ฏธ ๊ตฌ์ฒด์ ์ธ ์ „๋žต ํด๋ž˜์Šค์ธ DeleteAllStatement๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ณ ์ •๋˜์–ด ์žˆ๋‹ค๋ฉด ๋ญ”๊ฐ€ ์ด์ƒํ•˜๋‹ค. ์ปจํ…์ŠคํŠธ๊ฐ€ StatementStrategy ์ธํ„ฐํŽ˜์ด์Šค๋ฟ ์•„๋‹ˆ๋ผ ํŠน์ • ๊ตฌํ˜„ ํด๋ž˜์Šค์ธ DeleteAllStatement๋ฅผ ์ง์ ‘ ์•Œ๊ณ  ์žˆ๋‹ค๋Š” ๊ฑด, ์ „๋žต ํŒจํ„ด์—๋„ OCP์—๋„ ์ž˜ ๋งž์ง€ ์•Š๋Š”๋‹ค.

4. DI ์ ์šฉ์„ ์œ„ํ•œ ํด๋ผ์ด์–ธํŠธ/์ปจํ…์ŠคํŠธ ๋ถ„๋ฆฌ