๐Ÿ’ป Software Engineering/Java Spring

Spring 101 - #4 ์Šคํ”„๋ง ๋””์ž์ธ ํŒจํ„ด Spring Design Pattern

MayKim51 2020. 7. 24. 11:02

ํฌ์ŠคํŠธ ์ œ๋ชฉ ๊ทธ๋Œ€๋กœ Spring ๊ธฐ์ดˆ๋ฅผ ๋‹ค์น˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ•˜๋Š” TIL ์„ฑ๊ฒฉ์˜ ์Šคํ”„๋ง ๊ธฐ์ดˆ ์š”์•ฝ ์‹œ๋ฆฌ์ฆˆ์ž…๋‹ˆ๋‹ค.
Java๋Š” ์•„๋Š”๋ฐ Spring์€ ๋ญ”์ง€ ๋ชจ๋ฅด๊ฒ ๋Š” ์ดˆ๋ณด์ž๋“ค์—๊ฒŒ ์œ ์šฉํ•˜๋„๋ก ์š”์ ๋งŒ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

Spring 101 ์‹œ๋ฆฌ์ฆˆ

Spring 101 - #1 ์ž๋ฐ”์™€ ์ ˆ์ฐจ์ /๊ตฌ์กฐ์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ
Spring 101 - #2 ์ž๋ฐ” ํ‚ค์›Œ๋“œ์™€ OOP ํŠน์„ฑ 4๊ฐ€์ง€
Spring 101 - #3 ๊ฐ์ฒด์ง€ํ–ฅ์„ค๊ณ„ 5์›์น™ SOLID
Spring 101 - #4 ์Šคํ”„๋ง ๋””์ž์ธ ํŒจํ„ด Spring Design Pattern


 

์š”๋ฆฌ OOP ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ
์š”๋ฆฌ ๋„๊ตฌ ๊ฐ์ฒด์ง€ํ–ฅ 4๋Œ€ ํŠน์„ฑ (Encapsulation, Abstraction, Extend, Polymorphysim ์บก์ƒ์ถ”๋‹ค)
์š”๋ฆฌ ๋„๊ตฌ ์‚ฌ์šฉ๋ฒ• ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„ ์›์น™ (SOLID - SRP, OCP, LSP, ISP, DIP)
๋ ˆ์‹œํ”ผ Design Pattern ์„ค๊ณ„ ํŒจํ„ด

 

#์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ = OOP ํ”„๋ ˆ์ž„์›Œํฌ

 

#๋Œ€ํ‘œ์ ์ธ ์Šคํ”„๋ง ๋””์ž์ธํŒจํ„ด

  • Adapter Pattern
  • Proxy Pattern
  • Decorator Pattern
  • Singleton Pattern
  • Template Method Pattern
  • Factory Method Pattern
  • Strategy Pattern
  • Template callback Pattern

 

#Class diagram, Sequence diagram ๋ณด๋Š” ํˆด - Amateras UML

  1. Amateras UML ๋ฐฐํฌ์‚ฌ์ดํŠธ: http://sourceforge.jp/projects/amateras/releases  > AmaterasUML.zip ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ
  2. ์••์ถ•ํ•ด์ œํ•œ jar ํŒŒ์ผ๋“ค์„ STS์˜ plugin์— ๋ณต์‚ฌ
  3. STS ์žฌ์‹คํ–‰ -> ์„ค์น˜ ์™„๋ฃŒ

๋ผ๊ณ  ์ฑ…์— ๋‚˜์™€์žˆ๋Š”๋ฐ ๋‚˜๋Š” ์ €๋ ‡๊ฒŒ ํ•ด๋„ ์„ค์น˜๊ฐ€ ์•ˆ๋ผ์„œ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ์„ค์น˜ํ–ˆ๋‹ค.
์„ค์น˜ ๋ฐฉ๋ฒ•์€ ์ด ๋ธ”๋กœ๊ทธ ๋‹ค๋ฅธ ํฌ์ŠคํŠธ (Amateras UML ๋งฅ๋ถ Eclipsed์— ์„ค์น˜ํ•˜๊ธฐ)์— ์ •๋ฆฌ ํ–ˆ๋‹ค.
(์„ค์น˜ํ•˜๊ณ  ๋‚˜๋‹ˆ ์ง„์งœ ๋„ˆ๋ฌด ์ข‹๋‹ค ใ… ใ… โค๏ธ)


#Adapter Pattern

:ํ˜ธ์ถœ๋‹นํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ชฝ์˜ ์ฝ”๋“œ์— ๋Œ€์‘๋˜๋„๋ก ์ค‘๊ฐ„์— adapter ๋ณ€ํ™˜๊ธฐ๋ฅผ ํ†ตํ•ด ํ˜ธ์ถœํ•˜๋Š” ํŒจํ„ด.

  • ๊ฐ์ฒด๋ฅผ Service์˜ ์†์„ฑ์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ์ฐธ์กฐํ•œ๋‹ค. 

