JiwonDev

ํ† ๋น„์˜ ์Šคํ”„๋ง#1 ์˜ค๋ธŒ์ ํŠธ์™€ ์˜์กด๊ด€๊ณ„

by JiwonDev

# ์Šคํ”„๋ง์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

2004๋…„์— ๋“ฑ์žฅํ•œ ์ž๋ฐ” ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์•ฑ ๊ฐœ๋ฐœ์— ์‚ฌ์šฉ๋˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ. ์Šคํ”„๋ง์€ ๋‹จ์ˆœํžˆ ํ•œ ํšŒ์‚ฌ๊ฐ€ ๋ˆ์„ ๋ฒŒ๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ๋„๊ตฌ๊ฐ€ ์•„๋‹ˆ๋‹ค. ์˜ค๋ž˜์ „๋ถ€ํ„ฐ ์ž๋ฐ” ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์‹œ์Šคํ…œ์„ ๊ฐœ๋ฐœํ•ด์˜ค๊ณ  ์—ฐ๊ตฌํ•ด์˜จ ์ˆ˜ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์˜ ๊ฒฝํ—˜์ด ์ง‘์•ฝ๋œ ๊ฒฐ์ •์ฒด์ด๋‹ค. ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ์ฝ”๋“œ(POJO, Plain Old Java Object)๋ฅผ ์ถ”๊ตฌํ•œ ๋‹จ์ˆœํ•จ๊ณผ ๊ฒฐํ•ฉ๋„์™€ ์˜์กด์„ฑ์„ ๋‚ฎ์ถฐ ์„œ๋น„์Šค๋ฅผ ์ถ”์ƒํ™”ํ•˜๊ณ , ์ˆ˜๋งŽ์€ ๋„๊ตฌ๋“ค๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

 

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

  • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ ํ”„๋ ˆ์ž„์›Œํฌํ™”
    ์Šคํ”„๋ง์€ ์„ธ๊ฐ€์ง€ ํ•ต์‹ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ์„ ์ง€์›ํ•œ๋‹ค.
    1. IoC/DI๋ผ ๋ถˆ๋ฆฌ๋Š” ์˜ค๋ธŒ์ ํŠธ์˜ ์ƒ๋ช…์ฃผ๊ธฐ์™€ ์˜์กด๊ด€๊ณ„ ๋ชจ๋ธ
    2. ์„œ๋น„์Šค์˜ ์ถ”์ƒํ™”. ํŠน์ • ์„œ๋ฒ„, ๊ธฐ์ˆ ์— ์ข…์†๋˜์ง€ ์•Š๊ณ  ์ด์‹์„ฑ์ด ๋›ฐ์–ด๋‚œ ์•ฑ์„ ๋งŒ๋“ฌ.
    3. AOP. cross-cutting cocern์„ ๋ชจ๋“ˆ๋กœ ๋…๋ฆฝํ™”ํ•˜๋Š” ๊ธฐ์ˆ 

  • ๊ธฐ์ˆ  API
    ํ˜„์—…์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ๊ธฐ์ˆ ์— ๋Œ€ํ•ด API์™€ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค. https://spring.io/
 

Spring makes Java simple.

Level up your Java code and explore what Spring can do for you.

spring.io

 


# ์˜ค๋ธŒ์ ํŠธ์™€ ์˜์กด๊ด€๊ณ„

 

@ ๊ธฐ์กด์˜ ๋ฐฉ์‹

์Šคํ”„๋ง์€ ์ž๋ฐ”๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๊ธฐ์ˆ ์ด๋‹ค. ์ž๋ฐ”์™€ ์Šคํ”„๋ง ๋‘˜ ๋‹ค ๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ฒŒ ๊ฐ€์น˜๋ฅผ ๋‘๋Š” ๊ฒƒ์€ ๋ฐ”๋กœ '๊ฐ์ฒด'์ด๋‹ค. ์˜› ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ JDBC API๋ฅผ ์ด์šฉํ•œ DAO(Data Access Object, DB๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ๊ฐ์ฒด)๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

// User ๊ฐ์ฒด. ์ด์ œ UserDAO๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž
@Getter @Setter
public class User {
    String id;
    String name;
    String password;
}

 

์ด ๊ฐ์ฒด๋ฅผ DB ํ…Œ์ด๋ธ”๋กœ ๊ตฌ์„ฑํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์„ ๊ฒƒ์ด๋‹ค.

ํ•„๋“œ๋ช… ํƒ€์ž… ์„ค์ •
Id VARCHAR(10) PK ( Primary Key )
Name VARCHAR(20) NN ( Not Null )
Password VARCHAR(20) NN

 

์ด๋ฅผ MySQL๋“ฑ์„ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ CREATE TABLE ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

create table users{
    id varchar(10) primary key,
    name varchar(20) not null,
    password varchar(10) not null
}

์ž ์ด์ œ ์ด ๋‘๊ฐœ๋ฅผ JDBC API๋ฅผ ์ด์šฉํ•ด ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ DB์— ์ €์žฅํ•˜๋Š” UserDao ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

  • DB ์—ฐ๊ฒฐ์„ ์œ„ํ•œ JDBC Connection์„ ๊ฐ€์ ธ์˜จ๋‹ค
  • SQL์„ ๋‹ด์€ Statement ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • ๋งŒ๋“ค์–ด์ง„ Statement ๊ฐ์ฒด๋ฅผ ์‹คํ–‰ํ•œ๋‹ค
  • ์กฐํšŒ์˜ ๊ฒฝ์šฐ SQL ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ResultSet์— ๋ฐ›์•„ ๊ฐ์ฒด์— ์˜ฎ๊ฒจ์ค€๋‹ค.
  • ์ž‘์—…์ค‘์— ์ƒ์„ฑ๋œ ๋ฆฌ์†Œ์Šค๋Š” ์ž‘์—…์„ ๋งˆ์นœํ›„ ๋ฐ˜๋“œ์‹œ ๋ฐ˜ํ™˜ํ•ด์•ผํ•œ๋‹ค.
  • JDBC API๊ฐ€ ๋งŒ๋“ค์–ด๋‚ด๋Š” ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค. ๋‹จ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ ์‹œ์ ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.
public class UserDao {
// ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋Š” ์˜ˆ์ œ์—์„œ๋Š” ํ•˜์ง€์•Š์•˜๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ ์ฝ”๋“œ์—์„œ๋Š” ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค ์ฒ˜๋ฆฌํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.

    public void add(User user) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/myDB", "id", "password");

        String query = "insert into users(id, name, password) value(?,?,?)";
        PreparedStatement ps = conn.prepareStatement(query);
        ps.setString(1, user.getId()); // ๋ณ€์ˆ˜ ์ง€์ •
        ps.setString(2, user.getName());
        ps.setString(3, user.getPassword());

        ps.executeUpdate(); // ์ฟผ๋ฆฌ ์‹คํ–‰
        ps.close();
        conn.close();
    }
    
    
    public User get(String id) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/myDB", "id", "password");

        String query = "select * from users where id = ?";
        PreparedStatement ps = conn.prepareStatement(query);
        ps.setString(1, id);
        ResultSet rs = ps.executeQuery();

        User user = new User();
        rs.next(); // ์—ฌ๋Ÿฌ ๊ฐœ์ผ ๊ฒฝ์šฐ while(rs.next());
        user.setId(rs.getString("id"));
        user.setName(rs.getString("name"));
        user.setPassword(rs.getString("password"));

        rs.close();
        ps.close();
        conn.close();

        return user;
    }
}

