가로 세 줄. 이 단순한 아이콘 하나가 어쩌다 모바일 웹의 상징이 됐을까. 처음 보는 사람도 이 세 줄을 누르면 메뉴가 나온다는 걸 아는 세상이 됐지만, 정작 이걸 제대로 구현하는 일은 반응형에서 손에 꼽게 까다롭다. 나는 이 세 줄 버튼 하나에 며칠을 매달린 적이 있다. 열고 닫는 것까지는 쉬웠는데, 열린 다음이 문제였다.


내비게이션은 화면 폭에 따라 겉모습만 바뀌는 게 아니라 아예 다른 물건이 된다. 데스크톱에서는 상단에 가로로 쭉 펼쳐진 메뉴가, 모바일에서는 아이콘 하나로 접혔다가 옆에서 미끄러져 나오는 패널이 된다. 같은 메뉴인데 형태와 동작이 통째로 달라진다. 이번 편은 이 변신을 어떻게 매끄럽고 안전하게 만드는지, 그리고 그 과정에서 내가 빠졌던 함정들을 이야기한다.

1. 왜 메뉴는 통째로 바뀌나

데스크톱 상단 메뉴는 넓은 가로 공간을 전제로 한다. 항목 대여섯 개를 한 줄에 나란히 늘어놓아도 자리가 남는다. 그런데 이 가로 줄을 좁은 휴대폰에 그대로 얹으면, 항목들이 서로 밀치다가 두세 줄로 접히거나 화면 밖으로 튀어나간다. 나는 데스크톱 메뉴를 그냥 축소해서 모바일에 넣었다가, 항목 글자가 반 토막씩 잘리는 꼴을 봤다.


그래서 좁은 화면에서는 메뉴를 평소엔 숨겨두고, 필요할 때만 꺼내 보는 방식으로 바꾼다. 항상 펼쳐두기엔 자리가 없으니, 접어뒀다가 사용자가 원할 때 펼치는 것이다. 이 접기와 펼치기가 모바일 내비게이션의 뼈대다. 화면이라는 부동산이 좁을수록, 안 쓸 때는 치워두는 살림이 필요해진다.


여기서 중요한 판단이 하나 있다. 무엇을 접고 무엇을 남길지다. 나는 자주 쓰는 핵심 동작 한둘은 접지 않고 화면에 그대로 두고, 나머지 부차적인 항목만 메뉴 안으로 넣는다. 검색이나 로그인처럼 손이 자주 가는 것까지 세 줄 아이콘 뒤에 숨기면, 사용자는 매번 메뉴를 열어야 하는 수고를 진다. 접는 것도 요령이 필요하다.


접는다는 건 따지고 보면 사용자에게 한 번의 추가 동작을 요구하는 일이다. 메뉴를 열려면 아이콘을 누르고, 패널이 나오길 기다리고, 그 안에서 원하는 항목을 찾아야 한다. 이 세 걸음이 별것 아닌 것 같아도, 자주 오가는 항목이라면 매번 반복되는 이 비용이 쌓인다. 나는 무언가를 접기로 할 때마다, 이걸 접어서 아끼는 화면 공간이 이 추가 동작의 값어치를 넘어서는지를 저울에 올린다. 공간을 아끼려다 사용자의 손가락을 더 부리는 거래일 수 있기 때문이다.

2. 햄버거라는 오래된 관습

세 줄 아이콘을 흔히 햄버거라 부른다. 빵 사이에 패티가 든 모양을 닮아서다. 이 아이콘은 이제 워낙 널리 쓰여서, 설명 없이도 대부분의 사람이 메뉴라는 걸 안다. 관습의 힘이다.


