3.2 Blockly 와 빅데이터


Blockly는 지금까지 본 간단한 예제(미로 문제)뿐만 아니라 실제 데이터를 조작하는 알고리즘과 프로그램을 구성하는 것에 유용하다. 이번 장에는 “빅데이터” 스트림을 평가하고 조작하기 위해 Blockly를 사용하는 방법에 대한 학습을 시작할 것이다. 시작하는 스트림은 실제 빅데이터의 작은 버전들이다. 이 버전들은 학습의 도움으로 작업 중인 모든 데이터를 볼 수 있도록 사용된다. 그러나 구축하는 프로그램들은 이 작은 스트림들뿐만 아니라 실제 빅데이터 스트림에서도 동작한다.

 

3.2.1 Blockly의 동작

동작하는 Blockly 환경은 아래 그림에서 볼 수 있다. 이것은 Blockly 알고리즘을 반복적으로 개발하고, 실행할 수 있는 작업영역이다. 작업영역은 다섯 가지 주요 컴포넌트들로 구성된다.

  • 블록 메뉴 : 메뉴는 다양한 카테고리의 블록들을 가진다. 각 카테고리는 블록의 수를 포함한다. 블록은 선택되어질 수 있고, 알고리즘을 구성하는 영역에 삽입 될 수 있다. 각 메뉴의 내용은 아래에서 더 완전하게 설명한다.

 

  • 알고리즘 캔버스 : 이 영역은 알고리즘을 형성하기 위해 함께 조립된 블록 메뉴에서 선택된 블록들을 포함한다. 미로 블록과 마찬가지로, 이러한 블록은 의미있는 방식으로 함께 맞는다. 캔버스 오른쪽 아래 구석에 있는 휴지통 아이콘이 있다. 작업영역에 필요하지 않은 블록들은 작업 영역을 깨끗하게 하기위해 휴지통으로 끌어 올 수 있다.

 

  • 출력 영역 : 이 영역은 텍스트 출력(print 블록에 의해 생성) 및 선 그레프(“plot”블록에 의해 생성) 둘 다 출력한다. 이 그림에서 텍스트 출력 “30”(현재 온도)은 Blacksburg의 예상 온도에 대한 그래프와 함께 보여준다.

 

  • 상태 화면 : 이 영역은 알고리즘의 현재 상태를 보여준다. 이 영역의 컨트롤들은 단계적인 방식으로 실행되어 지도록 알고리즘을 허용한다. 현재 상태의 속성들과 속성 값들을 볼 수 있다.

 

  • 파이썬 코드 : Blockly 알고리즘에 해당하는 파이썬 코드를 볼 수 있다. 현재 파이썬 코드는 볼 수 없지만 궁금할 때마다 이 코드를 볼 수 있다. Blockly 표현과 파이썬 간의 대응되는 일부 부분을 인식 할 수 있어야 한다. Blockly 프로그램에 대한 파이썬 코드를 보는 것은 Blockly가 실제 프로그래밍 언어라는 것에 대한 증거이다. 결국 Blockly에서 프로그램 만드는 것은 파이썬으로 직접적이고 배타적으로 만드는 것으로 전환해야 한다. Blockly가 좋은 학습 도우미이지만, 결국 직접 파이썬을 사용하여 더 빨리 큰 프로그램을 작성할 수 있을 것이다.

../_images/Blockly-Environment.png
그림 3-11. Blockly에서 알고리즘을 탐색하기 위한 환경

 

Blockly 환경은 왼쪽 상단 영역(블록 메뉴와 알고리즘 캔버스 위)에 있는 컨트롤의 집합을 가지고 있다. “Run” 컨트롤은 캔버스에서 Blockly 프로그램을 실행한다. “Run” 컨트롤에 의해 실행된 프로그램에 의해 출력된 모든 결과가 출력 영역에 표시된다. “undo”와 “redo” 컨트롤들은 캔버스에서 한 마지막 작업을 회복 또는 반복한다. 블록을 실수로 지웠다면, “undo”컨트롤로 회복시킬 수 있다. “align” 컨트롤은 캔버스 왼쪽의 모든 블록들을 정렬한다. 출력, 속성 시각화, 파이썬 영역은 캔버스(“스택”) 또는 오른쪽(“옆에”) 캔버스에 배치 될 수 있다.

 

