오늘 만든 변경사항은 다음과 같다.
오늘은 커밋이 많지는 않지만, 지금까지 중에서 가장 힘든 날이었던 것 같다. 오늘은 컴포넌트의 선형화를 구현했다. 여기서 말하는 선형화라고 함은, 어떤 컴포넌트를 문자열로 표현하는 것을 의미한다.

이 컴포넌트들을 모두 모아 AND라는 통합 컴포넌트를 만들고자 한다.

이 컴포넌트의 선형화는 다음과 같다. 이 컴포넌트가 components 목록의 0번째 요소이기 때문에 components[0].flatten()을 통해서 다음을 얻어낼 수 있다.
['integrated',
[-1, 4],
0,
[['not', [-6, 7], false],
['not', [-6, 1], false],
['not', [7, 3], true],
['or', [0, 3], [true, true]]],
[[[1, 0], [3, 0]], [[0, 0], [3, 1]], [[3, 0], [2, 0]]],
'AND',
[[0, 0], [1, 0]],
[[2, 0]],
[]]
이 컴포넌트에 NOT을 연결하여 NAND 컴포넌트를 만들고, 그것을 추상화하면 다음과 같다.
![]() |
|
['integrated',
[3, 4],
1,
[['integrated_blueprint'
[-1, 4],
[false, false, true, [true, true]],
0],
['not', [6, 4], false]],
[[[0, 0], [1, 0]]],
'NAND',
[[0, 0], [0, 1]],
[[1, 0]],
[['integrated',
[-1, 4],
0,
[['not', [-6, 7], false],
['not', [-6, 1], false],
['not', [7, 3], true],
['or', [0, 3], [true, true]]],
[[[1, 0], [3, 0]], [[0, 0], [3, 1]], [[3, 0], [2, 0]]],
'AND',
[[0, 0], [1, 0]],
[[2, 0]],
[]]]]
저번 시간에 올린 글에서는 컴포넌트의 복사와 붙여넣기, 저장과 불러오기 기능을 구현해야 하겠다고 했다. 컴포넌트의 선형화는 이러한 기능들을 구현하기 위한 중심 기능이다.
이 프로그램에서 컴포넌트를 선형화한다는 것은 다르게 말하면 컴포넌트를 문자열로 표현하겠다는 뜻이다. 문자열로 컴포넌트를 표현할 수 있으면, 그 컴포넌트를 문자열에서 다시 구현할 수 있고, 구조 그대로 새로운 오브젝트들을 만들 수 있게 된다. 또한, SchBoard 2는 온라인에서 다른 사람들과 함께 작업할 수 있게 만들 것이기 때문에 컴포넌트의 구조 등을 문자열로 만들어 전송할 필요가 있다. 따라서 모든 현상들을 문자열로 기술할 수 있어야 하는 것이다.
어떤 컴포넌트를 선형화하기 위해서는 그 컴포넌트를 이루고 있는 소켓과 와이어, 서브컴포넌트들이 어떻게 연결되어있는지를 문자로 표현할 수 있어야 하고, 그것을 통해 만들어진 결과를 사용하여 똑같은 구조를 다시 구현해낼 수 있어야 한다.
전작의 컴포넌트의 선형화에서 가장 안타까운 점은 선형화 결과가 너무 방대해진다는 것이었다. 일례로 논리곱 컴포넌트를 만들기 위해서는 논리합 컴포넌트와 논리부정 컴포넌트를 합쳐 드 모르간 법칙을 구현해야 하는데, 예전 방식에서는 각각의 선형화 내 논리곱 서브 컴포넌트가 독립적으로 논리합 하나, 논리부정 3개와 와이어 3개로 구현되어 있었다. 따라서 문자열 내에서 같은 구조를 반복하는 일이 많았다.
하지만 이번에는 컴포넌트 통합에 대한 ID를 각각 부여하여, 같은 통합에 의해 생긴 컴포넌트들을 각각 같은 ID로 구분해, 저장할 때에 구조에 대한 ID와 기본적인 위치 정보, 소켓 상태 등에 대한 정보만 보내고, 정확한 구조에 대한 구현은 아이디마다 따로 모아두어, 한 통합 ID에 대해 언제나 하나의 구현만 선형화 결과에 포함되어있도록 했다.
하지만 같은 구조를 가지고 있다고 해서 언제나 완벽히 동일한 작업을 수행하는 것은 아니다. 일례로, R-S Latch는 2개의 OR 컴포넌트와 4개의 NOT 컴포넌트로 구현할 수 있는데, 여기서 OR 컴포넌트의 입력과 출력이 서로 다르다. R-S Latch 구현 시에 이것을 무시하면 펄스가 발생하기 때문에 사용이 불편해지고, 이는 전작에서도 겪은 문제다.
전작에서는 모든 와이어와 소켓의 상태를 함께 저장하는 것으로 구현했으나, 이번에는 구조를 따로 저장하기로 했으므로 이것을 구현하는 데에 큰 애를 먹었다.
결국 이번에는 새로운 방식으로 선형화를 진행하기로 했다.
integrated 형태의 선형화 결과는 하나의 통합 컴포넌트를 의미한다. 이 선형화 컴포넌트는 실제로 컴포넌트가 어떻게 구현되어있는지, 그 구조를 포함한다. 즉, 이번 버전의 선형화에서는 같은 통합 컴포넌트에 대해 이러한 컴포넌트가 한 번만 등장해야 한다. 따라서 integrated_blueprint라는 형태의 선형화 결과 포맷을 제시했다.
integrated_blueprint 역시도 통합 컴포넌트를 구현하는 선형화 통합 컴포넌트인데, 여기에는 통합 컴포넌트의 구조는 담겨있지 않고, 구현할 통합 컴포넌트를 이루는 출력 소켓들의 상태와 통합 컴포넌트 구조 아이디만을 포함한다.
integrated 컴포넌트는 통합 컴포넌트 구조 선형화 컴포넌트, 즉, integrated 형태의 컴포넌트들의 집합을 가지고 있다. 하지만 integrated_blueprint 형태의 선형화 컴포넌트에는 integrated 형태의 선형화 컴포넌트가 포함되지 않는데, 이는 integrated 선형화 컴포넌트가 구현될 때에 integrated 컴포넌트에 있는 이미 존재하는 다른 integrated 컴포넌트들을 템플릿으로 활용하여 integrated_blueprint 선형화 컴포넌트를 구현하게 하도록 하기 위함이다. 실제로 선형화 컴포넌트의 구조화를 structify라고 하는데, 이 과정 속에서 위와 같이 동작을 진행한다.
다음 개발일에는 진짜로 복사/붙여넣기와 저장, 불러오기 기능을 구현해야겠다.
나는 SchBoard를 실행하면 사용할 수 있는 작업공간을 하나의 단위로 설정하고, 그 안에 각각의 Tab들, 각각의 추상화 컴포넌트들을 넣고자 한다. 즉, 저장과 불러오기는 하나의 작업공간 단위로 구현될 것이다.
여러개의 탭과 추상화 컴포넌트들을 함께 이르는 이 작업의 단위를 프로젝트라고 하자.