Javascript Design Pattern 디자인 패턴

MNIII
9 min readApr 27, 2020

--

디자인 패턴은 다양한 이슈 해결에 도움을 주고 있고 공통의 규칙과 재사용 가능한 입증된 방법을 제시 하고 있다. 하지만 패턴이 모든 문제들을 해결하는 정확한 방법은 아니며, 문제 해결을 위한 체계를 제공하고 있다고 볼 수 있겠다.

패턴을 사용의 장점으로 코드 구조에 고민에 대한 시간을 줄이고 개발 프로세스의 사소한 문제들을 방지 할 수 있고, 일반화된 문서 제공이 가능하며, 불필요한 반복을 줄여 코드 전체 크기를 줄일 수 있다. 그리고 패턴을 알고 있는 개발자들과 의사소통이 빠르며, 패턴을 통해 새로운 패턴을 만들어 더 나은 코드를 만들어 볼 수도 있다.

Module

모듈은 하나의 블록으로 코드 단위를 분리하고 구성하는 필수 요소이다.

모듈을 구성하는 방법들

  • The Module pattern
  • Object literal notation
  • AMD modules
  • CommonJS modules
  • ECMAScript Harmony modules

이 중에서 Object literal notation 방법이 가장 일반적이다.

var obj = {
number: 0,
getNumber: function () {
console.log(this.number)
}
}
obj.getNumber() // 0

하지만 객체 외부에서 내부 number 변수에 접근이 가능하고, 브라우저에서 노출되는 자바스크립트는 전역에서 객체 리터럴 방법을 사용하게 되면 보안에 문제가 있을 수 있다.

Module Pattern

모듈 패턴은 구성 요소들을 다른 요소들로 부터 독립적으로 유지하는데 사용 되는 패턴이다.

(function() { 
// 비공개 변수, 함수 선언

return {
// 공개 변수, 함수 선언
}
})()

익명 함수나 클로저를 통해서 객체 내부 요소들을 캡슐화로 보호 할 수 있다.

var obj = (function() {
var number = 0
return {
getNumber: function () {
console.log(number)
}
}
})()
obj.getNumber() // 0
console.log(obj.number) // undefined

Revealing Module Pattern

공개 모듈 패턴은 모듈 패턴의 캡슐화를 유지하면서 모든 함수와 변수를 간단하게 정의하고 공개 하려는 기능에 대한 포인터를 반환하는 방법이다.

var obj = (function() {
var number = 0
var getNumber = function () {
console.log(number)
}
return {
print: getNumber
}
})()
obj.print() // 0
obj.getNumber() // Error

이 방법은 공개적으로 접근할 수 있는 변수, 함수들을 명확하게 하고 가독성이 좋다. 하지만 비공개 함수에 접근 할 방법이 없고 함수의 확장과 공개 함수의 수정에 어려움이 있다.

Singleton Pattern

싱글톤 패턴은 함수의 인스턴스를 하나만 유지하는 방법으로 여러개 객체를 생성 하더라도 최초의 객체를 사용하는데 이는 클로저를 사용하여 객체를 공유 한다.

var obj = (function () {
var instance
function init() {
var number = 0
return {
addNumber: function() {
return number++
},
getNumber: function () {
console.log(number)
}
}
}
return {
getInstance: function () {
if (!instance) {
instance = init()
}
return instance
}
}
})()
var first = obj.getInstance()
var second = obj.getInstance()
first.addNumber()
first.getNumber() // 1
second.getNumber() // 1
console.log(first === second) // true

싱글톤 패턴은 동일하게 연결이 필요한 객체를 생성 하거나, 단 하나만 존재해야되는 객체를 생성할 때 유용하게 사용 할 수 있다. 반면 숨겨진 의존성, 의존성 분리, 다중 인스턴스 생성에는 어려움이 있다.

Prototype Pattern

프로토타입 패턴은 객체를 효율적으로 생성 하는 방식으로 생성된 원본 객체를 복사해서 사용하고 객체를 생성하는 비용이 클때 사용 할 수 있다.

function person(name) {
function User() {}
User.prototype = {
name: '',
getName: function () {
console.log(this.name)
}
}
var user = new User() user.name = name return user
}
var developer1 = person('Jack')
var developer2 = person('Jack')
developer1.name = 'Hill'developer1.getName() // Hill
developer2.getName() // Jack

Observer Pattern

옵저버 패턴은 한 객체의 상태가 변경되면 그 객체에 의존하는 다른 객체에 알려 자동으로 갱신 되도록 하는 방식이다.

var UserObserver = (function(){
function Observer () {
this.observerList = []
}
Observer.prototype.register = function(observer) {
if (this.observerList.indexOf(observer) === -1) {
this.observerList.push(observer)
}
}
Observer.prototype.getName = function() {
this.observerList.forEach(function(observer) {
observer.print()
})
}
return Observer
})()
var User = (function(){
function User(name) {
this.name = name
}
User.prototype.print = function(meetingTime) {
console.log(this.name)
}
return User
})()
var user = new User('Jane')
var userObserver = new UserObserver()
userObserver.register(user)
userObserver.getName() // Jane

주객체와 관찰객체 간에 직접적인 영향을 주지 않아 상호의존성을 줄일수 있어서 변경에 유연한 편이다.

Factory Pattern

팩토리 패턴은 객체 또는 구성 요소 설정에 복잡성이 높고, 조건에 따라 인스턴스를 쉽게 생성 해야 하며, 동일한 속성을 공유하는 객체들이 반복적으로 필요할 때 사용 할수 있는 방식이다.

var Bike = (function(){
function Bike(options) {
this.color = options.color
this.wheel = options.wheel
}
Bike.prototype.show = function() {
console.log('Bike Color: ' + this.color + ' & Bike Wheel: ' + this.wheel)
}
return Bike
})()
var Truck = (function(){
function Truck(options) {
this.color = options.color
this.size = options.size
}
Truck.prototype.show = function() {
console.log('Truck Color: ' + this.color + ' & Truck Size: ' + this.size)
}
return Truck
})()
var abstractVehicleFactory = (function () {
var vehicles = {}
return {
add: function(type, Vehicle) {
if (Vehicle.prototype.show) {
vehicles[type] = Vehicle
}
},
create: function(type, option) {
var Vehicle = vehicles[type]
return (Vehicle ? new Vehicle(option) : null)
}
}
})()
abstractVehicleFactory.add('bike', Bike)
abstractVehicleFactory.add('truck', Truck)
var bike = abstractVehicleFactory.create('bike', {
color: 'blue',
wheel: 2,
})
var truck = abstractVehicleFactory.create('truck', {
color: 'red',
size: 'Big',
})
bike.show() // Bike Color: blue & Bike Wheel: 2
truck.show() // Truck Color: red & Truck Size: Big

코드를 작성하기 전, 개발 요구사항의 각 요소들이 다른 요소들과 어떤 관계를 가지고 어떻게 상호작용 하는지 알고 가능 하다면 디자인 패턴을 적절하게 적용 해 보도록 하자.

평소 이러한 디자인 패턴을 모르고 직관적 논리에 의해서만 개발 해왔다면 디자인 패턴을 적용 했을 때와 전후 코드를 비교해 보고 코드를 발전 시켜 보면 좋겠다.

--

--

No responses yet