** ๐Ÿ“Œ PART 2.1 DAO / DTO / Service ๊ตฌ์กฐ์˜ ์˜์กด์„ฑ ๊ด€๋ฆฌ + ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™” ์ „๋žต **


๐ŸŸข 1๋‹จ๊ณ„. DAO / DTO / Service๊ฐ€ ๋ญ”์ง€ ์•„์ฃผ ์‰ฝ๊ฒŒ ์„ค๋ช…

์ด๋ฆ„ ์—ญํ•  ๋น„์œ 
DAO (๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ฐ์ฒด) DB๋ž‘ ๋Œ€ํ™”ํ•˜๋Š” ์—ญํ•  โ€œ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์ „ํ™”๊ธฐโ€
DTO (๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๊ฐ์ฒด) ๋ฐ์ดํ„ฐ๋ฅผ ์˜ฎ๊ธฐ๋Š” ์ƒ์ž โ€œํƒ๋ฐฐ ์ƒ์žโ€
Service (๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ) ๋กœ์ง ํŒ๋‹จ, ์ฒ˜๋ฆฌ ํ๋ฆ„ ๋‹ด๋‹น โ€œ๋งค๋‹ˆ์ €โ€

โœ… ์˜ˆ์‹œ๋กœ ์‰ฝ๊ฒŒ ๋ณด๊ธฐ

[์‚ฌ์šฉ์ž] โ†’ ๊ธ€์“ฐ๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ
 โ†’ [Controller] โ†’ "๊ธ€ ์ €์žฅํ•ด์ค˜!"
 โ†’ [Service] โ†’ "๊ธ€์ด ์œ ํšจํ•œ์ง€ ๋จผ์ € ์ฒดํฌํ•˜์ž"
 โ†’ [DAO] โ†’ DB์— INSERT ์š”์ฒญ
 โ†’ [DTO] โ†’ ๊ธ€ ์ œ๋ชฉ/๋‚ด์šฉ์„ ํ•˜๋‚˜๋กœ ํฌ์žฅํ•ด์„œ ์ „๋‹ฌ

๐Ÿง  DAO ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ์ „๋žต

๐Ÿ’ฌ ๋ฌธ์ œ: DAO๋ฅผ ๊ณ„์† new ํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„

BoardDao dao = new BoardDao();  // ๐Ÿ’ฃ ์ด๊ฑธ ์š”์ฒญ๋งˆ๋‹ค ํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„

๐Ÿ’ก ํ•ด๊ฒฐ์ฑ…: ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด(Singleton Pattern)

โœจ ๋”ฑ ํ•œ ๊ฐœ๋งŒ ๋งŒ๋“ค๊ณ , ๋ชจ๋‘๊ฐ€ ๊ทธ๊ฑธ ์“ฐ๊ฒŒ ํ•˜๋Š” ํŒจํ„ด์ด์•ผ!


๐Ÿ”ง ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด ๊ตฌ์กฐ (์ค‘ํ•™์ƒ๋„ ์ดํ•ด ๊ฐ€๋Šฅ!)

public class BoardDao {
    // ๐Ÿ’ก ๋”ฑ ํ•œ ๊ฐœ๋งŒ ์ƒ์„ฑ๋˜๋Š” ๊ฐ์ฒด ์ €์žฅ์†Œ
    private static BoardDao instance = new BoardDao();

    // ๐Ÿ’ก ์™ธ๋ถ€์—์„œ new ๋ชปํ•˜๊ฒŒ ๋ง‰์Œ (์ƒ์„ฑ์ž private)
    private BoardDao() {}

    // ๐Ÿ’ก ์ด๊ฑธ๋กœ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
    public static BoardDao getInstance() {
        return instance;
    }
}

โœ… ์žฅ์  (๋ฉด์ ‘ ํฌ์ธํŠธ ํฌํ•จ)

