이 글은 웹접근성 전문가로서 공공 웹사이트를 꾸준히 모니터링해온 기록의 일부입니다. 이 글은 정치적 성격이 아닌 정보접근성과 기술의 발전을 목적으로 작성되었습니다.

최근에서야 청와대 홈페이지가 개편됐다는 걸 알았습니다. 일이 바쁘다 보니 늦게야 알게 됐는데, 반가운 마음으로 바로 접속해봤어요.

국가의 얼굴이기도 한 홈페이지가 새 단장을 했다니 기대가 됐습니다. 그리고 접근성 관점에서 살펴보는 것은 저에게 꽤 자연스러운 일이 됐습니다.

청와대 홈페이지 개편과 웹접근성 - 모든 국민에게 열린 정부 웹사이트를 위한 제안
청와대 홈페이지 개편과 웹접근성 - 모든 국민에게 열린 정부 웹사이트를 위한 제안
이미지: Nanobanana AI로 생성

올해 초 설 연휴 관련 글을 통해 이 홈페이지를 한 번 점검한 적이 있습니다. 이번 글은 그 후속입니다. 개편된 홈페이지에서 무엇이 달라졌는지, 그리고 다음 단계로 나아가기 위해 무엇이 더 필요한지를 이야기해보려 합니다.

개편된 청와대 홈페이지 메인 화면 - 새로운 디자인으로 단장한 president.go.kr
개편된 청와대 홈페이지 메인 화면 - 새로운 디자인으로 단장한 president.go.kr
개편된 청와대 홈페이지 (2026년 4월 기준)

1. 먼저, 잘 된 것들

개편된 홈페이지에서 접근성 관점으로 눈에 들어온 긍정적인 부분들이 있었습니다.

예전의 대통령실 임시 홈페이지에 비하면 잘 된 부분이 눈에 크게 들어왔습니다. 어떤 부분이 있었는지 함께 보시죠.

스킵 내비게이션 제공

페이지 상단에 스킵 내비게이션이 구현되어 있습니다.

html
<a href="#containerArea">본문 바로가기</a>
<a href="#headerArea">메뉴 바로가기</a>
<a href="#footerArea">푸터 바로가기</a>
청와대 홈페이지 스킵 내비게이션 - 탭키를 누르면 본문·메뉴·푸터 바로가기 링크가 나타난다
청와대 홈페이지 스킵 내비게이션 - 탭키를 누르면 본문·메뉴·푸터 바로가기 링크가 나타난다
탭키를 누르면 나타나는 스킵 내비게이션

키보드만으로 탐색하는 사용자나 스크린 리더 사용자에게 스킵 내비게이션은 반복 콘텐츠를 건너뛸 수 있는 중요한 수단입니다. 세 개의 목적지를 제공한다는 점도 좋았습니다.

KWCAG 2.2 성공 기준 2.4.1 반복 영역 건너뛰기: “반복되는 콘텐츠 블록은 건너뛸 수 있는 수단을 제공해야 한다.”

화면 설정 옵션 (다크모드)

메뉴에 “어두운 화면” 옵션이 제공되고 있습니다. 빛에 민감한 사용자나 저시력 사용자에게 도움이 되는 기능입니다. 단순한 디자인 트렌드 이상의 의미가 있어요.

다국어 지원

한국어(KOR)와 영어(ENG) 전환을 제공합니다. 국내 거주 외국인이나 해외 방문자가 정부 공식 정보에 접근할 수 있다는 점에서 중요한 기능입니다.

로고 대체 텍스트

로고 이미지에 alt="대한민국 청와대"가 적용되어 있습니다. 기본처럼 보이지만, 의외로 공공 웹사이트에서 빠지는 경우가 많습니다.

HTML 언어 속성 설정

<html lang="ko">가 정확히 명시되어 있습니다. 스크린 리더가 어떤 TTS 엔진을 사용할지 판단하는 가장 기본적인 근거가 되는 속성입니다. 언어 전환 기능이 있는 사이트에서 이 속성이 제대로 설정되어 있다는 건 꽤 중요한 포인트입니다.

KWCAG 2.2 성공 기준 3.1.1 언어 설정: “각 웹 페이지의 기본 인간 언어는 소프트웨어적으로 판별할 수 있어야 한다.”

참고로 영어 버전 전환 시 lang="en"으로 동적으로 바뀌는지도 확인할 만합니다. 그렇다면 더욱 모범적인 구현입니다.

깔끔한 화면

새롭게 개편된 웹사이트의 디자인은 제 기준에서 매우 깔끔하고 군더더기 없다고 생각합니다. 배치나 미적 요소 모두 마음에 들어요.


그런데, 아쉬운 부분을 곁들인..

2. 더 나아갈 수 있는 부분들

좋은 부분도 있었지만, 접근성 점검을 하면서 개선이 필요한 지점들도 발견했습니다. 각 항목마다 현황 → 영향 → 개선 방안 → 검증 방법 순서로 살펴보겠습니다.


🔴 ARIA 속성 미활용

현황

내비게이션, 메인 콘텐츠, 검색 등 주요 영역에 ARIA 랜드마크 및 상태 속성이 확인되지 않습니다.

html
<!-- 현재 (추정) -->
<div class="nav-container">...</div>
<div class="main-content">...</div>
<button class="menu-btn">메뉴</button>

영향

스크린 리더 사용자는 ARIA 랜드마크를 이용해 “내비게이션으로 이동”, “메인 콘텐츠로 이동” 같은 단축 탐색을 합니다. 랜드마크가 없으면 헤더부터 푸터까지 모든 요소를 순서대로 들어야 합니다. 또, 메뉴가 열리고 닫힐 때 상태 변화를 알 수 없어 키보드 사용자가 혼란을 겪습니다.

