U E D R , A S I H C RSS

토비�스프�3/오브�트와�존관계

1. 초난� DAO

  • 사용ìž� 정보를 JDBC API를 ì�´ìš©í•´ DBì—� 저장하고 조회할 수 있는 간단한 DAO 만들기.
  • DAO(Data Access Object)
    • DB를 사용하여 ë�°ì�´í„°ë¥¼ 조회, 조작하는 기능ì�„ 전담하ë�„ë¡� 만든 오브ì �트.

1.1. User

  • 사용ìž� 정보를 저장할 때 ìž�바빈 규약ì�„ 따르는 오브ì �트를 ì�´ìš©í•˜ë©´ 편리하다.
    • ìž�바빈(JavaBean)
      • 간단히 빈ì�´ë�¼ê³ ë�„ 한다.
      • ì›�래 ì�˜ë¯¸ëŠ” 비주얼 툴ì—�서 ì¡°ìž‘ 가능한 ì»´í�¬ë„ŒíЏ.
      • 요즘ì�€
        • 파ë�¼ë¯¸í„°ê°€ 없는 ë””í�´íЏ ìƒ�성ìž�를 가지고 있고
        • getter와 setter를 통해 조회, 수정할 수 있는 프로í�¼í‹°ë¥¼ 가진 오브ì �트를 ì�˜ë¯¸í•œë‹¤.
  • User : 사용ìž� ì •ë³´ 저장용 ìž�바빈 í�´ëž˜ìФ

package springbook.user.domain;

public class User {
    String id;
    String name;
    String password;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
  • USER í…Œì�´ë¸”
필드명 타입 설정
UserId VARCHAR(10) Primary Key
Name VARCHAR(20) Not Null
Password VARCHAR(20) Not Null

1.2. UserDao

  • UserDao : JDBC를 ì�´ìš©í•œ 등ë¡�, 조회 기능ì�´ 있는 DAO í�´ëž˜ìФ

package springbook.user.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import springbook.user.domain.User;

public class UserDao {
    public void add(User user) throws SQLException, ClassNotFoundException{
        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection("jdbc:mysql://localhost/springbook", "spring", "book");

        PreparedStatement ps = c.prepareStatement("insert into users(id, name, password) values(?,?,?)");
        ps.setString(1, user.getId());
        ps.setString(2, user.getName());
        ps.setString(3, user.getPassword());
		
        ps.executeUpdate();
		
        ps.close();
        c.close();		
    }
    public User get(String id) throws ClassNotFoundException, SQLException{
        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection("jdbc:mysql://localhost/springbook", "spring", "book");

        PreparedStatement ps = c.prepareStatement("select * from users where id = ?");
        ps.setString(1, id);
		
        ResultSet rs = ps.executeQuery();
        rs.next();
		
        User user = new User();
        user.setId(rs.getString("id"));
        user.setName(rs.getString("name"));
        user.setPassword(rs.getString("password"));
		
        rs.close();
        ps.close();
        c.close();
		
        return user;
    }
}

1.3. main()� �용한 테스트

  • 앞서 만든 í�´ëž˜ìŠ¤ê°€ 제대로 ë�™ìž‘하는지 확ì�¸í•˜ë ¤ë©´
    • DAOì�˜ 기능ì�„ 사용하는 웹 어플리케ì�´ì…˜ì�„ 만들어 서버ì—� 배치한 ë’¤ 웹 브ë�¼ìš°ì €ë¥¼ 통해 사용해보거나
      • UserDao 코드가 ë�™ìž‘하는지 확ì�¸í•˜ê¸° 위해 너무 복잡한 작업ì�´ í•„ìš”.
    • 오브ì �트가 스스로 ìž�ì‹ ì�„ ê²€ì¦�하ë�„ë¡� 만들어준다.
  • main 메소드를 ì�´ìš©í•œ 테스트 코드

public static void main(String[] args) throws SQLException, ClassNotFoundException {
    UserDao dao = new UserDao();

    User user = new User();		
    user.setId("zeropage");
    user.setName("제로페�지");
    user.setPassword("zp");
		
    dao.add(user);
		
    System.out.println(user.getId() + "등� 성공");
		
    User user2 = dao.get(user.getId());		
    System.out.println(user2.getName());
    System.out.println(user2.getPassword());
		
    System.out.println(user2.getId() + "조회 성공");
}
  • 테스트가 성공하면 다ì�Œê³¼ ê°™ì�´ ìœë ¥ë�œë‹¤.

zeropage 등� 성공
제로페�지
zp
zeropage 조회 성공

1.4. 초난� DAO� 문제�?

