Overview

HTML 페이지를 만들 때 고려해야 하는 것 중 하나가 웹 접근성입니다.

웹 접근성이란 시각장애인들이 웹 페이지를 원활하게 이용할 수 있도록 알려주는 가이드라인이라고 생각하면 됩니다.

대표적으로 input 과 label 이 있는데요.

일반 사람들은 별다른 설명 없이 input, button, a 등등의 태그만 있어도 어느정도 이용할 수 있지만 시각장애인들은 직접 클릭할 수도 없이 탭 같은 걸로 각 요소를 이동하는 수밖에 없습니다.

따라서 탭을 눌렀을 때 초점이 어느 순서로 이동하는지, 초점이 잡혔을 때의 안내 메시지가 제대로 나오는지 여부는 굉장히 중요합니다.

이런 설정들을 HTML native 요소만으로는 처리하기 어렵기 때문에 W3C 는 WAI-ARIA 라는 걸 정의했습니다.


1. WAI-ARIA

WAI-ARIA (Web Accessibility Initiative – Accessible Rich Internet Applications) 는 W3C 에서 정의한 기술로 웹 접근성을 위해 지원되는 여러 가지 특성들을 의미합니다.

일반 사용자가 보기에 정상인 화면들도 HTML 요소에 따라서 스크린 리더 등의 보조기기에서 제대로 읽히지 않을 수 있습니다.

WAI-ARIA 는 이를 개선하기 위해 웹 애플리케이션에 역할(Role), 속성(Property), 상태(State) 정보를 추가할 수 있습니다.


1.1. Role

Role 은 HTML 요소의 역할을 정의합니다.

일반적으로는 HTML native 요소만으로 이를 처리하는게 가장 이상적입니다.

버튼은 button, 링크는 a, 체크박스는 input checkbox 등등 이미 존재하는 요소들로도 충분히 표현할 수 있습니다.

하지만 이미지에 버튼 클릭 이벤트를 준다던가 좀더 세세하고 다양한 설정이 하고 싶을 때는 native 요소만으로 부족할 수 있습니다.

이럴 때 role 을 사용해서 해당 요소들의 역할을 명시합니다.

Role 의 종류는 W3C WAI ARIA 의 5.3 Categorization of Roles 에서 확인할 수 있습니다.

<!-- role example -->
<li role="menuitem">Open file…</li>

1.2. State and Property

속성 (Property) 는 해당 요소의 특징이나 상황을 정의하며 aria- 라는 접두사를 사용합니다.

상태 (State) 는 요소의 현재 상태를 나타냅니다.

<!-- property state example 1 -->
<li role="checkbox" aria-checked="true">체크박스 아이템</li>

<!-- property state example 2 -->
<div role="alert" aria-live="assertive">올바르지 않은 입력입니다.</div>

2. ARIA 속성들

공부한 속성들에 대해서 정리합니다.

앞으로도 생길때마다 조금씩 추가할 예정입니다.


2.1. role="checkbox" aria-checked="true"

<span role="checkbox" aria-checked="false" tabindex="0" aria-labelledby="chk1-label"></span> 
<label id="chk1-label">Remember my preferences</label>

<!-- native 요소로 사용할 수 있는 경우 -->
<input type="checkbox" id="chk1-label">
<label for="chk1-label">Remember my preferences</label>

특정 요소에 체크박스 역할을 부여합니다.

aria-checked 를 사용해서 체크됨, 체크안됨 여부를 판단할 수 있습니다.

focus 되지 않는 요소일 경우 tabindex 를 사용하기도 합니다.

가능하면 HTML native checkbox 를 사용하는게 권장되지만 사용할 수 없는 경우에 ARIA 속성을 사용합니다.


2.2. aria-label, aria-labelledby, aria-describedby

특정 요소를 설명하는 데 사용되는 ARIA 속성들입니다.

비슷해보이지만 조금씩 차이가 있습니다.


<button aria-label="menu" class="button"></button>

aria-label 은 우리가 흔히 알고 있는 Label 목적을 위한 속성입니다.

특정 요소에 대한 설명을 그대로 적습니다.