ํ•ญ๋ชฉ ์„ค๋ช…
๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ ๊ฐ์ฒด๋ฅผ ๋”ฑ 1๊ฐœ๋งŒ ์ƒ์„ฑ
GC ํšจ์œจ ์ค‘๋ณต ๊ฐ์ฒด ์ƒ์„ฑ ์—†์Œ โ†’ GC ์ค„์–ด๋“ฆ
์„ฑ๋Šฅ ํ–ฅ์ƒ ๋งค๋ฒˆ new ํ•  ํ•„์š” ์—†์Œ
์˜์กด์„ฑ ๊ด€๋ฆฌ ์–ด๋””์„œ๋“  ๋™์ผํ•œ ๊ฐ์ฒด ์‚ฌ์šฉ ๊ฐ€๋Šฅ

๐Ÿง  ๋ฉด์ ‘ ์˜ˆ์ƒ ์งˆ๋ฌธ

์™œ DAO๋Š” ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋งŒ๋“ค๊นŒ์š”?

โ†’ ์ž์ฃผ ์“ฐ๋Š” ๊ฐ์ฒด๋ผ ๊ณ„์† ์ƒ์„ฑํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„ + ์„ฑ๋Šฅ ์ €ํ•˜๊ฐ€ ๋ฐœ์ƒํ•ด์„œ!


๐Ÿง  DB ์ปค๋„ฅ์…˜ ํ’€(Connection Pool, CP)์˜ ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™” ์›๋ฆฌ

๐Ÿ’ฌ ๋จผ์ € ๊ฐœ๋…๋ถ€ํ„ฐ ์‰ฝ๊ฒŒ ์„ค๋ช…

๊ทธ๋ž˜์„œ ์ปค๋„ฅ์…˜์„ ๋ฏธ๋ฆฌ ์—ฌ๋Ÿฌ ๊ฐœ ๋งŒ๋“ค์–ด ๋†“๊ณ 

์š”์ฒญ ์˜ฌ ๋•Œ๋งˆ๋‹ค ๊บผ๋‚ด ์“ฐ๊ณ  ๋‹ค์‹œ ๋Œ๋ ค์ฃผ๋Š” ํ’€(pool)์„ ๋งŒ๋“ค์–ด ๋†“์€ ๊ฒƒ!


๐ŸŽฏ ์ปค๋„ฅ์…˜ ํ’€ ๋น„์œ 

๋ฐฉ์‹ ์„ค๋ช… ๋น„์œ 
๋งค๋ฒˆ new ์š”์ฒญ๋งˆ๋‹ค DB ์ ‘์† ์ƒˆ๋กœ ์ƒ์„ฑ ๋งค๋ฒˆ ๊ณต๊ตฌ ์‚ฌ๋Š” ๊ณต์žฅ
์ปค๋„ฅ์…˜ ํ’€ DB ์ ‘์† ์—ฌ๋Ÿฌ ๊ฐœ ๋งŒ๋“ค์–ด๋‘๊ณ  ์žฌ์‚ฌ์šฉ ๊ณต๊ตฌ ๋Œ€์—ฌ์†Œ ๋งŒ๋“ค๊ธฐ! ํ•„์š”ํ•  ๋•Œ ๋นŒ๋ ค ์“ฐ๊ณ  ๋Œ๋ ค์คŒ

๐Ÿ’ป ์ปค๋„ฅ์…˜ ํ’€ ๋™์ž‘ ๊ตฌ์กฐ

[ํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘ ์‹œ]
โ†’ ์ปค๋„ฅ์…˜ 10๊ฐœ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘ 

[์‚ฌ์šฉ์ž ์š”์ฒญ ์‹œ]
โ†’ ํ•˜๋‚˜ ๊บผ๋‚ด์„œ DAO์—์„œ ์‚ฌ์šฉ โ†’ ๋๋‚˜๋ฉด ๋‹ค์‹œ ๋ฐ˜๋‚ฉ

[๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ ๐Ÿ‘]
โ†’ ๋ถˆํ•„์š”ํ•œ ์ปค๋„ฅ์…˜ ์ƒ์„ฑ/ํŒŒ๊ดด ์—†์ด ๊ณ ์ •๋œ ๋ฆฌ์†Œ์Šค๋กœ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

โœ… ์‹ค๋ฌด ์‚ฌ์šฉ ์˜ˆ์‹œ: DBCP / HikariCP / TomcatCP


โœ… ์ปค๋„ฅ์…˜ ํ’€ ๋„์ž…์˜ ๋ฉ”๋ชจ๋ฆฌ / GC ์žฅ์ 