์ œ๋ฒ• ๋ณต์žกํ•ด ๋ณด์ด๋Š” ์ฝ”๋“œ๊ฐ€ ๋งŒ๋“ค์–ด์กŒ๋‹ค. ์ด ์ฝ”๋“œ๊ฐ€ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

  • ์›น ์•ฑ์„ ์‹ค์ œ ์„œ๋ฒ„์— ๋„์›Œ DB ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ค๋ณธ๋‹ค => ํ…Œ์ŠคํŠธ์น˜๊ณ ๋Š” ๋น„์šฉ์ด ๋„ˆ๋ฌด ํฐ๋ฐ?
  • ์ž‘๋™ํ•  ๊ฒƒ์ด๋ผ ๋ฏฟ๊ณ  ๊ธฐ๋„ํ•œ๋‹ค. => ์ง„์‹ฌ์œผ๋กœ?
  • main ๋ฉ”์„œ๋“œ์— DAO๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ฝ˜์†”์ฐฝ์— ์ฐ์–ด๋ณธ๋‹ค.
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        UserDao dao = new UserDao();

        User user = new User();
        user.setPassword("pw");
        user.setName("name");
        user.setId("id");

        dao.add(user);

        // ์Œ! ์ž˜ ๋™์ž‘ํ•˜๋Š” ๊ตฌ๋งŒ!
        System.out.println("[insert ์„ฑ๊ณต] user = " + user.getId());
        
    }

์ด ๋ฐฉ๋ฒ•์—๋Š” ์ •๋ง, ์ •๋ง ๋งŽ์€ ๋ฌธ์ œ๋“ค์ด ์ˆจ์–ด์žˆ๋‹ค. ๋งŒ์•ฝ ์‹ค์ œ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ด๋Ÿฌํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค๋ฉด ๊ฐœ๋ฐœํŒ€์— ์„œ๋ฐ”๋กœ ์ซ“๊ฒจ๋‚˜์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค. ์ด๋ฅผ ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ์ฝ”๋“œ๋กœ ๊ฐœ์„ ํ•ด๋‚˜๊ฐ€๋ฉฐ, ์Šคํ”„๋ง์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ณด์ž.

  • ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๋กœ์ง์„ ์‹คํ–‰ํ•˜๊ณ , ๊ฐ์ฒด๋ฅผ ํšŒ์ˆ˜ํ•˜๋Š” ๋“ฑ ๋„ˆ๋ฌด ๋งŽ์€ ์ฑ…์ž„์„ ํ•œ ๊ฐ์ฒด๊ฐ€ ์ง€๋‹ˆ๊ณ  ์žˆ๋‹ค.
  • main ์Šค๋ ˆ๋“œ ํ•˜๋‚˜๋กœ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค.
  • ์ฝ”๋“œ๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ˆ˜์ •ํ•ด๋„ ์•ฑ ์ „์ฒด์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๋‹ค.
  • ๋กœ๊ทธ๋ฅผ ์ฝ˜์†”์— ์ฐ๊ณ  ์žˆ๋‹ค. ๋น„์šฉ์ด ํฌ๊ณ  Thread-Safetyํ•˜์ง€ ์•Š๋‹ค.
  • ์ผ๋ถ€๋ถ„๋งŒ ์ชผ๊ฐœ์„œ ๋‹จ์œ„๋กœ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์—†๋‹ค.

 


@ ๊ฐœ์„ 1. ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ(Separation of Concerns)

UserDao์—์„œ๋Š” [DB์ปค๋„ฅ์…˜์„ ๋งŒ๋“ค๊ณ , ํšŒ์ˆ˜ํ•˜๋Š” ์„ค์ •๋ถ€๋ถ„]๊ณผ ์ง์ ‘ [User ๊ฐ์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์‹คํ–‰๋ถ€๋ถ„]์ด ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ ธ์žˆ๋‹ค. ์ด ๋‘ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌ์‹œํ‚ค๊ณ  ๋ชจ๋“ˆํ™”ํ•˜์—ฌ ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ค„์—ฌ๋ณด์ž.

  • ๊ด€์‹ฌ์‚ฌ1. DB ์—ฐ๊ฒฐ์„ ํ•˜๊ธฐ ์œ„ํ•œ ์ปค๋„ฅ์…˜
  • ๊ด€์‹ฌ์‚ฌ2. ์‚ฌ์šฉ์ž ๋“ฑ๋ก์„ ์œ„ํ•œ SQL ๋ฌธ์žฅ (Statement ๊ฐ์ฒด)๋ฅผ ๋งŒ๋“ค๊ณ  ์‹คํ–‰ํ•˜๊ธฐ
  • ๊ด€์‹ฌ์‚ฌ3. ์ž‘์—…์ด ๋๋‚˜๊ณ  ๋‚œ ํ›„ DB ์ปค๋„ฅ์…˜ ์ž์›์˜ ํšŒ์ˆ˜ 

์ด๋ ‡๊ฒŒ ์œ„ ์•„๋ž˜๋กœ ๋ฐ˜๋ณต๋˜๋Š” ์„ค์ •๋ถ€๋ถ„์„ Cross-Cutting Corcern (๋˜๋Š” ๊ณตํ†ต๊ด€์‹ฌ์‚ฌํ•ญ)์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

    public Connection getConnection() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/myDB", "id", "password");
        return conn;
    }
    
    public User get(String id) throws SQLException, ClassNotFoundException {
        Connection c = getConnection();
        // ์ดํ•˜ ์ฝ”๋“œ ์ƒ๋žต
    }

 

์—ฌ๊ธฐ์„œ ํ•œ๊ฑธ์Œ ๋” ๋‚˜์•„๊ฐ€ ์‚ฌ์—…์ด ์ปค์ง€๋ฉด์„œ N์‚ฌ์™€ D์‚ฌ์˜ ์‚ฌ์šฉ์ž๊ด€๋ฆฌ๋ฅผ ๋™์‹œ์— ๋งก๊ฒŒ ๋˜์—ˆ๋‹ค๊ณ  ์ƒ์ƒํ•ด๋ณด์ž. ์ด์ œ UserDao๋Š” ๊ฐ ํšŒ์‚ฌ๋งˆ๋‹ค ๋‹ค๋ฅธ DB๋ฅผ ํ†ตํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค. ์–ด๋–ป๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์„๊นŒ?

์ถ”์ƒํ™”์™€ ์ƒ์†์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค!

public abstract class UserDao{ 
	...
    // ์ถ”์ƒํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.
   	public abstract Connection getConnection() throws ClassNotFoundException, SQLException;
}


public class DUserDao extends UserDao {
    @Override
    public Connection getConnection() throws ClassNotFoundException, SQLException {
        Class.forName("N์‚ฌ์˜ DB ์ปค๋„ฅ์…˜ ์ƒ์„ฑ");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/myDB", "id", "password");
        return conn;
    }
}


public class NUserDao extends UserDao {
    @Override
    public Connection getConnection() throws ClassNotFoundException, SQLException {
        Class.forName("D์‚ฌ์˜ DB ์ปค๋„ฅ์…˜ ์ƒ์„ฑ");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/myDB", "id", "password");
        return conn;
    }
}

 

์ฐธ๊ณ ๋กœ ์ด๋Ÿฐ ํ˜•ํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ, ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

