[Front] 이메일 클라이언트 호환성 이슈 - Vue3로 크로스 브라우징 정상화 하기

devicii·2024년 11월 29일
0

Front

목록 보기
5/8

0. 문제 발생

인턴쉽 중 알림 이메일 템플릿 작업을 맡았는데... 은근히 문제가 있는 친구였다.

왜 고통인가?

  • Outlook은 flexbox를 지원 안 함 (2024년인데)
  • Gmail은 되는데 Apple Mail에선 안 되고
  • 모바일은 또 따로 노는...

근데 이걸 정상화 하는 방법을 찾아냈다!
Vue3로 컴포넌트 하나 만들어서 깔끔하게 해결할 수 있다.

1. HTML구조 만들기

<!-- EmailLayout.vue -->
<template>
  <table 
    :width="width" 
    :cellpadding="padding" 
    :cellspacing="0" 
    :style="tableStyle"
  >
    <tr>
      <td :align="align" :style="tdStyle">
        <slot></slot>
      </td>
    </tr>
  </table>
</template>

"헐 테이블이요?" 이라는 생각이 절로 들지만
이메일 클라이언트에서는 테이블 레이아웃이 가장 안전하다. (IE 6-7빼곤 다 지원함)

2. 스크립트 작성하기

<script setup>
import { computed } from 'vue'

const props = defineProps({
  width: {
    type: [String, Number],
    default: '100%'
  },
  padding: {
    type: [String, Number],
    default: 0
  },
  align: {
    type: String,
    default: 'left'
  },
  backgroundColor: {
    type: String,
    default: 'transparent'
  },
  border: {
    type: [String, Number],
    default: 0
  }
})

const tableStyle = computed(() => ({
  borderCollapse: 'collapse',
  msoTableLspace: '0pt',
  msoTableRspace: '0pt',
  backgroundColor: props.backgroundColor,
  border: props.border
}))

const tdStyle = computed(() => ({
  fontFamily: 'Arial, sans-serif',
  fontSize: '14px',
  lineHeight: '1.5',
  padding: typeof props.padding === 'number' ? `${props.padding}px` : props.padding
}))
</script>

props랑 스타일 설정해주는 부분이다.
msoTableLspacemsoTableRspace는 Outlook 전용

3. 컴포넌트 적용하기

<!-- EmailTemplate.vue -->
<template>
  <EmailLayout width="600" padding="20" backgroundColor="#f5f5f5">
    <!-- 메인 콘텐츠 -->
    <EmailLayout padding="20" backgroundColor="#ffffff">
      <h1>안녕하세요!</h1>
      <p>이메일 내용이 들어갈 자리입니다.</p>
    </EmailLayout>
    
    <!-- 이미지 섹션 -->
    <EmailLayout padding="10" backgroundColor="#ffffff" align="center">
      <img src="example.jpg" alt="예시 이미지" />
    </EmailLayout>
    
    <!-- 2단 레이아웃 -->
    <EmailLayout padding="20" backgroundColor="#ffffff">
      <table width="100%">
        <tr>
          <td width="50%">
            <h2>왼쪽 콘텐츠</h2>
            <p>내용 1</p>
          </td>
          <td width="50%">
            <h2>오른쪽 콘텐츠</h2>
            <p>내용 2</p>
          </td>
        </tr>
      </table>
    </EmailLayout>
  </EmailLayout>
</template>

이렇게 중첩해서 쓸 수 있다.

4. 주의할 점

####CSS는 무조건 인라인으로

외부 CSS 파일? 그런 거 안됌ㅋ
Gmail이 외부 CSS 파일을 자동으로 제거해버린다.
<link>태그도 보안상의 이유로 대부분 차단된다고 한다. (velog에서도 코드 주석 안 달면 차단됌)

style 태그도 되는 클라이언트/안 되는 클라이언트가 나뉨

Outlook은 <style> 태그를 완전히 무시함.
Gmail은 일부 속성만 허용하고 나머지는 제거한다고 한다.
그래서 중요한 스타일은 전부 인라인으로 넣어야 함

이미지는 무조건 절대경로로

상대경로 쓰면 망한다.
이메일 클라이언트마다 기준 경로가 다 다르다
이미지 서버 도메인까지 풀로 적어야 함 (https://부터 시작!)

alt 텍스트는 필수

이메일 클라이언트 중에는 기본적으로 이미지를 차단하는 경우가 많다.
이때 alt 텍스트라도 보여야 유저가 내용이라도 유추할 수 있다.
접근성 측면에서도 꼭 필요하니 까먹지 말자

반응형은 신중히 쓰자

max-width 말고 width="100%" 써야함
Outlook이 max-width를 지원하지 않는다.
반면에 width="100%"는 거의 모든 클라이언트가 지원한다.

후기

이렇게 컴포넌트를 수정하고 나니 크로스 브라우징 이슈가 대부분 해결됐다.

Outlook에서도 깔끔하게 나오고,
Gmail, Yahoo, Apple Mail 전부 호환되고,
모바일에서도 레이아웃이 망가지지 않는다.

테이블 레이아웃이 좀 구식으로 보일 수 있지만,
이메일 클라이언트 호환성을 위해서는 이런 옛날 태그도 활용할 필요가 있다.

profile
흘러가는대로 사는

0개의 댓글