  • 초난ê°� DAO?
    • UserDao í�´ëž˜ìŠ¤ëŠ”
      • main() 메소드ì—� 작성한 테스트로 확ì�¸í•´ë³´ë‹ˆ
      • 기능ì�´ ì •ìƒ�ì �으로 ìž‘ë�™í•œë‹¤
    • 그럼ì—�ë�„ 불구하고 UserDao í�´ëž˜ìФ 코드ì—�는 여러가지 문제가 있다.
DeleteMe) � 부분 아� � 씀. - 김수경

2. DAO� 분리

2.1. 관심사� 분리

  • 어플리케ì�´ì…˜ì�´ í��기처분ë�  때까지 오브ì �트 설계와 코드는 ë�Šìž„ì—†ì�´ 변한다. 그렇다면 변화ì—� 어떻게 대비할 것ì�¸ê°€?
  • 가장 좋ì�€ 대책 : 변화ì�˜ í�­ì�„ 최소한으로 줄ì�¸ë‹¤.
    • ë�™ì�¼í•œ 기능 변경ì�„ 요청했ì�„때
      • 단 몇 줄ì�˜ 코드만 수정하고 수정한 ë’¤ì—�ë�„ 문제 ì—†ì�´ ìž‘ë�™í•¨ì�„ 보여주는ë�° 5ë¶„ì�´ 걸리는 개발ìž� > 코드를 수정하는ë�° 5시간ì�´ 걸리고 수정한 ë’¤ 문제 ì—†ì�´ ìž‘ë�™í•˜ëŠ”ì§€ 확신할 수 없는 개발ìž�
    • 어떻게?
      • 분리와 확장ì�„ 고려한 설계
  • 모든 변경과 발전ì�€ 한 번ì—� 한 가지 관심사항ì—� 집중해서 ì�¼ì–´ë‚˜ì§€ë§Œ ê·¸ì—� 따른 작업ì�€ 한 ê³³ì—� 집중ë�˜ì§€ 않는 경우가 많다.
    • 관심사ì�˜ 분리
      • 한 가지 관심ì�´ 한 êµ°ë�°ì—� 집중ë�˜ê²Œ 하ë�¼.
      • 관심ì�´ ê°™ì�€ 것ë�¼ë¦¬ëŠ” 하나ì�˜ ê°�ì²´ 안으로, 관심ì�´ 다른 것ì�€ 가능한 떨어져 ì˜�í–¥ì�„ 주지 않ë�„ë¡� 분리.

2.2. 커넥션 만들기ì�˜ ì¶”ìœ

2.2.1. UserDao� 관심사항

  1. DB 연결� 위한 커넥션� 어떻게 가져올 것�가.
  2. 사용� 등�/조회를 위한 SQL문� 담� Statement를 만들고 실행하는 것.
  3. 작업� �나고 리소스를 close하는 것.

  4. 가장 � 문제 : DB 연결� 위한 커넥션 오브�트 가져오기
    • add() 메소드와 get() 메소드ì—� ë�™ì�¼í•œ 코드가 중복ë�˜ì–´ 있다.
      • 앞으로 수백개ì�˜ DAO 메소드를 만든다고 하면
        • DB 커넥션ì�„ 가져오는 코드가 수백군ë�°ì—� 중복으로 존재하게 ë�˜ì–´
        • DB 커넥션ì�„ 가져오는 ë°©ì‹�ì�´ 바뀌면 수백군ë�°ë¥¼ 하나하나 수정해야한다.

2.2.2. 중복 코드ì�˜ 메소드 ì¶”ìœ

  • 커넥션ì�„ 가져오는 중복ë�œ 코드를 분리한다.
  • UserDao : getConnection() 메소드를 ì¶”ìœí•˜ì—¬ 중복ì�„ 제거

public void add(User user) throws SQLException, ClassNotFoundException {
    Connection c = getConnection();
    …
}

public void get(String id) throws SQLException, ClassNotFoundException {
    Connection c = getConnection();
    …
}
    