UserDao์— ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์„ ์ ์šฉํ•ด์„œ getConnection()์˜ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š”๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”
  • ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด (Template method pattern)
      ๋ถ€๋ชจ์—์„œ ๊ธฐ๋ณธ์ ์ธ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๊ณ , ์„ธ๋ถ€์ ์ธ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”์ƒ๋ฉ”์„œ๋“œ๋กœ ๋‘ฌ ์ž์‹์ด ๊ตฌํ˜„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹
      ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋™์ž‘์„ ๋ถ€๋ชจ(ํ…œํ”Œ๋ฆฟ)๋ฅผ ํ†ตํ•ด ์ถ”์ƒํ™”(์ธํ„ฐํŽ˜์ด์Šค ํ™”) ์‹œํ‚ค๋Š” ๊ฒƒ.
    'ํ…œํ”Œ๋ฆฟ'์ด ์•„๋‹Œ 'ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ' ํŒจํ„ด์ธ ์ด์œ . ๋ฐ˜๋ณต or ๊ณตํ†ต๋œ ๋™์ž‘์„ ์ถ”์ƒํ™”์‹œํ‚ค์ž!


  • ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด (Factory method pattern)
     ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐฉ๋ฒ•(ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค์˜ ์—ญํ• )์„ ์„œ๋ธŒํด๋ž˜์Šค์— ์œ„์ž„ํ•˜์—ฌ ์บก์Šํ™” ํ•˜๋Š” ๊ฒƒ (์Šˆํผํด๋ž˜์Šค๋Š” ๊ด€์‹ฌ X)
      ์ฐธ๊ณ ๋กœ ์ž๋ฐ”์—์„œ๋Š” ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑ(new)ํ•˜๋Š” ๊ฐ์ฒด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ 'ํŒฉํ† ๋ฆฌ ๊ฐ์ฒด or ๋ฉ”์„œ๋“œ'๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. 
      ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ผ ์ด๋Ÿฐ ์ด๋ฆ„์ด ๋ถ™์€ ๊ฒƒ. [ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ == ํŒจํ„ด] ์•„๋‹˜!
    ์•„๋ž˜ ์˜ˆ์ œ๋ฅผ ๋ณด๋ฉด ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค. ConcreteCreator == IDCardFactory
// ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์˜ ์‚ฌ์šฉ์˜ˆ์ œ

// ๊ตฌ์ฒด์ ์ธ ์ƒ์„ฑ๋ฐฉ๋ฒ•์„ ์„œ๋ธŒํด๋ž˜์Šค์— ์บก์Šํ™”ํ•œ๋‹ค. (๋ถ€๋ชจ๋Š” ๊ด€์‹ฌX)
Factory factory = new IDCardFactory();

Product card1 = factory.create("ํ™๊ธธ๋™"); // factory ์ธํ„ฐํŽ˜์ด์Šค๋กœ Product์˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค.
Product card2 = factory.create("์ด์ˆœ์‹ "); // ๊ตฌ์ฒด์ ์ธ ์ƒ์„ฑ๋ฐฉ๋ฒ•์€ factory์˜ ์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ๋‹ด๋‹น.
Product card3 = factory.create("๊ฐ•๊ฐ์ฐฌ"); // Product card3 = new IDProduct("id")
card1.use();
card2.use();
card3.use();
abstract class Factory {
    public final Product create(String owner) {
        Product p = createProduct(owner); // ๊ฐ์ฒด์ƒ์„ฑ ๋ฐฉ๋ฒ•์€ ์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ๊ฒฐ์ •
        registerProduct(p);
        return p;
    }
    protected abstract Product createProduct(String owner);
    protected abstract void registerProduct(Product p);
}


class IDCardFactory extends Factory {
    @Override
    protected Product createProduct(String owner) { return new IDCard(owner); }
    // .. ์ดํ•˜ ๊ตฌํ˜„๋ถ€ ์ƒ๋žต
}


class AdminCardFactory extends Factory {
    @Override
    protected Product createProduct(String owner) { return new IDCard(owner); }
	// .. ์ดํ•˜ ๊ตฌํ˜„๋ถ€ ์ƒ๋žต
}

 


@๊ฐœ์„ 2 ๋ฌด์ง€๋Š” ์šฐ๋ฆฌ์˜ ๋ฌด๊ธฐ. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•œ ๋ถ„๋ฆฌ

๊ฐ์ฒด๊ฐ€ ์„œ๋กœ๋ฅผ ๋ชฐ๋ผ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ถ„๋ฆฌ์‹œ์ผœ ๋ฒ„๋ฆฌ์ž. ์ฆ‰ ํ•œ ๊ฐ์ฒด๋ฅผ ๋ณ€๊ฒฝํ–ˆ์„ ๋•Œ ๋ณ€๊ฒฝ์ด ํ™•์‚ฐํ•˜๋Š” ๊ฒƒ์„ ๋ง‰์ž.

๋‹ค๋งŒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๊ฒฐ๊ตญ ์–ธ์  ๊ฐ€๋Š” '๊ตฌํ˜„์ฒด'๋ฅผ ์—ฐ๊ฒฐํ•ด์•ผํ•œ๋‹ค. ์„ค์ •์ž‘์—…์€ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์—†๋‹ค. ์ˆ˜์ •์€ ๋ถˆ๊ฐ€ํ”ผํ•˜๋‹ค.

// ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๊ฒฐํ•ฉ๋„(์˜์กด๊ด€๊ณ„)๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค.
interface MemberRepository{...}
interface DiscountPolicy{...}

Class MemoryMemberRepository implement MemberRepository{...}
Class FixDiscountPolicy implement DiscountPolicy{...}
// ํ•˜์ง€๋งŒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค๊ณ  ํ•œ๋“ค, ๊ฒฐ๊ตญ ์–ธ์  ๊ฐ€๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ์ง์ ‘ ์—ฐ๊ฒฐํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
// ๊ตฌํ˜„์ฒด๊ฐ€ ๋ฐ”๋€๋‹ค๋ฉด? ๊ธฐ์กด์˜ ์ƒ์„ฑ & ์„ค์ • ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผํ•œ๋‹ค. ์ „ํ˜€ ์ƒ๊ด€์—†๋Š” ๊ฐ์ฒด๋ผ๊ณ  ํ•˜๋”๋ผ๋„
private final MemberRepository memberRepository = new MemoryMemberRepository();
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();

 


@๊ฐœ์„ 3. ๊ด€๊ณ„, ์„ค์ • ์ฑ…์ž„์˜ ๋ถ„๋ฆฌ

๊ทธ๋Ÿผ ์•„์˜ˆ [๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ, ์„ค์ •ํ•˜๋Š” ์˜์—ญ]๊ณผ [๋กœ์ง ์‹คํ–‰์˜์—ญ]์„ ๋ถ„๋ฆฌํ•  ์ˆ˜๋Š” ์—†์„๊นŒ?

-> ์˜์กด์„ฑ ์ฃผ์ž…(DI, Dependency Injection), ๊ตฌํ˜„์ฒด๋Š” ๋‹ˆ๊ฐ€ ์•Œ์•„์„œ ๋„ฃ์–ด๋ผ. ๋‚œ ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์˜์กดํ•ด์„œ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค.

public class OrderService {
    // ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด์—์„œ๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ์ƒ์„ฑ, ์„ค์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค.
    public final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;
    
    // ๋‹ˆ๊ฐ€ ์•Œ์•„์„œ ๊ฐ์ฒด ์ƒ์„ฑํ•ด์„œ ๋„ฃ์œผ๋ ด. ๋‚œ ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ๋ณด๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    public MemberServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
 }