ํ•ญ๋ชฉ ํšจ๊ณผ
์ปค๋„ฅ์…˜ ๊ฐ์ฒด ์žฌ์‚ฌ์šฉ ๋งค๋ฒˆ ์ƒ์„ฑํ•  ํ•„์š” ์—†์Œ โ†’ ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„โ†“
GC ๋ถ€๋‹ด ๊ฐ์†Œ ์ž์ฃผ ์ƒ์„ฑ/์‚ญ์ œ ๋˜๋Š” ๊ฐ์ฒด๊ฐ€ ์ค„์–ด๋“ฆ
์‘๋‹ต ์†๋„ ํ–ฅ์ƒ DB ์—ฐ๊ฒฐ ์‹œ๊ฐ„์ด ์ค„์–ด๋“ฆ

๐Ÿง  ๋ฉด์ ‘ ํฌ์ธํŠธ ์ •๋ฆฌ

์งˆ๋ฌธ ์š”์ 
DAO๋ฅผ ์™œ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋งŒ๋“ค๊นŒ์š”? ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ ์ค„์—ฌ์„œ ์„ฑ๋Šฅ, ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ
์ปค๋„ฅ์…˜ ํ’€์„ ์“ฐ๋ฉด ๋ญ๊ฐ€ ์ข‹์€๊ฐ€์š”? ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ, ์„ฑ๋Šฅ ํ–ฅ์ƒ, GC ๋ถ€๋‹ด ๊ฐ์†Œ
์ปค๋„ฅ์…˜ ํ’€์„ ์•ˆ ์“ฐ๋ฉด ์–ด๋–ค ์ผ์ด ์ƒ๊ธฐ๋‚˜์š”? ์ปค๋„ฅ์…˜ ๊ฐ์ฒด๊ฐ€ ๋งค๋ฒˆ ์ƒ์„ฑ โ†’ GC ๋ถ€๋‹ด + ์„œ๋ฒ„ ๋‹ค์šด ์œ„ํ—˜
DAO๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์•„์ง€๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”? ๊ณตํ†ต ๋กœ์ง ์ถ”์ƒํ™” (GenericDAO ๋˜๋Š” Repository ํŒจํ„ด ์ ์šฉ)

โœ… ๋งˆ๋ฌด๋ฆฌ ์š”์•ฝํ‘œ

์š”์†Œ ์„ค๊ณ„ ์ „๋žต ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™” ํฌ์ธํŠธ
DAO ์‹ฑ๊ธ€ํ†ค ์ค‘๋ณต ๊ฐ์ฒด ์ œ๊ฑฐ, ์žฌ์‚ฌ์šฉ
DTO ๊ฐ€๋ณ๊ฒŒ ์„ค๊ณ„, ๋ถˆ๋ณ€ ๊ฐ์ฒด ์‚ฌ์šฉ ํ•„์š” ์‹œ GC ๋Œ€์ƒ, ์ƒ์„ฑ ์ตœ์†Œํ™”
Service ์š”์ฒญ๋งˆ๋‹ค ์ƒ์„ฑ ๊ฐ€๋Šฅ (์ƒํƒœ ์—†์Œ) ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๋งŒ ์ˆ˜ํ–‰
Connection ํ’€๋กœ ๊ด€๋ฆฌ ๊ฐ์ฒด ์žฌ์‚ฌ์šฉ โ†’ ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ •

โœ… PART 2.2 JDBC ์ปค๋„ฅ์…˜ & ๋ฆฌ์†Œ์Šค ๋ˆ„์ˆ˜ ๋ฐฉ์ง€ ์ „๋žต

โ€œ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ž‘ ์—ฐ๊ฒฐํ•  ๋•Œ ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„ ์—†์ด, ๋ณด์•ˆ๋„ ์ž˜ ์ง€ํ‚ค๋Š” ๋ฐฉ๋ฒ•โ€


๐ŸŸข 1๋‹จ๊ณ„. JDBC ์—ฐ๊ฒฐ์ด ๋ญ์•ผ?

๐Ÿ’ฌ ์•„์ฃผ ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด:

Java์—์„œ DB๋ž‘ ๋Œ€ํ™”ํ•˜๋ ค๋ฉด ์ „ํ™”์„ ์„ ์—ฐ๊ฒฐํ•ด์•ผ ํ•ด.