private Connection getConnection() throws SQLException, ClassNotFoundException {
    Class.forName("com.mysql.jdbc.Driver");
    Connection c = DriverManager.getConnection("jdbc:mysql://localhost/springbook", "spring", "book");
}
  • ì�´ì œ 수백개ì�˜ DAO 메소드가 있어ë�„ DB 커넥션ì�„ 가져오는 ë°©ì‹�ì�´ 바뀌면 getConnection() 메소드만 수정해주면 ë�œë‹¤.

2.2.3. 변경사항� 대한 검� : 리팩토�과 테스트

  • 리팩토ë§�
    • 코드 ë‚´ë¶€ 구조를 변경하여 재구성하는 작업
    • 외부 ë�™ìž‘ ë°©ì‹�ì�€ 변화하지 않ì�Œ.
    • 장ì �
      • ë‚´ë¶€ 설계가 개선ë�˜ì–´ 코드를 ì�´í•´í•˜ê¸° 편해지고 변화ì—� 효율ì �으로 대ì�‘í•  수 있다.
    • 리팩토ë§�(마틴 파울러, 켄트 벡 공저)
DeleteMe) 추후 내용 보강 예정 - 김수경

2.3. DB 커넥션 만들기� �립

3. DAO� 확장

  • 관심사ì—� ë”°ë�¼ 오브ì �트 나누기
    • 관심사가 다르다
    • 변화ì�˜ 성격ì�´ 다르다
      • 변화ì�˜ 성격ì�´ 다르다는 것ì�€ 변화ì�˜ ì�´ìœ ì™€ 시기, 주기가 다르다는 것ì�„ ì�˜ë¯¸í•¨
    • ì¶”ìƒ�í�´ëž˜ìŠ¤ë¥¼ 만들어놓고 ìƒ�ì†�ì�„ 통해 변화를 구현하는 방법 -> 불편하다
  • 1.3.1 í�´ëž˜ìФì�˜ 분리
    • 서로 다른 관심사를 ë�…립ì �ì�¸ í�´ëž˜ìŠ¤ë¡œ 분리해보ìž�
      • 기존ì�˜ 코드를 수정할 때는 기능ì�˜ 변화가 아닌 ë‚´ë¶€ 설계를 변경해 ë�” 나ì�€ 코드를 만드는 것 ì�´ë‹¤(리팩토ë§�)
      • 리팩토ë§� 후 기능ì�˜ 변화가 없는지 ê²€ì¦�해야 한다. 테스트 코드가 ì�´ë¥¼ ê²€ì¦�í•´ 준다.
    • 분리ë�œ ë‘� í�´ëž˜ìŠ¤ëŠ” ì�˜ì¡´ê´€ê³„를 가진다.
  • 1.3.2 ì�¸í„°íŽ˜ì�´ìФì�˜ ë�„ìž…
    • í�´ëž˜ìФ 분리ì—�서 가장 중요한 ì �ì�€ ë‘� í�´ëž˜ìŠ¤ê°€ ë‚®ì�€ ê²°í•©ë�„를 가져야 한다는 것ì�´ë‹¤.
    • ì¶”ìƒ�í™”
      • ì–´ë–¤ 것들ì�˜ 공통ì �ì�¸ 성격ì�„ 뽑아내어 ì�´ë¥¼ 따로 분리해내는 작업
      • interface ì�´ìš©
      • ìƒ�ì†�보다 유연한 관계 설정 가능
  • 1.3.3 관계설정 ì±…ìž„ì�˜ 분리
    • 코드ì�˜ í�¬ê¸°ê°€ 작고 간단해ë�„ í�´ëž˜ìŠ¤ì™€ëŠ” 다른 ë�…립ì �ì�¸ 관심사를 가지고 있다면 분리해야한다.
      • í�´ëž˜ìФì�˜ 확장성ì�„ í•´ì¹  수 있다.
    • í�´ëž˜ìŠ¤ê°„ì�˜ 관계설정
      • 오브ì �트와 오브ì �트간ì�˜ 관계설정ì�„ ì�˜ë¯¸í•œë‹¤.
      • 런타임 사용관계 : 오브ì �트 사ì�´ì�˜ 관계란 런타임시ì—� 한 오브ì �트가 다른 오브ì �트ì�˜ ë ˆí�¼ëŸ°ìŠ¤ë¥¼ 가지고있는 것.
      • 방법
        • 사용할 오브ì �트를 ë‚´ë¶€ì—�서 ìƒ�성
        • ì�¸í„°íŽ˜ì�´ìŠ¤ë¡œ 구현ë�œ 파ë�¼ë©”터를 ì�´ìš©í•´ 외부ì—�서 전달받는다. (다형성)
  • 1.3.4 윈칙과 패턴
    • 개방 í��쇄 ì›�ì¹™(OCP) ê°�체지향 설계ì›�ì¹™(SOLID)
      • í�´ëž˜ìŠ¤ë‚˜ 모듈ì�€ 확장ì—�는 ì—´ë ¤ 있어야 하고 변경ì—�는 닫혀 있어야 한다
    • 높ì�€ ì�‘ì§‘ë�„와 ë‚®ì�€ ê²°í•©ë�„
      • 개방 í��쇄 ì›�ì¹™ì�˜ ì›�리
      • 높ì�€ ì�‘ì§‘ë�„
        • 변화가 ì�¼ì–´ë‚  때 해당 모듈ì—�서 변하는 부분ì�´ í�¬ë‹¤ëŠ” 것ì�„ ì�˜ë¯¸í•œë‹¤.
      • ë‚®ì�€ ê²°í•©ë�„
        • 높ì�€ ì�‘ì§‘ë�„보다 민ê°�한 사항
        • ê²°í•©ë�„란 하나ì�˜ 오브ì �트가 ì�˜ì¡´ê´€ê³„ì—� 있는 다른 오브ì �트ì—�게 변화를 요구하는 ì •ë�„를 ì�˜ë¯¸í•œë‹¤.
        • 변화가 다른 모듈ì�´ë‚˜ 오브ì �트ì—�게 전파ë�˜ì§€ 않는 것ì�´ 좋다.
    • ì „ëžµ 패턴
      • ë””ìž�ì�¸ 패턴ì�˜ ì�¼ë¶€
      • 변경ì�´ 필요한 알고리즘ì�„ ì�¸í…ŒíŽ˜ì�´ìŠ¤ë¥¼ 통해 외부로 분리시키고, ì�´ë¥¼ 구체화한 í�´ëž˜ìŠ¤ë¥¼ í•„ìš”ì—� ë”°ë�¼ 바꿔 사용하게 하는 패턴
  • ê²°êµ­.. 스프ë§�ì�´ëž€?
    • ê°�체지향ì � 설계 ì›�칙과 ë””ìž�ì�¸ 패턴ì—� 나타난 장ì �ì�„ ìž�연스럽게 개발ìž�들ì�´ 활용할 수 있게 해주는 프레임워í�¬

