지난 편에서 요소에 우리만의 정보를 담는 법을 익혔습니다. 이번에는 이 시리즈의 마지막으로, 지금까지 만든 문서가 문법적으로 올바른지 검증하고 흔한 실수를 피하는 법을 다룹니다. 아무리 신경 써서 만들어도 사람은 실수를 합니다. 태그를 닫는 것을 잊거나, 요소를 잘못된 자리에 넣거나, 속성을 틀리게 쓰는 일이 생기죠. 이런 실수를 스스로 잡아내는 검증이 좋은 문서의 마지막 관문입니다.
제가 검증의 가치를 깨달은 것은, 이상하게 동작하는 페이지의 원인을 몇 시간 동안 찾다가 결국 태그 하나를 닫지 않은 사소한 실수였음을 알았을 때였습니다. 검증 도구에 넣었으면 몇 초 만에 찾을 문제를 사람 눈으로 찾느라 반나절을 허비한 것이죠. 그날 이후 저는 문서를 검증하는 것을 습관으로 삼았습니다. 이번 편에서 그 검증과 흔한 실수들을 정리하겠습니다.
1. 왜 검증하는가
문서가 문법적으로 올바르다는 것은 정해진 규칙을 어기지 않았다는 뜻입니다. 태그가 제대로 열리고 닫혔는지, 요소가 올바른 자리에 있는지, 속성이 규칙에 맞는지 같은 것들이죠. 브라우저는 문법이 조금 틀려도 나름대로 해석해 화면을 보여 주려 애씁니다. 그래서 문법 오류가 있어도 겉보기에는 멀쩡해 보일 때가 많습니다. 이것이 오히려 함정입니다.
겉보기에 멀쩡해도 문법 오류는 조용히 문제를 일으킵니다. 어떤 브라우저에서는 잘 나오던 것이 다른 브라우저에서는 깨지거나, 화면 낭독 프로그램이 구조를 잘못 읽거나, 예상치 못한 자리에서 배치가 어긋납니다. 브라우저마다 틀린 문법을 해석하는 방식이 조금씩 달라, 오류가 있으면 브라우저 사이의 일관성이 무너지는 것이죠.
그래서 문법을 올바르게 지키는 것은 브라우저 사이의 일관성과 접근성의 토대가 됩니다. 문법이 정확하면 모든 브라우저가 문서를 같은 방식으로 해석하고, 화면 낭독 프로그램도 구조를 제대로 읽습니다. 반면 문법이 틀리면 그 해석이 브라우저마다 제각각이 되어, 어디서 어떻게 깨질지 예측하기 어려워집니다.
이 문법 오류를 사람 눈으로 찾는 것은 무척 어렵습니다. 태그가 수백 개 든 문서에서 닫지 않은 태그 하나를 눈으로 찾는 것은 건초 더미에서 바늘 찾기와 같습니다. 그래서 이 일을 대신해 주는 검증 도구가 있습니다. 문서를 이 도구에 넣으면 문법 규칙을 어긴 곳을 콕 집어 알려 줍니다.
제가 검증 도구를 쓰기 시작한 뒤로 원인 모를 문제로 헤매는 시간이 크게 줄었습니다. 이상한 증상이 나타나면 먼저 검증 도구부터 돌려, 문법 오류가 원인인지를 빠르게 가려냅니다. 문법 오류가 없다고 확인되면 다른 원인을 찾고, 있으면 그것부터 고칩니다. 이 순서가 문제 해결을 훨씬 효율적으로 만들어 주었습니다.
정리하면 문법 검증은 겉보기에 드러나지 않는 오류를 잡아 브라우저 사이의 일관성과 접근성을 지키는 관문입니다. 사람 눈으로는 찾기 어려운 오류를 도구가 대신 찾아 줍니다. 이제 그 도구가 흔히 잡아내는 실수들을 살펴보겠습니다.
2. 태그와 식별자의 실수
검증에서 가장 흔히 걸리는 실수가 태그를 닫지 않은 것입니다. 대다수의 태그는 여는 것과 닫는 것이 짝을 이루어야 하는데, 닫는 것을 잊으면 그 태그의 범위가 엉뚱하게 늘어나 뒤의 내용까지 그 안으로 빨려 들어갑니다. 이 하나의 실수가 문서 뒷부분 전체를 어그러뜨릴 수 있습니다. 그래서 태그를 열면 닫는 것을 반드시 챙겨야 합니다.
닫는 것을 잊는 것과 반대로, 여는 것과 닫는 것의 짝이 어긋나게 겹치는 실수도 있습니다. 두 태그를 감쌀 때는 안쪽에서 연 것을 안쪽에서 먼저 닫고 바깥 것을 나중에 닫아야 하는데, 이 순서가 뒤엉키면 구조가 꼬입니다. 태그는 상자를 겹쳐 담듯 안쪽부터 순서대로 닫아야 한다는 원칙을 지켜야 합니다.
식별자가 중복되는 것도 흔한 실수입니다. 요소를 유일하게 지목하는 식별자는 한 문서 안에서 겹치면 안 됩니다. 그런데 같은 식별자를 여러 요소에 붙이는 실수가 자주 일어납니다. 이렇게 되면 그 식별자로 요소를 지목할 때 어느 것을 가리키는지 불분명해져, 코드나 링크가 예상과 다르게 동작합니다.
이 식별자 중복은 특히 페이지의 여러 조각을 복사해 붙일 때 잘 생깁니다. 식별자가 든 조각을 그대로 복사하면 그 식별자가 두 곳에 존재하게 되니까요. 그래서 조각을 복사한 뒤에는 식별자가 겹치지 않는지 확인하는 습관이 필요합니다. 저는 복사 후에 이 점을 반드시 점검합니다.
대체 글이 빠진 이미지나, 목록 항목이 목록 밖에 놓인 것 같은 실수도 검증 도구가 잡아냅니다. 이미지에 대체 글이 없으면 접근성이 무너지고, 목록 항목이 제 목록 안에 있지 않으면 구조가 어긋납니다. 이런 실수들은 하나하나는 사소해 보여도 쌓이면 문서의 품질을 떨어뜨립니다.
아래는 태그 미닫힘과 식별자 중복의 잘못된 예와 올바른 예를 비교한 것입니다. 짝과 유일성에 주목하세요.
<!-- 잘못: 닫지 않음, 식별자 중복 -->
<p>문단<div id="x"></div><div id="x"></div>
<!-- 올바름 -->
<p>문단</p><div id="a"></div><div id="b"></div>
3. 중첩 규칙 지키기
요소를 다른 요소 안에 넣을 때는 지켜야 할 규칙이 있습니다. 아무 요소나 아무 요소 안에 들어갈 수 있는 것이 아닙니다. 어떤 요소는 특정 요소만 자식으로 받고, 어떤 요소는 특정 요소 안에는 들어갈 수 없습니다. 이 중첩 규칙을 어기면 브라우저가 구조를 이상하게 바로잡으려 하다가 예상치 못한 결과를 냅니다.
대표적인 예가 문단 안에 큰 덩어리 요소를 넣는 것입니다. 문단은 글의 한 단락을 담는 요소라, 그 안에 다시 큰 구획을 나누는 덩어리 요소를 넣을 수 없습니다. 이것을 넣으면 브라우저가 문단을 강제로 닫아 버려, 우리가 의도한 구조와 전혀 다른 결과가 나옵니다. 문단 안에는 글과 인라인 요소만 넣어야 합니다.
목록도 중첩 규칙이 엄격합니다. 목록의 직접적인 자식은 목록 항목만 될 수 있습니다. 목록 안에 항목을 거치지 않고 다른 요소를 바로 넣으면 규칙 위반입니다. 목록에 무언가를 담고 싶으면 반드시 항목 안에 담아야 합니다. 이 규칙을 어기면 목록 구조가 깨져 화면 낭독 프로그램이 잘못 안내합니다.
누를 수 있는 요소 안에 또 누를 수 있는 요소를 넣는 것도 금물입니다. 예를 들어 버튼 안에 링크를 넣거나 링크 안에 버튼을 넣으면, 사용자가 그것을 눌렀을 때 어느 것이 반응해야 하는지 모호해집니다. 누를 수 있는 요소는 겹치지 않게, 나란히 두어야 합니다. 이 규칙은 사용성과 접근성 모두를 위한 것입니다.
제가 중첩 규칙을 배우기 전에는, 원하는 모양을 만들려고 요소를 아무렇게나 겹쳐 넣곤 했습니다. 그러다 브라우저가 구조를 제멋대로 바로잡아 배치가 무너지는 일을 여러 번 겪었습니다. 중첩 규칙을 알고 나서는 그런 문제가 사라졌습니다. 규칙 안에서 원하는 모양을 만드는 법을 익힌 것이죠.
아래는 중첩 규칙을 어긴 예와 지킨 예를 비교한 것입니다. 문단 안에 덩어리를 넣은 잘못을 보세요.
<!-- 잘못 -->
<p>글 <div>덩어리</div></p>
<!-- 올바름 -->
<div><p>글</p></div>
4. 속성을 둘러싼 실수
속성을 쓸 때도 흔한 실수가 있습니다. 그중 하나가 있음과 없음만으로 뜻이 정해지는 속성을 잘못 다루는 것입니다. 이런 속성은 존재하기만 하면 참이고, 아예 없으면 거짓입니다. 그런데 이 속성에 거짓이라는 값을 넣으면 거짓이 되는 줄 아는 오해가 흔합니다. 값이 무엇이든 속성이 존재하는 한 참이므로, 거짓으로 만들려면 속성 자체를 빼야 합니다.
이 오해는 실제로 문제를 일으킵니다. 예를 들어 어떤 입력창을 필수가 아니게 하려고 필수 속성에 거짓을 넣으면, 여전히 필수로 동작합니다. 값이 거짓이어도 속성이 존재하니까요. 필수를 해제하려면 그 속성을 아예 지워야 합니다. 이 성질을 모르면 왜 해제가 안 되는지 몰라 한참을 헤맵니다.
속성값을 감싸는 따옴표를 빠뜨리는 것도 실수입니다. 값에 공백이나 특수한 문자가 있으면 따옴표로 감싸지 않을 때 값이 엉뚱하게 잘립니다. 그래서 속성값은 따옴표로 감싸는 것을 습관으로 하는 것이 안전합니다. 따옴표가 있으면 값의 시작과 끝이 분명해져 이런 문제가 생기지 않습니다.
같은 속성을 한 요소에 두 번 쓰는 것도 실수입니다. 실수로 같은 속성을 중복해 적으면 브라우저는 대개 앞의 것만 쓰고 뒤의 것을 무시합니다. 그래서 뒤에 적은 값이 반영되길 기대했다가 반영되지 않아 혼란을 겪습니다. 한 요소에 같은 속성은 한 번만 써야 합니다. 이것도 조각을 복사하다 보면 잘 생기는 실수입니다.
제가 이 속성 실수들 때문에 겪은 일 중 기억에 남는 것은, 있음과 없음으로 정해지는 속성에 거짓을 넣고 왜 해제가 안 되는지 오래 고민한 것입니다. 알고 보니 속성이 존재하는 한 참이라는 규칙 때문이었죠. 이 규칙을 알고 나니 허무할 만큼 간단한 문제였습니다. 검증 도구도 이런 실수를 잘 짚어 줍니다.
아래는 있음과 없음으로 정해지는 속성의 올바른 사용 예입니다. 존재 자체가 참임을 보세요.
<input type="checkbox" checked>
<input type="text" required>
5. 검증을 습관으로
검증은 한 번 하고 끝내는 것이 아니라 습관으로 삼아야 효과가 큽니다. 문서를 고칠 때마다 새로운 실수가 끼어들 수 있으니, 중요한 변경을 한 뒤에는 검증을 돌려 확인하는 것이 좋습니다. 그래야 실수가 쌓이기 전에 잡아, 나중에 원인을 찾느라 고생하는 일을 막을 수 있습니다.
검증을 사람이 매번 손으로 하는 것은 번거롭습니다. 그래서 이 검증을 자동으로 돌아가게 만드는 것이 좋습니다. 문서를 배포하기 전 단계에 검증을 끼워 넣어, 문법 오류가 있으면 배포가 멈추게 하는 것이죠. 이렇게 해 두면 오류 있는 문서가 사용자에게 나가는 것을 자동으로 막을 수 있습니다. 사람의 깜빡함에 기대지 않는 것이 핵심입니다.
이 자동 검증은 여럿이 함께 일할 때 특히 빛을 발합니다. 사람마다 실수하는 부분이 다르고 꼼꼼함의 정도도 다른데, 자동 검증은 누구의 작업이든 똑같은 기준으로 점검합니다. 그래서 팀 전체의 문서 품질을 일정한 수준으로 유지해 줍니다. 저는 여럿이 하는 일일수록 이 자동 검증의 가치가 커진다고 느낍니다.
검증이 알려 주는 것을 오류와 경고로 나눠 보는 안목도 필요합니다. 반드시 고쳐야 할 오류가 있는가 하면, 당장 문제는 아니지만 개선하면 좋은 경고도 있습니다. 오류는 우선 고치고, 경고는 상황을 보아 판단합니다. 모든 경고에 강박적으로 매달릴 필요는 없지만, 그렇다고 무시만 하는 것도 좋지 않습니다.
제가 검증을 습관으로 삼고 자동화한 뒤로, 문서의 품질이 눈에 띄게 안정되었습니다. 예전에는 배포한 뒤에야 문제를 발견해 허둥댔는데, 이제는 문제가 사용자에게 닿기 전에 걸러집니다. 검증에 들이는 작은 수고가 훨씬 큰 고생을 덜어 준다는 것을, 저는 여러 해에 걸쳐 확인했습니다.
이것으로 이 시리즈의 문법 편을 마무리합니다. 처음 문서의 뼈대를 세우는 것에서 시작해, 텍스트와 링크와 이미지, 표와 폼, 미디어와 메타 정보, 접근성과 검증까지 긴 길을 걸어왔습니다. 문법을 정확히 다루는 것은 화려하지 않지만, 좋은 웹 문서의 흔들리지 않는 토대입니다. 이 토대 위에서 여러분이 튼튼하고 모두에게 열린 웹을 만들어 가시길 바랍니다.