์ด ์ „ํ™”์„ ์„ JDBC ์ปค๋„ฅ์…˜(Connection) ์ด๋ผ๊ณ  ๋ถˆ๋Ÿฌ.


๐Ÿ“ฆ JDBC ๊ธฐ๋ณธ ํ๋ฆ„ ์š”์•ฝ

Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;

try {
   conn = DriverManager.getConnection(...);   // ๐Ÿ“ž ์ „ํ™” ์—ฐ๊ฒฐ
   pstmt = conn.prepareStatement("SELECT * FROM member");  // ๐Ÿ’ฌ ๋งํ•˜๊ธฐ ์ค€๋น„
   rs = pstmt.executeQuery();                 // ๐Ÿ“ฅ ๊ฒฐ๊ณผ ๋ฐ›๊ธฐ
   while(rs.next()) { ... }                   // ๐Ÿ” ๊ฒฐ๊ณผ ๋ฐ˜๋ณต
} catch(Exception e) {
   e.printStackTrace();
} finally {
   rs.close(); pstmt.close(); conn.close();   // ๐Ÿงน ๋งˆ๋ฌด๋ฆฌ ์ •๋ฆฌ!
}

๐Ÿ”ฅ 2๋‹จ๊ณ„. ๋ฆฌ์†Œ์Šค ๋ˆ„์ˆ˜๊ฐ€ ๋ญ์•ผ?

๐Ÿ’ฃ ๋ฆฌ์†Œ์Šค ๋ˆ„์ˆ˜(Resource Leak)๋ž€

DB ์ปค๋„ฅ์…˜, Statement, ResultSet ๊ฐ™์€ ๊ฒƒ๋“ค์„

์“ฐ๊ณ  ๋‚˜์„œ ๋‹ซ์ง€ ์•Š์•„์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณ„์† ์žก์•„๋จน๋Š” ํ˜„์ƒ์ด์•ผ.


๐Ÿง  ์™œ ์œ„ํ—˜ํ• ๊นŒ?


โœ… 3๋‹จ๊ณ„. try-with-resources๋กœ ์ž๋™์œผ๋กœ ๋‹ซ๊ธฐ!

๐Ÿ’ฌ ์ด ๊ธฐ๋Šฅ์€ Java 7๋ถ€ํ„ฐ ์ถ”๊ฐ€๋œ โ€œ์ž๋™ ์ •๋ฆฌ ๊ธฐ๋Šฅโ€์ด์•ผ!

๐Ÿ’ก try๋ฌธ์—์„œ AutoCloseable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด๋Š”

try๊ฐ€ ๋๋‚˜๋ฉด ์ž๋™์œผ๋กœ close()๊ฐ€ ํ˜ธ์ถœ๋ผ!


โœ… ์˜ˆ์ œ ์ฝ”๋“œ (์˜›๋‚  ๋ฐฉ์‹ vs ์ตœ์‹  ๋ฐฉ์‹ ๋น„๊ต)

// ๐Ÿงน ์ตœ์‹  try-with-resources ๋ฐฉ์‹
try (
   Connection conn = DriverManager.getConnection(...);
   PreparedStatement pstmt = conn.prepareStatement("...");
   ResultSet rs = pstmt.executeQuery();
) {
   while(rs.next()) { ... }
} catch(Exception e) {
   e.printStackTrace();
}
// โœ… rs, pstmt, conn ๋ชจ๋‘ ์ž๋™์œผ๋กœ ๋‹ซํž˜!

โœ… ์žฅ์ 

ํ•ญ๋ชฉ ํšจ๊ณผ
์ฝ”๋“œ ๊น”๋” try ๋ธ”๋ก ํ•˜๋‚˜๋กœ close ์ฒ˜๋ฆฌ
์•ˆ์ „์„ฑ โ†‘ ์˜ˆ์™ธ ๋ฐœ์ƒํ•ด๋„ ์ž๋™์œผ๋กœ ์ •๋ฆฌ๋จ
๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ • GC ๋Œ€์ƒ์ด ๋จ โ†’ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€

๐Ÿง  ๋ฉด์ ‘ ํฌ์ธํŠธ