4. 제어� 역전(IoC)

  • 1.4.1 오브ì �트 팩토리
    • 팩토리
      • ê°�ì²´ì�˜ ìƒ�성 방법ì�„ 결정하고 만들어진 오브ì �트를 ë�Œë ¤ì¤€ë‹¤.
      • 관심사ì�˜ 분리 - 오브ì �트를 ìƒ�성하는 쪽과 ìƒ�성ë�œ 오브ì �트를 사용하는 쪽ì�„ 분리하는 ì—­í• ì�„ 한다.
      • DaoFactory 장ì � : 애플리케ì�´ì…˜ì�˜ ì»´í�¬ë„ŒíЏ ì—­í• ì�„ 하는 오브ì �트와 구조를 결정하는 오브ì �트를 분리.
  • 1.4.2 오브ì �트 팩토리ì�˜ 활용
    • 오브ì �트 ìƒ�성 코드 반복ì�„ 분리한다

public class DaoFactory{
	//  ConnectionMaker를 설정하고 �성하는 코드가 반복�
	public UserDao userDao( ){
		return new UserDao(new DConnectionMaker());
	}

	public AccountDao accountDao( ){
		return new AccountDao(new DConnectionMaker());
	}

	public MessageDao messageDao( ){
		return new MessageDao(new DConnectionMaker());
	}
}
분리 전
public class DaoFactory{
	public UserDao userDao( ){
		return new UserDao(connectionMaker());
	}

	public AccountDao accountDao( ){
		return new AccountDao(connectionMaker());
	}

	public MessageDao messageDao( ){
		return new MessageDao(connectionMaker());
	}

