후기 목록이 이렇게 생겼다.
<div className="grid grid-3">
<div>후기 1</div>
<div>후기 2</div>
</div>
보이는 건 <ul>/<li> 로 만든 것과 똑같다. 다른 것은 눈에 안 보이는 쪽이다 — 검색 엔진은 「여기 후기가 몇 개 있다」를 못 읽고, 화면 읽기 도구는 「목록, 항목 3개」를 안 알려준다.
안 A div 로 만들고 필요하면 role 로 알린다
안 B 역할에 맞는 태그가 있으면 그것을 쓴다
먼저: 재보니 SEO 쪽은 잘 되어 있었다
이건 원칙이 아니라, 문제를 잘못 짚을 뻔한 기록이다.
처음엔 헤딩이 문제일 거라 보고, 페이지 하나하나(라우트)마다 h1이 있는지 셌는데 두 번 틀렸다.
1차 h1 이 없는 라우트 6개 → 하위 폴더를 중복으로 세서 틀림
2차 h1 이 없는 라우트 6개 → grep -c 가 파일 하나일 때 형식이 달라 0으로 셈
3차 13개 라우트 전부 h1 이 있다 → 맞음
세 번째가 맞았다. 그리고 재보니 이쪽은 손댈 것이 없었다.
h1 13개 라우트 전부 정확히 하나 (분기 셋은 로딩·에러·정상이라 실제로는 하나)
헤딩 계층 Hero 가 h1, 각 섹션이 h2 — 순서가 맞다
JSON-LD lib/structured-data.js 에 LocalBusiness
metadata 14곳에서 내보낸다
여기서 JSON-LD는 검색 엔진이 사람 대신 기계로 읽도록 페이지 안에 적어 둔 구조화 데이터이고, metadata는 페이지 제목·설명을 코드에서 내보내는 Next.js 기능이다. 둘 다 이미 자리를 잡고 있어 손댈 것이 없었다.
「값이 말이 되는지 보고 다음으로 간다」가 두 번 걸렸다. /about 에 제목이 없다는 결과가 이상해서 파일을 열었고, 거기서 측정이 틀린 걸 찾았다.
먼저: 그런데 태그는 거의 전부 div 다
div 202 개
p 83 개
section 23 개 · h2 23 개 · main 20 개 · h1 18 개
article 5 개
ul 2 개 · li 2 개
aside 0 개
ul 이 2개다. 후기 목록도 FAQ 목록도 div 로 되어 있다.
후기 목록 <div className="grid grid-3">
FAQ 목록 <div className="faq-groups">
왜 그렇게 했는지 기록이 없다. 「격자 배치를 하려고」였을 수 있는데 ul 도 display:grid 가 되므로 그 이유는 성립하지 않는다.
원칙 1. 역할에 맞는 태그가 있으면 그것을 쓴다
무엇을 기준으로 태그를 고르는가.
안 A — div 로 만들고 필요하면 role 로 알린다. 태그를 외울 필요가 없고 div 하나로 다 된다. 버린 이유는 role 을 붙이는 것도 기억해야 하는 일이라는 것이다. 실제로 목록에는 role="list" 조차 안 붙어 있다. 태그를 안 외우는 대신 role 을 외워야 하면 아낀 것이 없다.
그리고 role 은 화면 읽기 도구에만 알린다. 검색 엔진은 role 을 구조로 읽지 않는다.
골랐다 — 안 B, 역할에 맞는 태그가 있으면 그것을 쓴다.
| 이런 것이면 | 이 태그 |
|---|---|
| 여러 개가 나열된다 | ul · li (순서가 뜻을 가지면 ol) |
| 용어와 설명이 짝이다 | dl · dt · dd |
| 떼어내도 말이 되는 글 하나 | article |
| 제목이 있는 구획 | section |
| 페이지의 본문 | main (페이지당 하나) |
| 길 안내 링크 묶음 | nav |
| 본문 옆에 딸린 것 | aside |
| 위 어디에도 안 맞는 순수 배치 | div |
div 는 마지막 칸이다. 「이 덩어리에 이름을 붙일 수 있나」를 먼저 묻고, 붙일 이름이 없을 때만 div 다.
대가는 CSS 를 다시 손봐야 하는 것이다. ul 은 기본 여백과 점(list-style)이 붙어 있어 지워야 한다. 그 몇 줄이 이 표준의 전체 비용이다.
원칙 2. 태그가 없는 것에만 role 을 쓴다
role 자체가 나쁜 것은 아니다. 지금 쓰이는 role 은 전부 올바르다.
role="tablist" · role="tab" HTML 에 「탭」 태그가 없다
role="dialog" 커스텀 팝업이다
role="status" 갱신되는 알림 영역이다
이것들은 네이티브 태그가 없어서 role 로 알리는 것이 정답이다.
판별은 한 줄이다 — 그 역할을 뜻하는 HTML 태그가 있는가.
있다 → 태그를 쓴다. role 을 붙이지 않는다
없다 → role 로 알린다
<ul role="list"> 처럼 태그와 role 을 겹쳐 쓰지 않는다. 태그가 이미 그 뜻이라 role 이 하는 일이 없다.
원칙 3. 안 쓰기로 했으면 그 이유를 파일에 적는다
원칙 1에 맞는 태그가 있는데 안 쓰기로 했다면, 왜 그랬는지를 그 자리에 적는다.
지금 후기 목록이 div 인 이유를 아무도 모른다. 판단이 있었는지, 그냥 그렇게 됐는지 알 수 없다. 이유가 안 적힌 판단은 되돌릴 근거도 없어서, 고치려 할 때마다 「혹시 무슨 이유가 있었나」를 처음부터 다시 확인해야 한다.
이건 만들 것인가 가져다 쓸 것인가 표준이 요구하는 것과 같은 기록이다. 거기서는 「왜 가져다 쓰지 않았나」를 적게 했고, 여기서는 「왜 그 태그를 안 썼나」를 적는다.
// ul 을 쓰지 않는 이유: <그 자리에서만 성립하는 사정>
<div className="...">
기본은 태그를 쓰는 쪽이다. 이유가 없으면 원칙 1을 따른다.
판단 기준 정리
| 질문 | 답 | 결론 |
|---|---|---|
| 무엇으로 태그를 고르나 | 역할에 맞는 태그가 있는가 | 「이 덩어리에 이름을 붙일 수 있나」 |
| 여러 개가 나열된다 | ul · li |
검색 엔진이 개수를 읽고 읽기 도구가 알린다 |
div 는 언제 쓰나 |
붙일 이름이 없을 때 | 마지막 칸이지 첫 칸이 아니다 |
role 은 언제 쓰나 |
태그가 없을 때만 | 탭·팝업·알림처럼 HTML 에 없는 것 |
태그와 role 을 같이 |
안 쓴다 | 태그가 이미 그 뜻이라 하는 일이 없다 |
| 태그를 안 쓰기로 했다 | 이유를 파일에 적는다 | 안 적으면 되돌릴 근거가 없다 |
ul 로 격자 배치가 되나 |
된다 | display:grid 는 어느 요소에나 걸린다 |
이 표준을 정하기까지
SEO 를 고려해야 한다는 말에서 시작했고, 처음엔 헤딩을 의심했다. 세어 보니 h1 이 없는 라우트가 여섯이라고 나와서 「제목 없는 페이지가 절반」이라고 적을 뻔했다.
그 숫자가 이상해서 파일을 열었고, 측정이 틀린 걸 찾았다. 두 번 틀렸다 — 처음엔 하위 폴더를 중복으로 셌고, 고친 뒤에는 grep -c 가 파일 하나일 때 파일:개수 형식이 아니라 개수만 내놓는 걸 놓쳤다. 세 번째에 재니 13개 라우트 전부 h1 이 정확히 하나였다.
그래서 이 글에 「SEO 쪽은 잘 되어 있었다」를 먼저 적었다. 헤딩 계층도 JSON-LD 도 metadata 도 손댈 것이 없다. 문제를 잘못 짚었으면 안 고쳐도 될 것을 고치게 했을 것이다.
남은 것은 태그였다. div 202개에 ul 2개. 후기 목록도 FAQ 목록도 div 다.
그런데 role 쓰임새를 보니 방향이 하나 정해졌다. role="tablist" · role="dialog" · role="status" 가 쓰이고 있었고 전부 올바른 사용이다 — 탭도 팝업도 알림 영역도 HTML 에 태그가 없다. 접근성을 의식하고는 있었다. 다만 목록처럼 태그가 있는 것까지 div 로 간 것이 문제였다.
그래서 기준이 「div 를 쓰지 마라」가 아니라 「태그가 있으면 태그를 쓴다」가 됐다. div 는 나쁜 태그가 아니라 붙일 이름이 없을 때 쓰는 마지막 칸이다.
왜 div 로 만들었는지 물었더니 기록이 없었다. 「격자 배치 때문」이었을 수 있는데 ul 도 display:grid 가 되므로 그 이유는 성립하지 않는다. 그리고 이유가 안 적힌 판단은 되돌릴 근거도 없다 — 그래서 원칙 3으로 「안 쓰기로 했으면 이유를 적는다」를 넣었다. 앞 표준이 「직접 만들었으면 이유를 적는다」로 정한 것과 같은 자리다.
정리
- 역할에 맞는 태그가 있으면 그것을 쓴다. 「이 덩어리에 이름을 붙일 수 있나」를 먼저 묻는다.
div는 마지막 칸이다. 붙일 이름이 없을 때만 쓴다.role은 태그가 없을 때만 쓴다. 탭·팝업·알림은 HTML 에 태그가 없어role이 맞다.- 태그와
role을 겹쳐 쓰지 않는다. 태그가 이미 그 뜻이다. - 태그를 안 쓰기로 했으면 이유를 파일에 적는다. 안 적으면 되돌릴 근거가 없다.
ul로도 격자 배치가 된다. 기본 여백과 점을 지우는 몇 줄이 이 표준의 전체 비용이다.
자신만의 철학을 만들어가는 중입니다.
댓글남기기