3 분 소요

코딩 패턴 - 즉시 실행 함수를 이용한 모듈화

연관있는 일련의 함수들을 모아 모듈화를 하면, 구조적이고 계층적으로 코드를 관리를 할 수 있어 가독성과 생산성이 좋아집니다. 기본적으로 클로저와 정보 은닉을 사용하므로 private 함수와 public 함수로 구분할 수도 할 수 있습니다.

다음에서 Module은 즉시 실행되어 publicFunc 함수를 메서드로 가진 개체를 리턴합니다. privateFunc은 빼고요. 이렇게 하면 privateFunc은 외부에서 접근할 방법이 없어 사용할 수 없고, publicFunc만 리턴된 개체를 통해 사용할 수 있습니다. 또한 publicFunc이 사용되는 한 Module내의 실행 환경이 소멸되지 않고 유지되므로, publicFunc에서는 privateFunc을 안심하고 사용할 수 있습니다.(클로저와 정보 은닉 참고)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Module = (() => { // 즉시 실행 함수입니다.
    const privateFunc = (a, b) => { // 외부에서 접근할 방법이 없습니다.
        return a + b;
    };
    const publicFunc = (a, b) => { // 외부에서 접근할 수 있도록 리턴합니다.
        return privateFunc(a, b);
    }; 

    // public 함수 선언들로 구성된 개체를 리턴합니다.
    return {
        publicFunc // 함수가 리턴되므로 함수 실행 환경이 소멸되지 않고 유지됩니다.
    };
})();

console.log('모듈의 public 함수 호출', Module.publicFunc(1, 2)); // 3
Module.privateFunc(a, b); // (X) 오류 발생. 접근할 수 없습니다.

코딩 패턴 - 즉시 실행 함수를 이용한 개체 선언

개체의 생성자 함수와 메서드들을 즉시 실행 함수를 이용하여 응집하면 코드의 가독성이 좋아집니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const User = (() => { // 즉시 실행 함수입니다.
    function User(name) { // #1
        this.name = name;
    };
    User.prototype.getName = function() { // 메서드는 프로토타입에 선언합니다.
        return this.name;
    }; 
    
    return User; // #1. 생성자 함수를 리턴합니다.
})();

const user1 = new User('Kim');
const user2 = new User('Lee');

console.log('즉시 실행 함수를 이용한 개체 선언', user1.getName()); // Kim
console.log('즉시 실행 함수를 이용한 개체 선언', user2.getName()); // Lee 

코딩 패턴 - MixIn을 이용한 메서드 동적 추가

mixIn 헬퍼 함수를 이용하여 개체의 메서드를 추가할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const user1 = {name: 'Kim'};
const user2 = {name: 'Lee'};

const getNameMixIn = (obj) => {
    obj.getName = function() { // this를 사용하므로 화살표 함수를 사용하지 않습니다.
        return this.name;
    };
}; 

// user1, user2에 getName 메서드를 만들어 줍니다.
getNameMixIn(user1); 
getNameMixIn(user2);

console.log('MixIn으로 추가된 메서드', user1.getName()); // Kim
console.log('MixIn으로 추가된 메서드', user2.getName()); // Lee

mixIn들을 모아 즉시 실행 함수를 이용한 모듈 개체로 리턴하면 주어진 mixIn들중에서 필요한 것만 선택해서 결합할 수 있습니다.

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
const user1 = {name: 'Kim'};
const user2 = {name: 'Lee'};

const MixInModule = (() => {
    const getNameMixIn = (obj) => {
        obj.getName = function() { 
            return this.name;
        };
    };
    const printNameMixIn = (obj) => {
        obj.printName = function() {
            console.log(this.name);
        };
    };

    // MixIn 함수 선언들로 구성된 개체를 리턴합니다.
    return {
        getNameMixIn,
        printNameMixIn,
    };
})();       

// user1, user2에 추가할 메서드들을 MixInModule에서 선택적으로 결합합니다.
MixInModule.getNameMixIn(user1); 
MixInModule.printNameMixIn(user2);

console.log('MixInModule에서 추가된 메서드', user1.getName()); // Kim
user2.printName(); // Lee 출력

또다른 방법으로는 MixIn개체를 만들고 Object.assign()으로 메서드를 추가할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const user1 = {name: 'Kim'};
const user2 = {name: 'Lee'};

const mixIn = {
    getName: function() {
        return this.name;
    },
    printName: function() {
        console.log(this.name);
    }
}; 

// user1, user2에 mixIn을 추가합니다.
Object.assign(user1, mixIn); // 기존 속성중 동일한게 있으면 덮어쓰고, 없다면 추가
Object.assign(user2, mixIn);

console.log('Object.assign()을 이용한 MixIn', user1.getName()); // Kim
user2.printName(); // Lee 출력    

코딩 패턴 - 정적 함수

정적 함수생성자 함수의 속성 기능을 이용하여 구현 할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const User = (() => { 
    function User(name) { 
        this.name = name;
    }
    User.prototype.getName = function() { 
        return this.name;
    }; 

    User.staticFunc = (msg) => { // 생성자 함수의 속성 메서드 입니다.
        console.log(msg);
    };
    
    return User; 
})();

const user1 = new User('Kim');
const user2 = new User('Lee');

console.log('개체의 메서드', user1.getName()); // Kim
console.log('개체의 메서드', user2.getName()); // Lee
User.staticFunc('생성자 함수의 속성 메서드입니다. 정적 함수와 유사합니다.');

코딩 패턴 - 클로저를 이용한 캡슐화

클로저를 이용하면, C++에서 클래스의 멤버 변수를 private로 은닉하듯이 감출 수 있습니다.

다음 예에서 count 변수는 함수 내부에서만 사용할 수 있는 변수이지만, 중첩 함수를 통해 내부에서만 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Counter() {
    let count = 0; // 외부에서 접근 할 수 없는 변수입니다. 마치 private와 유사합니다.

    this.inc = () => {
        return ++count;
    };
    this.dec = () => {
        return --count;
    };
};

const counter = new Counter();

console.log('counter', counter.inc()); // 1
console.log('counter', counter.dec()); // 0

댓글남기기