그런데 이 관습을 두고 오래된 논쟁이 있다. 아이콘만 덩그러니 있으면 그 안에 뭐가 들었는지 미리 알 수 없어, 사용자가 눌러보기 전엔 메뉴의 존재조차 모를 수 있다는 지적이다. 실제로 여러 실험에서, 세 줄 아이콘 옆에 메뉴라는 글자를 함께 붙였을 때 사람들이 그걸 훨씬 자주 눌렀다는 결과가 나왔다. 나는 이 이야기를 알고 나서, 공간이 허락하면 아이콘 옆에 짧은 글자 라벨을 붙이는 쪽으로 기울었다. 아이콘 하나만 믿기엔 발견성이 아쉽다.


아이콘을 만들 때 내가 신경 쓰는 건 누르는 영역의 크기다. 세 줄은 시각적으로 작지만, 손끝이 닿는 영역은 넉넉해야 한다. 앞서 터치를 다룰 때 이야기한 그 최소 크기를 여기에도 적용해, 아이콘 자체는 작아도 누를 수 있는 상자는 크게 잡는다. 상징이 된 아이콘이라도 손끝에 인색하면 소용없다.


아이콘 위치도 은근히 중요하다. 오랫동안 세 줄 아이콘은 화면 왼쪽 위에 놓는 게 관습이었는데, 요즘 휴대폰은 세로로 길어져서 왼쪽 위 구석은 한 손으로 쥔 엄지가 가장 닿기 힘든 자리다. 나는 이 점을 알고 나서, 자주 여는 메뉴라면 엄지가 편히 닿는 오른쪽이나 화면 아래쪽 배치도 진지하게 검토한다. 관습을 따르는 게 편하긴 하지만, 그 관습이 큰 화면 시절에 굳은 것이라면 한 번쯤 의심해볼 값이 있다.

3. 옆에서 미끄러져 나오는 패널

접힌 메뉴를 꺼내는 방식으로 요즘 표준처럼 자리 잡은 게 오프캔버스 패널이다. 평소엔 화면 밖 옆에 숨어 있다가, 아이콘을 누르면 옆에서 스르륵 밀려 들어오는 서랍 같은 것이다. 위에서 아래로 펼쳐지는 방식도 있지만, 나는 항목이 많을 때는 옆에서 나오는 세로 패널이 스크롤하기 편해 즐겨 쓴다.


이 패널의 원리는 단순하다. 패널을 평소엔 화면 오른쪽 바깥에 완전히 밀어둔 상태로 두고, 열릴 때 그 밀어둔 값을 제자리로 되돌린다. 이 되돌아오는 움직임에 짧은 전환 시간을 주면, 패널이 툭 나타나는 게 아니라 부드럽게 미끄러져 들어온다. 나는 이 미끄러짐을 위치 자체를 옮기는 방식보다, 요소를 변형하는 방식으로 처리한다. 그래야 움직임이 매끄럽고 화면이 버벅이지 않는다.


패널이 나올 때 뒤 배경을 어둡게 덮는 것도 챙긴다. 패널만 나오고 뒤 화면이 그대로면, 지금 초점이 어디에 있는지 흐릿해진다. 나는 패널 뒤에 반투명한 어두운 막을 깔아, 시선이 자연스럽게 패널로 모이게 한다. 이 막은 보기 좋으라고 까는 게 아니라, 이 막을 누르면 패널이 닫히는 넓은 닫기 버튼 역할도 겸한다. 사용자는 패널 밖 아무 데나 누르면 닫힌다는 걸 직관적으로 안다.


움직임에 민감한 사용자를 위한 배려도 잊지 않는다. 앞서 선호 쿼리를 다룰 때 이야기했듯, 큰 미끄러짐 효과는 누군가에게 어지럼증을 부를 수 있다. 나는 움직임을 줄여달라는 설정이 감지되면 미끄러지는 전환을 걷어내고, 패널이 그냥 나타났다 사라지게 바꾼다. 화려한 슬라이드는 어디까지나 덤이고, 메뉴가 열리고 닫히는 기능 자체는 그 덤 없이도 온전해야 한다.

4. 열고 닫는 상태를 제대로 알리기

