하프톤 원리부터 각도까지, 망점이 만들어지는 방식

계조를 점 크기로 바꾸는 일

사진에는 끊기지 않는 계조가 있어요. 어느 지점이든 12% 회색일 수도, 13% 회색일 수도 있죠. 인쇄기에는 그런 단계가 없어요. 잉크는 종이에 묻거나 안 묻거나 둘 중 하나예요.

하프톤은 그 간극을 면적으로 메워요. 이미지를 일정한 격자로 나누고, 칸마다 점을 하나씩 찍되 그 자리가 얼마나 어두운지에 따라 점 크기를 정하는 거예요. 8%만 덮으면 되는 칸에는 작은 점이, 85%를 덮어야 하는 칸에는 옆 점과 거의 닿을 만큼 큰 점이 들어가요. 잉크 농도는 처음부터 끝까지 똑같고 달라지는 건 종이를 덮은 비율뿐이에요. 점이 하나하나 구분되지 않을 만큼 떨어져서 보면 눈이 칸마다 평균을 내주고, 그게 원본이 요구한 회색이 돼요.

하프톤 도구의 모든 설정은 결국 셋 중 하나를 건드려요. 칸을 얼마나 크게 나눌지, 격자를 어느 방향으로 돌릴지, 칸을 무슨 모양으로 채울지요.

인쇄에는 다른 방법이 없어요

옵셋 인쇄기는 사실상 정해진 농도의 잉크막을 얹어요. 여기는 절반 농도로, 저기는 진하게 찍어달라고 주문할 수가 없어요. 잉크가 재료에 닿는 방식은 대체로 사정이 비슷해서, 실크스크린은 메시가 열려 있거나 막혀 있거나 둘 중 하나고 레이저 프린터는 토너를 녹여 붙이거나 말거나예요. 조절할 수 있는 변수가 덮는 면적뿐이라, 오래된 신문지를 확대경으로 보면 그림이 점으로 흩어져요.

요즘 디자인이 하프톤을 쓰는 이유는 하나 더 있어요. 인쇄기와 상관없는, 그냥 그 느낌이에요. 만화나 리소 진, 실크스크린 포스터가 하프톤을 고르는 건 “인쇄된 것처럼 보인다”는 이유 하나 때문이거든요. 목적이 그쪽이면 아래 이야기는 지켜야 할 규칙이 아니라 고를 수 있는 선택지가 돼요. 다만 원래 무엇 때문에 생긴 규칙인지 알아야 어떤 걸 깨도 되는지 판단이 서요.

격자 간격이 곧 스크린 선수예요

인쇄에서는 하프톤이 얼마나 촘촘한지를 lpi, 1인치에 들어가는 점의 줄 수로 따져요. 신문은 85lpi 정도로 굵고 잡지 용지는 133~175lpi, 고급 코팅지는 200을 넘기기도 해요. 굵게 찍는 게 대충 하는 게 아니에요. 흡수가 잘 되는 종이는 잉크가 번져서, 촘촘한 점을 신문지에 찍으면 서로 뭉쳐 검게 뭉개지거든요. 브라우저 도구는 같은 개념을 픽셀 단위 격자 간격으로 다뤄요.

여기서 같이 봐야 할 숫자가 원본 해상도예요. 칸 하나는 원본의 작은 조각을 읽어 값 하나로 뭉치기 때문에, 칸 안에 최소한 몇 픽셀은 들어 있어야 읽을 게 있어요. 스캔할 때 쓰던 “해상도는 스크린 선수의 두 배”, 그러니까 150lpi에 300ppi를 맞추라는 경험칙이 바로 이 관계를 인쇄 단위로 말한 거예요. 원본이 감당하는 것보다 격자를 촘촘하게 두면 하프톤이 사진 대신 JPEG 압축 자국을 성실하게 그리기 시작해요.

인쇄할 계획이라면 굵은 쪽으로 잡는 편이 안전해요. 점이 0.3mm보다 작아지면 잉크가 번지면서 서로 붙어서, 화면에서 섬세해 보이던 어두운 부분이 통짜 검정으로 돌아와요.

격자를 왜 돌릴까요

잉크가 한 가지면 각도는 대체로 취향이고, 전통적인 답은 45°예요. 격자가 수직·수평으로 서 있으면 줄과 칸이 대놓고 보이는데, 기울여 두면 눈이 격자를 알아채기 훨씬 어려워요. 점이 뒤로 물러나고 그림이 앞으로 나오는 거죠.

잉크가 둘 이상이면 각도는 더 이상 미관 문제가 아니에요. 규칙적인 격자 두 개가 살짝 어긋난 채 겹치면 서로 간섭해서 훨씬 크고 물결치는 제3의 무늬가 생겨요. 이게 모아레고, 한 번 생기면 이미지를 통째로 망쳐요. 방법은 스크린끼리 각도를 최대한 벌리는 것뿐인데, 사각 격자는 90°마다 같은 모양으로 돌아오기 때문에 스크린 셋을 균등하게 벌릴 수 있는 최대 간격이 30°예요.

CMYK 관용 각도가 여기서 나와요. 검정 45°, 마젠타 75°, 시안 105°, 그리고 105°는 15° 격자와 같은 모양이에요. 이 셋이 종이 위에서 대비가 뚜렷한 잉크라서, 30°씩 벌려 두면 간섭이 크게 출렁이는 무늬 대신 촘촘한 로제트로 정리돼요. 노랑은 남은 자리인 90°로 밀려나 이웃과 15°밖에 차이가 안 나는데, 다른 잉크였다면 못 버틸 배치예요. 그래도 되는 건 흰 종이 위의 노랑이 워낙 대비가 약해서 거기서 생기는 간섭이 눈에 띄지 않기 때문이에요.

