62.1 아랍어 화면은 왜 거울처럼 뒤집혀 보이죠?

아랍어나 히브리어 사이트를 처음 열면 화면이 통째로 거울에 비친 것 같아요. 로고가 오른쪽에, 메뉴도 오른쪽부터, 글자도 오른쪽에서 왼쪽으로 흘러요. 이런 언어를 RTL(right-to-left, 오른쪽에서 왼쪽)이라고 불러요. 우리가 쓰는 한국어나 영어는 반대로 LTR(left-to-right)이고요.


여기서 오해 하나를 풀고 갈게요. RTL은 글자만 오른쪽 정렬하는 게 아니에요. 읽기 시작점이 오른쪽이라 버튼 순서, 목록 번호, 여백이 붙는 방향까지 레이아웃 전체가 좌우로 뒤집혀야 자연스러워요. 그래서 RTL 지원은 번역이 아니라 방향 전환 작업이에요.


RTL을 쓰는 인구는 생각보다 많아요. 아랍어, 히브리어에 페르시아어(이란), 우르두어(파키스탄)까지 더하면 수억 명이거든요. 중동이나 북아프리카로 서비스를 넓힐 계획이라면 언젠가 꼭 만나는 관문이에요. 그리고 한 가지 짚을 게, 뒤집히는 건 가로 방향뿐이에요. 위에서 아래로 읽는 세로 흐름은 그대로라, 헤더가 아래로 내려가거나 하진 않아요.

62.2 방향은 어디서 정하죠?

방향을 켜는 스위치는 딱 하나예요. HTML의 dir 속성이에요. 보통 최상단 <html> 태그에, 언어를 알려주는 lang 속성과 짝으로 걸어요.


<html lang="ar" dir="rtl">
<html lang="ko" dir="ltr">


dir을 "rtl"로 주는 순간, 브라우저가 그 안의 텍스트와 인라인 흐름을 오른쪽부터 시작해요. 텍스트 정렬, 목록 마커 위치, 문장 안 요소 순서가 한꺼번에 뒤집히죠. 페이지 일부만 방향이 다르면 그 요소에만 dir을 걸 수도 있어요. 아랍어 페이지 안의 영어 인용 블록을 dir="ltr"로 감싸는 식으로요. CSS direction: rtl도 같은 일을 하지만, 방향은 내용의 속성이라 HTML dir로 두는 걸 권해요.

62.3 왼쪽 여백을 줬는데 왜 자꾸 깨지죠?

dir만 바꾸면 끝일 것 같지만 진짜 고생은 CSS에서 시작돼요. 우리가 습관처럼 쓰는 margin-left, padding-right, left: 0 같은 속성 때문이에요. 이름 그대로 물리적인 왼쪽, 오른쪽에 딱 고정돼 있거든요.


.avatar {
margin-left: 12px; /* 항상 물리적 왼쪽 */
}


LTR에선 아바타 오른쪽에 이름이 오니 왼쪽 여백이 맞아요. 그런데 RTL로 뒤집히면 아바타는 오른쪽, 이름은 왼쪽으로 가는데 여백은 여전히 왼쪽에 붙어 있어요. 이름과 아바타 사이가 아니라 엉뚱한 바깥쪽에 틈이 생기죠. 방향은 뒤집혔는데 여백은 안 따라간 거예요. 이런 좌우 고정 속성이 페이지에 수십 개 흩어져 있으면 RTL 화면이 곳곳에서 어긋나요.

62.4 그럼 뭘로 바꿔야 하죠?

답은 논리 속성(logical properties)이에요. "왼쪽, 오른쪽"이라는 물리 방향 대신 "시작(start), 끝(end)"이라는 상대 방향으로 말하는 거예요. 시작이 어디인지는 dir이 정해줘요. LTR이면 start가 왼쪽, RTL이면 start가 오른쪽이 되죠.


.avatar {
margin-inline-start: 12px; /* 시작 쪽 여백 */
}


이제 dir이 뒤집히면 여백도 알아서 반대편으로 따라가요. 코드 한 벌로 양쪽 방향을 다 커버하는 거죠. 대응표를 외워두면 편해요.


margin-left → margin-inline-start
padding-right → padding-inline-end
left: 0 → inset-inline-start: 0
text-align: left → text-align: start
border-left → border-inline-start