์ปจํ…Œ์ด๋„ˆ์— ๊ด€๋ฆฌ๋˜๋Š” ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง์—์„œ๋Š” ์Šคํ”„๋ง ๋นˆ(Bean)์ด๋ผ ๋ถ€๋ฅธ๋‹ค.

// ๊ฐ์ฒด ์ƒ์„ฑ, ์ฆ‰ ์˜์กด์„ฑ ์ฃผ์ž…์„ ๋‹ด๋‹นํ•˜๋Š” '์„ค์ •'์„ ๋‹ด๋‹นํ•˜๋Š” ๊ฐ์ฒด
// ์ด๋ฅผ IoC ์ปจํ…Œ์ด๋„ˆ, DI ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ ๋„ ๋ถ€๋ฅธ๋‹ค.
public class AppConfig { 
    // Repository
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
 
    // DiscountPolicy
    public DiscountPolicy discountPolicy() {
        return new FixDiscountPolicy();
    }
    
    // OrderService
    public OrderService orderService() {
        return new OrderServiceImpl(
                  this.memberRepository(),
                  this.discountPolicy()
                );
    }
}

์ด๋Ÿฐ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ ๊ฒƒ์„ ์ „๋žตํŒจํ„ด์ด๋ผ๊ณ  ํ•œ๋‹ค.

  • ์ „๋žต ํŒจํ„ด(strategy pattern)
    ์ •์ฑ…(Policy) ํŒจํ„ด์ด๋ผ๊ณ ๋„ ํ•˜๋ฉฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜(๊ตฌํ˜„์ฒด)์„ ํ•„์š”์— ๋”ฐ๋ผ ์ „๋žต์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ํŒจํ„ด.
    ์ฆ‰ ์‹คํ–‰ํ๋ฆ„(Context)์—์„œ ์•„์˜ˆ ํŠน์ •๋ถ€๋ถ„์„ ํด๋ž˜์Šค(Startegy)๋กœ ๋ถ„๋ฆฌ์‹œ์ผœ ํ™•์žฅ์„ฑ๊ณผ ๋‹คํ˜•์„ฑ์„ ๊ตฌํ˜„ํ•œ ๊ฒƒ.
    ํด๋ผ์ด์–ธํŠธ(Context)๋Š” ์ธํ„ฐํŽ˜์ด์Šค(Startegy)์—๋งŒ ์˜์กดํ•˜๊ธฐ์— ๊ฐ€๋Šฅํ•œ ํŒจํ„ด
    public interface DiscountPolicy { // ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์˜์กดํ•˜๋„๋ก ํด๋ผ์ด์–ธํŠธ๋ฅผ ์„ค๊ณ„.
    	double calculateWithDisCountRate(Item item);
    }
    
    // ํ•„์š”ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ƒํ™ฉ์— ๋งž์ถฐ ์„ ํƒ 
    public class FirstCustomerDiscount implements DiscountPolicy{
    	@Override // ๋ฐฉ๋ฒ•1.
    	public double calculateWithDisCountRate(Item item) {
    		return item.getPrice() * 0.9;
    	}
    }
    
    public class LastCustomerDiscount implements DiscountPolicy{
    	@Override // ๋ฐฉ๋ฒ•2.
    	public double calculateWithDisCountRate(Item item) {
    		return item.getPrice() * 0.8;
    	}
    }
    
    public class UnFreshFruitDiscount implements DiscountPolicy{
    	@Override // ๋ฐฉ๋ฒ•3.
    	public double calculateWithDisCountRate(Item item) {
    		return item.getPrice() * 0.8;
    	}
    }

@๊ฐœ์„ 4. ์ œ์–ด์˜ ์—ญ์ „(IoC)

์ด๋Š” @๊ฐœ์„ 3๊ณผ ๋™์‹œ์— ์ง„ํ–‰๋˜์—ˆ๋‹ค. ๊ธฐ์กด์˜ ์ฝ”๋“œ์—์„œ๋Š” ์„ค์ •๋ถ€๋ถ„ (๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ, ์˜์กด์„ฑ ์ฃผ์ž…, ๋ฐ˜ํ™˜)๋ถ€ํ„ฐ ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋˜๊ณ  ์ข…๋ฃŒ๋˜๋Š” ๋ฉ”์ธ์Šค๋ ˆ๋“œ์˜ ํ๋ฆ„๊นŒ์ง€ ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์กฐ์ข…ํ•˜์˜€๋‹ค.

 

ํ•˜์ง€๋งŒ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ  ์˜์กด์„ฑ์„ ์ฃผ์ž…๋ฐ›๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์„œ, ์ด์ œ ๋” ์ด์ƒ ๊ฐ์ฒด๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ์‹คํ–‰๊ณผ์ •์— ์˜ํ–ฅ์„ ๋ผ์น˜์ง€ ์•Š๋Š”๋‹ค. ๋‹จ์ง€ '๊ฐ์ฒด'๊ฐ€ ๋งก์€ ์ฑ…์ž„์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ๋กœ์ง์„ ์‹คํ–‰ํ•  ๋ฟ์ด๋‹ค. ๊ฐ์ฒด๋Š” ์•ฑ ์‹คํ–‰์˜ ์ œ์–ด๊ถŒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋‹ค. ์ด๋ ‡๊ฒŒ ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„ ๊ตฌ์กฐ๊ฐ€ ๋’ค๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ์ œ์–ด์˜์—ญ์ „(IoC, Inverse of Control)์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

์‚ฌ์‹ค ์ œ์–ด์˜ ์—ญ์ „๊ฐœ๋…์€ ๊ณผ๊ฑฐ๋ถ€ํ„ฐ ํญ๋„“๊ฒŒ ์ ์šฉ๋˜์–ด ์žˆ์—ˆ๋‹ค. ์ž๋ฐ”์˜ ์„œ๋ธ”๋ฆฟ์„ ์ƒ๊ฐํ•ด๋ณด์ž. ์ผ๋ฐ˜์ ์œผ๋กœ ํ”„๋กœ๊ทธ๋žจ์€ main()๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์•ฑ์˜ ์ œ์–ด๊ถŒ์„ ๊ฐ€์ง„๋‹ค. ํ•˜์ง€๋งŒ ์„œ๋ธ”๋ฆฟ์„ ํ†ตํ•œ ๊ฐœ๋ฐœ์€, ๊ฐœ๋ฐœ์ž๋Š” ์„œ๋ธ”๋ฆฟ ๊ฐ์ฒด์˜ ์ฑ…์ž„์„ ์ •ํ•˜๊ณ  ๊ทธ ์ฑ…์ž„์— ๋งž๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๊ตฌํ˜„ํ•  ๋ฟ์ด๋‹ค. ์ด ๊ฐ์ฒด๊ฐ€ ์–ธ์ œ ์–ด๋””์„œ ์‚ฌ์šฉ๋ ์ง€ ํ”„๋กœ๊ทธ๋žจ์ด ์–ด๋–ป๊ฒŒ ์‹คํ–‰๋˜๋Š”์ง€๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์•Œ ์ˆ˜ ์—†๋‹ค. WAS๊ฐ€ ๋‹ด๋‹นํ•  ๋ฟ. ์ œ์–ด๊ถŒ์ด ์—ญ์ „๋˜์–ด์žˆ๋‹ค.

 