텍스트 대신 그래픽을 사용하는 경우처럼 추가 설명이 필요한 경우 사용할 수 있습니다.


<span id="rg-label">음료수 옵션</span>
<div role="radiogroup" aria-labelledby="rg-label"></div>

aria-labelledbyaria-label 과 비슷하지만 조금 다릅니다.

aria-label 은 어떤 요소에 대한 설명을 직접 적는 반면, aria-labelledby 은 다른 요소의 ID 값을 매칭시킵니다.

aria-labelledby 은 Label 자체를 재정의하기 때문에 다른 모든 Label 속성들, aria-label 또는 HTML native label 과 함께 쓰여도 항상 aria-labelledby 을 우선합니다.


<label for="pw">Password:</label>
<input type="password" id="pw" aria-describedby="pw-help">
<div id="pw-help">비밀번호는 12 자 이상으로 이루어져야 합니다</div>

aria-describedbyaria-labelledby 와 같은 방식으로 다른 요소의 ID 를 매칭하여 현재 요소에 대한 설명을 나타냅니다.

둘의 사용법과 쓰임새가 굉장히 비슷하여 헷갈릴 수도 있지만 다른 목적으로 사용됩니다.

MDN Web Docs - Using the aria-describedby attribute 에는 다음과 같이 나와있습니다.

This is very similar to aria-labelledby: a label describes the essence of an object, while a description provides more information that the user might need.

label 관련 속성들과의 가장 큰 차이점은 Label 이 요소의 필수 설명이라면 aria-describedby 은 어디까지나 부연 설명이라는 점입니다.

그래서 위 예시 코드에서처럼 label 태그와 함께 사용할 수 있습니다.


2.3. aria-live

JavaScript 를 사용하면 페이지를 새로 로드하지 않고 일부만 동적으로 변경하는게 가능합니다.

동적인 변경은 페이지를 볼 수 있는 사용자들은 알 수 있지만, 시각 장애인들은 알아채기 어렵습니다.

그래서 이런 동적인 (실시간) 변경들을 알려줄 수 있는 aria-live 라는 속성이 제공됩니다.


<input type="text" name="email">
<div role="alert" aria-live="assertive">이메일 형식이 올바르지 않습니다.</div>

회원가입 또는 로그인 페이지에서 사용하는 Email Input 은 실시간으로 Email 형식 검사를 하여 올바른 형식이 아니면 빨간색 에러 메시지를 사용자에게 노출합니다.

페이지를 볼 수 있는 사용자는 그 정보를 실시간으로 확인할 수 있지만 시각장애인은 에러 메시지가 노출되었다는 사실을 모를 수 있습니다.

이럴 때 role="alert" 로 경고 역할을 갖고 있는 요소를 만들고 실시간 변화를 감지해서 알려주는 aria-live 속성을 추가할 수 있습니다.

aria-live 의 값으로는 다음 값들이 올 수 있습니다.

  • off (default)
  • polite : 현재 진행중인 음성 또는 타이핑 이후에 알림
  • assertive : 현재 진행중인 알림을 중단하고 즉시 알림

assertive 값은 사용자의 현재 작업을 방해할 수 있기 때문에 신중하게 적용해야 합니다.


2.4. role="alert"

alert 역할은 사용자에게 동적인 변화를 알려줄 때 사용합니다.

스크린 리더는 alert 역할이 붙은 요소가 업데이트 되면 바로 읽기 시작합니다.

role="alert" 로 설정한다는 건 aria-live="assertive" aria-atomic="true" 와 동일합니다.


2.5. role="timer"

현재 요소가 timer 로 사용되고 있다는 걸 의미합니다.

초를 계속 세주려면 aria-live 속성을 켜주면 되지만.. 1초마다 계속 컨텐츠가 갱신되기 때문에 알림이 부자연스럽게 계속 끊기는 이슈가 존재합니다.

만약 timer 에 초점이 잡혔을 때의 남은 시간만 읽어주길 바란다면 role="timer" 설정만 추가해주면 됩니다.


Reference

'공부 > Web' 카테고리의 다른 글

