자동화 slecs

에디터 이미지 치환 로직에 CDN 호스트 예외 추가

목차

에디터의 외부 이미지 자동 치환 로직에 CDN 호스트 허용 예외를 추가했다.

왜 이 작업이 필요했나

사내 서비스 에디터에는 외부 이미지를 내부 프록시나 자체 스토리지로 자동 치환하는 로직이 붙어 있었다. 이런 구조는 흔하다. 에디터에서 임의 외부 URL 이미지를 그대로 허용하면 broken image 리스크, mixed content 문제, 외부 도메인 응답 지연, 그리고 콘텐츠 보안 정책(CSP) 위반 같은 문제들이 줄줄이 따라온다. 그래서 에디터 단에서 외부 이미지를 감지해 치환하는 로직을 심어 두는 건 꽤 일반적인 선택이다.

문제는 CDN이었다. 서비스가 커지거나 인프라가 변경될수록 이미지를 올리는 CDN 호스트가 늘어난다. 기존 로직이 "외부 이미지 = 전부 치환 대상"이라는 단순한 판단으로 돌아가고 있었다면, CDN 호스트에 올라간 이미지조차 치환 대상으로 잡아서 의도치 않은 URL 재처리가 발생했을 가능성이 높다. 결국 치환 로직이 믿어도 되는 출처(CDN)를 모르는 상태였던 것.

변경 내용 정리

editor.js 한 파일에 집중된 수정이었다. 변경 통계가 명시되지 않았지만, 로직 개선이라는 표현과 파일 범위를 보면 대규모 리팩터링보다는 허용 목록(allowlist) 추가 + 조건 분기 수정 수준의 핀포인트 작업으로 보인다.

치환 로직의 전형적인 구조는 이런 흐름이다.

// Before: 단순 외부 도메인 판별
function isExternalImage(src) {
  const internalHost = location.hostname;
  return new URL(src).hostname !== internalHost;
}

// After: CDN 허용 호스트 포함 예외 처리
const ALLOWED_HOSTS = [
  location.hostname,
  'cdn.example-internal.com',  // CDN 호스트 추가
];

function isExternalImage(src) {
  try {
    const { hostname } = new URL(src);
    return !ALLOWED_HOSTS.some(host => hostname === host || hostname.endsWith(`.${host}`));
  } catch {
    return false;
  }
}

실제 코드가 이 패턴과 완전히 같진 않겠지만, 흐름 자체는 이와 크게 다르지 않을 거다. 핵심은 "치환해야 할 외부 이미지"와 "신뢰할 수 있는 외부 호스트"를 구분하는 기준을 에디터 JS가 갖게 됐다는 것.

구분 기존 변경 후
내부 호스트 이미지 치환 제외 치환 제외
CDN 호스트 이미지 치환 대상 (문제) 치환 제외 (수정)
기타 외부 이미지 치환 대상 치환 대상

이런 로직, 어디서 꼬이는가

이 작업을 하면서 다시 떠올린 건 "프론트 JS에 도메인 허용 목록을 박아 두는 게 옳은 구조인가"라는 질문이다. 사실 이상적으로는 서버 사이드에서 이미지 origin을 판별하고 치환 여부를 결정하는 게 더 안전하고 관리하기 쉽다. 프론트에 하드코딩된 허용 목록은 CDN 도메인이 바뀔 때마다 JS를 수정하고 배포해야 한다는 단점이 있다.

팀 내에서도 이 부분은 다음 스프린트에 논의할 포인트로 남겨뒀다. 지금은 일단 에디터에서 발생하는 오작동을 막는 것이 우선이었고, 구조 개선은 그 다음 순서다. 기술 부채를 인식하면서 일단 실용적인 수정을 택하는 상황은 현업에서 늘 있는 일이다. 중요한 건 그 판단을 팀이 공유하고 있어야 한다는 것.

허용 목록 관리 방식 측면에서 흔히 비교되는 옵션들을 정리하면 이렇다.

  • JS 상수 hardcode: 빠르지만 변경 시 배포 필요
  • 서버 API로 허용 목록 조회: 유연하지만 에디터 초기화 시 요청 추가
  • CSP(Content-Security-Policy) 헤더 기반: 브라우저 레벨에서 차단, 에디터 로직 단순화 가능
  • 에디터 초기화 옵션으로 주입: 서버 렌더링 시점에 허용 호스트를 넘겨줘 하드코딩 회피

코드리뷰에서 이 옵션들을 간략히 언급했고, 팀원도 장기적으로는 서버 주입 방식이 낫다는 데 동의했다. 당장의 수정은 최소 범위로 가되, 방향성은 맞춰 두는 것.

에디터 관련 JS는 건드릴 때마다 "이게 어디까지 영향 가지?"를 먼저 따지게 된다. 에디터는 콘텐츠를 만드는 진입점이라 여기서 발생한 버그는 저장된 데이터까지 오염시킬 수 있기 때문. 이번 수정은 작은 조건 추가였지만, 그 판단을 꼼꼼하게 가져가야 하는 파일이라는 걸 다시 한번 확인했다.

끝.

댓글 0

첫 댓글 달아줘.