์Šคํ”„๋ง์—์„œ๋Š” ์ œ์–ด์˜ ์—ญ์ „์„ ์ด๋ ‡๊ฒŒ ์„ค์ • ์ปจํ…Œ์ด๋„ˆ(AppConfig ๊ฐ์ฒด)๊ฐ€ ์˜์กด์„ฑ ์ฃผ์ž…์„ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฒ”์šฉ์ ์ธ ๋‹จ์–ด์ธ [IoC ์ปจํ…Œ์ด๋„ˆ] ๋Œ€์‹ ์— ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ• ๋ ค๊ณ  ์˜์กด์„ฑ ์ฃผ์ž…(DI, Dependency Injection) [DI ์ปจํ…Œ์ด๋„ˆ]๋ผ๋Š” ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ๋‘๊ฐœ๋Š” ๊ฐ™์€ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

 


# ์˜ค๋ธŒ์ ํŠธ ํŒฉํ† ๋ฆฌ๋ฅผ ์ด์šฉํ•œ ์Šคํ”„๋ง IoC

@ Application Context์™€ ์„ค์ •์ •๋ณด

์ด์ œ ์Šคํ”„๋ง์—์„œ ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์ž. ์Šคํ”„๋ง์—์„œ๋Š” ์ง์ ‘ ๋งŒ๋“ค๊ณ  ๊ด€๊ณ„๋ฅผ ๋ถ€์—ฌ๋ฐ›๋Š” ๊ฐ์ฒด๋“ค์„ ์Šคํ”„๋ง ๋นˆ(Bean)์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ์˜›๋‚ ์— ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์ž๋ฐ”๋นˆ(EJB)์—์„œ ์‚ฌ์šฉํ•œ ๊ฐ์ฒด๋‹จ์œ„์˜ ์ปดํฌ๋„ŒํŠธ์™€ ๋น„์Šทํ•œ ์˜๋ฏธ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

 

์ฆ‰ ์Šคํ”„๋ง ๋นˆ์€ ์•ฑ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋ฉด์„œ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ(DI ์ปจํ…Œ์ด๋„ˆ)๊ฐ€ ๊ฐ์ฒด์ƒ์„ฑ, ์˜์กด๊ด€๊ณ„์„ค์ •, ์‚ฌ์šฉ๋“ฑ์„ ์ œ์–ดํ•ด์ฃผ๋Š” IoC๊ฐ€ ์ ์šฉ๋œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๊ฐ€๋ฅดํ‚ค๋Š” ๋ง์ด๋‹ค. ์Šคํ”„๋ง์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์ƒ์„ฑ, ๊ด€๊ณ„์„ค์ •์„ ๋‹ด๋‹นํ•˜๋Š” IoC ๊ฐ์ฒด๋ฅผ ๋นˆ ํŒฉํ† ๋ฆฌ(Bean Factory)๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. 

 

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

// ์ฐธ๊ณ ๋กœ ์„ค์ •๊ฐ์ฒด(AppConfig) ๋˜ํ•œ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” key-map ๊ตฌ์กฐ๋กœ ๋ฌธ์ž์—ด๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ๋“ฑ๋ก๋œ๋‹ค.
// UserDao ํƒ€์ž…์˜ "userDao"๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง„ ์Šคํ”„๋ง ๋นˆ์„ ์ฃผ์ž…๋ฐ›๋Š” ์ฝ”๋“œ.
UserDao dao = context.getBean("userDao", UserDao.class);

// Object.class ๋Š” ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ •๋ณด๋ฅผ ๋„˜๊ฒจ์ฃผ์–ด ํ•„์š”ํ•  ๋–„ ๊ฐ์ฒด ์ƒ์„ฑ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค.
// ์ด๋Ÿฌํ•œ ๊ธฐ์ˆ ์„ ์ž๊ธฐ์ž์‹ ์˜ ์„ค๊ณ„๋„(class)๋ฅผ ๋ณต์ œํ•ด์„œ ๋„˜๊ธฐ๋Š”, ๋ฆฌํ”Œ๋ ‰์…˜ ๊ธฐ์ˆ ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
// ๊ฐ์ฒด๋ฅผ ๋ฌธ์ž์—ด("userDao")๋กœ ๊ตฌ๋ถ„์ง€์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋„ ์ด๋Ÿฌํ•œ ๋ฆฌํ”Œ๋ ‰์…˜ ๊ธฐ์ˆ  ๋•๋ถ„์ด๋‹ค.

์ฐธ๊ณ ๋กœ BeanFactory์™€ App..Context๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค. ๊ตฌํ˜„์ฒด๊ฐ€ ์•„๋‹ˆ๋‹ค. ์ด๋Š” [์ปจํ…Œ์ด๋„ˆ] ์ž์ฒด๋„ ์œ ์—ฐํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“  ๊ฒƒ์ด๋‹ค.

 

App..Context์˜ ๊ตฌํ˜„์ฒด๋ฅผ ์–ด๋…ธํ…Œ์ด์…˜(AnnotationConfigApp...Context)๋กœ ์ •ํ–ˆ์œผ๋‹ˆ, ์šฐ๋ฆฐ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํ”„๋ง์—์„œ ์„ค์ •์ •๋ณด๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ ์„ค์ •์ •๋ณด๋ฅผ ๋‹ด๋Š” ๊ฐ์ฒด์— @Configuration ํƒœ๊ทธ๋ฅผ ๋‹ฌ๋ฉด๋œ๋‹ค. ์œ„์—์„œ ๋งํ–ˆ์ง€๋งŒ ์ด ๊ฐ์ฒด(AppConfig) ๋˜ํ•œ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  ๊ฐ์ฒด๋“ค์„ @Bean ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ƒ์„ฑํ•˜๋ฉด ๋œ๋‹ค. @Bean ํƒœ๊ทธ๋Š” ๋ฉ”์„œ๋“œ์—๋งŒ ์ ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•œ๋‹ค.

@Configuration
public class AppConfig {
    @Bean // ์ด๋ฆ„์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฐ˜ํ™˜ ๊ฐ์ฒด ์ด๋ฆ„์ธ "memberRepository"๋กœ ์ž๋™์„ค์ •๋œ๋‹ค.
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
 
    @Bean(name="myCustomBean") // ๋ฌผ๋ก  ์ด๋ ‡๊ฒŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
    public DiscountPolicy discountPolicy() {
        return new FixDiscountPolicy();
    }
    
    @Bean // ["orderService", OrderService.class] ๋ฅผ ๊ฐ€์ง„ ์Šคํ”„๋ง ๋นˆ์ด ์ƒ์„ฑ๋จ.
    public OrderService orderService() {
        return new OrderServiceImpl(
                this.memberRepository(),
                this.discountPolicy());
    }
}

 

์žฌ๋ฐŒ๋Š” ์ ์€ @Configuration ๊ฐ™์€ ํƒœ๊ทธ๊ฐ€ ์—†๋”๋ผ๋„ @Bean์œผ๋กœ ์Šคํ”„๋ง๋นˆ์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ๊ทธ๋Ÿผ ํ•ด๋‹น ํƒœ๊ทธ๋Š” ์™œ ์ ๋Š”๊ฑธ๊นŒ? ๊ทธ๋ƒฅ ํ—ท๊ฐˆ๋ฆฌ์ง€๋ง๋ผ๊ณ  ์ ๋Š”๊ฑธ๊นŒ? ๋‹น์—ฐํžˆ ์•„๋‹ˆ๋‹ค. @Configuration์€ ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ์„ค์ •๊ฐ์ฒด(AppConfig)์ž„์„ ์Šคํ”„๋ง์—๊ฒŒ ์•Œ๋ ค์„œ, ์‹ฑ๊ธ€ํ†ค์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค.

 

