Post

๐Ÿฅœ [Spring] FactoryMethod ํŒจํ„ด & Spring DI

MVC vs Front-Controller

image-27

MVC ์™€ FrontController ์˜ ์ฐจ์ด๋ฅผ ์•Œ์•„๋ณด์ž

MVC Pattern

์žฅ์ 

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๊ฐ๊ฐ ๋ชจ๋“ˆํ™” ๋˜์–ด ํ˜ธ์ถœ์ด ๋˜์–ด์ง

์š”๊ตฌ์‚ฌํ•ญ์ด ๋ณ€๊ฒฝ๋˜๋”๋ผ๋„ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์— ๋ผ์ง€์น˜์ง€ ์•Š์Œ

ํ™•์žฅ์„ฑ์ด ์žˆ๋‹ค

๋‹จ์ 

ํ•˜๋‚˜์˜ ์š”๊ตฌ์‚ฌํ•ญ (Business Logic)์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ผ์ผํžˆ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•จ

Front-Controller

์žฅ์ 

ํ•˜๋‚˜์˜ ์„œ๋ธ”๋ฆฟ์ด ๋ชจ๋“  ์š”์ฒญ์„ ๋‹ค ์ฒ˜๋ฆฌ

๋‹จ์ 

ํ•˜๋‚˜์˜ Servlet ์—์„œ ๋ชจ๋“  Business Logic ์„ Method Block ์œผ๋กœ ๋‹ค ์ฒ˜๋ฆฌ

๋งค์šฐ ๋ฌด๊ฑฐ์šด Controller ๊ฐ€ ์ƒ์„ฑ ๋จ



Factory Method Pattern

MVC ์™€ FrontController ์˜ ์žฅ์ ์„ ๋ชจ์•„๋†“์€ ๊ฒƒ

image-28

Client๋กœ ๋ถ€ํ„ฐ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ๊ฐ€์žฅ ๋จผ์ € FrontController๊ฐ€ ๋ฐ›๊ฒŒ ๋˜๋Š”๋ฐ

์—ฌ๊ธฐ์„œ ์–ด๋–ค ์š”์ฒญ์ด ์™”๋Š”์ง€ command ๋ณ€์ˆ˜์— ๋„ฃ์–ด์ฃผ๊ณ  ControllerFactory์— ๋„ฃ์–ด์ค€๋‹ค.

ControllerFactory ๋Š” ๋ง ๊ทธ๋Œ€๋กœ Controller ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ณต์žฅ์ด๋ผ๋Š” ์˜๋ฏธ ์ด๋‹ค.

ControllerFactory๋Š” command๋ฅผ ๋ณด๊ณ  ์–ด๋–ค ํ•ด๋‹น command์— ๋”ฐ๋ฅธ Controller ๋ฅผ ๋งŒ๋“ค์–ด FrontController ์—๊ฒŒ ์ „๋‹ฌํ•ด์ค€๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ํ•ด๋‹น Controller ์˜ Component ๋ฉ”์†Œ๋“œ ์ค‘ handleRequest() ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๊ฒฐ๊ณผ ํŽ˜์ด์ง€๋ฅผ ์–ป์–ด

FrontController ๋กœ ๋ณด๋‚ด๊ณ  FrontController ์—์„œ๋Š” forward ๋‚˜ Redirect ๋ฅผ ํ•ด์„œ ๋„ค๋น„๊ฒŒ์ด์…˜์„ ํ•ด์ค€๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// frontController

package web.client;
import java.util.Scanner;

import web.controller.Controller;
import web.factory.ControllerFactory;

/*
 * ๋‚˜์ค‘์— Servlet์—ญํ• 
 * FrontController๊ฐ€ ๋œ๋‹ค.
 */
public class FrontController {

