Development
0.배경
우연히 삼청동에 가끔, 여러 번 가게 되었다. 그 골목의 잔상이 종종 떠오르곤 했다. 골목은 조잡하다. 간판, 담, 기와, 전선, 새로 바른 벽이 한자리에 섞여 있다. 그런데 골목을 통으로 보면 안정된다. 왜 조잡한데도 전체가 안정되는 모순된 감정이 드는지를 생각한 것이 이 작업으로 이어졌다.
부분은 어긋나 있고, 전체는 가라앉아 있다. 산조 모듈은 그 모순을 칸으로 옮긴다. 칸은 붙거나 비거나 튀고, 장은 그 난잡을 하나의 비율 안에 둔다.
이를 참조하여, 자연의 프랙탈처럼 적용해 보게 되었다. 가지와 잎, 산의 능선처럼 가까운 데는 어긋나 있어도, 같은 비율이 반복되면 전체가 안정된다.
산조 모듈(Sanjo Module) 명칭
산조(散調)는 흩어질 산(散)과 가락 조(調)를 합친 말이다. 한국 전통 음악에서 산조는 장단이라는 박의 틀 위에서, 연주자가 가락을 밀고 당기며 미세한 엇박을 만든다. 이 이름은 그 출발점을 가져온다. 틀은 정해져 있고, 그 안의 가락은 어긋난다.
칸의 기준은 1:1.35로 고정된다. 그 위에 병합, 굴곡, 텐션이 칸을 밀고 당긴다. 정대칭 그리드에서 멈추지 않고, 같은 비례 안에 비대칭이 남게 하려는 작동을 이 이름이 가리킨다.
원소는 회색 면, 흰색 면, 가로선, 세로선, 점의 다섯이고, 강조색은 하나다. 산조는 반복 속의 변주라는 출발점이지, 장단과 그리드가 같다는 주장이 아니다. 아래의 1.35와 42°는 이 이름을 증명하지 않는다. 칸의 초기값을 어디서 읽었는지 적는다.
1.35를 안정한 비례로 읽은 기록, 그리고 그 비례가 42°로 열리는 계산.
Christopher Bartlett는 그림의 캔버스에서 1.35 근처의 변 비율이 반복되는 것을 읽고, Dirk Huylebrouck와 함께 그 비율을 χ(카이)로 적었다. χ는 약 1.355다. 황금비로 나뉘는 직사각형, 반 데르 란의 플라스틱 수, 데 라 호스의 코르도바 비례와 같은 자리에서 이야기된다. 산조 모듈의 1.35는 그 기록을 칸의 초기값으로 가져온 것이다. 생성기가 거리를 재서 얻은 법칙은 아니다.
42°는 같은 수의 다른 얼굴이다. 수평을 1로 두면, 42°로 올라간 빗변의 길이는 sec 42° = 1/cos 42° = 1.346이다. 모듈은 이 값을 1.35로 쓴다. 비율을 1.35에 정확히 맞추면 각은 arccos(1/1.35) = 42.2°다.
아래 선은 사진의 픽셀 위에서 다시 계산했다. 물체에서 잰 각이 42°가 아니면 42°라고 쓰지 않았다. 42° 선은 사진 속의 수평을 밑변으로 둔 작도다.