여기서부터가 내가 며칠을 매달린 진짜 어려운 부분이다. 화면에서 패널이 미끄러지는 건 눈에 보이지만, 화면을 소리로 듣는 사용자에게는 아무 일도 안 일어난 것과 같다. 메뉴가 열렸는지 닫혔는지를 눈이 아니라 다른 감각으로도 알 수 있어야 한다.


가장 흔한 실수는 세 줄 아이콘을 아무 의미 없는 상자로 만드는 것이다. 나도 처음엔 그냥 클릭되는 네모에 아이콘 그림만 얹었다. 이러면 스크린리더는 이게 버튼인지, 눌러서 뭘 하는 건지 전혀 읽어주지 못한다. 나는 이걸 제대로 된 버튼 요소로 만들고, 이 버튼이 메뉴를 여는 것임을 알리는 이름을 붙였다. 아이콘만 있고 글자가 없는 버튼에는 이름을 따로 달아줘야 소리로도 읽힌다.


다음으로 챙긴 게 열림 여부를 알리는 상태다. 버튼에 지금 메뉴가 펼쳐졌는지 접혔는지를 나타내는 표시를 달고, 누를 때마다 이 값을 뒤집는다. 그러면 스크린리더가 접힘, 펼침을 읽어주어, 눈으로 패널을 못 보는 사용자도 자기가 방금 연 건지 닫은 건지 안다. 이 상태 표시는 버튼이 제어하는 메뉴가 어느 것인지 가리키는 연결과 짝을 이룬다. 버튼과 메뉴가 서로를 가리키게 묶어두는 것이다.


이 상태를 눈에 보이는 아이콘 모양과도 맞춘다. 닫혔을 땐 세 줄, 열렸을 땐 가위표로 바뀌는 흔한 처리가 그것이다. 나는 눈에 보이는 아이콘 변화와 소리로 읽히는 상태 값이 늘 같이 움직이게 한다. 하나만 바뀌고 다른 하나가 안 바뀌면, 보는 사람과 듣는 사람이 서로 다른 화면을 겪게 된다.


자바스크립트 없이 이 여닫기를 구현하는 오래된 편법들도 있다. 숨은 체크박스의 체크 상태로 패널을 여닫거나, 주소의 특정 표식에 반응하는 방식으로 순수하게 스타일만으로 토글하는 식이다. 스크립트가 안 켜진 환경에서도 동작한다는 장점 때문에 한때 널리 쓰였다. 다만 이런 편법은 열림 상태를 소리로 알리는 표시를 함께 얹기가 까다로워, 나는 접근성을 제대로 챙겨야 하는 자리에서는 결국 제대로 된 버튼과 약간의 스크립트로 돌아왔다. 편법은 가볍지만, 그 가벼움의 대가를 누가 치르는지 봐야 한다.

5. 열린 뒤가 진짜다

패널을 여는 것보다 어려운 게 열린 상태를 제대로 다루는 일이다. 여기서 어설프면 열자마자 사용자가 길을 잃는다.


첫째로 뒤 배경의 스크롤을 잠근다. 패널이 열렸는데 뒤의 본문이 같이 스크롤되면, 사용자가 패널 안 항목을 밀려다 엉뚱하게 뒤 페이지를 밀어버린다. 나는 패널이 열리는 동안 본문 스크롤을 막아, 지금은 패널에만 집중하라는 신호를 준다. 이걸 안 하면 두 층이 동시에 움직여 정신이 없어진다.


둘째로 초점을 패널 안으로 데려온다. 키보드나 스크린리더 사용자에게는 지금 어디를 조작하는지가 초점의 위치로 정해진다. 패널을 열었는데 초점이 여전히 뒤 본문에 남아 있으면, 사용자는 열린 메뉴에 닿지도 못한 채 보이지 않는 뒤 페이지를 헤맨다. 나는 패널이 열리면 초점을 패널 안 첫 항목으로 옮기고, 닫히면 원래 눌렀던 그 아이콘 버튼으로 되돌린다. 이 왕복이 어긋나면 사용자는 자기 위치를 완전히 잃는다.