margin-inline처럼 양쪽을 한 번에 주는 단축형도 있어요. 특히 text-align: start는 정말 자주 써요. left로 박아두면 RTL에서 글이 왼쪽에 붙어 어색한데, start면 방향 따라 알아서 정렬되거든요.


반가운 소식도 있어요. flexboxgrid는 애초에 방향을 알아듣게 설계돼서, 배치 순서가 dir을 따라 자동으로 뒤집혀요. 예를 들어 가로로 나열한 버튼들은 RTL에서 왼쪽부터가 아니라 오른쪽부터 알아서 놓여요.


.toolbar {
display: flex;
gap: 8px; /* 순서는 dir 따라 자동으로 뒤집힘 */
}


그러니 배치는 flex와 grid에 맡기고, 남는 여백과 정렬만 논리 속성으로 챙기면 일이 확 줄어요. 새 프로젝트라면 처음부터 논리 속성으로 쓰는 습관을 들이면 나중에 RTL을 붙일 때 고칠 게 거의 없어요.

62.5 아이콘이랑 화살표는 어떻게 하죠?

레이아웃을 논리 속성으로 다 뒤집어도 아이콘이 남아요. "뒤로 가기" 화살표가 LTR에선 왼쪽을 가리키는데, RTL에선 진행 방향이 반대니 오른쪽을 가리켜야 자연스러워요. 방향을 품은 아이콘은 좌우로 뒤집어(mirror) 줘야 하는 거죠.


[dir="rtl"] .icon-arrow {
transform: scaleX(-1); /* 좌우 반전 */
}


scaleX(-1)은 요소를 좌우로 뒤집는 변형이에요. 화살표, 꺾쇠(chevron), 되돌리기처럼 방향이 곧 의미인 아이콘에 걸어요. 그런데 전부 뒤집으면 안 돼요. 로고, 시계, 체크 표시, 재생 버튼 같은 건 방향과 무관해서 뒤집으면 오히려 이상해져요. 특히 재생 버튼은 RTL에서도 그대로 둬요. 그래서 mirror는 화살표 계열에만 콕 집어 거는 게 요령이에요.

62.6 안 뒤집혀야 할 숫자나 코드도 있죠?

마지막 복병은 양방향 섞임(bidi)이에요. 아랍어 문장 속에 전화번호, 영어 단어, URL이 끼면 순서가 뒤죽박죽 보일 때가 있어요. 브라우저엔 이걸 정리하는 양방향 알고리즘이 있지만, 사용자가 입력한 값은 경계가 헷갈려 깨지기 쉬워요.


이때 그 조각을 독립된 방향 섬으로 격리해 주면 돼요. 인라인 조각엔 bdi 태그가 딱이에요.


<span>주문자: <bdi>+82 10-1234-5678</bdi></span>


bdi(bidirectional isolation, 양방향 격리)로 감싼 전화번호는 바깥 문장 방향에 휘둘리지 않고 제 순서를 지켜요. 블록 요소라면 dir="auto"로 내용을 보고 방향을 스스로 판단하게 해도 되고요. 사용자 이름, 전화번호처럼 어떤 문자가 들어올지 모르는 값은 이렇게 격리해두면 RTL 화면에서도 안 깨져요.

62.7 오늘 배운 걸 묶어볼게요

RTL 지원의 뼈대예요.


핵심
1. 방향은 <html dir="rtl">로 켜고, RTL은 정렬이 아니라 레이아웃 전체가 뒤집혀요.
2. margin-left 같은 물리 속성 대신 margin-inline-start 같은 논리 속성을 써요.
3. text-align은 left 말고 start로.
4. 화살표 계열 아이콘만 scaleX(-1)로 뒤집고 로고와 재생 버튼은 그대로.
5. 전화번호처럼 섞이는 값은 bdi나 dir="auto"로 격리해요.


RTL은 번역이 끝난 뒤에야 시작되는 진짜 국제화예요. 물리 방향을 논리 방향으로 바꿔두는 습관 하나면, 나중에 아랍어나 히브리어를 붙일 때 dir 한 줄로 화면이 통째로 제대로 뒤집혀요. 왼쪽과 오른쪽으로 생각하던 걸 시작과 끝으로 바꾸는 게 전부예요.