점 모양이 인상을 정해요

원은 신문 인쇄의 기본이자 하프톤 하면 떠오르는 모양이에요. 알아둘 성질이 하나 있는데, 점이 커지다 보면 위아래 좌우 이웃과 거의 동시에 닿아요. 그래서 어두운 구간 어딘가에서 흩어진 점이 한꺼번에 그물처럼 이어지고 톤도 거기서 툭 튀어요. 사각형은 50% 덮는 지점에서 네 변이 한 번에 만나 그 도약이 중간 톤에서 일어나고, 결과가 더 단단하고 그래픽해요. 마름모는 두 변이 먼저 닿고 나머지가 나중에 닿아서 톤이 고르게 이어져요. 인쇄에서 타원형이나 마름모 스크린이 기본이 된 이유가 이거예요. 선은 점 대신 굵기로 계조를 표현해서 동판화 같은 질감이 나고요.

설정만큼 중요한 게 원본이에요. 대비가 낮고 밋밋한 사진은 거의 모든 칸이 중간값으로 몰려서, 비슷비슷한 점만 잔뜩 깔리고 그림은 질감 속으로 사라져요. 대비를 올리면 어두운 곳은 꽉 찬 쪽으로, 밝은 곳은 빈 종이 쪽으로 벌어지면서 점이 그릴 게 생겨요. 하프톤용으로는 원본만 봤을 때 필요해 보이던 것보다 대비를 더 올려야 하는 경우가 많아요.

벡터로 뽑을까요, 래스터로 뽑을까요

SVG로 내보내면 점 하나하나가 진짜 도형으로 남아요. 옥외 광고 크기로 키워도 처음 그대로 선명하고, 색을 바꾸거나 일러스트레이터에서 점을 개별로 손볼 수 있고, 픽셀 대신 패스를 받아야 하는 커팅 플로터나 실크스크린 작업에도 그대로 넘길 수 있어요.

대신 도형 개수가 문제인데 그것도 꽤 험하게 늘어나요. 칸 수는 면적을 격자 간격의 제곱으로 나눈 값에 비례해서, 간격을 절반으로 줄이면 도형이 네 배가 돼요. 큰 캔버스에 촘촘한 스크린을 걸면 수십만 개까지 금방 올라가고, 그 정도 파일은 어떤 편집 프로그램에서 열어도 버벅여요. PNG는 성격이 정반대예요. 점이 몇 개든 비용은 픽셀 크기로 고정이고 어디서든 열려요. 그래서 인쇄나 대형 출력, 추가 편집으로 갈 굵은 그래픽 하프톤은 SVG가 맞고, 웹이나 크기가 정해진 레이아웃에 들어갈 고운 스크린은 PNG가 맞아요.

브라우저에서 직접 만들기

하프톤 효과 만들기 도구는 이 과정을 전부 기기 안에서 처리해요. JPEG·PNG·WebP·AVIF·GIF를 올리면 설정을 움직이는 대로 미리보기가 바뀌어요. 격자 간격은 440px, 격자 각도는 0180° 전 구간, 점 크기는 칸 대비 50150%인데 100%를 넘기면 점끼리 겹치면서 어두운 부분이 꽉 차요. 밝기와 대비는 −100+100 범위에서 점 크기를 정하기 전 톤을 다시 잡고, 뒤집기를 켜면 밝은 쪽으로 점이 커져요. 점 모양은 원·사각형·마름모·선 네 가지고, 색은 흰 바탕에 검은 점, 검은 바탕에 흰 점, 직접 고른 두 색, 배경 투명 중에서 고를 수 있어요. 투명은 PNG와 SVG 양쪽에서 유지돼요.

못 하는 것도 분명해요. 채널을 나누지는 않아요. 한 번 내보낼 때 격자 하나, 각도 하나, 점 색 하나이고 기준은 이미지의 밝기값이에요. 그러니까 위에서 이야기한 CMYK 네 각도는 인쇄물을 읽을 때 쓰는 배경지식이지 이 도구가 만들어주는 결과물이 아니에요. 배경을 투명으로 두고 색과 각도를 바꿔가며 여러 번 내보낸 뒤 직접 겹치면 비슷한 느낌은 낼 수 있지만, 채널을 나누는 건 직접 해야 하는 일이에요.

시작하기 전에 제한 두 가지는 알아두면 좋아요. PNG는 원본 해상도로 나오되 긴 변이 6,000px을 넘으면 그 크기로 줄여요. 그보다 크면 그리는 도중에 브라우저 메모리가 모자랄 수 있거든요. SVG는 도형이 60,000개를 넘으면 버튼이 잠기는데, 그 이상은 어디서 열어도 감당이 안 되는 파일이라서예요. 격자 간격을 몇 px만 키워도 대개 기준 아래로 내려가요. 하나 더, 투명한 이미지는 밝기를 재기 전에 흰 배경 위에 얹어서, 배경이 없는 로고를 넣어도 검은 덩어리가 아니라 종이 위의 그림처럼 하프톤이 걸려요.

이 과정에 업로드 자체가 없어요. 이미지를 읽고 계산하고 다시 그리는 일이 전부 브라우저 안에서 일어나서, 아직 공개되지 않은 클라이언트 사진으로 작업해도 파일이 서버로 전송되지 않아요.