try-with-resources๋ฅผ ์•ˆ ์ผ์„ ๋•Œ ResultSet ์•ˆ ๋‹ซํžˆ๋ฉด GC๊ฐ€ ์ˆ˜๊ฑฐ ๋ชปํ•ด์š”

โ†’ GC๋Š” โ€œ์ ‘๊ทผ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒดโ€๋งŒ ์ •๋ฆฌํ•จ โ†’ ์—ฐ๊ฒฐ๋œ ๋ฆฌ์†Œ์Šค๋Š” ๋‚จ์Œ


๐Ÿง  4๋‹จ๊ณ„. Statement / ResultSet ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ ํƒ€์ด๋ฐ

๊ฐ์ฒด ํ•ด์ œ ์‹œ์  ์ฃผ์˜์ 
Connection ๋ฐ˜๋“œ์‹œ ์ œ์ผ ๋งˆ์ง€๋ง‰์— ๋‹ซ์•„์•ผ ํ•จ ์—ฐ๊ฒฐ ๋Š๊ธฐ
Statement / PreparedStatement ์ฟผ๋ฆฌ ๋๋‚˜๋ฉด ๋‹ซ๊ธฐ SQL ์‹คํ–‰ ๋„๊ตฌ
ResultSet next() ๋ฐ˜๋ณต๋ฌธ ๋๋‚˜๊ณ  ๋‹ซ๊ธฐ ๊ฒฐ๊ณผ ๋ฉ”๋ชจ๋ฆฌ ํด ์ˆ˜ ์žˆ์Œ!

GC ๊ด€์  ์š”์•ฝ


๐Ÿ” 5๋‹จ๊ณ„. PreparedStatement ์žฌ์‚ฌ์šฉ + ๋ณด์•ˆ + ๋ฉ”๋ชจ๋ฆฌ ์ „๋žต


๐Ÿ“Œ ๊ฐœ๋… ๋จผ์ € ์„ค๋ช…

String sql = "SELECT * FROM member WHERE id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "hong");
ResultSet rs = pstmt.executeQuery();

๐Ÿ”Ž ์™œ ์ข‹์„๊นŒ?

ํ•ญ๋ชฉ ์„ค๋ช…
๋ณด์•ˆ SQL Injection ๋ฐฉ์ง€ (์ž…๋ ฅ๊ฐ’์„ ๋ฌธ์ž๋กœ escape ์ฒ˜๋ฆฌ)
์†๋„ SQL์„ ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผ ํ•ด๋‘ฌ์„œ ์‹คํ–‰ ์†๋„โ†‘
๋ฉ”๋ชจ๋ฆฌ ๋ฐ˜๋ณต ์‹คํ–‰ ์‹œ PreparedStatement๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„ โ†“

โ˜ ๏ธ ๋‚˜์œ ์˜ˆ์‹œ: ๋ฌธ์ž์—ด๋กœ SQL ๋งŒ๋“ค๊ธฐ

String sql = "SELECT * FROM member WHERE id = '" + userInput + "'";
// ๐Ÿ‘ฟ SQL Injection ๊ณต๊ฒฉ์— ๋šซ๋ฆผ!

๐Ÿ’ก ๋ฉด์ ‘์—์„œ ๋‚˜์˜ฌ ์งˆ๋ฌธ ์ •๋ฆฌ

์งˆ๋ฌธ ํ•ต์‹ฌ ๋‹ต๋ณ€ ์š”์•ฝ
JDBC ์ž์›์„ ์–ธ์ œ ๋‹ซ์•„์•ผ ํ•˜๋‚˜์š”? ์‚ฌ์šฉ์ด ๋๋‚œ ์งํ›„, ์—ญ์ˆœ์œผ๋กœ close() ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค
try-with-resources์˜ ์žฅ์ ์€? ์ฝ”๋“œ ๊ฐ„๊ฒฐ + ์ž๋™ close + ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์•ˆ์ •์„ฑ
ResultSet์„ ์•ˆ ๋‹ซ์œผ๋ฉด ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋‚˜์š”? ๋ฉ”๋ชจ๋ฆฌ ๋ฆญ, ์ปค๋„ฅ์…˜ ๋ˆ„์ˆ˜, ์„ฑ๋Šฅ ์ €ํ•˜
PreparedStatement๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š”? SQL Injection ๋ฐฉ์ง€ + ์„ฑ๋Šฅ + ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ
Connection์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€? ์ปค๋„ฅ์…˜ ํ’€(Connection Pool) ์‚ฌ์šฉ (์˜ˆ: HikariCP)