	// 중복 코드 분리
	public ConnectionMaker connectionMaker(){
		return new DConnectionMaker();
	}
}
분리 후

  • 1.4.3 제어권ì�˜ ì�´ì „ì�„ 통한 제어관계 ì—­ì „
    • 제어ì�˜ ì—­ì „ì�´ëž€?
      • 프로그램ì�˜ 제어 í��름 구조가 뒤바뀌는 것
      • 제어 권한ì�„ 다른 대ìƒ�ì—�게 위임한다.
      • 프레임워í�¬ëŠ” 제어ì�˜ ì—­ì „ì�´ ì �ìš©ë�œ 대표ì �ì�¸ 기술ì�´ë‹¤.
        • ë�¼ì�´ë¸ŒëŸ¬ë¦¬ëŠ” 애플리케ì�´ì…˜ì�´ 능ë�™ì �으로 사용한다.
        • 반면 프레임워í�¬ëŠ” 애플리케ì�´ì…˜ 코드가 프레임워í�¬ì—� 사용ë�œë‹¤.

  • 스프ë§�ì�€ IoC를 극한까지 ì �용한 프레임워í�¬ë‹¤.
    • 프레임워í�¬ëŠ” 분명한 제어ì�˜ ì—­ì „ ê°œë…�ì�´ ì �ìš©ë�˜ì–´ 있어야 한다.

5. 스프�� IoC

5.1 오브�트 팩토리를 �용한 스프� IoC
  • 5.1.1
    • 빈(bean) : 스프ë§�ì�´ 제어권ì�„ 가지고 ì§�ì ‘ 만들고 관계를 부여하는 오브ì �트. ìž�바빈ì—�서 ë§�하는 빈과 비슷한 오브ì �트 단위ì�˜ 애플리케ì�´ì…˜ ì»´í�¬ë„ŒíЏ. 스프ë§�ì�´ ì§�ì ‘ ìƒ�성과 제어를 담당하는 오브ì �트만ì�„ 빈ì�´ë�¼ê³  부른다.
    • 빈 팩토리(bean factory) : 빈ì�˜ ìƒ�성과 관계설정 등ì�˜ 제어를 담당하는 IoC오브ì �트. 스프ë§�ì�˜ IoC를 담당하는 핵심 컨테ì�´ë„ˆ. ì�¼ë°˜ì �으로 ì§�ì ‘ 사용하지 않고 ì�´ë¥¼ 확장한 애플리케ì�´ì…˜ 컨í…�스트를 사용한다.
    • 애플리케ì�´ì…˜ 컨í…�스트(application context) : IoCë°©ì‹�ì�„ ë”°ë�¼ 만들어진 ì�¼ì¢…ì�˜ 빈팩토리. 별ë�„ì�˜ 정보를 참고해서 빈ì�˜ ìƒ�성, 관계설정 등ì�˜ 제어 작업ì�„ ì´�괄한다. 설정 정보를 따로 받아와서 ì�´ë¥¼ 활용하는 IoC엔진ì�´ë�¼ê³  ë³¼ 수 있다. 주로 설정ì—�는 xmlì�„ 사용한다.
    • 설정정보 : 애플리케ì�´ì…˜ 컨í…�스트나 빈 팩토리가 IoC를 ì �용하기 위해 사용하는 ì •ë³´. 주로 IoC 컨테ì�´ë„ˆì—� ì�˜í•´ 관리ë�˜ëŠ” 애플리케ì�´ì…˜ 오브ì �트를 ìƒ�성하고 구성할 때 사용ë�œë‹¤.
    • 컨테ì�´ë„ˆ/IoC컨테ì�´ë„ˆ : IoCë°©ì‹�으로 빈ì�„ 관리한다는 ì�˜ë¯¸ì—�서 애플리케ì�´ì…˜ 컨í…�스트나 빈 팩토리를 컨테ì�´ë„ˆ/IoC컨테ì�´ë„ˆë�¼ê³ ë�„ 한다.
  • 5.1.2
    • 빈 팩토리 ë˜�는 애플리케ì�´ì…˜ 컨í…�스트ì�˜ 설정정보를 만드는 방법 ->
      • 1. 스프ë§�ì�´ 빈 팩토리를 위한 오브ì �트 설정ì�„ 담당하는 í�´ëž˜ìФë�¼ê³  ì�¸ì‹�í•  수 있ë�„ë¡� @Configurationì�´ë�¼ëŠ” 애노테ì�´ì…˜ì�„ 추가한다.