Adapter Pattern - Adapater ServiceA์—์„œ ServiceA ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•œ๋‹ค!

 

#Proxy Pattern

: ์ œ์–ด ํ๋ฆ„์„ ์กฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ์ค‘๊ฐ„์— ๋Œ€๋ฆฌ์ž๋ฅผ ๋‘๋Š” ํŒจํ„ด. "์ž๋™์ฐจ - ํƒ€์ด์–ด" ๊ด€๊ณ„

  • Proxy(๋Œ€๋ฆฌ์ž)๋Š” IService์˜ interfacef๋ฅผ ๊ตฌํ˜„ + ์‹ค์ œ ์„œ๋น„์Šค์™€ ๊ฐ™์€ ์ด๋ฆ„์˜ method๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.
  • ์‹ค์ œ ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ณ€์ˆ˜๋ฅผ ๊ฐ–๋Š”๋‹ค (IService service = new Service();) - ํ•ฉ์„ฑ!
  • ์‹ค์ œ ์„œ๋น„์Šค์™€ ๊ฐ™์€ ์ด๋ฆ„์„ ๊ฐ€์ง„ method๋ฅผ client์— ๋ฐ˜ํ™˜ํ•œ๋‹ค (Proxy์˜ ๋ฉ”์†Œ๋“œ๋Š” abstract)
  • ์‹ค์ œ ์„œ๋น„์Šค ์ „ํ›„์— ๋ณ„๋„ ๋กœ์ง์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ’์€ ์ œ์–ดํ•˜์ง€ ์•Š๋Š”๋‹ค. (Decorator์™€์˜ ์ฐจ์ด)

package proxyPattern;

public class Proxy implements IService {
	IService service1;

	public String runSomething() {
		System.out.println("ํ˜ธ์ถœ์— ๋Œ€ํ•œ ํ๋ฆ„ ์ œ์–ด๊ฐ€ ์ฃผ๋ชฉ์ , ๋ฐ˜ํ™˜ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ");

		service1 = new Service();
		return service1.runSomething();
	}
}

Proxy class์—์„œ IService ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ํ›„, ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ๋ฅผ return ํ•œ๋‹ค

package proxyPattern;

public class ClientWithProxy {
	public static void main(String[] args) {
		// ํ”„๋ก์‹œ๋ฅผ ์ด์šฉํ•œ ํ˜ธ์ถœ
		IService proxy = new Proxy();
		System.out.println(proxy.runSomething());
	}
}

Client์—์„œ๋Š” Proxy ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด์„œ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•œ๋‹ค

 

# Decorator Pattern

: ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ์˜ ๋ฐ˜ํ™˜๊ฐ’์— ๋ณ€ํ™”๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด ์ค‘๊ฐ„์— decorator๋ฅผ ๋‘๋Š” ํŒจํ„ด

  • ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์€ Proxy์™€ ๊ฐ™์œผ๋‚˜, ๋‹จ Client๊ฐ€ ์ตœ์ข…์ ์œผ๋กœ ๋Œ๋ ค๋ฐ›๋Š” ๋ฐ˜ํ™˜๊ฐ’์— ์žฅ์‹์„ ๋ง์ž…ํžŒ๋‹ค.

 

#Singleton Pattern

: ์ธ์Šคํ„ด์Šค ํ•˜๋‚˜๋งŒ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํŒจํ„ด. (e.g. ์ปค๋„ฅ์…˜ ํ’€, ์Šค๋ ˆ๋“œ ํ’€, ๋””๋ฐ”์ด์Šค ์„ค์ • ๊ฐ์ฒด)

  • Private Generator
  • Static Variable
  • Static Method
  • ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ ์†์„ฑ์„ ๊ฐ–์ง€ ์•Š๋Š”๋‹ค.
package singletonPattern;

public class Singleton {
	static Singleton singletonObject; // ์ •์  ์ฐธ์กฐ ๋ณ€์ˆ˜

	private Singleton() {
	}; // private ์ƒ์„ฑ์ž

	// ๊ฐ์ฒด ๋ฐ˜ํ™˜ ์ •์  ๋ฉ”์„œ๋“œ
	public static Singleton getInstance() {
		if (singletonObject == null) {
			singletonObject = new Singleton();
		}

		return singletonObject;
	}
}

๊ณต์œ  ๊ฐ์ฒด์ด๋ฏ€๋กœ ์†์„ฑ์„ ๋˜๋„๋ก ๊ฐ–์ง€ ์•Š๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ •์„์ด๋‹ค. (์ฝ๊ธฐ ์ „์šฉ์€ ๊ดœ์ฐฎ์Œ.)

 

#Template Method Pattern