์‹ฑ๊ธ€ํ†ค์€ ๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ 1๋ฒˆ๋งŒ ์ƒ์„ฑ๋˜๋„๋ก ๋งŒ๋“ค์–ด์„œ ๋Œ๋ ค์“ฐ๋Š” ๊ฒƒ์„ ๋งํ•˜๋Š”๋ฐ, ์•„๋ž˜์˜ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ดํ•ด๊ฐ€ ์‰ฝ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด @Configuration ์—†์ด ์ƒ์„ฑํ•˜๊ฒŒ๋˜๋ฉด ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง๋นˆ์œผ๋กœ ์—ฌ๋Ÿฌ๋ฒˆ ์ค‘๋ณตํ•ด์„œ ๋“ฑ๋กํ•˜๊ฒŒ ๋œ๋‹ค.

public class AppConfig {
    @Bean
    public MemberService memberService() {
        // MemberService๊ฐ์ฒด๋Š” ๋นˆ์œผ๋กœ 1๋ฒˆ ์ƒ์„ฑ๋จ, Repository() ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์˜์กด์„ฑ ์—ฐ๊ฒฐ
        System.out.println("call AppConfig.memberService");
        return new MemberServiceImpl(memberRepository());
    }
    
    @Bean
    public OrderService orderService() {
        // OrderSerivce ๊ฐ์ฒด๋Š” ๋นˆ์œผ๋กœ 1๋ฒˆ ์ƒ์„ฑ๋จ. Repository()๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์˜์กด์„ฑ ์—ฐ๊ฒฐ
        System.out.println("call AppConfig.orderService");
        return new OrderServiceImpl(
                memberRepository(),
                discountPolicy());
    }
 
    @Bean
    public MemberRepository memberRepository() {
        // ?? ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœํ–ˆ๋Š”๋ฐ ๊ทธ๋Ÿผ ๋‚˜๋Š” ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋ช‡๊ฐœ๋ฅผ ์ค‘๋ณตํ•ด์„œ ๊ฐ€์ง€๊ณ ์žˆ๋Š”๊ฑฐ์•ผ?
        return new MemoryMemberRepository();
    }
}

์ด๊ฒŒ ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•œ๊ฑธ๊นŒ? @Configuration์„ ๋‹ฌ๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ๊ฐ์ฒด ์œ„์น˜์ถ”์ ์ด๋ผ๋„ ํ•ด์„œ ์ค‘๋ณต ์ƒ์„ฑํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ฑธ๊นŒ?

 


# ์Šคํ”„๋ง Application Context์˜ ๋™์ž‘๋ฐฉ์‹

์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์„ค์ •๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹๊ณผ (=Object Factory)ํ–ˆ๋˜ ๋ฐฉ์‹๊ณผ ์Šคํ”„๋ง์—์„œ์˜ App..Context์€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ์ง€ ์•Œ์•„๋ณด์ž.

  • ํด๋ผ์ด์–ธํŠธ๋Š” ๊ตฌ์ฒด์ ์ธ ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค(์ƒ์„ฑ, ์„ค์ •์ •๋ณด)๋ฅผ ์•Œ ์ˆ˜ ์—†๊ณ , ์•Œ ํ•„์š”๋„ ์—†๋‹ค.
  • App..Context๋Š” ์•ฑ ์ „์ฒด์— ์ข…ํ•ฉ์ ์ธ IoC ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•ด์ค€๋‹ค.
  • App..Context๋Š” ๋“ฑ๋ก๋œ ์„œ๋น„์Šค ๊ฐ์ฒด(์Šคํ”„๋ง๋นˆ)๋ฅผ ํŽธํ•˜๊ฒŒ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‹ค์–‘ํ•œ ๊ฒ€์ƒ‰ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค.

๊ธฐ์กด์— ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค์—ˆ๋˜ AppConfig(๋˜๋Š” UserDaoFactory)๋Š” ๋‹จ์ˆœํžˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•„์š”ํ•œ ๊ด€๊ณ„๋ฅผ ๋งบ์–ด์ฃผ๋Š” ์ œํ•œ์ ์ธ ์—ญํ• ์„ ํ•˜๋Š”๋ฐ ๋ฐ˜ํ•ด, ์Šคํ”„๋ง์˜ App...Context๋Š” ์ „์ฒด ์•ฑ ์ž์ฒด์— IoC๋ฅผ ์ ์šฉํ•˜์—ฌ ์„œ๋น„์Šค์— ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ์— ๋Œ€ํ•œ ์ƒ์„ฑ๊ณผ ๊ด€๊ณ„์„ค์ •์„ ๋‹ด๋‹นํ•œ๋‹ค. ๋˜ํ•œ DaoFactory์™€ ๋‹ฌ๋ฆฌ ์ž๋ฐ”์ฝ”๋“œ๋กœ ๊ด€๊ณ„๋ฅผ ์ง์ ‘ ๋งบ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ฝ”๋“œ์™€ ๋ถ„๋ฆฌ๋œ ์„ค์ •์ •๋ณด(@Bean)๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐœ๋ฐœ์ž ์ฝ”๋“œ์™€ ๋ณ„๋„๋กœ ์กด์žฌํ•˜๋Š” ์Šคํ”„๋ง์˜ ์˜ค๋ธŒ์ ํŠธ ํŒฉํ† ๋ฆฌ์— ๊ทธ ์ž‘์—…์„ ์œ„์ž„ํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ๋‹ค ์‚ฌ์šฉํ•œ๋‹ค.

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” @Bean ์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜๊ฐ’์„ ์Šคํ”„๋ง๋นˆ์œผ๋กœ ๋งŒ๋“ ๋‹ค.

๊ทธ๋ฆฌ๊ณ  @Bean ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ์•„๋†“์€ AppConfig ๊ฐ์ฒด์— @Configuration์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด๋“ค์˜ ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•˜๊ณ , ๊ฐ ๊ฐ์ฒด๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์œ ์ง€ํ•˜์—ฌ ์Šคํ”„๋ง ๋นˆ ์ค‘๋ณต ์ƒ์„ฑ์„ ๋ฐฉ์ง€ํ•ด์ค€๋‹ค. (์„ค์ •์„ ํ†ตํ•ด ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์ด ์‹ฑ๊ธ€ํ†ค)

repository() ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœํ•ด๋„, ํ•œ ๊ฐ์ฒด๋งŒ ์ฐธ์กฐํ•˜๋„๋ก ์‹ฑ๊ธ€ํ†ค์„ ์œ ์ง€ํ•œ๋‹ค.

 

@ ์Šคํ”„๋ง์—์„œ ์‹ฑ๊ธ€ํ†ค์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

์Šคํ”„๋ง์€ CGLIB๋ผ๋Š” ๋ฐ”์ดํŠธ์ฝ”๋“œ ์กฐ์ž‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹ฑ๊ธ€ํ†ค์„ ๊ตฌํ˜„ํ•œ๋‹ค. ์‹ค์ œ ์ปดํŒŒ์ผํ•œ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด AppConfig.class ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ๋˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ AppConfig@CGLIB ๋ผ๋Š” ์ƒ์†๋ฐ›์€ ํด๋ž˜์Šค๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค.

// CGLIB๋Š” ์ž๋ฐ”์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์กฐ์ž‘ํ•˜๊ธฐ์— ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์ด ์–ด๋ ต๊ณ  ๋ณต์žกํ•˜๋‹ค.
// ์ดํ•ด๋ฅผ ๋•๊ธฐ์œ„ํ•ด ์ž๋ฐ”์ฝ”๋“œ๋กœ ๋น„์œ ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋™์ž‘ํ•œ๋‹ค.