@Configuration
public class DaoFactory{}
  • 2. 오브ì �트를 만들어주는 메소드ì—�는 @Beanì�´ë�¼ëŠ” 애노테ì�´ì…˜ì�„ 붙여준다.

@Configuration
public class DaoFactory{
@Bean
public UserDao userDao(){ ...}
}
  • 만들어진 설정정보를 사용하는 애플리케ì�´ì…˜ 컨í…�스트ì�˜ ìƒ�성 ë°� 빈 ìƒ�성 ->
    • 1. 애플리케ì�´ì…˜ 컨í…�스트는 ApplicationContext타입ì�˜ 오브ì �트다. 사용시 @Configurationì�´ ë¶™ì�€ ìž�바코드를 설정정보로 사용하려면 AnnotationConfigApplicationContextì—� ìƒ�성ìž� 파ë�¼ë¯¸í„°ë¡œ @Configurationì�´ ë¶™ì�€ í�´ëž˜ìŠ¤ë¥¼ 넣어준다.

public static void main(Strings[] args) throws ClassNotFoundException, SQLException{
ApplicatioContext context = new AnnotationConfigApplicationContext(DaoFactory.class);
}
  • 2. 준비ë�œ ApplicationContextì�˜ getBean()메소드를 ì�´ìš©í•´ 등ë¡�ë�œ 빈ì�˜ 오브ì �트를 가져올 수 있다.

public static void main(Strings[] args) throws ClassNotFoundException, SQLException{
ApplicatioContext context = new AnnotationConfigApplicationContext(DaoFactory.class);
UserDao dao = context.getBean("userDao", UserDao.class);
}
getBean()메소드 : ApplicationContextê°€ 관리하는 오브ì �트를 요청하는 메소드. ""안ì—� 들어가는 것ì�€ ApplicationContextì—� 등ë¡�ë�œ 빈ì�˜ ì�´ë¦„. 빈ì�„ 가져온다는 것ì�€ 메소드를 호ìœí•´ì„œ 결과를 가져온다고 ìƒ�ê°�하면 ë�œë‹¤. 위ì—�서는 userDao()ë�¼ëŠ” 메소드ì—� 붙였기 때문ì—� ""안ì—� userDaoê°€ 들어갔다. 메소드ì�˜ ì�´ë¦„ì�´ myUserDao()ë�¼ë©´ "myUserDao"ê°€ ë�œë‹¤. 기본ì �으로 Object타입으로 리턴하게 ë�˜ì–´ìžˆì–´ì„œ 다시 ìº�스팅ì�„ 해줘야 하지만 ìž�ë°” 5 ì�´ìƒ�ì�˜ 제네릭 메소드 ë°©ì‹�ì�„ 사용해 ë‘� 번째 파ë�¼ë¯¸í„°ì—� 리턴 타입ì�„ 주면 ìº�스팅ì�„ 하지 않아ë�„ ë�œë‹¤.
5.2 애플리케�션 컨�스트� �작방�
  • 5.2.1
    • @Configurationì�´ ë¶™ì�€ í�´ëž˜ìŠ¤ëŠ” 애플리케ì�´ì…˜ 컨í…�스트가 활용하는 IoC 설정정보가 ë�œë‹¤. ë‚´ë¶€ì �으로는 애플리케ì�´ì…˜ 컨í…�스트가 @Configurationí�´ëž˜ìФì�˜ @Bean메소드를 호ìœí•´ì„œ 오브ì �트를 가져온 것ì�„ í�´ë�¼ì�´ì–¸íŠ¸ê°€ getBean() 메소드로 요청할 때 전달해준다.
  • 5.2.2
    • 애플리케ì�´ì…˜ 컨í…�스트를 사용했ì�„ 때 ì–»ì�„ 수 있는 장ì �
      1. ���언트는 구체�� 팩토리 �래스를 알 필요가 없다.
      2. 애플리케�션 컨�스트는 종합 IoC 서비스를 제공해준다.
      3. 애플리케�션 컨�스트는 빈� 검색하는 다양한 방법� 제공한다.

6. 싱글톤 레지스트리와 오브�트 스코프