KWCAG 2.2 성공 기준 4.1.2 이름·역할·값: “모든 사용자 인터페이스 컴포넌트는 이름과 역할을 소프트웨어적으로 판별할 수 있어야 한다.”

개선 방안

랜드마크 역할 부여와 동적 상태 표현, 두 단계로 나눌 수 있습니다. ① <nav>, <main> 같은 시맨틱 HTML 요소를 사용하거나 role 속성을 추가하고, ② 메뉴 버튼에 aria-expanded로 열림/닫힘 상태를 알립니다.

💻 개발자를 위한 코드

① 시맨틱 요소 또는 ARIA 랜드마크 적용

html
<!-- div 대신 시맨틱 HTML 요소를 사용하거나 -->
<nav aria-label="주 메뉴">...</nav>
<main>...</main>
<aside aria-label="관련 링크">...</aside>
<footer>...</footer>

<!-- 기존 div 구조를 유지해야 한다면 role 속성 추가 -->
<div role="navigation" aria-label="주 메뉴">...</div>
<div role="main">...</div>

② 메뉴 버튼 열림/닫힘 상태 표현

html
<!-- 닫힌 상태 -->
<button aria-expanded="false" aria-controls="nav-menu" aria-label="전체 메뉴 열기">
  메뉴
</button>
<ul id="nav-menu" hidden>...</ul>

<!-- 열린 상태 (JavaScript로 토글) -->
<button aria-expanded="true" aria-controls="nav-menu" aria-label="전체 메뉴 닫기">
  메뉴
</button>
<ul id="nav-menu">...</ul>
javascript
const menuBtn = document.querySelector('.menu-btn');
const navMenu = document.querySelector('#nav-menu');

menuBtn.addEventListener('click', () => {
  const isExpanded = menuBtn.getAttribute('aria-expanded') === 'true';
  menuBtn.setAttribute('aria-expanded', String(!isExpanded));
  navMenu.hidden = isExpanded;
});

검증 방법

NVDA(Windows) 또는 VoiceOver(Mac)를 켠 상태에서 탭 탐색을 해보면 랜드마크 인식 여부를 바로 확인할 수 있습니다. NVDA 탐색 모드(Browse Mode)에서 D(다음 랜드마크) / Shift + D(이전 랜드마크)로 이동해볼 수 있습니다. WAVE 웹접근성 평가 도구를 통해 랜드마크 시각화도 가능합니다.


🟠 tabindex 비표준 사용

현황

tabindex="#none" 형태의 비표준 값이 확인됩니다.

html
<!-- 비표준 사용 -->
<div tabindex="#none">...</div>

영향

tabindex의 유효한 값은 정수입니다. #none은 사양에 없는 값이므로 브라우저마다 다르게 처리합니다. 일부 브라우저는 0으로 해석해 의도치 않게 탭 순서에 포함시키고, 일부는 무시합니다. 키보드만 사용하는 사람이 특정 브라우저에서 예측하기 어려운 동작을 경험하게 됩니다.