JWT (Json Web Token)  (3) 2021.05.22
URI 란?  (0) 2020.08.26

1. JWT 란 (Json Web Token)

JSON 객체를 사용해서 토큰 자체에 정보를 저장하는 Web Token 입니다.

Header, Payload, Signature 3 개의 부분으로 구성되어 있으며 쿠키나 세션을 이용한 인증보다 안전하고 효율적입니다.

일반적으로는 Authorization: <type> <credentials> 형태로 Request Header 에 담겨져 오기 때문에 Header 값을 확인해서 가져올 수 있습니다.


1.1. 장단점

  • 장점
    • 중앙 인증 서버, 저장소에 대한 의존성이 없어서 수평 확장에 유리
    • Base64 URL Safe Encoding 이라 URL, Cookie, Header 어떤 형태로도 사용 가능
    • Stateless 한 서버 구현 가능
    • 웹이 아닌 모바일에서도 사용 가능
    • 인증 정보를 다른 곳에서도 사용 가능 (OAuth)

  • 단점
    • Payload 의 정보가 많아지면 네트워크 사용량 증가
    • 다른 사람이 토큰을 decode 하여 데이터 확인 가능
    • 토큰을 탈취당한 경우 대처하기 어려움
      • 기본적으로는 서버에서 관리하는게 아니다보니 탈취당한 경우 강제 로그아웃 처리가 불가능
      • 토큰 유효시간이 만료되기 전까지 탈취자는 자유롭게 인증 가능
      • 그래서 유효시간을 짧게 가져가고 refresh token 을 발급하는 방식으로 많이 사용

1.2. Token 구성요소

  • Header

    • alg: Signature 를 해싱하기 위한 알고리즘 정보를 갖고 있음
    • typ: 토큰의 타입을 나타내는데 없어도 됨. 보통 JWT 를 사용
  • Payload

    • 서버와 클라이언트가 주고받는, 시스템에서 실제로 사용될 정보에 대한 내용을 담고 있음
    • JWT 가 기본적으로 갖고 있는 키워드가 존재
    • 원한다면 추가할 수도 있음
      • iss: 토큰 발급자
      • sub: 토큰 제목
      • aud: 토큰 대상
      • exp: 토큰의 만료시간
      • nbf: Not Before
      • iat: 토큰이 발급된 시간
      • jti: JWT의 고유 식별자
  • Signature

    • 서버에서 토큰이 유효한지 검증하기 위한 문자열
    • Header + Payload + Secret Key 로 값을 생성하므로 데이터 변조 여부를 판단 가능
    • Secret Key 는 노출되지 않도록 서버에서 잘 관리 필요

1.3. 토큰 인증 타입

Authorization: <type> <credentials> 형태에서 <type> 부분에 들어갈 값입니다.

엄격한 규칙이 있는건 아니고 일반적으로 많이 사용되는 형태라고 생각하면 됩니다.

  • Basic
    • 사용자 아이디와 암호를 Base64 로 인코딩한 값을 토큰으로 사용
  • Bearer
    • JWT 또는 OAuth 에 대한 토큰을 사용
  • Digest
    • 서버에서 난수 데이터 문자열을 클라이언트에 보냄
    • 클라이언트는 사용자 정보와 nonce 를 포함하는 해시값을 사용하여 응답
  • HOBA
    • 전자 서명 기반 인증
  • Mutual
    • 암호를 이용한 클라이언트-서버 상호 인증
  • AWS4-HMAC-SHA256
    • AWS 전자 서명 기반 인증

2. Refresh Token

JWT 역시 탈취되면 누구나 API 를 호출할 수 있다는 단점이 존재합니다.

세션은 탈취된 경우 세션 저장소에서 탈취된 세션 ID 를 삭제하면 되지만, JWT 는 서버에서 관리하지 않기 때문에 속수무책으로 당할 수밖에 없습니다.

그래서 탈취되어도 피해가 최소화 되도록 유효시간을 짧게 가져갑니다.

하지만 만료 시간을 30분으로 설정하면 일반 사용자는 30 분마다 새로 로그인 하여 토큰을 발급받아야 합니다.