6.1 싱글톤 레지스트리로서� 애플리케�션 컨�스트
  • 애플리케ì�´ì…˜ 컨í…�스트는 싱글톤ì�„ 저장하고 관리하는 싱글톤 레지스트리ì�´ê¸°ë�„ 하다. 스프ë§�ì�€ 기본ì �으로 별다른 설정ì�´ 없으면 ë‚´ë¶€ì—�서 ìƒ�성하는 빈 오브ì �트를 모ë‘� 싱글톤으로 만든다.
  • 스프ë§�ì�€ 주로 서버환경ì—� ì �ìš©ë�˜ê¸° 때문ì—� 서버ì—� 걸리는 부하를 줄ì�´ê¸° 위해 빈ì�„ 싱글톤으로 만들게 ë�˜ì–´ìžˆë‹¤. 스프ë§� 컨테ì�´ë„ˆëŠ” 싱글톤ì�„ ìƒ�성, 관리하는 싱글톤 관리 컨테ì�´ë„ˆì�´ê¸°ë�„ 하다.
  • ì�¼ë°˜ì �ì�¸ 싱글톤 패턴ì�˜ 구현ì�˜ 한계
    • 1. private ìƒ�성ìž�를 가지고 있기 때문ì—� ìƒ�ì†�í•  수 없다.
    • 2. 싱글톤ì�€ 테스트하기가 힘들다.
    • 3. 서버환경ì—�서는 싱글톤ì�´ 하나만 만들어지는 것ì�„ 보장하지 못한다.
    • 4. 싱글톤ì�˜ 사용ì�€ ì „ì—­ìƒ�태를 만들 수 있기 때문ì—� 바람ì§�하지 못하다.
6.2 싱글톤과 오브�트� �태
  • 싱글톤 오브ì �트ì�˜ ì�¸ìŠ¤í„´ìŠ¤ 변수를 수정 시 서로 ê°’ì�„ ë�®ì–´ì“°ê³  ì�½ì–´ì˜¬ 수 있기 때문ì—� 위험하다. ì�½ê¸°ì „ìš©ì�˜ ì†�성ì�„ 가진 ì •ë³´ë�¼ë©´ ì�¸ìŠ¤í„´ìŠ¤ 변수로 사용해ë�„ 좋다.
6.3 스프� 빈� 스코프
  • 스코프(scope) : 스프ë§�ì�´ 관리하는 빈ì�´ ìƒ�성ë�˜ê³  존재하고 ì �ìš©ë�˜ëŠ” 범위. 빈ì�˜ 기본 스코프는 싱글톤으로 컨테ì�´ë„ˆ ë‚´ì—� 한 ê°œì�˜ 오브ì �트만 만들어져서 강제로 제거하지 않는 한 계ì†� 유지ë�œë‹¤. 경우ì—� ë”°ë�¼ì„œ 싱글톤 외ì�˜ 프로토타입(prototype), 요청(request), 세션(session)스코프 등ì�„ 가질 수 있다.

7. �존관계 주입(DI)

  • ì�˜ì¡´ê´€ê³„ : ë‘� í�´ëž˜ìФ ë˜�는 모듈ì�´ 있ì�„ 때 한 쪽ì�˜ 변화가 다른 쪽ì—� ì˜�í–¥ì�„ 미치는 ìƒ�황.
  • ì�˜ì¡´ê´€ê³„ 주입(DI)? : ì�˜ì¡´ê´€ê³„ 주입(Dependency Injection)ì�´ëž€ 스프ë§�ì—� 사용ë�œ 제어ì�˜ ì—­ì „(IoC) ë°©ì‹�ì�„ 조금 ë�” 명확하게 나타내기 위해서 사용한 용어ì�´ë‹¤.
    • ì�˜ì¡´ê´€ê³„ 주입ì�˜ 세 가지 ì¡°ê±´
      1. �래스 모��나 코드�는 런타임 시�� �존관계가 드러나지 않는다. 그러기 위해서는 �터페�스�만 �존하고 있어야 한다.
      2. 런타임 시�� �존관계는 컨테�너나 팩토리 같� 제3� 존재가 결정한다.
      3. �존관계는 사용할 오브�트� 대한 레�런스를 외부�서 제공(주입)해줌으로� 만들어진다.
  • DIì�˜ 장ì � : DI를 받았ì�„ 경우 주입ë�œ 오브ì �트를 ì�¸í„°íŽ˜ì�´ìŠ¤ë¡œ 받는ë�° ì�´ë ‡ê²Œ 하면 코드ì—� 런타임 í�´ëž˜ìŠ¤ì™€ì�˜ 관계가 ì§�ì ‘ 드러나지 않기 때문ì—� 주입시 주입하는 오브ì �트를 바꿔주는 것으로 코드ì�˜ 변경, 확장ì—� 쉽게 대ì�‘í•  수 있다.
  • 스프ë§�ì—�서ì�˜ DI
    • Bean : 스프ë§�ì—�서는 DI를 쉽게 하기 위해서 Beanì�„ ì�´ìš©í•˜ì—¬ 오브ì �트를 관리한다.
    • Bean Factory : 런타임 시ì �ì—�서 ì�˜ì¡´ê´€ê³„를 결정하기 위해 Bean Factoryì—�서 Beanì�„ 관리하고 오브ì �트간ì�˜ 관계를 맺어준다.
    • ì�˜ì¡´ê´€ê³„ 검색(Dependency Lookup) : 스프ë§�ì�˜ DIë°©ì‹�ì�„ ì�´ìš©í•˜ê¸° 위해서는 DI를 받는 오브ì �트가 반드시 Beanì�´ì–´ì•¼ 한다. 하지만 DLì�„ ì�´ìš©í•˜ë©´ Beanì�´ 아닌 오브ì �트ì—�서ë�„ ì�˜ì¡´ê´€ê³„를 설정할 수 있다.