3.2.2 블록 찾기

블록의 팔레트는 세 가지 주요 카테고리로 구성되어 있다. 맨 위의 카테고리는 알고리즘의 기본 요소(속성, 계산, 결정, 반복, 기능 및 출력)에 대한 메뉴들이 포함되어있다. 중간 카테고리는 데이터의 다양한 형태(단순 값, 리스트 및 사전)에 대한 메뉴들이 포함되어 있다. 이 장에서 데이터의 형태에 대해 더 배울 것이다. 맨 아래 카테고리는 “빅 데이터” 스트림을 생성하는 블록들의 메뉴가 포함되어 있다. 이 데이터 스트림은 일기예보, 금융주, 지진, 미국의 범죄 보고서 및 도서에 대한 추상적인 것을 포함하고 있다. 메뉴 이름을 클릭하여 각 카테고리에 블록들을 알아볼 수 있다. 이 팔레트에는 당장 필요한 것보다 더 많은 블록들이 있다. 익숙하지는 않겠지만 곧 배울 것이다.


용어에 대한 단어가 여기에 필요하다. Blockly(그리고 많은 다른 프로그래밍 언어)에서 “변수 속성”(때때로 속성)으로 언급된 것은 “변수”로 지칭된다.


작업 영역에서 두 개의 원래 블록들이 남겨진 아래 작업 공간을 탐색해보아라. 이 절에서 문제를 해결할 수 있는 블록들이 무엇인지 알기 위해 각 카테고리에 사용 가능한 블록들의 셋을 보아라. 작업 영역에 블록들을 끌어다 놓고, 블록들을 혼합하고, 휴지통에 모든 블록들을 이동하여 작업 영역을 깨끗하게 하라.

날씨 메뉴에서 두 가지 블록들은 날씨 데이터에 대한 접근 권한을 주고, 주식 메뉴에 있는 두 가지 블록들은 주식 시장 데이터에 대한 접근 권한을 준다는 것을 알 수 있다. 이 블록들은 다음과 같다.

  • get temperature in: 선택한 도시에 대한 화씨 온도를 단일 수로 반환
  • get forecasted temperature in: 선택한 도시에 대한 다음 9일 동안 온도 예보에 수들을 리스트로 반환
  • get current stock of: 선택한 주식의 값의 현재 변화를 단일 수로 반환
  • get past stocks of: 선택한 주식의 값의 변화를 가장 최근 9개 수의 리스트를 반환

 

블록의 두 단일 번호를 반환하고 블록의 두 숫자의 목록을 반환한다. 이 블록들에 의해 반환된 데이터를 처리하기 위해 계산, 배열, 결정, 반복이 사용하는 작은 Blockly 프로그램 구성 방법을 예를 통해서 볼 수 있다. 동일한 기술은 지진, 범죄, 책에 대한 질문에 답변하기 위해 컴퓨터를 사용할 수 있다.

 

위 작업영역 예에서 함께 연결된 두 개의 블록들이 있다 : “Blacksburg, VA”가 선택된 도시에서 “print”블록과 “get temperature in” 블록 이다. 실행 버튼을 클릭하고, 출력 영역에 출력된 것(작업영역 아래)이 무엇인지 관찰한다.

“get temperature for”블록과 “get current stock for” 블록을 “print”블록과 조합하여 사용하는 질문에 대한 답변으로 작업영역에서 생산된 출력을 사용한다.

 

Multiple Choice Seattle, WA의 온도는 몇인가?




 

Multiple Choice 현재 거래되는 마이크로소프트의 주식가격이 상승하고 있나? 하락하고 있나?


 

 

Multiple Choice 알고리즘캔버스는 텍스트와 선, 그래프를 출력하는 부분이다.


 

Multiple Choice 작업영역에 필요하지 않은 블록들은 작업영역을 깨끗하게 하기위해 휴지통으로 끌어올 수 있다.




3.2.3 배열과 계산

“get temperature in”블록에 의해 반환된 온도는 Fahrenheit 척도로 계산한다. 대안 척도는 Celsius( 또는 Centigrade) 척도이다. 두 척도 사이의 전환은 다음과 같다.

Celsius = (Fahrenheit - 32)/1.8

 