KWCAG 2.2 성공 기준 4.1.1 마크업 오류: 속성값으로 정수가 아닌 문자열(#none)을 사용하는 것은 HTML 파싱 오류에 해당합니다. 브라우저가 이를 0으로 해석할 경우 2.1.1 키보드 사용 보장 위반으로 이어질 수 있습니다.

개선 방안

의도에 따라 올바른 정수 값으로 교체합니다. 탭 순서에서 제외할 때는 -1, 탭 순서에 포함할 때는 0을 사용합니다. tabindex="1" 이상의 양수 값은 탭 순서를 강제로 바꾸기 때문에 사용하지 않는 것이 원칙이며, DOM 순서와 시각적 순서를 일치시키는 것이 훨씬 좋은 접근입니다.

💻 개발자를 위한 코드
html
<!-- 탭 순서에서 제외하되 JavaScript로 포커스 이동 가능하게 -->
<div tabindex="-1">...</div>

<!-- 기본 탭 순서에 포함 (대화형 요소가 아닌 div에 필요한 경우) -->
<div tabindex="0" role="button" aria-label="...">...</div>

<!-- tabindex가 전혀 필요 없는 경우라면 속성 자체를 제거 -->
<div>...</div>

검증 방법

개발자 도구 콘솔에서 비표준 tabindex를 가진 요소를 일괄 조회할 수 있습니다.

🔍 검증 방법 (개발자용)
javascript
document.querySelectorAll('[tabindex]').forEach(el => {
  const val = el.getAttribute('tabindex');
  if (isNaN(Number(val))) {
    console.warn('비표준 tabindex 발견:', el, '값:', val);
  }
});

🟠 이미지 대체 텍스트 누락

현황

일부 SVG 이미지에 alt 속성이 없는 경우가 확인됩니다.

html
<!-- alt 속성 자체가 없는 경우 -->
<img src="/images/202511/1763535424915_0.svg">

영향

alt 속성이 없으면 스크린 리더는 파일 이름을 읽어버립니다. 사용자는 “1763535424915_0.svg” 같은 의미 없는 문자열을 듣게 됩니다. 장식용 이미지인지 정보 전달용 이미지인지도 구분되지 않아, 스크린 리더가 모든 이미지를 동등하게 읽으려 시도합니다.

KWCAG 2.2 성공 기준 1.1.1 적절한 대체 텍스트: “텍스트 아닌 콘텐츠에는 그 의미나 용도를 인식할 수 있도록 적절한 대체 텍스트를 제공해야 한다.”

개선 방안

이미지 목적에 따라 두 가지로 나뉩니다. 장식용은 alt=""(빈 값)으로 스크린 리더가 건너뛰게 하고, 정보 전달 이미지는 내용을 설명하는 alt 텍스트를 제공합니다. SVG 인라인 사용 시에는 <title> 요소로 대체 텍스트를 제공합니다.

💻 개발자를 위한 코드
html
<!-- ① 장식용 이미지: alt="" (빈 값)으로 스크린 리더가 건너뜀 -->
<img src="background-pattern.svg" alt="">

<!-- ② 정보 전달 이미지: 내용을 설명하는 alt 텍스트 -->
<img src="policy-icon-economy.svg" alt="정책 아이콘: 경제">
<img src="press-release-photo.jpg" alt="대통령 국무회의 주재 — 2026년 4월 20일">

SVG를 인라인으로 사용할 때:

html
<svg role="img" aria-labelledby="icon-title">
  <title id="icon-title">정책 아이콘: 경제</title>
  <!-- svg 경로 -->
</svg>

검증 방법

브라우저 콘솔에서 alt 누락 이미지를 일괄 조회하거나, Lighthouse 접근성 감사(Accessibility 탭 → Image elements do not have [alt] attributes)로 자동 탐지할 수 있습니다.

🔍 검증 방법 (개발자용)
javascript
document.querySelectorAll('img:not([alt])').forEach(img => {
  console.warn('alt 누락:', img.src);
});

🟡 폼 레이블 연결 부재

현황

검색 입력창 등의 폼 요소에 명시적인 <label> 연결이 확인되지 않습니다.

html
<!-- 현재 (추정) -->
<input type="search" placeholder="검색어를 입력하세요">

영향

스크린 리더는 폼 요소에 포커스가 이동하면 레이블을 먼저 읽어줍니다. 레이블이 없으면 “편집창” 또는 “검색창"이라는 역할만 알 뿐, 무엇을 입력해야 하는지 알 수 없습니다. placeholder 텍스트는 레이블을 대체하지 못합니다. 입력이 시작되는 순간 placeholder는 사라지고, 일부 스크린 리더는 placeholder를 아예 읽지 않기도 합니다.

KWCAG 2.2 성공 기준 3.3.2 레이블 제공: “입력 서식에는 그 목적에 맞게 레이블을 제공해야 한다.”

개선 방안

세 가지 방법 중 상황에 맞게 선택합니다. 가장 권장하는 방법은 명시적 <label for> 연결이며, 시각적으로 레이블을 숨겨야 한다면 sr-only 클래스를, HTML 구조를 바꾸기 어렵다면 aria-label을 사용합니다.

💻 개발자를 위한 코드
html
<!-- ① 가장 권장: 명시적 label 연결 -->
<label for="site-search">검색</label>
<input type="search" id="site-search" placeholder="검색어를 입력하세요">

<!-- ② 시각적으로 label을 숨겨야 할 때: sr-only 클래스 활용 -->
<label for="site-search" class="sr-only">사이트 검색</label>
<input type="search" id="site-search" placeholder="검색어를 입력하세요">

<!-- ③ label 마크업을 추가하기 어려운 경우: aria-label -->
<input type="search" aria-label="사이트 검색" placeholder="검색어를 입력하세요">

검증 방법

Chrome DevTools의 접근성 트리(Elements 패널 → Accessibility 탭)에서 입력 요소를 선택했을 때 Name 필드가 채워져 있으면 정상입니다. 비어 있다면 레이블이 연결되지 않은 상태입니다.


🟡 스크린 리더 전용 텍스트 패턴 부재

현황

시각적으로는 맥락이 명확하지만 스크린 리더에게는 불분명한 텍스트가 있습니다. “더보기” 링크가 여러 개일 때, 어떤 콘텐츠의 더보기인지 스크린 리더 사용자는 알 수 없습니다.

html
<!-- 화면에는 자연스럽지만 스크린 리더에서는 구분 불가 -->
<a href="/news">더보기</a>
<a href="/policy">더보기</a>
<a href="/speech">더보기</a>

영향

스크린 리더 사용자가 링크 목록을 불러오면(“링크 탐색” 단축키 활용) “더보기, 더보기, 더보기"만 나열됩니다. 어디로 이동하는 링크인지, 무엇을 더 보는 건지 알 수 없습니다.

KWCAG 2.2 성공 기준 2.4.4 링크 목적: “링크 텍스트만으로도 링크 목적을 이해할 수 있어야 한다.”

개선 방안

화면에는 보이지 않지만 스크린 리더에게는 전달되는 텍스트를 추가합니다. sr-only 클래스 CSS 한 세트를 추가하면, 시각 디자인을 전혀 바꾸지 않으면서 “더보기(주요 뉴스)”, “더보기(연설문)“처럼 맥락을 전달할 수 있습니다.

💻 개발자를 위한 코드
html
<!-- sr-only 클래스로 맥락 텍스트 추가 -->
<a href="/news">더보기<span class="sr-only"> 주요 뉴스</span></a>
<a href="/policy">더보기<span class="sr-only"> 국정과제</span></a>
<a href="/speech">더보기<span class="sr-only"> 연설문</span></a>

<!-- 또는 aria-label로 전체 링크 텍스트를 교체 -->
<a href="/news" aria-label="주요 뉴스 더보기">더보기</a>
css
/* 화면에는 감추고 스크린 리더에게는 전달 */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

검증 방법

NVDA의 Insert + F7로 Elements List(요소 목록) 다이얼로그를 열면 링크, 제목, 랜드마크 탭에서 각 항목이 어떻게 읽히는지 한눈에 확인할 수 있습니다. VoiceOver에서는 VO + U로 로터를 열어 링크 목록을 확인합니다.


WCAG 2.2 국제 기준 — 추가로 살펴볼 항목들

KWCAG 2.2는 WCAG 2.1을 기반으로 하고 있습니다. 2023년 10월에 발표된 WCAG 2.2에서는 실무에서 자주 놓쳤던 영역들이 새롭게 추가됐습니다. 아직 KWCAG에 반영되지 않아 법적 의무는 아니지만, 국제 수준의 공공 웹사이트를 목표로 한다면 충분히 참고할 가치가 있습니다.

🟡 포커스 표시 품질 (2.4.13 Focus Appearance, AA)

“포커스가 보인다"는 것과 “포커스가 잘 보인다"는 것은 다릅니다. WCAG 2.2는 포커스 인디케이터의 크기명도 대비까지 기준으로 정했습니다.

  • 최소 면적: 포커스된 요소의 둘레(perimeter) × 2px 이상
  • 명도 대비: 포커스 인디케이터와 인접 색상 간 3:1 이상

단순히 outline: none으로 포커스를 숨기거나 기본 브라우저 스타일에만 의존하면 이 기준을 충족하지 못할 수 있습니다. 스킵 내비게이션, 메뉴 버튼, 달력 날짜 셀 등 포커스 가능한 모든 요소가 해당됩니다.

💻 개발자를 위한 코드
css
/* 기존: 브라우저 기본 포커스에 의존 */
:focus { outline: auto; }

/* 2.4.13을 고려한 포커스 스타일 예시 */
/* 충분한 두께와 명도 대비가 핵심 — 배경색에 따라 검증 필요 */
:focus-visible {
  outline: 3px solid #005fcc;
  outline-offset: 2px;
}

🟡 클릭·터치 타깃 최소 크기 (2.5.8 Target Size, AA)

대화형 요소의 클릭 가능 영역이 최소 24×24 CSS px 이상이어야 합니다(Level AA). 아이콘 버튼, 소셜 공유 버튼, 달력 이전/다음 버튼처럼 작게 디자인되기 쉬운 요소들이 해당됩니다. 타겟이 24px 미만이더라도 타겟 중심 반경 24px 내에 다른 타겟이 없으면 충족 가능하며, 인라인 텍스트 링크 등 예외도 있습니다.

앞서 설날 포스트에서 메인 배너 컨트롤 버튼이 너무 작다는 점을 지적했는데, WCAG 2.2는 이를 명시적 기준으로 확정했습니다. 개편된 홈페이지의 작은 버튼들도 점검이 필요합니다.

💻 개발자를 위한 코드
css
/* 시각적 크기는 유지하면서 클릭 가능 영역 확보 */
.icon-btn {
  min-width: 24px;
  min-height: 24px;
  padding: 8px; /* 아이콘 주변 여백으로 클릭 영역 확장 */
}

🟡 포커스 가림 방지 (2.4.11 Focus Not Obscured, AA)

스티키 헤더가 있을 경우, 키보드로 탐색 중인 요소가 헤더 뒤에 완전히 가려지면 안 됩니다. 연설문처럼 긴 콘텐츠 페이지에서 Tab 키로 탐색하다 보면 포커스가 헤더 아래로 숨어버리는 현상이 생길 수 있습니다.

이 한 줄로 포커스된 요소가 스티키 헤더와 겹치지 않게 됩니다. 별도의 JavaScript 없이 CSS만으로 해결할 수 있습니다.

💻 개발자를 위한 코드
css
/* 스티키 헤더 높이만큼 스크롤 여백 확보 */
html {
  scroll-padding-top: 80px; /* 실제 헤더 높이로 조정 */
}

3. 서브 페이지 점검

메인 페이지만 접근성이 좋다고 해서 웹사이트 전체가 접근성을 갖추었다고 말할 수는 없습니다. 실제로 국민이 자주 방문하는 서브 페이지들을 살펴봤습니다.

메인 페이지는 양반이었습니다.


대통령 인사말 — 이미지와 텍스트가 충돌합니다

인사말 페이지(president.go.kr/president/greeting)에서 텍스트를 마우스로 드래그하면 중반부부터 선택이 제대로 되지 않습니다. 이미지가 텍스트 위로 겹쳐 있어 드래그 이벤트를 이미지가 가로채는 현상입니다.

청와대 인사말 페이지에서 텍스트 드래그가 이미지에 막히는 현상 - 이미지가 텍스트 위에 겹쳐 마우스 이벤트를 가로채고 있다
청와대 인사말 페이지에서 텍스트 드래그가 이미지에 막히는 현상 - 이미지가 텍스트 위에 겹쳐 마우스 이벤트를 가로채고 있다
인사말 페이지 중반부에서 드래그가 끊기는 지점

영향

이건 접근성 문제이기 전에 기본적인 사용성 문제입니다. 일반 사용자라도 불편하지만, 다음 상황에서는 더 치명적입니다.

  • 저시력 사용자: 텍스트를 선택해 브라우저 확대 또는 복사·붙여넣기 후 별도 도구로 읽을 때
  • 스크린 리더 가상 커서 모드: 일부 스크린 리더는 마우스 드래그로 읽기 범위를 지정하는 기능을 활용함
  • 자동 번역 사용자: 번역 확장 프로그램이 텍스트 선택에 의존할 때
  • 복사해서 인용하려는 사용자: 대통령 인사말은 자주 인용되는 텍스트임

원인 (추정)

대부분의 경우 이 문제는 절대 위치로 배치된 이미지가 텍스트 위에 겹쳐 있고, 이미지가 기본값인 pointer-events: auto 상태라 마우스 이벤트를 가로채는 구조입니다.

css
/* 추정되는 문제 구조 */
.greeting-image {
  position: absolute;
  /* 또는 float + 음수 마진 등으로 텍스트 영역 침범 */
  z-index: 1; /* 텍스트 위로 올라와 있음 */
}

개선 방안

① 이미지에 pointer-events: none 추가 (가장 빠른 해결)

이미지가 마우스 이벤트를 가로채지 못하도록 한 줄로 해결합니다. 이미지와 텍스트의 시각적 배치는 그대로 유지됩니다.

② 레이아웃 구조 수정 (근본적 해결)

이미지와 텍스트가 겹치지 않도록 플렉스박스 또는 그리드로 나란히 배치합니다.

💻 개발자를 위한 코드

① pointer-events: none 적용

css
.greeting-image {
  pointer-events: none; /* 이미지가 마우스 이벤트를 가로채지 않음 */
}

② 레이아웃 구조 수정

html
<div class="greeting-layout">
  <div class="greeting-text">
    <p>인사말 본문...</p>
  </div>
  <figure class="greeting-image">
    <img src="president-photo.jpg" alt="대통령 공식 사진">
  </figure>
</div>
css
.greeting-layout {
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: 2rem;
  align-items: start;
}
/* 이미지가 텍스트 위로 절대 겹치지 않는 구조 */

검증 방법

페이지에서 첫 단락부터 마지막 단락까지 마우스 드래그 선택을 시도합니다. 끊기는 지점이 있다면 그 위치에서 개발자 도구로 요소를 확인하면 원인을 특정할 수 있습니다.

🔍 검증 방법 (개발자용)
javascript
// 클릭 이벤트를 가로채는 요소 탐지
document.addEventListener('mousedown', e => {
  console.log('클릭된 요소:', e.target, e.target.style.position);
});

연설문 게시판 — 목록에서 상세까지

연설문 목록(president.go.kr/speechs)은 국민이 대통령의 발언을 확인하는 핵심 페이지입니다.

목록 페이지

현황 및 주요 이슈

게시판 형태의 목록 페이지에서 점검해야 할 항목들입니다.

① 날짜 마크업

날짜를 단순 텍스트로만 제공하면 기계가 날짜로 인식하지 못합니다. <time> 요소는 브라우저, 검색엔진, 스크린 리더 모두에게 날짜 정보를 명확히 전달합니다.

💻 개발자를 위한 코드
html
<!-- ❌ 단순 텍스트 -->
<span>2026.04.15</span>

<!-- ✅ time 요소로 의미 부여 -->
<time datetime="2026-04-15">2026.04.15</time>

② 게시판이 table인 경우 — caption과 th scope

scope="col"이 없으면 스크린 리더가 셀 데이터를 읽을 때 어느 열의 데이터인지 컨텍스트를 잃어버립니다.

💻 개발자를 위한 코드
html
<!-- ❌ scope 없는 th -->
<table>
  <thead>
    <tr><th>번호</th><th>제목</th><th>날짜</th></tr>
  </thead>
  ...
</table>

<!-- ✅ caption과 scope 포함 -->
<table>
  <caption>연설문 목록</caption>
  <thead>
    <tr>
      <th scope="col">번호</th>
      <th scope="col">제목</th>
      <th scope="col">날짜</th>
    </tr>
  </thead>
  ...
</table>

③ 페이지네이션 현재 페이지 표시

💻 개발자를 위한 코드
html
<!-- ❌ 시각적으로만 구분 -->
<nav>
  <a href="/speechs?page=1">1</a>
  <strong>2</strong>  <!-- 현재 페이지지만 스크린 리더는 모름 -->
  <a href="/speechs?page=3">3</a>
</nav>

<!-- ✅ aria-current로 현재 페이지 명시 -->
<nav aria-label="페이지 탐색">
  <a href="/speechs?page=1">1페이지</a>
  <a href="/speechs?page=2" aria-current="page">2페이지 (현재)</a>
  <a href="/speechs?page=3">3페이지</a>
</nav>

KWCAG 2.2 성공 기준 2.4.4 링크 목적: “링크 텍스트만으로도 링크 목적을 이해할 수 있어야 한다.”

상세 페이지

연설문 상세 페이지에서는 본문이 실제 HTML 텍스트인지 이미지인지가 중요합니다. 설날 포스트에서 지적했던 카드뉴스의 문제와 동일한 맥락입니다. 첨부파일(PDF, HWP)만 제공하는 경우도 마찬가지입니다. 본문에 텍스트 전문을 제공하고, 첨부파일은 보조 수단으로 사용해야 합니다.

💻 개발자를 위한 코드
html
<!-- ❌ 연설문 본문이 이미지로만 제공될 경우 -->
<img src="speech-20260415.jpg">  <!-- 스크린 리더가 읽을 수 없음 -->

<!-- ✅ 텍스트로 제공 -->
<article>
  <h2>연설 제목</h2>
  <p>연설 본문 텍스트...</p>
</article>

이전글/다음글 네비게이션

💻 개발자를 위한 코드
html
<!-- ❌ 모호한 네비게이션 -->
<a href="/speechs/124">이전글</a>
<a href="/speechs/126">다음글</a>

<!-- ✅ 제목 포함 또는 aria-label로 구체화 -->
<nav aria-label="게시글 탐색">
  <a href="/speechs/124" aria-label="이전 연설문: 국무회의 모두 발언">
    ← 이전글
  </a>
  <a href="/speechs/126" aria-label="다음 연설문: 취임 1주년 기념사">
    다음글 →
  </a>
</nav>

공개일정 — 달력 테이블의 접근성

공개일정 페이지(president.go.kr/schedule)는 대통령의 공식 일정을 7열 달력 형태로 보여줍니다. 달력은 접근성을 갖추기 까다로운 UI 컴포넌트 중 하나입니다.

청와대 공개일정 달력 - 7열 테이블 레이아웃으로 구현된 대통령 공식 일정 달력
청와대 공개일정 달력 - 7열 테이블 레이아웃으로 구현된 대통령 공식 일정 달력
청와대 공개일정 달력 (2026년 4월 기준)

현황 및 주요 이슈

① 달력 table의 구조적 마크업

scope="col"이 없으면 스크린 리더가 날짜 셀을 읽을 때 “무슨 요일인지"를 알 수 없습니다. abbr 속성은 긴 요일명을 요약해 반복 읽힘을 줄여줍니다.

💻 개발자를 위한 코드
html
<!-- ❌ 구조 정보 없는 달력 -->
<table>
  <tr><th></th><th></th>...<th></th></tr>
  <tr><td></td><td></td>...<td>1</td></tr>
  ...
</table>

<!-- ✅ 완전한 시맨틱 달력 구조 -->
<table aria-label="2026년 4월 대통령 공개일정">
  <caption>2026년 4월</caption>
  <thead>
    <tr>
      <th scope="col" abbr="일">일요일</th>
      <th scope="col" abbr="월">월요일</th>
      <th scope="col" abbr="화">화요일</th>
      <th scope="col" abbr="수">수요일</th>
      <th scope="col" abbr="목">목요일</th>
      <th scope="col" abbr="금">금요일</th>
      <th scope="col" abbr="토">토요일</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td></td>
      <td><span class="sr-only">4월 </span>1일</td>
      ...
    </tr>
  </tbody>
</table>

② 오늘 날짜 표시

💻 개발자를 위한 코드
html
<!-- ❌ 시각적으로만 강조 (CSS class만) -->
<td class="today">20</td>

<!-- ✅ aria-current로 현재 날짜 명시 -->
<td aria-current="date" class="today">
  <span class="sr-only">오늘, </span>20
</td>

③ 이전/다음 월 버튼의 accessible name

💻 개발자를 위한 코드
html
<!-- ❌ 단순 텍스트 -->
<button>이전</button>
<button>다음</button>

<!-- ✅ 어느 월로 이동하는지 명시 -->
<button aria-label="이전 달 (2026년 3월)로 이동">이전</button>
<button aria-label="다음 달 (2026년 5월)로 이동">다음</button>

④ 월 전환 시 동적 콘텐츠 업데이트 안내

이 속성이 없으면 월이 바뀌어도 스크린 리더는 변화를 인식하지 못합니다. 사용자는 버튼을 눌렀는데 아무 변화도 없는 것처럼 느끼게 됩니다.

💻 개발자를 위한 코드
html
<!-- 달력 영역에 aria-live 추가 -->
<div aria-live="polite" aria-atomic="true">
  <table>...</table>
</div>

⑤ 일정 항목 링크 텍스트

💻 개발자를 위한 코드
html
<!-- ❌ 일정 제목만 있는 링크 -->
<td>
  <a href="/schedule/123">국무회의</a>
</td>

<!-- ✅ 날짜 맥락이 포함된 링크 -->
<td>
  <a href="/schedule/123" aria-label="4월 20일 국무회의 일정 상세보기">
    국무회의
  </a>
</td>

KWCAG 2.2 성공 기준 1.3.1 정보와 관계: “정보, 구조, 관계는 소프트웨어적으로 판별할 수 있어야 한다.”


뉴스룸 — 카드 목록의 사용성

뉴스룸(president.go.kr/briefings) 등 카드 형태 목록 페이지에서 공통적으로 점검해야 할 항목입니다.

① 카드 썸네일 이미지의 alt 처리

썸네일이 제목과 같은 정보를 전달하는 경우 alt=""로 처리해 스크린 리더의 중복 읽힘을 방지합니다.

💻 개발자를 위한 코드
html
<!-- ❌ 제목과 동일한 alt (중복 읽힘) -->
<article>
  <img src="brief.jpg" alt="국무회의 결과 브리핑">
  <h3><a href="...">국무회의 결과 브리핑</a></h3>
</article>

<!-- ✅ 장식용 이미지로 처리해 중복 방지 -->
<article>
  <img src="brief.jpg" alt="">  <!-- 같은 정보를 제목이 이미 전달함 -->
  <h3><a href="...">국무회의 결과 브리핑</a></h3>
</article>

② 카드 전체를 클릭 가능하게 하는 방식

카드 전체 영역을 링크로 만들 때, 링크 텍스트를 어떻게 제공하느냐가 중요합니다. 시각적으로는 카드 전체가 클릭되는 것처럼 동작하지만, 스크린 리더는 제목 텍스트만 링크로 읽는 패턴이 권장됩니다.

💻 개발자를 위한 코드
html
<!-- ❌ 카드 전체를 빈 링크로 감쌈 -->
<a href="/briefings/123">
  <img src="brief.jpg" alt="...">
  <h3>국무회의 결과 브리핑</h3>
  <time>2026.04.20</time>
  <p>요약 텍스트...</p>
</a>
<!-- 스크린 리더가 이미지 alt + h3 + time + p를 모두 읽어 너무 김 -->

<!-- ✅ 제목 링크 + 가상 요소로 클릭 영역 확장 -->
<article class="card">
  <img src="brief.jpg" alt="">
  <h3><a href="/briefings/123" class="card-link">국무회의 결과 브리핑</a></h3>
  <time datetime="2026-04-20">2026.04.20</time>
  <p>요약 텍스트...</p>
</article>
css
/* 제목 링크의 가상 요소로 카드 전체 클릭 영역 확장 */
.card { position: relative; }
.card-link::after {
  content: '';
  position: absolute;
  inset: 0;
}

4. 개선 항목 요약

지금까지 메인 페이지와 주요 서브 페이지에서 살펴본 내용을 우선순위와 함께 정리합니다.

메인 페이지

데이터 표
항목우선순위난이도영향 범위
HTML lang 속성 추가🔴 즉시매우 낮음전체 페이지
ARIA 랜드마크 적용🔴 즉시낮음전체 구조
tabindex 비표준 수정🟠 단기낮음키보드 사용자
이미지 alt 속성 점검🟠 단기낮음시각장애 사용자
폼 레이블 연결🟡 중기보통폼 사용 전반
sr-only 텍스트 패턴 도입🟡 중기보통모호한 링크·버튼 전반

서브 페이지

데이터 표
항목우선순위난이도영향 범위
인사말: 이미지 pointer-events: none🔴 즉시매우 낮음모든 방문자
연설문: <time> 요소 적용🟠 단기낮음목록 전반
연설문: table caption + th scope🟠 단기낮음스크린 리더 사용자
연설문: 본문 텍스트 직접 제공🔴 즉시보통시각장애·번역 사용자
페이지네이션: aria-current="page"🟠 단기낮음키보드·스크린 리더
달력: caption + th scope="col"🔴 즉시낮음스크린 리더 사용자
달력: aria-current="date" (오늘)🟠 단기낮음스크린 리더 사용자
달력: 이전/다음 버튼 aria-label🔴 즉시매우 낮음키보드·스크린 리더
달력: aria-live="polite"🟠 단기낮음스크린 리더 사용자
카드 목록: 썸네일 alt="" 처리🟠 단기낮음스크린 리더 사용자

🔴 즉시 항목들은 CSS 한 줄 또는 HTML 속성 추가 수준입니다. 설계 변경 없이 빠르게 반영할 수 있습니다.

국제 기준 (WCAG 2.2 신규, 참고용)

데이터 표
항목기준난이도영향 범위
포커스 표시 크기·대비 충족2.4.13낮음키보드 사용자 전반
작은 버튼·아이콘 클릭 영역 확보2.5.8낮음마우스·터치 사용자
스티키 헤더에 의한 포커스 가림 방지2.4.11매우 낮음키보드 사용자

WCAG 2.2 신규 기준들은 현재 KWCAG에 반영되어 있지 않아 법적 의무는 아닙니다. 그러나 국제 표준이 이미 이 방향으로 움직이고 있으며, 향후 KWCAG 개정에 반영될 가능성이 높습니다.


5. 설날 점검 이후, 달라진 것들

지난 2월, 설 연휴 정보 접근성을 점검하는 글에서 카드뉴스 이미지에 대체 텍스트가 없고, 정보가 이미지 안에만 갇혀 있다는 문제를 지적했습니다.

홈페이지가 개편되면서 전체적인 구조가 바뀐 만큼, 카드뉴스 제공 방식도 다시 살펴볼 필요가 있습니다. 형식보다 중요한 것은 ‘이 정보가 모든 국민에게 닿는가’라는 질문입니다. 새 홈페이지에서는 이 질문에 더 나은 답을 줄 수 있길 기대합니다.


6. 공공 웹사이트 접근성이 특별한 이유

민간 서비스의 접근성도 중요하지만, 공공 웹사이트는 조금 다른 무게를 가집니다.

선택할 수 없기 때문입니다.

민간 서비스는 불편하면 다른 걸 쓰면 됩니다. 하지만 국가기관의 공지는, 정책 안내는, 국민 서비스 신청은 대체재가 없습니다. 국가가 제공하는 정보에 접근하지 못한다는 것은 그 자체로 국민으로서의 권리가 침해되는 일입니다.

2026년 1월 22일, 디지털포용법이 시행됐습니다. 국가기관의 디지털 서비스 접근성 보장 의무를 명문화한 법입니다. 청와대 홈페이지는 이 법의 적용을 받는 가장 상징적인 사이트 중 하나입니다.

법적 의무이기 이전에, 모든 국민에게 열려 있어야 할 정보를 실제로 열어두는 일이기도 합니다.


7. WCAG 3.0 시대를 내다보며

WCAG 3.0은 아직 초안 단계입니다. 확정된 기준은 아니지만, 이미 공개된 방향에서 미래의 접근성 평가가 어떻게 달라질지 읽을 수 있습니다. 이 시리즈의 이전 글들(WCAG 3.0이 온다 — 왜 새로운 지침인가, 점수 기반 적합성 모델)에서 더 자세히 다뤘으니, 여기서는 청와대 홈페이지에 적용했을 때의 시사점만 살펴봅니다.

Critical Error — 점수와 무관하게 즉시 실패

WCAG 3.0의 가장 큰 특징 중 하나는 Critical Error 개념입니다. 전체 점수가 아무리 높아도, Critical Error가 하나라도 있으면 적합성 등급을 받을 수 없습니다. 사용자가 핵심 작업을 완료할 수 없는 근본적인 장벽이 그 기준입니다.

이 글에서 지적한 항목들 중 Critical Error 후보를 꼽자면:

  • lang 속성 누락: 스크린 리더가 언어를 잘못 인식 → 외국인 및 다국어 환경 사용자의 접근 차단
  • 연설문 본문이 이미지로만 제공: 시각장애 사용자가 정보 자체에 접근 불가
  • 인사말 텍스트 드래그 차단: 복사·번역·보조 도구 활용이 근본적으로 막힘

현재 WCAG 2.x 체계에서도 심각한 이슈들이지만, WCAG 3.0에서는 이 중 하나라도 남아 있으면 Bronze 등급조차 받을 수 없는 구조가 됩니다.

인지 접근성 — WCAG 3.0이 가장 강화한 영역

WCAG 3.0에서 가장 크게 확장된 영역이 **인지 접근성(Cognitive Accessibility)**입니다. “기술적으로 접근 가능하더라도, 내용 자체를 이해하기 어려우면 접근 가능하다고 볼 수 없다"는 관점에서 출발합니다.

정부 웹사이트에서 특히 관련이 깊습니다.

  • 명확한 언어(Clear Language): 연설문과 정책 안내문이 일반 국민이 이해할 수 있는 언어로 작성되어 있는가
  • 일관된 탐색(Consistent Navigation): 메인, 연설문, 공개일정 페이지에서 메뉴와 탐색 패턴이 일관되는가
  • 예측 가능한 동작: 달력의 월 전환, 게시판 페이지네이션이 기대하는 방식으로 동작하는가

기술적 마크업을 넘어 콘텐츠 자체의 접근성을 따지기 시작한다는 점에서, 공공 웹사이트에 미치는 영향이 클 것입니다.

기능별 요구(Functional Needs) — 질문이 달라진다

WCAG 3.0은 사용자의 **기능별 요구(Functional Needs)**를 중심에 두는 방향으로 논의 중입니다. 초기 Working Draft에서는 시각(Vision), 청각(Hearing), 인지(Cognitive), 신체/운동(Physical/Motor), 언어/음성(Speech) 등의 카테고리가 제안됐습니다. 구조 자체는 아직 확정되지 않았지만, 평가의 핵심 질문이 달라진다는 방향성은 분명합니다.

WCAG 2.x: “이 기술 기준을 충족했는가?” WCAG 3.0(논의 방향): “이 사용자 그룹이 실제로 목표를 달성할 수 있는가?”

청와대 홈페이지를 이 관점으로 보면, 기술 기준 충족 여부를 넘어 “시각장애인이 연설문 전문을 읽을 수 있는가”, “인지장애인이 공개일정에서 원하는 날짜를 찾을 수 있는가"까지 묻게 됩니다.


8. 마무리: 다음 개편을 기대하며

접근성은 한 번에 완성되는 것이 아닙니다. 지속적인 관심과 개선의 과정입니다.

이번 개편에서 스킵 내비게이션, 다크모드, 다국어 지원 같은 부분이 갖춰진 건 분명 긍정적인 신호입니다. 여기서 한 걸음 더 나아가면 됩니다.

이 글에서 제안한 개선 사항들은 디자인을 뜯어고치거나 대규모 예산이 필요한 것들이 아닙니다. ARIA 속성 추가, 레이블 연결, tabindex 값 정정 — 그 수준입니다. 하지만 이 작은 변화들이 만들어내는 차이는, 접근 보조 기술에 의존하는 분들에게는 엄청납니다.

국가의 얼굴인 홈페이지가 모든 국민에게 열려 있기를 바라는 마음으로 이 글을 씁니다. 다음번 점검에서는 더 많이 달라져 있길 기대합니다.


질문으로 다시 보기

청와대 홈페이지에서 우선적으로 개선이 필요한 접근성 항목은 무엇인가요?
ARIA 랜드마크와 상태 속성 미활용이 가장 광범위한 영향을 줍니다. 랜드마크가 없으면 스크린 리더 사용자가 페이지 구역 간 단축 탐색을 할 수 없고, 메뉴 버튼의 aria-expanded 같은 상태 정보가 없으면 UI 변화를 인식하지 못합니다. <nav>, <main> 시맨틱 요소 사용 또는 role 속성 추가만으로도 크게 개선됩니다.
KWCAG와 WCAG의 차이점은 무엇인가요?
KWCAG(한국형 웹 콘텐츠 접근성 지침)는 WCAG 2.1을 기반으로 한국 실정에 맞게 제정된 국내 표준입니다. 기본 구조와 원칙은 WCAG와 동일하지만, 국내 공공 웹사이트는 KWCAG 2.2 준수가 법적 의무입니다. WCAG 2.2의 신규 기준(2.4.11~2.5.8 등)은 아직 KWCAG에 반영되지 않았습니다.
공공 웹사이트의 접근성 준수는 법적 의무인가요?
네. 「장애인차별금지법」과 「국가정보화기본법」에 따라 공공기관 웹사이트는 KWCAG 준수가 의무입니다. 미준수 시 시정 권고 및 법적 제재를 받을 수 있습니다.
스크린 리더 사용자가 웹사이트를 탐색하는 방법은?
NVDA·JAWS 같은 스크린 리더는 키보드만으로 웹을 탐색합니다. Tab키로 포커스 이동, D/Shift+D로 랜드마크 이동, H로 제목 이동, Insert+F7로 Elements List(링크·제목 목록 보기) 등을 사용합니다. 포커스 표시가 없거나 의미 없는 div로 구성된 버튼은 스크린 리더가 인식하지 못합니다.
웹 접근성 개선을 가장 빠르게 시작하는 방법은?
세 가지 기초 작업으로 시작하세요: ① <html lang="ko"> 추가, ② 모든 이미지에 의미 있는 alt 텍스트 작성, ③ 키보드로만 전체 페이지를 탐색해보기. 이 세 가지만으로도 접근성 수준이 크게 달라집니다.

참고 자료