셋째로 초점을 패널 안에 가둔다. 열린 패널 안에서 키보드로 항목을 훑다가, 마지막 항목을 지나면 초점이 뒤 본문으로 새어 나가면 안 된다. 나는 열린 동안 초점이 패널의 처음과 끝 사이를 맴돌게 가둬, 사용자가 메뉴 안에서만 움직이게 한다. 이건 앞서 모달을 이야기할 때 나온 그 초점 가두기와 같은 원리다. 열린 패널은 사실상 작은 모달인 셈이다.


넷째로 닫는 길을 여럿 열어둔다. 아이콘을 다시 누르는 것 말고도, 뒤 배경 막을 누르거나 키보드의 빠져나가기 키를 눌러도 닫히게 한다. 사람마다 닫으려고 손이 가는 곳이 다르다. 나는 이 세 갈래를 모두 열어두어, 어떤 방식으로 닫으려 해도 통하게 한다. 여는 길은 하나여도, 닫는 길은 넉넉할수록 좋다.

6. 두 세계 사이를 잇기

모바일 패널과 데스크톱 가로 메뉴는 결국 같은 항목의 두 얼굴이다. 나는 이 둘을 별개로 만들지 않고, 하나의 메뉴가 화면 폭에 따라 다른 모습으로 나타나게 짠다. 좁은 화면을 기본으로 두고 세 줄 아이콘과 패널을 깔아둔 다음, 화면이 넓어지는 지점에서 아이콘을 감추고 항목들을 가로로 펼친다.


두 모습을 잇는 지점, 곧 세 줄 아이콘이 사라지고 가로 메뉴가 나타나는 폭을 어디로 잡느냐도 고민거리다. 나는 이 지점을 특정 기기 크기가 아니라, 메뉴 항목들이 한 줄에 무리 없이 다 들어가는 폭에서 잡는다. 항목이 다섯 개인 메뉴와 두 개인 메뉴는 가로로 펼 수 있는 최소 폭이 다르니, 그 폭도 메뉴마다 달라진다. 남들이 흔히 쓰는 숫자를 그대로 베끼기보다, 내 메뉴가 실제로 언제 줄바꿈되는지를 보고 정하는 편이 어긋남이 없다.


이 전환에서 가장 조심하는 건 상태가 어긋나 남는 것이다. 모바일에서 패널을 연 채로 화면을 데스크톱 폭으로 넓히면, 패널을 여닫던 상태가 데스크톱 가로 메뉴에 엉뚱하게 눌어붙는 일이 있다. 나는 화면 폭이 데스크톱으로 넘어가는 지점에서 열림 상태를 깨끗이 초기화해, 두 모습이 서로의 상태에 오염되지 않게 한다. 화면 폭을 넘나들 때 어정쩡하게 남은 상태가 가장 지저분한 버그를 만든다.


세 줄 아이콘이 유일한 답은 아니라는 것도 덧붙이고 싶다. 항목이 서너 개뿐이라면 굳이 접지 않고, 좁은 화면에서도 아이콘과 짧은 글자로 나란히 두는 게 더 빠르다. 화면 아래에 고정된 탭 막대가 어울리는 서비스도 있다. 나는 세 줄 아이콘을 관성적으로 집어넣기 전에, 이 메뉴가 정말 접어야 할 만큼 많은지부터 되묻는다. 접는 건 자리가 없을 때의 해법이지, 항목이 몇 개 없는데도 유행이라 따라 하는 장식이 아니다. 다음 편에서는 그 메뉴 글자를 화면에 그려내는 폰트 자체로 넘어가, 폰트를 어떻게 불러오고 언제 시스템 폰트에 기대야 하는지를 다룬다.