다음 작업 영역은 Fahrenheit에서 Celsius로 온도 변화하는데 필요한 프로그램을 나타낸다. 이 프로그램에서 변환 계산은 수학 카테고리에 몇몇 블록들을 사용하여 수행된다. “set to”와 변수 블록은 변수 카테고리에 있다. print 블록은 텍스트 카테고리에 있다.

 

작업영역에서 코드는 동작의 배열을 사용한다.

  • 화씨의 현재 온도를 속성 “ftemp” 로 설정
  • 섭씨 온도 변환 계산 결과를 속성 “ctemp”로 설정
  • 변환된 온도를 출력

 

블록들을 조립하는 것은 여러 단계를 포함한다. 아래는 화씨에서 섭씨로 변환하는 것에 대한 블록들을 조립할 수 있는 방법을 도식화 한 도면이다. 화살표들은 블록들이 함께 연결된 방법을 보여준다. 어느 블록이 먼저 조립 되었는지에 대한 엄격한 순서가 없다.


../_images/Blockly-Fahrenheit-Celsius-Conversion.png

그림 3-12. 블록조립을 통한 온도변화 예제

 

속성 이름이 “ftemp”와 “ctemp” 블록을 만드는 것은 기본 블록들 중 하나의 이름을 변경하는 것이다. 예를 들어 “set ftemp to”블록을 만드는 것은 다음과 같다.

  • “set item to”블록을 변수 카테고리에서 작업영역으로 끌어다 놓는다.
  • 이름 “item”을 클릭하고, “변수 이름 바꾸기" 옵션을 선택한다.
  • 나타난 창에서 “item”을 “ftemp”로 이름 변경을 하고, OK버튼을 클릭한다.

 

비슷한 이름 변경은 변수 블록에서 수행한다.

또 따른 온도 척도는 Kelvin 척도이다. 화씨 온도는 Kelvin 척도에 다음과 같이 변환 될 수 있다.

Kelvin = 273.15 + ((Fahrenheit - 32) *5)/9

위의 작업 영역을 사용하여 화씨에서 Kelvin으로 변환하는 Blockly 프로그램을 구축한다. 아래 질문에 대한 답변으로 이 프로그램을 실행한다.

 

Multiple Choice Miami, FL의 온도는 켈빈으로 몇도인가? (반올림)




 

Multiple Choice Blacksburg, Va와 Miami, FL의 정확한 온도차이는 켈빈으로 몇도인가?(반올림)




 

Multiple Choice 위 그림 3-12을 설명한 것으로 옳지 않은 것은??




 

Multiple Choice Question Title
다음 리스트에 대한 설명으로 옳지 않은 것은??" opta="위의 리스트의 아이템은 총 7개이다." optb="위의 리스트의 아이템은 순서가 있다." optc="위의 리스트에서 5번째 아이템은 ‘f’이다." ]

 

3.2.4 반복에서 첫 번째 단계

지금까지는 데이터 스트림으로부터 검색된(현재 온도 또는 현재 주가) 단일 값을 다루었다. 다음 단계는 데이터의 스트림 작업 할 수 있는 도구를 개발하는 것을 시작한다. 즉, 스트림을 포함하고 있는 값들의 순서로 작업한다. 비록 시작은 작은 예제 스트림으로 작동했지만, 알고리즘은 작은 스트림으로 같은 종류의 더 큰 스트림에서도 동작한다. 단지 실행 시간이 더 오래 걸린다.

 

빅 데이터에서 효과적으로 동작하기 위해서 아래 두 가지 개념을 함께 가져가는 것이 필요하다.

  • list: 데이터 스트림을 표현하는 데이터 구조
  • iteration: 리스트의 각 아이템(한 번에 하나의 아이템)을 위한 알고리즘을 적용

 

데이터 스트림과 같은 리스트는 차례 차례 배치된 개별 아이템들의 간단한 배열이다. 1~9까지의 리스트는 다음과 같이 쓸 수 있다.