: ๋™์ผํ•œ ๋ถ€๋ถ„์€ ์ƒ์œ„ ํด๋ž˜์Šค๋กœ, ๋‹ฌ๋ผ์ง€๋Š” ๋ถ€๋ถ„๋งŒ ํ•˜์œ„ ํด๋ž˜์Šค๋กœ ๋ถ„ํ• ํ•˜๋Š” ์„ค๊ณ„ 
Animal Template์•„๋ž˜์˜ ๋ณผํŠธ ๊ฐ•์•„์ง€์™€ ํ‚คํ‹ฐ ๊ณ ์–‘์ด.

  • ์ƒ์œ„ ํด๋ž˜์Šค: ๊ณตํ†ต ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ…œํ”Œ๋ฆฟ method(Override method) + ์„ ํƒ์ ์œผ๋กœ overrideํ•˜๋Š” Hook method๋ฅผ ๋‘”๋‹ค

 

#Factory Method Pattern

: Override๋œ method๊ฐ€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํŒจํ„ด 
๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ ๋ฐ˜ํ™˜ํ•˜๋Š” method. ๊ฐ•์•„์ง€์™€ ๊ณ ์–‘์ด์˜ ๊ฐ์ž์˜ Toy.

  • Abstract Class๊ฐ€ 2๊ฐœ
package factoryMethodPattern;

public class Cat extends Animal {
	// ์ถ”์ƒ ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ
	@Override
	AnimalToy getToy() {
		return new CatToy();
	}
}

Override๋œ method๊ฐ€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค

Abstract Class๊ฐ€ ์œ„์•„๋ž˜ Animal, AnimalToy ๊ฐ 2๊ฐœ๋‹ค

 

#Strategy Patternโญโญโญโญโญ

:  ๋””์ž์ธ ํŒจํ„ด์˜ ๊ฝƒ์ธ Strategy Pattern! Client๊ฐ€ Strategy๋ฅผ ์ƒ์„ฑํ•ด ์ด๋ฅผ ์‹คํ–‰ํ•  Context์— ์ฃผ์ž…ํ•˜๋Š” ํŒจํ„ด

๊ตฌ์„ฑ์š”์†Œ - Strategy, Context, Client

  • ์ „๋žต ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์ง„ ์ „๋žต ๊ฐ์ฒด Strategy - interface
  • ์ „๋žต ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Context (์‚ฌ์šฉ์ž/์†Œ๋น„์ž) - runContext()
  • ์ „๋žต ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ Context์— ์ฃผ์ž…ํ•˜๋Š” Client (์ œ3์ž / ์ „๋žต ๊ฐ์ฒด์˜ ๊ณต๊ธ‰์ž) - strategy ๊ฐ์ฒด, Context ๊ฐ์ฒด ๋ชจ๋‘ ์ƒ์„ฑ! runContext๋ฅผ ์‹คํ–‰ํ•œ๋‹ค

 

#Template Callback Patternโญโญโญโญโญ

: Spring DI์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด. Strategy Pattern + ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•œ๋‹ค

package templateCallbackPattern;

public class Client {
	public static void main(String[] args) {
		Soldier rambo = new Soldier();

		rambo.runContext(new Strategy() {
			@Override
			public void runStrategy() {
				System.out.println("์ด! ์ด์ดˆ์ข…์ด ์ด! ์ด!");
			}
		});

		System.out.println();

	}
}

 

Refactoring : Context ์•ˆ์— Strategy ๊ฐ์ฒด ์ƒ์„ฑ์„ ๋„ฃ๋Š”๋‹ค.โญโญโญโญโญ

package templateCallbackPatternRefactoring;

public class Soldier {
	void runContext(String weaponSound) {
		System.out.println("์ „ํˆฌ ์‹œ์ž‘");
		executeWeapon(weaponSound).runStrategy();
		System.out.println("์ „ํˆฌ ์ข…๋ฃŒ");
	}

	private Strategy executeWeapon(final String weaponSound) {
		return new Strategy() {
			@Override
			public void runStrategy() {
				System.out.println(weaponSound);
			}
		};
	}
}

 

#Strategy & Template Callback & Refactored Template Callback - ๋ฐ˜๋“œ์‹œ ๊ธฐ์–ตํ•  ๊ฒƒ

์ด์™ธ์—๋Š” Spring MVC - Frong Controller Pattern, MVC Pattern, etc ๋“ฑ์ด ์žˆ๋‹ค.

 

#์ฐธ์กฐ

[์ฑ…] ์Šคํ”„๋ง ์ž…๋ฌธ์„ ์œ„ํ•œ ์ž๋ฐ” ๊ฐ์ฒด ์ง€ํ–ฅ์˜ ์›๋ฆฌ์™€ ์ดํ•ด, ๊น€์ข…๋ฏผ, ์œ„ํ‚ค๋ถ์Šค