더북(TheBook)

큐 모듈 작성하기

앞 절에서 작성한 큐 코드의 작성자는 큐의 맨 뒤에 데이터를 저장하고 큐의 맨 앞에서 데이터를 가져오도록 설계했다. 하지만 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] 등의 문서에 소개되어 있다.

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