[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

 

대 괄호는 리스트를 둘러싸고 있고, 리스트에 아이템은 콤마로 분리되어있다. 리스트는 왼쪽에서 오른쪽으로 읽는다. 따라서 가장 왼쪽의 아이템은 리스트의 첫 번째 아이템이고, 가장 오른쪽의 아이템은 마지막 아이템이다. 위의 예에서, 숫자 1은 첫 번째 아이템이며, 숫자 9는 마지막 아이템이다.
데이터 스트림을 나타내는 목록을 처리하는 일반적인 패턴이 있다. 패턴은 아래의 3가지 단계로 되어 있다.

  1. 스트림 데이터의 변수 설정
  2. 변수가 반복에 각 단계를 위해 사용된 데이터 스트림의 아이템을 나타내는 곳에서 “for each”를 사용하여 반복을 수행
  3. 현재 아이템에 어떤 프로세싱을 적용

 

일반적인 구조는 각 아이템에 수행되는 전문화된 프로세싱의 종류에 의해 개별 문제에 적용할 수 있다. 프로세싱 단계는 아래의 4가지 종류 중 하나이다.

  1. uniform(균등) : 스트림의 각 아이템에 동일한 프로세싱을 적용
  2. Accumulate(누적) : 글로벌 속성이 각 아이템에 의해 업데이트 되고 스트림에 대한 글로벌 속성을 계산
  3. Filter(필터) : 처리하기 위해 스트림 내에 확실한 아이템을 선택하고, 다른 아이템들은 무시
  4. Transform(변환) : 어떤 방법으로 개별 아이템들을 변환함으로써 본 스트림으로부터 새로운 데이터 스트림을 생산

 

이 4가지 패턴의 예들을 각각 살펴볼 것이다. 첫 번째는 두 가지 패턴인, Uniform과 accumulate에 대해 살펴보는 것으로 시작할 것이다. 결정이 Blockly에서 표현되는 방법을 본 후, 마지막 두 패턴인 filter와 transform을 설명할 것이다.

 

Iteration: Uniform

아래의 Blocky 작업 영역은 uniform방법에서 데이터 스트림에 각 아이템을 처리하기 위해 리스트와 반복을 조합하는 예를 보여준다. 이 코드는 하나의 아이템 당 한줄로 데이터 스트림의 각 아이템을 간단하게 출력한다. 코드를 실행시키고, 다른 도시에 대한 데이터 스트림의 값들이 무엇인지를 참조하여라. 참고 : 모든 출력을 볼 수 있는 오른쪽의 스크롤 바를 사용해야 할 것이다.

위에 예는 uniform 프로세싱 중 하나이다. 데이터 스트림에 각 아이템은 출력되어진다. 배제되는 아이템들은 없다.

 

반복 : Accumulate(축적)

축적에 관련된 프로세싱의 예제는 기상 예측의 평균을 찾는 것이다. 평균을 찾기 위해, 데이터 스트림에 얼마나 많은 아이템들이 있는지 그리고 전체 온도가 예측을 통해서 하는 것인지 알아야 한다. 다음 작업 공간은 이것에 대한 Blockly 프로그램을 보여준다.

프로그램에서 데이터 스트림의 두 속성은 스트림에서 각 아이템을 검토한 것처럼 축적되고 있다. 하나의 속성은 스트림에서 아이템들의 수이다. 변수 “num-items”에 의해 표현되어지는 속성이다. 두 번째 속성은 데이터 스트림에서 모든 온도의 합이다. 변수 “total-temp”에 의해 표현되어지는 속성이다. 그 반복의 각 단계에서 “ set-to” 블록은 속성들이 업데이트될 때 사용된다. “set-to”블록은 그 블록에 끼워진 블록이 무엇이든지 표시된 값으로 선택되어진 변수를 업데이트 한다. 따라서, “set num-items to num-items + 1”은 “num-items”의 값에 1을 증가시킨다는 의미이다. 그리고 “set total-temp to total-temp + temp”는 “temp”의 값 만큼 증가되는 것을 의미한다.(반복의 이 단계에서 예측 온도) 누적 패턴의 중요한 부분은 누적에 사용되는 변수들을 초기화하는 것이다. 이 프로그램에서 두 변수 “num-items”와 “total-temp”는 0으로 초기화된다. 초기화는 첫 번째 반복에서 두 “set to” 블록들과 이어져 있어서 필요하다. 예를 들어, 0으로 초기화된 “num-items”가 반복의 첫 번째 단계에서 블록 “set num-tiems to num-items +1”(0+1의 결과로 num-items의 값으로 업데이트함)와 통한다.

데이터 스트림 프로세싱의 패턴은 각 반복에서 어떤 변수들이 데이터 스트림의 선택된 전역 속성들에 대해 정확한 값으로 증가하여 수집하기 때문에 “축적"이라고 한다. 이 경우 프로그램은 스트림의 아이템 수와 총 예상 온도에 대한 더 정확한 값을 누적한다.

연습문제 : 시원한 날의 수를 계산하고 반복 한 후 출력하라

 

3.2.5 결정(Decision)

특정 온도로 작업하는 것 외에 온도가 어떤 임계값 이상 또는 이하일 때를 알고 싶어 할 수 있다. 너무 높은 온도는 불쾌하게 뜨거울 수 있으며, 너무 낮은 온도는 불편하게 추울 수 있다. 예를 들어, 60도 아래는 “시원함", 60~70도는 “가벼움", 75~85도는 “따뜻함", 85도 이상은 “뜨거움"으로 모든 화씨 온도를 계산 할 수 있다. 아래 작업 영역은 현재 온도와 현재 온도가 “차가움"인지 “따뜻함"인지를 출력하기 위하여 결정 블록(Decisions 카테고리로부터) 사용한다.

위의 작업 영역에서 코드에 대해 주목해야 할 두 가지 중요한 것이 있다. 첫 째는 결정에 사용되는 블록이다. 이 블록은 “if” 테스트를 하기 위해 조건을 가고 있는 두 슬롯이 있다. 두 번째 조건은 첫 번째 조건이 거짓으로 확인된 경우에만 테스트된다. 왜냐하면 이 로직은 온도가 60도보다 작으면, 75~85도 사이에 있을 수 없기 때문이다. 그러므로 온도가 60도 보다 작으면, 결정 블록에 의해 “차가움"이 출력되고, 두 번째 조건을 평가하지 않는다. 그러나 60도 이하가 아니라면, “따뜻함"을 인쇄할 것인지 아닌지를 결정하기 위해 두 번째 조건을 평가해야 한다.

위에서 사용된 것처럼 Blocky에서 “if..do..else if..do” 결정 블록을 만드는 것은 약간 까다롭다. 아래 수행 방법이 있다.

  • Decisions 카테고리에서 “if..do” 블록을 선택한다. 블록은 단어 “if” 의 왼쪽에 파란 박스 안에 별표를 가지고 있다는 것을 주목해야 한다.

 

  • 파란 박스 안에 별표를 클릭해라. 팝업창에서 오른쪽에는 “if” 폼, 왼쪽에는 “else if”와 “else”폼이 있다. 왼쪽 “else if” 폼을 오른쪽 “if” 폼에 끌어넣어라. 그 자리 안에 들어갈 때 “if..do”블록이 변하는 것을 볼 수 있다.

 

  • 팝업을 닫기 위해서는 파란 박스 안에 별표를 눌러라.

 

위에 작업 영역에서 코드에 대해 주목해야 할 것은 두 번째 조건이다. 온도가 범위 내에 있는 경우, 테스트하기 위해 분할된 두 개의 관련 조건들이 있다.

  • 온도가 범위의 하한 값 이상
  • 온도가 상한 값 이하

 

두 개의 분할된 조건들을 하나의 복합 상태로 조합하기 위해 “and” 부울 연산자가 사용되어진다. 불울 로직에서 “and”연산자에 복합 조건은 두 가지 조건이 모두 참일때만 참이다(그렇지 않으면 거짓). 관련된 불울 연산자인 “or”연산자는 두 조건 중 하나가 참이면 참이다(그렇지 않으면 거짓). 복합 and/or 조건을 구축하기 위한 블록은 Logic(로직) 카테고리에 있다. 이 카테고리는 세 번째, 부울 연산자인 “not”을 포함하고 있다. 이 블록은 조건을 끼울 수 있는 하나의 슬롯을 가진다. “not”과 조건의 조합은 조건이 참이면 거짓, 거짓이면 참인 복합 조건을 형성한다. 예를 들어, 복합 조건

not (temp > 50)

 

  • 변수의 값이 50 또는 그 아래이면 참이다.
  • 변수의 값이 50 보다 위이면 거짓이다.

 

부정 조건은 부정 조건을 쉽게 이해할 수 있을 때 종종 사용되어진다.

 

연습문제 : 위에 법칙에 따라 온도를 cool, mild, wrm, hot으로 분류할 수 있는 blockly 프로그램을 작성하라.

 

 

Multiple Choice temp의 값이 65이면 복합조건 (temp > 40) and (temp < 70)은 참인가 거짓인가?


 

Multiple Choice temp의 값이 65이면 복합조건 (temp > 40) and (temp < 65)은 참인가 거짓인가?


 

Multiple Choice temp의 값이 65이면 복합조건 (temp > 40) or (temp < 70)은 참인가 거짓인가?


 

Multiple Choice temp의 값이 65이면 복합조건 (temp > 40) or (temp < 65)은 참인가 거짓인가?


 

Multiple Choice temp의 값이 65이면 복합조건 not (temp > 40)은 참인가 거짓인가?


연습문제. 온도를 각각 시원함, 미지근함, 따듯함, 더움으로 분류할 수 있는 Blockly 프로그램을 위의 조건에 맞춰서 짜도록 하여라.

 

3.2.6 재 반복

Blockly에서 결정이 표현되는 방법을 보았듯이 반복과 결정이 filter patter로부터 결합되는 방법을 볼 수 있다. 새 리스트 값이 변환 patter를 사용하여 기존 리스트에 만들어질 수 있는 방법을 고려할 수 있다.

반복 : 필터

다른 경우에는 특히 관심 있는 데이터 스트림에 특정 아이템들이 있다. 관심 있는 아이템을 찾고 관심 없는 것은 무시하는 스트림을 반복하여 데이터 스트림을 필터링 할 수 있다. 즉, 관심 있는 아이템들만 처리된다. 예를 들어, 예상 온도 데이터 스트림에 대해 예상된 시원한 온도만 출력할 수 있다. 이전 정의에 따라 차가운 온도는 60도 이하이다. 아래 Blokcly 작업 영역은 데이터 스트림을 필터링하는 패턴을 설명한다.

반복 : 변환

변환 패턴은 주어진 데이터 스트림으로 부터 새로운 데이터 스트림을 생성한다. 주어진 데이터 스트림의 각 아이템은 새로운 데이터 스트림의 각 아이템을 생성하기 위한 어떤 방법으로 변경된다. 예를 들어 예측 스트림에 각 아이템은 화씨 온도이다. 필요로 하는 것은 각 아이템이 같은 온도를 가지지만 섭씨로 측정된 데이터 스트림이다. 변화 패턴은 화씨 데이터 스트림에서 섭씨 데이터 스트림을 생성하기 위해 사용될 수 있다. 이 패턴은 아래 Blockly 프로그램에서 설명한다.

Blockly 프로그램은 생성할 데이터 스트림을 표현하기 위해 “Cstream”라는 이름의 새 리스트를 만든다. “Cstream” 리스트는 처음에 어떤 아이템도 포함하고 있지 않기 때문에 비어있는 것으로 초기화된다. 예상 데이터 스트림은 변수 “Fstream”을 초기화하는데 사용된다. “Fstream”리스트는 출력된다. 각각 출력된 값은 화씨로 될 것이다. 반복은 변환된 데이터 스트림"Cstream”을 생성한다.

  • “temp”로 표기되어진 아이템은 화씨 데이터 스트림으로부터 선택된다.
  • “celsius”의 값은 섭씨의 동일한 온도로 “temp” 를 변환한 결과를 설정한다. 이후 가독성을 용이하게 하기 위해 변환 결과는 가장 가까운 정수 값으로 반올림된다.
  • “ celsius”의 값은 화씨 데이터 스트림을 표현하는 Cstream”리스트에 추가된다.

반복이 완료되면, “Cstream”리스트가 출력된다. 프로그램을 실행하고, 원래 데이터 스트림과 새로운 데이터 스트림에서 변환된 값 간의 대응 관계를 볼 수 있다.

연습문제 : Kelvin 스케일로 온도 데이터를 변환하도록 위에 변환 Blockly 코드를 수정하라

 

3.2.7 패턴 조합

uniform(균등), filter(필터), accumulate(누적) 그리고 transform(변환) 각 패턴을 결합할 수 있다. 예를 들어, 아이템이 85도 이상(뜨거운 온도)의 온도일지라도, 섭씨인 데이터 스트림을 원할 수 있다. 이 데이터 스트림을 생성하기 위해 프로그램은 변환 패턴과 필터 패턴을 사용한다.

Leave a Reply

Your email address will not be published. Required fields are marked *

*