개발 도구
화면은 Next.js 15, React 19, TypeScript로 만든다. Vue가 아니고, Java 서버도 아니다. 따로 둔 백엔드가 없다.
생성기의 난수와 노이즈는 p5.js 1.11.2의 LCG와 Perlin을 이 저장소 안에 옮겨 둔 것이다. p5 런타임을 불러 오지 않는다. 포스터는 Canvas 2D로 그린다.
글자는 Sora, IBM Plex Sans KR, Cairo, Zen Kaku Gothic New, Manrope다. 스타일은 Tailwind CSS다.
// p5.js 1.11.2 random(). The runtime is not loaded.
const M = 4294967296;
const A = 1664525;
const C = 1013904223;
function lcg(state) {
const next = (A * state + C) % M;
return { state: next, value: next / M };
}개발한 사람
멀티미디어 공학과 디지털콘텐츠를 전공했다. 밴쿠버에서 culture technology를 이수하고, Vancouver Film School에서 Sound Design for Visual Media를 했다. 프로그래밍과 데이터베이스, UI와 UX, 후각과 향의 자격이 있다.
웹을 13년 만들었다. 디지털 인터페이스와 인터랙티브, 웹사이트와 디지털 서비스가 그 일이고, 프로젝트는 스무 개가 넘는다. 한국과 튀르키예에서 일했다. 이 모듈을 만든 작업실은 Sensory Studio다.
이 페이지는 포스터 생성기가 따르는 규칙이다. 삼청동에 우연히 가끔, 여러 번 가게 되면서 종종 떠오르던 잔상을 하나의 절차로 고정한 것이며, 1.35가 자연 법칙이라거나 관찰자가 이미 안정감을 느꼈다는 실험 결과는 아니다.
01기본 질서
기본 모듈은 너비 w, 높이 h = r w인 직사각형이다. 초기 비율은 r = 1.35 = 27/20이다. 열 C개, 행 R개를 놓으면 격자의 크기는 W = C w, H = R · 1.35 w다. 기본 판형은 10열, 12행, 셀 너비 48px이다.
병합과 내부 무늬가 바뀌어도 외곽과 기준 좌표는 그대로다. v1.0은 기본 셀을 1:1.35로 고정한다. 1:1.00, 1:1.20, 1:1.414, 1:1.618은 고정하기 전에 둔 비교이고, 1.414와 1.618은 초안에 적힌 소수 세 자리다.
02모듈 병합
격자를 왼쪽 위부터 훑는다. 아직 비어 있는 칸에서 확률 pₘ으로 병합을 시도한다. 후보는 2×1, 1×2, 2×2뿐이고, 경계 안이며 다른 모듈과 겹치지 않는 후보 중에서 하나를 고른다. 가능한 후보가 없으면 1×1로 남는다.
2×2만 1:1.35를 유지한다. 2×1과 1×2는 다른 비율이 된다. 그래서 1.35는 결과 전체의 비율이 아니라 기본 단위의 비율이다.
시도 확률과 병합 면적은 다르다. 병합 면적비는 두 칸 이상을 차지한 셀 수를 전체 셀 수로 나눈 값이며, 화면의 측정에 그 값이 표시된다.
03다섯 원소
Sanjo Module 디자인 체계의 아이덴티티를 구축하기 위해 선택한 회색, 하얀색, 검정색, 진핑크, 그리고 시각 이외의 감각이라는 다섯 원소는, 서로 다른 물리적·감각적 성질을 가지면서도 과도한 치우침이 없는 절대적 중성성과 그 침묵을 깨는 단 하나의 엇박자를 완성하기 위해 기획되었다.
본 시스템의 목적은 특정 색이나 감각을 강요하여 시각적 피로를 유발하는 것이 아니라, 관찰자가 어떤 환경에서도 정서적 안식을 느낄 수 있는 가장 중립적이고 유연한 바탕을 제공하는 것이다. 그러나 완벽한 무채색의 경직성을 극복하기 위해, 단 하나의 감각적 변주를 허용한다.
1. 회색. 치우침 없는 균형과 중립적 캔버스. 흑과 백 사이의 정확한 중간 지점에 위치한 회색은 어느 한쪽으로도 치우치지 않는 절대적 중립성을 상징한다. 시각적 자극을 배제하여 눈을 이완시키는 베이스이고, 다른 요소가 스며들 완충 지대를 형성한다.
2. 하얀색. 비워진 호흡과 여백의 공간. 백색은 1:1.35 그리드 사이로 공기가 드나들 수 있는 물리적·심리적 틈이다. 빛을 반사하여 공간을 확장하고, 인위적 감정이 개입되지 않은 여백을 전달한다.
3. 검정색. 엄격한 뼈대와 흔들리지 않는 침묵. 구조적 축을 잡아 주고 전체 톤을 가라앉힌다. 시각적 균형을 지탱하는 뼈대이며, 시스템에 정제된 신뢰감을 부여한다.
4. 진핑크. 경직성을 깨는 의도된 엇박자. 무채색의 중성이 차갑고 지루한 완벽으로 빠지지 않도록 넣은 온기다. 중성의 흐름을 해치지 않는 선에서 하나의 포인트로 작용한다.
5. 시각 이외의 감각. 후각과 촉각의 결. 시각이 과부하될 때 향과 손끝의 결은 다른 안정으로 이끈다. 평면 그래픽을 공간 경험으로 확장한다.
이 다섯 원소는 회·백·흑의 중성 위에 진핑크의 엇박자와 후각·촉각의 결을 더해, 정서적 안식을 주는 공감각적 모듈을 완성한다.
각 모듈은 다섯 원소 중 하나를 받는다. 초기 가중치는 임의로 둔 출발값이다.
| 원소 | 가중치 |
|---|---|
| 회색 면 | 19 |
| 흰색 면 | 11 |
| 가로선 | 27 |
| 세로선 | 20 |
| 점 | 23 |
가로선 가중치에는 다시 가로 가중 1.4를 곱한다. 그다음, 왼쪽에서 맞닿거나 위에서 맞닿은 모듈과 같은 원소의 가중치에 반복 계수 λ를 곱한다. 1이면 추가가 없고, 1보다 크면 이어지며, 1보다 작으면 반복이 줄어든다. 수정된 가중치로 다시 정규화해 하나를 고른다.
선과 점의 간격은 모듈 높이가 아니라 기본 셀 너비를 분할 수로 나눈 값이다. 그래서 병합된 모듈 안에서는 같은 밀도의 선이 길어지고, 위아래 모듈의 선은 1.35 비율 때문에 한 줄로 만나지 않을 수 있다.
Module
점, 선, 면이 칸을 만들고, 색과 시각 밖의 감각이 그 칸을 채운다.
01점Point
그리드 좌표 위에서 정대칭의 균형을 미세하게 비틀어주는 시발점이자, 산조의 엇박자를 만드는 노드(Node).
02선Line
점이 이어져 형성된 구조적 축으로, 1:1.35 비례와 42° 앙각 투시 왜곡을 지탱하는 뼈대.
03면Plane
선이 확장되어 이루어진 2차원 공간이자, 질감과 색채가 채워지는 감각의 캔버스. 기본 모듈 블록이다.
04하얀색White
그리드 사이로 공기가 드나드는 물리적·심리적 여백, 틈.
05그레이Gray
어느 한쪽으로도 치우치지 않는 절대적 중립성과 균형의 베이스.
06블랙Black
전체 구조를 단단하게 지탱하는 엄격하고 묵직한 뼈대와 침묵.
07강조색Accent
차가운 대칭의 경직성을 깨고 미세한 온기와 긴장감을 주는 의도된 엇박자 포인트(Warm Offset). 기본은 진핑크이고, 성향과 목적에 따라 바꿀 수 있다.
08시각 이외의 감각Sense
3D 입체적 결, 1:1.35 주파수 옥타브와 엇박자 앰비언트, Top–Middle–Base 비례의 텍스처 센트. 시각 밖의 감각으로 공간의 층고를 인지하게 하는 공감각적 요소.
04굴곡과 연결
직선 P(t)의 양 끝은 고정한다. 중간만 법선 방향으로 밀어낸다.
// The ends stay fixed. Only the middle moves.
function bend(t, p, a, phi) {
const e = Math.sin(Math.PI * t);
const f =
0.75 * Math.sin(1.3 * Math.PI * t + phi) +
0.25 * Math.sin(3.1 * Math.PI * t + 0.7 * phi);
return p + a * e * f;
}φ와 세기 계수는 선마다 다른 노이즈 값이다. 세기 계수는 0.45에서 1 사이이고, 진폭 A는 슬라이더의 픽셀 값에 그 계수를 곱한 것이다. 화면의 α는 그 픽셀 값을 셀 너비로 나눈 상대 진폭이다. 초안이 제안한 A = α w와 같은 양을 두 단위로 함께 보여 준다.
세로선 모듈의 약 40%에는 이웃한 두 선 사이에 짧은 가로 연결선이 하나 붙는다. 위치는 시드로 재현된다. 연결선은 휘지 않는다. 선의 단절, 방향 전환, 부분 중첩은 이 버전에 없다.
05색채
색은 다섯이다. 바탕은 White #FFFFFF다. 포스터가 놓인 지면이고, 화면의 바탕도 같다. 흰색 면은 같은 White이고, 가장자리는 Black으로 닫는다. Bone #E9DFD1은 바탕에 쓰지 않는다. 회색 면은 Charcoal #5A5757이다. 가로선, 세로선, 연결선, 점은 Black #000000이다. 진핑크 표식은 Base Punch #DF3C82다.
각 요소가 그 색을 쓰는 이유는 역할이 다르기 때문이다. 회색 면은 칸을 Charcoal로 채운 덩어리다. 흰색 면은 White이고, 테두리는 장식이 아니라 면의 가장자리다. 가로선과 세로선은 Black이고, 양 끝은 격자에 고정된 채 중간만 휘어진다. 세로선 사이의 연결선은 휘지 않는 짧은 Black 선이다. 점은 같은 Black으로 찍은 표식이다.
Base Punch는 여섯 번째 원소가 아니다. 모듈이 만들어질 때 8% 확률로 붙는 표식이고, 표식이 켜진 모듈에서만 보인다. 회색 면은 면 전체가 진핑크가 되고, 선은 네 줄마다 한 줄이 핑크가 되며, 점은 점 전부가 핑크가 된다. 흰색 면은 핑크 표식을 쓰지 않는다. 표식은 항상 보인다.
06글자
포스터의 글자는 Sora다. Jonathan Barnbrook과 Julián Moncada가 그린 기하 고딕이고, Google Fonts의 SIL 오픈 폰트 라이선스라 포스터에 그대로 심는다. 포스터의 제목, 본문, 숫자, 시드가 이 글자를 쓴다.
Sora에는 한글이 없다. 한글은 IBM Plex Sans KR로 이어 받는다. 영문은 Sora를 그대로 쓴다. 아랍어는 Cairo, 일본어는 Zen Kaku Gothic New, 터키어는 Manrope다.
07재현
같은 시드와 같은 구조 매개변수는 같은 모듈을 만든다. 난수와 노이즈는 p5.js 1.11.2의 LCG와 Perlin 구현을 따른다. 선 굵기, 분할 수, 핑크 표식 표시, 셀 너비는 모듈을 다시 뽑지 않고 그림만 바꾼다. 텐션은 병합 시도를 바꾸므로 모듈이 달라진다. 굴곡의 세기도 텐션을 곱한 뒤 그려진다.
p5.js의 이후 버전이 같은 수열을 보장하지는 않는다. 기록을 남길 때는 매개변수 복사로 남는 엔진 이름, 시드, 비율, 병합 시도 확률, 실제 병합 면적, 반복 계수, 굴곡, 원소별 셀 수를 함께 적으면 된다.
포스터 하단에는 시드와 그 장의 비율이 들어간다. 시트 전체의 가로는 1, 세로는 그 비율이다. 1:1.35이면 바깥 사각형도 1:1.35다. 칸이 그 비율보다 길게 쌓이면 좌우 여백이 늘고, 짧으면 위아래 여백이 늘어 격자는 가운데에 있다. 비교 시트는 다섯 비율을 같은 조건으로 나란히 저장한다. 바깥 비율을 맞추므로 시트 면적까지 같지는 않다.
08sanjoBalance
원소를 칸마다 독립으로 뽑으면 이웃이 서로를 바꾸지 않는다. v1.0은 배치한 뒤 S = 0.34B + 0.28R + 0.24C − 0.22D를 계산한다. B는 좌우·상하 명도 차이고, 작은 차이는 감점하지 않는다. R은 맞닿은 모듈이 달라지는 비율이 0.62 근처에 있는 정도다. C는 가로선이 가로선으로, 세로선이 세로선으로 이어지는 비율이다. D는 병합 면적과 같은 원소가 길게 이어진 길이다.
텐션 t에서 하한은 S_min = 0.62 − 0.34t다. t가 0이면 병합 시도와 굴곡이 0이다. t가 올라가면 설정된 병합 확률과 굴곡을 그 비율만큼 쓴다. 모듈을 넣은 뒤 S가 하한보다 낮고 그 모듈이 병합되어 있으면 1×1로 되돌린다. 그래도 낮으면, 이미 어두운 쪽의 회색 면은 흰색 면으로, 이미 밝은 쪽의 흰색 면은 회색 면으로 바꾼다. 반대편을 복제하지는 않는다.
놓는 동안의 관계도 있다. 넓은 회색 면 옆에서는 점의 가중치가 올라가고, 병합된 세로선 옆에서는 세로선이 이어질 가중치가 올라간다. 한 쪽이 다른 쪽보다 밝으면 그 쪽에 회색 면이, 어두우면 흰색 면이 나올 확률이 커진다.
목표는 안정성을 최대로 만드는 것이 아니다. 하한을 지키면서 원소 분포의 변화 V를 남기는 것이다. S와 V는 이 시스템이 정의한 수이지, 사람이 느낀 안정감의 측정이 아니다.
09아직 측정하지 않은 것
안정감, 자연스러움, 통일성, 복잡성, 리듬, 선호는 관찰자가 답해야 하는 항목이다. 화면의 좌우·상하 명도는 색의 상대 휘도를 면적으로 가중해 추정한 값일 뿐, 그 답을 대신하지 않는다.
한국 전통 경관과의 대응, 프랙탈 자기유사성의 수치 검증, 여러 문화의 색채 데이터, 타일과 직물의 제작 제약도 이 생성기에 들어 있지 않다. 이름의 산조는 반복 속의 변주라는 출발점이지, 장단과 그리드가 같다는 주장이 아니다.