โœ… ์š”์•ฝ ๋งˆ๋ฌด๋ฆฌ ํ‘œ

ํ•ญ๋ชฉ ์„ค๋ช… ๋ฉ”๋ชจ๋ฆฌ ์˜ํ–ฅ
try-with-resources ์ž๋™์œผ๋กœ close() ํ˜ธ์ถœ ๋ฆฌ์†Œ์Šค ๋ˆ„์ˆ˜ ๋ฐฉ์ง€
PreparedStatement ๋ฏธ๋ฆฌ SQL ์ปดํŒŒ์ผ + ? ๋ฐ”์ธ๋”ฉ ์„ฑ๋Šฅ โ†‘, ๋ณด์•ˆ โ†‘
close ์ˆœ์„œ ResultSet โ†’ Statement โ†’ Connection GC๊ฐ€ ๋ฐ”๋กœ ์ •๋ฆฌ ๊ฐ€๋Šฅํ•˜๊ฒŒ

โœ… PART 2.3 DTO ๊ฐ์ฒด์˜ ์„ค๊ณ„ ๊ด€์ 

โ€œDTO๋ฅผ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ๋น ๋ฅด๊ณ , ์•ˆ์ „ํ•˜๊ณ , ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๋„ ์—†์„๊นŒ?โ€


๐ŸŸข 1๋‹จ๊ณ„. DTO๊ฐ€ ๋ญ์•ผ?

๐Ÿ“ฆ ์ •์˜ (์‰ฝ๊ฒŒ)

DTO(Data Transfer Object)๋Š” ๋ง ๊ทธ๋Œ€๋กœ

๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฉ์–ด๋ฆฌ๋กœ ์˜ฎ๊ธฐ๊ธฐ ์œ„ํ•œ ์ƒ์ž ๊ฐ™์€ ์—ญํ• ์„ ํ•ด.

์˜ˆ์‹œ

public class Member {
    private String id;
    private String name;
    private int age;

    // getter, setter ๋“ฑ
}

โ†’ Member๋ผ๋Š” DTO๋ฅผ ๋งŒ๋“ค์–ด์„œ, ์ปจํŠธ๋กค๋Ÿฌ โ†” DB โ†” ๋ทฐ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด.


โœจ A. Serializable vs Jackson: ์™œ ์“ฐ๊ณ , ์„ฑ๋Šฅ์€ ์–ด๋–ค ์ฐจ์ด?


โœ… 1. Serializable ์ด๋ž€?

๐Ÿ’ฌ ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ ๊ทธ๋Œ€๋กœ ํŒŒ์ผ, ๋„คํŠธ์›Œํฌ, ์„ธ์…˜์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ธฐ๋Šฅ

๐Ÿ”ง ์‚ฌ์šฉ ์˜ˆ์‹œ:

public class MemberDTO implements Serializable {
    private String id;
    private String name;
}

๐Ÿ“ฆ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ:


โœ… ์ž‘๋™ ๋ฐฉ์‹ (์‰ฝ๊ฒŒ)

[์ž๋ฐ” ๊ฐ์ฒด] โ†’ (Serializable) โ†’ [0๊ณผ 1์˜ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜] โ†’ ์ €์žฅ/์ „์†ก

๐Ÿง  ๋‹จ์ 

ํ•ญ๋ชฉ ์„ค๋ช…
์†๋„ ๋А๋ฆผ Reflection ๊ธฐ๋ฐ˜ ์ง๋ ฌํ™”๋Š” ๋ฌด๊ฒ๊ณ  ๋น„ํšจ์œจ์ 
ํฌ๊ธฐ ํผ ํ•„์š” ์—†๋Š” ์ •๋ณด๊นŒ์ง€ ๊ฐ™์ด ์ €์žฅ๋จ
๋ณด์•ˆ ๋‚ฎ์Œ ๋ฏผ๊ฐํ•œ ํ•„๋“œ๊นŒ์ง€ ๊ทธ๋Œ€๋กœ ๋…ธ์ถœ ๊ฐ€๋Šฅ