class AppConfig@CGLIB123 extends AppConfig{
    @Bean
    public MemberRepository memberRepository() {
            if (memoryMemberRepository๊ฐ€ ์ด๋ฏธ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋˜์–ด ์žˆ์œผ๋ฉด?) {
                return ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ฐพ์•„์„œ ๋ฐ˜ํ™˜;

            } else { //์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์—†์œผ๋ฉด
                ๊ธฐ์กด ๋กœ์ง์„ ํ˜ธ์ถœํ•ด์„œ MemoryMemberRepository๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก
                return ๋ฐ˜ํ™˜
            }
    }
    ... ์ƒ๋žต ...
}

 


# ์Šคํ”„๋ง IoC ์šฉ์–ด์ •๋ฆฌ

ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๋„๋ก ์Šคํ”„๋ง์—์„œ ์ œ๊ณตํ•˜๋Š” IoC ์ปจํ…Œ์ด๋„ˆ(DI ์ปจํ…Œ์ด๋„ˆ)์™€ ๊ด€๋ จ๋œ ์šฉ์–ด๋“ค์„ ์ •๋ฆฌํ•ด๋ณด์ž.

 

  • IoC์™€ DI
    - ์ œ์–ด์˜ ์—ญ์ „(Inverse of Control)์€ ์•ฑ์˜ ์‹คํ–‰ํ๋ฆ„(๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ, ์„ค์ •, ํšŒ์ˆ˜)์„ ์„œ๋น„์Šค ๊ฐ์ฒด(๊ฐœ๋ฐœ์ž)๊ฐ€ ์•„๋‹Œ ์™ธ๋ถ€(์Šคํ”„๋ง)์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์ด๊ธฐ๋„ ํ•˜๋‹ค.
    - ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)์€ IoC๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•œ๊ฐ€์ง€๋กœ, ์Šคํ”„๋ง IoC์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. IoC๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” DI ๋ง๊ณ ๋„ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋Š” ๊ฑฐ๋งŒ ์ธ์ง€ํ•˜๊ณ  ์žˆ์ž.

  • Bean (๋นˆ)
    - ๋นˆ ๋˜๋Š” ๋นˆ ๊ฐ์ฒด๋Š” ์Šคํ”„๋ง์ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ†ตํ•ด IoC๋ฐฉ์‹์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์ฃผ์˜ํ•  ์ ์€ ์Šคํ”„๋ง์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ๋นˆ์ธ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์Šคํ”„๋ง์ด ์ง์ ‘ ์ƒ์„ฑ๊ณผ ์ œ์–ด๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ๋งŒ ๋นˆ์ด๋ผ๊ณ  ํ•œ๋‹ค.

  • Bean Factory(๋นˆ ํŒฉํ† ๋ฆฌ)
    - ์•ž์—์„œ ๋งŒ๋“ค์—ˆ๋˜ AppConfig ๊ฐ์ฒด๋ฅผ Object-Container๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ์Šคํ”„๋ง์˜ IoC๋ฅผ ๋‹น๋‹นํ•˜๋Š” ํ•ต์‹ฌ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๋ณดํ†ต์€ ๋นˆ ํŒฉํ† ๋ฆฌ๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ด๋ฅผ ์ƒ์†ก๋ฐ›์€ App...Context ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

  • Application Context(์•ฑ ์ปจํ…์ŠคํŠธ)
    - ๋นˆ ํŒฉํ† ๋ฆฌ๋ฅผ ์ƒ์†๋ฐ›์•„ ํ™•์žฅํ•œ IoC ์ปจํ…Œ์ด๋„ˆ๋‹ค. ๋นˆ ํŒฉํ† ๋ฆฌ์—์„œ๋Š” ๊ฐ์ฒด์˜ ์ƒ์„ฑ๊ณผ ๊ด€๋ฆฌ๋งŒ์„ ๋‹ด๋‹นํ–ˆ์—ˆ๋‹ค๋ฉด, ์•ฑ ์ปจํ…์ŠคํŠธ๋Š” ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ๊ฐ์ข… ๋ถ€๊ฐ€๊ธฐ๋Šฅ๋“ค์„ ์ถ”๊ฐ€๋กœ ์ œ๊ณตํ•œ๋‹ค.

  • Configuration Metadata(์„ค์ •์ •๋ณด, ๋ฉ”ํƒ€์ •๋ณด)
    - ์•ฑ ์ปจํ…์ŠคํŠธ(๋นˆ ํŒฉํ† ๋ฆฌ)๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”ํƒ€์ •๋ณด๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์ •๋ง ์Šคํ”„๋ง์— ํ•„์š”ํ•œ ์„ค์ • ์ •๋ณด๋ฅผ ์ ๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์ง€๋งŒ, ๋ณดํ†ต์€ IoC ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ๊ด€๋ฆฌ๋  ๊ฐ์ฒด๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.
    - ์ฐธ๊ณ ๋กœ ์Šคํ”„๋ง์€ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ์„ค์ •์ •๋ณด๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜›๋‚ ์—๋Š” xml๋ฐฉ์‹์œผ๋กœ ๋งŽ์ด ์ž‘์„ฑํ–ˆ์—ˆ๋Š”๋ฐ, ์š”์ฆ˜์€ ์„ค์ •ํŒŒ์ผ์„ ๋ถ„๋ฆฌํ•˜์ง€ ์•Š๊ณ  ์ž๋ฐ”์ฝ”๋“œ์— ๋ฐ”๋กœ ์ ์„ ์ˆ˜ ์žˆ๋Š” ์–ด๋…ธํ…Œ์ด์…˜๋ฐฉ์‹(@Configuration)๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

  • Container (DI ์ปจํ…Œ์ด๋„ˆ)
    - IoC ๋ฐฉ์‹์œผ๋กœ ๋นˆ ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค๋Š” ์˜๋ฏธ์—์„œ ์œ„์˜ [์•ฑ ์ปจํ…์ŠคํŠธ, ๋นˆ ํŒฉํ† ๋ฆฌ]๋ฅผ IoC ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋„ ํ•œ๋‹ค. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ ๋ณด๋‹ค IoC ์ปจํ…Œ์ด๋„ˆ๋ผ ๋ถ€๋ฅด๋Š”๊ฒŒ ๋” ์˜๋ฏธ๊ฐ€ ์ •ํ™•ํ•˜๊ฒŒ ์ „๋‹ฌ๋˜๋Š” ํšจ๊ณผ๋„ ์žˆ๋‹ค.
    - ๋‹ค๋งŒ IoC๋ผ๋Š” ์šฉ์–ด๋Š” ๋ฒ”์šฉ์ ์ธ ๋‹จ์–ด์ด๊ธฐ์—, ์Šคํ”„๋ง์—์„œ๋Š” IoC๋ฅผ DI๋กœ ๊ตฌํ˜„ํ•œ๋‹ค๋Š” ์˜๋ฏธ์—์„œ DI ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ ๋„ ๋ถ€๋ฅธ๋‹ค. ์ด ๋‘˜์€ ๊ฐ™์€ ๋‹จ์–ด์ด๋‹ค. ์ •ํ™•ํžˆ๋Š” Dependency Injection์„ ํ†ตํ•ด IoC๋ฅผ ๊ตฌํ˜„ํ•œ ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค.

  • Spring Core (์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ)
    ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๋Š” IoC ์ปจํ…Œ์ด๋„ˆ(์•ฑ ์ปจํ…์ŠคํŠธ)๋ฅผ ํฌํ•จํ•ด์„œ ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ํ†ตํ‹€์–ด ๋งํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ๋ณดํ†ต Spring Core๋ผ ํ•จ์€ ์•ฑ์„ ๋งŒ๋“œ๋Š”๋ฐ ์‚ฌ์šฉํ•˜๋Š” ํ•ต์‹ฌ๊ธฐ๋Šฅ๋“ค (IoC์ปจํ…Œ์ด๋„ˆ, AOP, ์ด๋ฒคํŠธ๋“ฑ)์„ ์˜๋ฏธํ•˜์ง€๋งŒ ๋ณดํ†ต '์Šคํ”„๋ง'์ด๋ผ ํ•˜๋ฉด ์Šคํ”„๋ง ์ง„ํ˜•์—์„œ ์ œ๊ณตํ•˜๋Š” ๋‹ค๋ฅธ ๊ธฐ๋Šฅ๋“ค์„ ํฌํ•จํ•œ ์˜๋ฏธ๋กœ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.
    ์Šคํ”„๋ง์€ 2004๋…„์— ๋‚˜์™”์ง€๋งŒ, ์Šคํ”„๋งMVC๊ฐ€ ๋Œ€์ค‘ํ™” ๋œ ๊ฒƒ์€ 2010๋…„ ๋ฌด๋ ต์ด๋‹ค.
    ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ํ•„์š”์— ๋”ฐ๋ผ ๊ธฐ์ˆ (๋„๊ตฌ)๋“ค์„ ๊ณจ๋ผ์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณตํ•ด์ค€๋‹ค. ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ํ•ต์‹ฌ๊ธฐ๋Šฅ๋“ค ์ด์™ธ์—๋„ ํ˜„์—… ์„œ๋น„์Šค์— ํ•„์š”ํ•œ ๊ฑฐ์˜ ๋ชจ๋“  ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
    ์Šคํ”„๋ง Core ๋ง๊ณ ๋„ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๋“ค์ด ์žˆ๋‹ค.