8. XML� �용한 설정

  • XML 설정
  • 스프ë§�ì—�서는 DIì�˜ì¡´ê´€ê³„를 만들 때 ì§�ì ‘ì �으로 코드를 수정하는 것 외ì—�ë�„ 다양한 ë°©ì‹�ì�„ 제공하고 있다. XMLì�€ 단순한 í…�스트 파ì�¼ì�´ê¸° 때문ì—� 다루기 쉽고 추가ì �ì�¸ 빌드작업ì�´ 필요하지 않다.
    • <beans> : @Configurationì—� 대ì�‘한다. 여러 ê°œì�˜ <bean>ì�´ 들어간다.
      • <bean> : @Beanì�´ ë¶™ì�€ ìž�ë°” 메소드ì—� 대ì�‘한다.
        • <id> : @Bean 메소드ì�˜ ì�´ë¦„. getBean()ì—�서 사용한다.
        • <class> : @Bean 메소드가 return하는 ê°’. 패키지까지 모ë‘� ì�¨ 줘야 한다.
        • <property> : @Bean 메소드ì—� DI를 í•  때 사용한다. 수정ìž� 메소드ì�´ë‹¤.
          • <name> : 수정ìž� 메소드ì—�서 set부분ì�„ 제외한 나머지 부분ì�˜ ì�´ë¦„ì�´ë‹¤.
          • <ref> : 수정ìž� 메소드를 ì�´ìš©í•´ì„œ 주입할 오브ì �트ì�˜ Beanì�˜ idì�´ë‹¤.
          • <value> : 다른 Bean 오브ì �트가 아니ë�¼ 단순 ê°’ì�„ 주입할 때 <ref> 대신 사용한다. 스프ë§�ì—�서 프로í�¼í‹°ì�˜ ê°’ì�„ ì �절하게 변환하기 때문ì—� 스트ë§�, 오브ì �트 등 다양한 ê°’ì�„ 사용할 수 있다.
  • 예시 (Java 코드)

@Configuration
class DaoFactory {
 ...

 @Bean
 public ConnectionMaker connectionMaker() {
  return new DConnectionMaker();
 }

 @Bean
 userDao setConnectionMaker(connectionMaker()) {
 ... };
}
  • 예시 (XML)

<beans>
 <bean id="myConnectionMaker" class="springbook.user.dao.DConnectionMaker" />

 <bean id="userDao" class="springbook.dao.UserDao">
  <property name="connectionMaker ref="myConnectionMaker" />
 </bean>
</beans>
  • XMLì�„ ì�´ìš©í•˜ëŠ” 애플리케ì�´ì…˜ 컨í…�스트
    • 애플리케ì�´ì…˜ 컨í…�스트 ìƒ�성시 GenericXmlApplicationContext("xml 경로")를 ì�´ìš©í•´ì„œ 컨í…�스트를 ìƒ�성한다.

ApplicationContext context = new GenericXmlApplicationContext("springbook/user/dao/daoContext.xml")

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:31:21
Processing time 0.0161 sec