	public static void main(String[] args) {
		// ๋ธŒ๋ผ์šฐ์ € ํผ์—์„œ ๋ฐ›์€ ๊ฐ’์„...
		Scanner sc = new Scanner(System.in);
		System.out.println(">>>Command ๊ฐ’์ž…๋ ฅ");
		
		String command = sc.next();
		
		//ControllerFactory๋กœ ๋„˜๊น€
		Controller controller = ControllerFactory.getInstance().createController(command);
		
		controller.handleRequest();

		//์ง€๊ธˆ์€ ๊ฒฐ๊ณผํŽ˜์ด์ง€ ๋„ค๋น„๊ฒŒ์ด์…˜ ์•ˆํ•˜๊ณ  ์ฝ˜์†”์—์„œ ํ™•์ธ
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//factory controller

package web.factory;

import web.controller.Controller;
import web.controller.FindController;
import web.controller.LoginController;
import web.controller.RegisterController;
import web.controller.UpdateController;

/*
 * Controller๋ฅผ ๋งŒ๋“œ๋Š” ๊ณต์žฅ
 * ์ด๊ณณ์—์„œ Register, Find, Update, Login.,... Controller๋ฅผ ๊ฐ๊ฐ ์ƒ์„ฑํ•œ๋‹ค.
 * ::
 * 1) 4๊ฐœ์˜ Controller๋ฅผ ์ƒ์„ฑ --> ControllerFactoryrk 4๊ฐœ ํ•„์š”??
 * 2) 4๊ฐœ์˜ Controller์ƒ์„ฑ --> ControllerFactory๊ฐ€ 1๊ฐœ ํ•„์š”?
 * 
 * ControllerFactory ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์œผ๋กœ ์ž‘์„ฑ
 */
public class ControllerFactory {
	private static ControllerFactory factory = new ControllerFactory();
	private static Controller controller;

	private ControllerFactory() {
		System.out.println("Creating ControllerFactory...");
	}
	
	public static ControllerFactory getInstance() {
		return factory;
	}
	
	//ํด๋ผ์ด์–ธ๋“œ์˜ ์š”์ฒญ์— ๋”ฐ๋ผ์„œ ์„œ๋กœ ๋‹ค๋ฅธ Controller๋ฅผ ๊ณต์žฅ์—์„œ ์ƒ์„ฑํ•ด๋‚ธ๋‹ค.
	public Controller createController(String command) {
		if(command.equals("register")) {
			controller = new RegisterController();
			System.out.println("RegisterController...Creating...OK");
		}
		else if(command.equals("find")) {
			controller = new FindController();
			System.out.println("FindController...Creating...OK");
		}
		else if(command.equals("update")) {
			controller = new UpdateController();
			System.out.println("UpdateController...Creating...OK");
		}
		else if(command.equals("login")) {
			controller = new LoginController();
			System.out.println("LoginController...Creating...OK");
		}
		return controller;
	}
}

FrontController๋กœ ์–ป์€ command๋ฅผ ๋ฐ›์•„์„œ ํ•ด๋‹น command์— ๋”ฐ๋ฅธ Controller๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

Controller๋ฅผ ์ƒ์„ฑํ•˜๊ณ  Controller๋ฅผ ํ˜ธ์ถœํ•œ FrontController๋กœ ๋Œ์•„๊ฐ„๋‹ค.

1
2
3
4
5
//ControllerFactory๋กœ ๋„˜๊น€
Controller controller = ControllerFactory.getInstance().createController(command);

//handleRequest ํ˜ธ์ถœ
controller.handleRequest();

์ด์ œ handleRequest๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

Controller ํƒ€์ž…์€ Interface ์ด๋‹ค.

1
2
3
4
5
package web.controller;
//Template ๊ธฐ๋Šฅ๋งŒ์œผ๋กœ ๊ตฌ์„ฑ... 
public interface Controller {
	String handleRequest();
}

์ฆ‰, ๊ฐ ๊ธฐ๋Šฅ๋‹น Controller๋ฅผ ๊ตฌํ˜„ํ•ด ์กด์žฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฌ๋ฉด command์— ๋”ฐ๋ฅธ Controller๋ฅผ return ๋ฐ›๊ณ  ๊ทธ Controller๊ฐ€ handleRequest() ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด

๊ธฐ๋Šฅ์— ๋งž๋Š” handleRequest()๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package web.controller;

public class FindController implements Controller{

	@Override
	public String handleRequest() {
		/*
		 Controller์˜ ์—ญํ• 
		 1. ํผ๊ฐ’ ๋ฐ›์•„์„œ 
		 2. vo ์ƒ์„ฑ
		 3. dao ๋ฆฌํ„ด ๋ฐ›๊ณ 
		 4. business logic ํ˜ธ์ถœ
		 5. ๋„ค๋น„๊ฒŒ์ด์…˜
		 //MVC ํŒจํ„ด์—์„œ๋Š” Controller ์—ญํ• ์€ Servlet ๋‹จ์œ„๊ฐ€ ํ–ˆ๊ณ 
		 //FrontController์—์„œ๋Š” ๋ฉ”์†Œ๋“œ ๋‹จ์œ„๊ฐ€ ํ–ˆ๊ณ 
		 //์ง€๊ธˆ์€ ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์†๋ฐ›์€ ์ž๋ฐ” ํด๋ž˜์Šค์—์„œ ํ•˜๊ณ  ์žˆ๋‹ค.
		  * ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์€ ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์€ ์ž๋ฐ” ํด๋ž˜์Šค๋ฅผ ์ปดํฌ๋„ŒํŠธ๋ผ๊ณ  ํ•œ๋‹ค.
		 */
		System.out.println("FIndController... Find Member");
		return "find_ok.jsp";
	}

}

์ค‘์š”ํ•œ ์ ์€ ์ง€๊ธˆ๊นŒ์ง€ ์ด๋Ÿฌํ•œ Controller์˜ ์—ญํ• ์„ MVC์—์„œ๋Š” Servlet์ด ํ•ด์ฃผ์—ˆ๊ณ ,

FrontController ํŒจํ„ด์—์„œ๋Š” ํ•˜๋‚˜์˜ Servlet ์•ˆ์— ๋ฉ”์†Œ๋“œ๋“ค์ด ํ•ด์ฃผ์—ˆ๋‹ค.

FactoryMethod ํŒจํ„ด์—์„œ๋Š” Controller ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์€ ์ž๋ฐ” ํด๋ž˜์Šค์—์„œ ํ•˜๊ณ  ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ž๋ฐ” ํด๋ž˜์Šค๋ฅผ Component(์ปดํฌ๋„ŒํŠธ) ๋ผ๊ณ  ํ•œ๋‹ค.

Spring

image-29

์Šคํ”„๋ง ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์œ„์™€ ๊ฐ™์ด ๋ชจ๋“ˆํ™” ๋˜์–ด ์žˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๋จผ์ € Core Container๋ฅผ ์‚ดํŽด๋ณธ๋‹ค.

Spring DI(Core Container)

image-30

Container ๋Š” ๋‘ ๊ฐ€์ง€๋กœ ๋‚˜๋‰˜๋Š”๋ฐ Presentation Layer ์™€ Business Logic Layer ๋กœ ๋‚˜๋‰œ๋‹ค.

์ด ๋‘ ๊ฐœ๋ฅผ ํ•ฉ์น˜๋ฉด 2 Architecture Layer ๋ผ๊ณ  ํ•จ

Business Logic Layer ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ MemberDAOImpl ์ธ๋ฐ

๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹Œ DI ๊ฐ€ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ž„

Container ๋Š” DD ํŒŒ์ผ์„ ์ฝ๊ณ  Servlet ์„ ์ƒ์„ฑํ•จ (Components ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹˜)

์ด๋Ÿฌํ•œ DAOImpl ์„ DB ์™€ ์—ฐ๊ฒฐํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ JDBC Framework ์ด๋‹ค. (MyBatis, Hybernateโ€ฆ)

Presentation Layer ์„ ํ”„๋ ˆ์ž„์›Œํฌํ™” ํ•œ ๊ฒƒ์„ SpringMVC ๋ผ๊ณ  ํ•œ๋‹ค.

DI(Dependency Injection)

Container ๊ฐ€ ์ž‘๋™ํ•˜๋ฉด dd (web.xml =servlet ๋งคํ•‘ ์ •๋ณด๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Œ) ๋ฅผ ์ฝ๊ณ  Servlet ์„ ๋งŒ๋“ ๋‹ค.

์ธ๊ฐ„์˜ ์—ญํ• ์€ ์ฃผ๋ฌธ์„œ ์ž‘์„ฑ์ด๊ณ  ๊ธฐ๊ณ„๋Š” ๋ณต์žกํ•œ ์ž‘์—…์„ ํ•œ๋‹ค.

Container ๊ฐ€ Client ๋กœ ์š”์ฒญ์„ ๋ฐ›์œผ๋ฉด Factory ์—๊ฒŒ ์•Œ๋ฆฌ๊ณ  Factory ๋Š” component ๋ฅผ ๋งŒ๋“ ๋‹ค.

๋งŒ๋“ค์–ด์ง„ Component ๋Š” Business Logic์„ ํ˜ธ์ถœํ•œ๋‹ค.

์ด๋Ÿฌํ•œ Component ๋ฅผ ๋งŒ๋“œ๋Š” Factory ๋ฅผ DI Container๋ผ๊ณ  ํ•œ๋‹ค.

DI Container ์ค‘์— BeanFactory๋กœ ๋งŒ๋“ค์—ˆ์ง€๋งŒ ์ด๋ฒˆ์—” ApplicationContext๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

DI Container ๋Š” ๋งค์šฐ ๊ฒฝ๋Ÿ‰ํ•œ Container ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€๋‹ด์ด ์—†๋‹ค.

DI Container ๋Š” WAS์— ์˜ํ•ด ํ˜ธ์ถœ๋˜๋„๋ก ๋˜์–ด์žˆ๋‹ค.

DI Container๋„ ์ฃผ๋ฌธ์„œ๋ฅผ ์ฝ๊ณ  Component ๋ฅผ ๋งŒ๋“ ๋‹ค.

์–ด์ œ ๊ธฐ์ค€์œผ๋กœ ์ฃผ๋ฌธ์„œ๋Š” diceservice.xml ์ด๋‹ค.

๋จผ์ € vo ์ธ User class ์ž‘์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package spring.service.domain;
public class User implements Serializable {
	
		///Field
    private String userId; 			/* ํšŒ์› ID */
    private String password;     /* ๋น„๋ฐ€๋ฒˆํ˜ธ */
    private int age;    					/* ๋‚˜์ด */ 
    
    ///Constructor
    public User() {
		System.out.println("\n::"+getClass().getName()+" ๋””ํดํŠธ ์ƒ์„ฑ์ž....");
		}

		public User(int age, String userId) {
			System.out.println("\n::"+getClass().getName()+" age,userId ์ธ์ž ๋ฐ›๋Š” ์ƒ์„ฑ์ž....");
			this.age = age;
			this.userId = userId;
		}

		public User(int age, String password, String userId) {
			System.out.println("\n::"+getClass().getName()+"age,password,userId ์ธ์ž ๋ฐ›๋Š” ์ƒ์„ฑ์ž");
			this.age = age;
			this.password = password;
			this.userId = userId;
		}
		///Method (getter/setter)
		public String getUserId(){
			return this.userId;
		}
		public void setUserId( String userId ){
		   System.out.println("::"+getClass().getName()+".setUserId()");
		   this.userId= userId;
		}
		public String getPassword(){
		   return this.password;
		}
		public void setPassword( String password ){
		   System.out.println("::"+getClass().getName()+".setPassword()");		
		   this.password= password;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
	        System.out.println("::"+getClass().getName()+".setAge()");
			this.age = age;
		}
		
		@Override
		public String toString() {
			return "UserVO [userId=" + userId + ", password=" + password + ", age="+ age + "]";
		}
}//end of class
1
2
BeanFactory factory = 
				new XmlBeanFactory(new FileSystemResource("./src/main/resources/config/userservice01.xml"));

๋จผ์ € BeanFactory ๋ฅผ ํ†ตํ•ด DI ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค.

์ด์ œ userservice01.xml ์ฃผ๋ฌธ์„œ๋ฅผ ์ฝ๊ณ  bean์„ ์ƒ์„ฑํ•ด์ค€๋‹ค.

1
2
User user01 = (User)factory.getBean("user01");
System.out.println(user01);

id๊ฐ€ โ€œuser01โ€ ์ธ bean์„ ์ƒ์„ฑํ•œ๋‹ค.

์ด์— ํ•ด๋‹นํ•˜๋Š” ์ฃผ๋ฌธ์„œ๋ฅผ ์‚ดํŽด๋ณธ๋‹ค.

  1. setter ์ฃผ์ž… :: ๋‹จ์ˆœ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’ ์ฃผ์ž…
  2. User user01 = new User()
  3. user01.setUserId(โ€01์œ ์ €โ€)

    user01.setAge(โ€01โ€)

1
2
3
4
<bean id="user01" class="spring.service.domain.User">
	<property name="userId" value="01์œ ์ €"/>
	<property name="age" value="01"/>
</bean>

์ˆœ์„œ๋Œ€๋กœ ๋””ํดํŠธ ์ƒ์„ฑ์ž โ†’ setUserId() โ†’ setAge() ๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๋‹ค.

DI Container ์˜ Bean ์ƒ์„ฑ ์‹œ์ 

DI Container์—์„œ ๋นˆ ์ƒ์„ฑ ์‹œ์ ์€ ์–ธ์ œ์ผ๊นŒ?

  1. ์ฃผ๋ฌธ์„œ ์ฝ์ž ๋งˆ์ž ๋นˆ์„ ๋งŒ๋“œ๋Š”์ง€? (preloading)
  2. getBean()ํ•  ๋•Œ (์š”์ฒญ ํ• ๋•Œ) ๋งŒ๋“œ๋Š”์ง€? (lazy loading)
1
2
3
4
5
6
BeanFactory factory = 
				new XmlBeanFactory(new FileSystemResource("./src/main/resources/config/userservice01.xml"));

System.out.println("\n=============================================================================");
User user01 = (User)factory.getBean("user01");
System.out.println(user01);

::spring.service.domain.User ๋””ํดํŠธ ์ƒ์„ฑ์žโ€ฆ

::spring.service.domain.User.setUserId()

::spring.service.domain.User.setAge()

UserVO [userid=01์œ ์ €, password=null, age=1]

์œ„ Factory๋Š” BeanFactory๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.(=lazy loading)

๋‹ค๋ฅธ Factory์ธ ApplicationContext๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๋ฉด

1
2
3
4
5
ApplicationContext factory = new ClassPathXmlApplicationContext("/config/userservice.xml");
				
System.out.println("\n=============================================================================");
User user01 = (User)factory.getBean("user01");
System.out.println(user01);

::spring.service.domain.User ๋””ํดํŠธ ์ƒ์„ฑ์žโ€ฆ

::spring.service.domain.User.setUserId()

::spring.service.domain.User.setAge()

::spring.service.domain.User ๋””ํดํŠธ ์ƒ์„ฑ์žโ€ฆ

::spring.service.domain.User.setUserId()

::spring.service.domain.User.setAge()

::spring.service.domain.User.setPassword()

::spring.service.domain.User ๋””ํดํŠธ ์ƒ์„ฑ์žโ€ฆ

::spring.service.domain.UserAge,password,userId ์ธ์ž ๋ฐ›๋Š” ์ƒ์„ฑ์ž

::spring.service.domain.UserAge,password,userId ์ธ์ž ๋ฐ›๋Š” ์ƒ์„ฑ์ž

==========================================

UserVO [userId=01์œ ์ €, password=null, age=1]

์œ„์™€ ๊ฐ™์ด ํ˜„์žฌ ์ฃผ๋ฌธ์„œ์— ์ž‘์„ฑ๋˜์–ด์žˆ๋Š” ๋ชจ๋“  bean์„ ๋งŒ๋“ค์–ด ๋†“๊ณ  DI Container์— ์ €์žฅํ•ด๋‘๊ณ 

getBean() ์ด ํ˜ธ์ถœ๋˜๋ฉด ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋‘์—ˆ๋˜ bean๋งŒ return ํ•ด์ค€๋‹ค.

This post is licensed under CC BY 4.0 by the author.