#IoC์˜ ์˜๋ฏธ

IoC๋Š” ์†Œํ”„ํŠธ์›จ์–ด์—์„œ ์ž์ฃผ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ๋Š” ์ผ๋ฐ˜์ ใ…‡๋‹ˆ ๊ฐœ๋…์ด๋‹ค. ๊ฐ์ฒด์ง€ํ–ฅ์  ์„ค๊ณ„, ๋””์ž์ธ ํŒจํ„ด, ๊ทธ๋ฆฌ๊ณ  ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋™์ž‘ํ•˜๋Š” ์„œ๋ฒ„๊ธฐ์ˆ ์„ ๋™์ž‘ํ•œ๋‹ค๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ IoC๋ฅผ ์ ์šฉํ•˜๊ฑฐ๋‚˜ ๋น„์Šทํ•œ ์›๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

 

๊ทธ๋ž˜์„œ IoC๋ผ๊ณ  ๋‹จ์ˆœ ์นญํ•˜๊ฒŒ๋˜๋ฉด ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ์„œ๋น„์Šค ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฑด์ง€, ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด์„ ์ด์šฉํ•œ๊ฑด์ง€, ์•„๋‹ˆ๋ฉด ๋˜ ๋‹ค๋ฅธ IoC ๊ธฐ์ˆ ์ธ๊ฑด์ง€ ์˜๋ฏธ๊ฐ€ ๋ช…ํ™•ํ•˜์ง€ ์•Š๊ธฐ์— ์Šคํ”„๋ง์—์„œ๋Š” DI ์ปจํ…Œ์ด๋„ˆ๋ผ๋Š” ๋ช…ํ™•ํ•œ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

 

# ์˜์กด๊ด€๊ณ„ ๊ฒ€์ƒ‰๊ณผ ์ฃผ์ž…

์Šคํ”„๋ง์—์„œ ์ œ๊ณตํ•˜๋Š” IoC๋Š” ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์„ค์ •์ •๋ณด๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…(@Configuration, @Bean) ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์ง€๋งŒ, App..Context๋ฅผ ์ด์šฉํ•˜์—ฌ ์ง์ ‘ ์˜์กด๊ด€๊ณ„๋ฅผ ๊ฒ€์ƒ‰(DL, Dependency Lookup)ํ•ด์„œ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์ œ๊ณตํ•ด์ค€๋‹ค.

public UserDao(){
	AnnotationConfigApplicationContext context = 
      new AnnotationConfigApplicationContext(DaoFactory.class);
      
     // getBean์œผ๋กœ ์ง์ ‘ ์›ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๊ฒ€์ƒ‰ํ•ด์„œ ์—ฐ๊ฒฐ์‹œํ‚จ๋‹ค.
    this.connectionMaker = context.getBean("connectionMaker", ConnectionMaker.class);
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์„ค์ • ๊ฐ์ฒด(AppConfig)๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๊ธดํ•˜๋‚˜, ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…๋ฐ›๋Š” ์ชฝ์ด ํ›จ์”ฌ ๋‹จ์ˆœํ•˜๊ณ  ๊น”๋”ํ•˜๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•์„ DL์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค๋Š” ๊ฒƒ๋งŒ ์•Œ๊ณ  ์ผ๋‹จ์€ ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜์ž.

 

 

# ์Šคํ”„๋ง์˜ ์œ ์—ฐํ•จ, ๋‹ค์–‘ํ•œ ์„ค์ •์ •๋ณด ์ž‘์„ฑ๋ฐฉ๋ฒ•

์Šคํ”„๋ง์€ ์–ด๋…ธํ…Œ์ด์…˜, XML์„ ํฌํ•จํ•œ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์„ค์ •์ •๋ณด๋ฅผ ์ฝ์–ด๋“ค์ผ ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—๋Š” ์„ค์ •์ •๋ณด๋ฅผ '์ฝ๋Š” ์ธํ„ฐํŽ˜์ด์Šค'๋งŒ ์กด์žฌํ•  ๋ฟ, ์–ด๋–ป๊ฒŒ ์ฝ๋Š”์ง€๋Š” ์ ํ˜€์žˆ์ง€ ์•Š๋‹ค. 

@์–ด๋…ธํ…Œ์ด์…˜, ์„ค์ •.xml, ๊ทธ ์™ธ ํ•„์š”ํ•˜๋‹ค๋ฉด ํ™•์žฅํ•  ์ˆ˜๋„ ์žˆ๋‹ค.


์Šคํ”„๋ง์—์„œ ์ œ๊ณตํ•˜๋Š” ์„ค์ •์ •๋ณด Reader ๊ตฌํ˜„์ฒด, ๋˜๋Š” ๋‚ด๊ฐ€ ์ง์ ‘๋งŒ๋“  Reader๋ฅผ ์ด์šฉํ•ด BeanDefinition์„ ๊ตฌํ˜„๋งŒ ํ•˜๋ฉด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ์Šคํ”„๋ง ์ž์ฒด์˜ ์ฝ”๋“œ๋ฅผ ๋ณผ ์ผ์€ ์—†๊ฒ ์ง€๋งŒ, ์ด์ฒ˜๋Ÿผ ์Šคํ”„๋ง ์ž์ฒด๋„ ๊ฐ์ฒด์ง€ํ–ฅ์„ ํ™œ์šฉํ•ด ์œ ์—ฐํ•˜๊ฒŒ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค๋Š” ๊ฒƒ๋งŒ ์•Œ๊ณ  ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜์ž.

์ฐธ๊ณ ๋กœ BeanFactory์™€ ApplicationContext๋Š” ๊ตฌํ˜„์ฝ”๋“œ๊ฐ€ ์—†๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