사용자가 매번 로그인 하는 과정을 생략하기 위해 필요한 게 Refresh Token 입니다.


Refresh Token 은 로그인 토큰 (Access Token) 보다 긴 유효 시간을 가지며, Access Token 이 만료된 사용자가 재발급을 원할 경우 Refresh Token 을 함께 전달합니다.

서버는 Access Token 에 담긴 사용자의 정보를 확인하고 Refresh Token 이 아직 만료되지 않았다면 새로운 토큰을 발급해줍니다.

이렇게 하면 사용자가 매번 로그인해야 하는 번거로움 없이 로그인을 지속적으로 유지할 수 있습니다.


Refresh Token 은 사용자가 로그인 할 때 같이 발급되며, 클라이언트가 안전한 곳에 보관하고 있어야 합니다.

Access Toekn 과 달리 매 요청마다 주고 받지 않기 때문에 탈취 당할 위험이 적으며, 요청 주기가 길기 때문에 별도의 저장소에 보관 합니다. (정책마다 다르게 사용)


2.1. Refresh Token 저장소

Refresh Token 은 서버에서 별도의 저장소에 보관하는 것이 좋습니다.

  • Refresh Token 은 사용자 정보가 없기 때문에 저장소에 값이 있으면 검증 시 어떤 사용자의 토큰인지 판단하기 용이
  • 탈취당했을 때 저장소에서 Refresh Token 정보를 삭제하면 Access Token 만료 후에 재발급이 안되게 강제 로그아웃 처리 가능
  • 일반적으로 Redis 많이 사용

2.2. Refresh Token 으로 Access Token 재발급 시나리오

  1. 클라이언트는 access token 으로 API 요청하며 서비스 제공
  2. access token 이 만료되면 서버에서 access token 만료 응답을 내려줌
  3. 클라이언트는 access token 만료 응답을 받고 재발급을 위해 access token + refresh token 을 함께 보냄
  4. 서버는 refresh token 의 만료 여부를 확인
  5. access token 으로 유저 정보 (username 또는 userid) 를 획득하고 저장소에 해당 유저 정보를 key 값으로 한 value 가 refresh token 과 일치하는지 확인
  6. 4~5번의 검증이 끝나면 새로운 토큰 세트 (access + refresh) 발급
  7. 서버는 refresh token 저장소의 value 업데이트

Reference

'공부 > Web' 카테고리의 다른 글

웹 접근성과 WAI-ARIA  (1) 2021.11.10
URI 란?  (0) 2020.08.26

URI 란?

URI (Uniform Resource Identifier) 는 인터넷에 있는 자원을 나타내는 유일한 주소이다.

URI 에는 URL 과 URN 두 종류가 있는데 일반적으로 URL 을 많이 사용한다.


문법

scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]

RFC 3986 에 정의 되어 있는 URL 은 다음과 같은 형태를 나타낸다.

여러 구성 요소 중에 가장 중요한 세 가지는 scheme, host, path 이다.


요소

  1. scheme
    • 스킴이라고 하며 보통 프로토콜을 의미한다.
    • URL 나머지 부분들과 콜론(:) 으로 구분된다.
    • 대소문자를 구분하지 않는다.
    • 리소스에 어떻게 요청, 접근할 것인지 명시하는 how 를 담당한다.
    • ex) http, ftp, rtsp 등등..
  2. host
    • 접근하려고 하는 리소스를 가지고 있는 인터넷 상의 호스트 장비
    • 도메인명 (localhost) 또는 IP 주소 (127.0.0.1) 로 제공한다.
  3. port
    • 하나의 호스트에서 여러 개의 통신을 할 때 구분되는 값
    • 서버가 열어놓을 수 있다.
    • 포트 번호를 명시하지 않으면 default 로 80 이 사용된다.
  4. path
    • 리소스가 서버의 어디에 있는지 알려준다.


'공부 > Web' 카테고리의 다른 글

웹 접근성과 WAI-ARIA  (1) 2021.11.10
JWT (Json Web Token)  (3) 2021.05.22

+ Recent posts