โœ… 2. Jackson ์ด๋ž€?

๐Ÿ’ฌ Jackson์€ ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ JSON ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์•ผ.

์˜ˆ์‹œ:

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(member); // ๊ฐ์ฒด โ†’ JSON

โœ… Jackson ์žฅ์ 

ํ•ญ๋ชฉ ์„ค๋ช…
๋น ๋ฆ„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•๋œ ์ง๋ ฌํ™” ๋ฐฉ์‹์œผ๋กœ ์„ฑ๋Šฅ ์ข‹์Œ
๊ฐ€๋ฒผ์›€ JSON ํฌ๋งท์ด ์ž‘๊ณ  ๊ฐ€๋ณ๋‹ค
ํ™•์žฅ์„ฑ โ†‘ ์™ธ๋ถ€ API, ํ”„๋ก ํŠธ์—”๋“œ์™€ ์—ฐ๊ฒฐ ์‹œ ๋งค์šฐ ์œ ๋ฆฌ

โœ… ์„ฑ๋Šฅ ๋น„๊ต ์š”์•ฝ (๋ฉด์ ‘ ํ•ต์‹ฌ)

ํ•ญ๋ชฉ Serializable Jackson
์‚ฌ์šฉ ๋ชฉ์  ์„ธ์…˜ ์ €์žฅ, ๋„คํŠธ์›Œํฌ ์ „์†ก JSON ์‘๋‹ต, API ํ†ต์‹ 
์†๋„ ๋А๋ฆผ (๋‚ด์žฅ ๋ฐฉ์‹) ๋น ๋ฆ„ (์ตœ์ ํ™” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)
ํฌ๋งท ๋ฐ”์ด๋„ˆ๋ฆฌ (0,1) JSON (๋ฌธ์ž์—ด)
๊ฐ€๋…์„ฑ ์—†์Œ ์žˆ์Œ (์‚ฌ๋žŒ๋„ ์ฝ๊ธฐ ์‰ฌ์›€)
GC ์˜ํ–ฅ ๋ฌด๊ฑฐ์›€ ์ƒ๋Œ€์ ์œผ๋กœ ์ ์Œ

โœจ B. ๋ถˆ๋ณ€ ๊ฐ์ฒด(Immutable DTO): ์™œ ๋งŒ๋“ค๊ณ , ๋ฉ”๋ชจ๋ฆฌ์—” ์–ด๋–ค ์˜ํ–ฅ?


โœ… 1. ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ž€?

๐Ÿ’ฌ ํ•œ ๋ฒˆ ๋งŒ๋“ค์–ด์ง€๋ฉด ์ ˆ๋Œ€ ๊ฐ’์ด ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ๊ฐ์ฒด

์˜ˆ์‹œ: (Immutable DTO)

public class Member {
    private final String id;
    private final String name;

