큐 모듈 작성하기

    앞 절에서 작성한 큐 코드의 작성자는 큐의 맨 뒤에 데이터를 저장하고 큐의 맨 앞에서 데이터를 가져오도록 설계했다. 하지만 q라는 변수가 전역으로 선언되어 있으므로 이 함수를 거치지 않고 외부에서 데이터를 조작해버릴 수 있다. 그리고 이때 데이터의 무결성Integrity이 다음과 같이 깨질 수 있다.

    > enqueue(1)
    > q <- c(q, 5)  # 전역 변수 q를 조작
    > print(size())
    [1] 1
    > dequeue()
    [1] 1
    > dequeue()
    [1] 5
    > size()
    [1] -1
    

    보다시피 q의 외부에서 q에 직접 값을 할당해버린 탓에 실제로는 q 내부에 데이터가 2개 저장되어 있지만 size( )를 호출했을 때 크기가 1로 나타나는 문제가 있다. 이러한 문제를 막기 위한 방법은 큐 코드 전체와 관련된 변수를 한 함수 안으로 감추는 것이다.

    > queue <- function() {
    +   q <- c()
    +   q_size <- 0
    +
    +   enqueue <- function(data) {
    +     q <<- c(q, data)
    +     q_size <<- q_size + 1
    +   }
    +
    +   dequeue <- function() {
    +     first <- q[1]
    +     q <<- q[-1]
    +     q_size <<- q_size - 1
    +     return(first)
    +   }
    +
    +   size <- function() {
    +     return(q_size)
    +   }
    +
    +   return(list(enqueue=enqueue, dequeue=dequeue, size=size))
    + }
    

    이 코드가 앞서와 다른 점이라면 q와 q_size가 이제 queue( ) 함수 안에 있는 지역 변수라는 점이다. 따라서 이 변수들은 외부에서 접근이 불가능하다. 또 함수 enqueue( ), dequeue( ), size( )는 함수 queue( )의 반환 값이 되었고 이 값은 리스트로 반환되고 있다.

    이렇게 만든 queue( )는 다음과 같이 사용할 수 있다.

    > q <- queue()
    > q$enqueue(1)
    > q$enqueue(3)
    > q$size()
    [1] 2
    > q$dequeue()
    [1] 1
    > q$dequeue()
    [1] 3
    > q$size()
    [1] 0
    

    queue( ) 함수 호출 시 만들어지는 queue( ) 함수 내부의 지역 변수 q와 q_size가 생성되는 공간은 queue( ) 함수를 호출할 때마다 매번 새로 생성된다. 즉, queue( )를 다음과 같이 여러 개 만들어서 사용해도 데이터가 서로 섞이지 않게 된다.

    > q <- queue()
    > r <- queue()
    > q$enqueue(1)
    > r$size()
    [1] 0
    > r$enqueue(3)
    > q$dequeue()
    [1] 1
    > r$dequeue()
    [1] 3
    > q$size()
    [1] 0
    > r$size()
    [1] 0
    

    이러한 코딩 기법을 모듈 패턴이라고 하며, <Software for Data Analysis>[4]에 소개되어 있다. 그러나 모듈 패턴은 비단 R만의 전유물은 아니며, 자바스크립트에서도 같은 이름으로 널리 사용되어 <JavaScript Module Pattern: In-Depth>[5] 등의 문서에 소개되어 있다.

    신간 소식 구독하기
    뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.