    public Member(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() { return id; }
    public String getName() { return name; }
}

๐Ÿง  ์™œ ์ข‹์„๊นŒ?

์žฅ์  ์„ค๋ช…
์•ˆ์ „์„ฑ โ†‘ ๊ฐ’์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†์–ด์„œ ๋™์‹œ ์ฒ˜๋ฆฌ(๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ)์— ๊ฐ•ํ•จ
์˜ค๋ฅ˜ โ†“ ์–ด๋””์„œ ๊ฐ’์ด ๋ฐ”๋€Œ๋Š”์ง€ ์ถ”์  ์•ˆ ํ•ด๋„ ๋จ
GC ์œ ๋ฆฌ ๋ณต์žกํ•œ ์ฐธ์กฐ ๊ด€๊ณ„๊ฐ€ ์—†์Œ โ†’ ๋นจ๋ฆฌ GC ๋Œ€์ƒ์ด ๋จ
์บ์‹ฑ ์ตœ์ ํ™” ๊ฐ™์€ ๋‚ด์šฉ์˜ ๊ฐ์ฒด๋Š” ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ โ†’ ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์„ ์ค„์ž„

๋ฐ˜๋Œ€ ์˜ˆ์‹œ (Mutable DTO)

member.setName("๋ณ€๊ฒฝ๋จ");  // ๐Ÿ”ฅ ๋‹ค๋ฅธ ๊ณณ์—์„œ ๊ฐ‘์ž๊ธฐ ๋ฐ”๋€Œ๋ฉด ์ถ”์  ์–ด๋ ค์›€

โœ… 2. ๋ฉ”๋ชจ๋ฆฌ(GC) ๊ด€์ ์—์„œ ์™œ ์œ ๋ฆฌํ•œ๊ฐ€?

ํ•ญ๋ชฉ ๋ถˆ๋ณ€ ๊ฐ์ฒด ๊ฐ€๋ณ€ ๊ฐ์ฒด
์ฐธ์กฐ ๋ณต์žก๋„ ๋‚ฎ์Œ ๋†’์Œ
GC ํšŒ์ˆ˜ ์†๋„ ๋น ๋ฆ„ ๋А๋ฆผ
๊ฐ์ฒด ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์–ด๋ ค์›€

โ†’ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ์ฐธ์กฐ ํŠธ๋ฆฌ(tree)๊ฐ€ ๋‹จ์ˆœํ•ด์„œ GC๊ฐ€ ๋นจ๋ฆฌ ์ˆ˜๊ฑฐํ•  ์ˆ˜ ์žˆ์–ด!


โœ… ๋ฉด์ ‘ ์งˆ๋ฌธ ์š”์•ฝ & ์ •๋‹ต ํฌ์ธํŠธ

์งˆ๋ฌธ ํ•ต์‹ฌ ๋‹ต๋ณ€
Serializable์„ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”? ์„ธ์…˜ ์ €์žฅ, ํŒŒ์ผ ์ „์†ก์ฒ˜๋Ÿผ ๊ฐ์ฒด ์ „์ฒด๋ฅผ ์ €์žฅํ•  ๋•Œ
Jackson์„ ์™œ ์“ฐ๋‚˜์š”? JSON ํ†ต์‹ ์šฉ ๊ฐ์ฒด ๋ณ€ํ™˜, ๋น ๋ฅด๊ณ  ๊ฐ€๋ฒผ์›€
๋ถˆ๋ณ€ ๊ฐ์ฒด์˜ ์žฅ์ ์€? ์•ˆ์ „์„ฑ โ†‘, ๋ฒ„๊ทธ โ†“, GC ๋Œ€์ƒ ๋น ๋ฆ„
DTO์— setter๊ฐ€ ์—†์œผ๋ฉด ์•ˆ ๋˜๋‚˜์š”? ๋Œ€๋ถ€๋ถ„ ํ•„์š” ์—†์Œ, ์ƒ์„ฑ์ž๋กœ ๊ฐ’ ์ฃผ์ž…์ด ์•ˆ์ „ํ•จ
DTO ๊ฐ์ฒด๊ฐ€ ๋งŽ์•„์ง€๋ฉด ์„ฑ๋Šฅ์— ์˜ํ–ฅ ์žˆ๋‚˜์š”? GC ๋Œ€์ƒ์ด ๋งŽ์•„์ง€๋ฏ€๋กœ ์„ค๊ณ„๋ฅผ ์ตœ์ ํ™”ํ•ด์•ผ ํ•จ

โœ… ๋งˆ๋ฌด๋ฆฌ ์š”์•ฝํ‘œ

ํ•ญ๋ชฉ ์„ค๋ช… ๋ฉ”๋ชจ๋ฆฌ ์ธก๋ฉด
Serializable ๊ฐ์ฒด๋ฅผ ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ ์ €์žฅ ๋ฌด๊ฑฐ์›€, ๋А๋ฆผ
Jackson ๊ฐ์ฒด โ†” JSON ๋ฌธ์ž์—ด ๊ฐ€๋ณ๊ณ  ๋น ๋ฆ„
Immutable DTO ๊ฐ’์ด ์ ˆ๋Œ€ ์•ˆ ๋ฐ”๋€œ ์•ˆ์ „์„ฑ โ†‘, GC ์œ ๋ฆฌ
Setter ์—†๋Š” DTO ๊ฐ’์ด ํ•œ ๋ฒˆ๋งŒ ๋“ค์–ด๊ฐ ๋ฒ„๊ทธ ์œ„ํ—˜ โ†“, ์žฌ์‚ฌ์šฉ โ†‘