fix(backend): 관광공사 사진 주소를 https 로 맞춤

관광공사 장소 사진 1,059건 중 279건이 http 였다. 같은 서버(tong.visitkorea.or.kr)가 https 로도 주므로
저장할 때 https 로 바꾼다(장소·행사 모두). 앱은 http 사진도 받지만 웹(https 페이지)에서는 혼합 콘텐츠로 막힌다.
확인하지 않은 다른 서버의 주소는 그대로 둔다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-05 13:37:16 +09:00
parent 4f50df00d8
commit 898ef04266
7 changed files with 58 additions and 8 deletions
@@ -52,8 +52,9 @@ describe('festivalItemToEvent', () => {
ldongRegnCd: '27',
ldongSignguCd: '260',
phone: '053-666-4842',
imageUrl: 'http://tong.visitkorea.or.kr/f.jpg',
imageThumbUrl: 'http://tong.visitkorea.or.kr/f_s.jpg',
// 관광공사 사진 서버는 https 로 맞춘다
imageUrl: 'https://tong.visitkorea.or.kr/f.jpg',
imageThumbUrl: 'https://tong.visitkorea.or.kr/f_s.jpg',
imageLicense: 'Type3',
sourceModifiedAt: new Date('2026-10-20T01:15:00.000Z'),
});
@@ -1,5 +1,6 @@
import { isInKorea } from '@/shared/utils/geo';
import { extractUrl, htmlToText } from '@/shared/utils/html-text';
import { preferHttps } from '@/shared/utils/image-url';
import { parseKstTimestamp } from '@/shared/utils/kst';
import { IMAGE_LICENSES } from '../place.constants';
import type { EventKind, ImageLicense } from '../place.constants';
@@ -88,8 +89,8 @@ export function festivalItemToEvent(
ldongRegnCd: str(item, 'lDongRegnCd'),
ldongSignguCd: str(item, 'lDongSignguCd'),
phone: htmlToText(item.tel),
imageUrl: str(item, 'firstimage'),
imageThumbUrl: str(item, 'firstimage2'),
imageUrl: preferHttps(str(item, 'firstimage')),
imageThumbUrl: preferHttps(str(item, 'firstimage2')),
imageLicense: (IMAGE_LICENSES as readonly string[]).includes(license ?? '')
? (license as ImageLicense)
: null,
@@ -70,8 +70,9 @@ describe('listItemToPlace', () => {
ldongRegnCd: '27',
ldongSignguCd: '110',
phone: '053-661-2194',
imageUrl: 'http://tong.visitkorea.or.kr/a.jpg',
imageThumbUrl: 'http://tong.visitkorea.or.kr/a_s.jpg',
// 관광공사 사진 서버는 https 로 맞춘다(웹에서 혼합 콘텐츠로 막히지 않게)
imageUrl: 'https://tong.visitkorea.or.kr/a.jpg',
imageThumbUrl: 'https://tong.visitkorea.or.kr/a_s.jpg',
imageLicense: 'Type1',
sourceModifiedAt: new Date('2026-10-15T00:30:00.000Z'),
});
@@ -1,5 +1,6 @@
import { isInKorea, isInSido, sidoCodeFromAddress } from '@/shared/utils/geo';
import { extractUrl, htmlToText } from '@/shared/utils/html-text';
import { preferHttps } from '@/shared/utils/image-url';
import { parseKstTimestamp } from '@/shared/utils/kst';
import { parseOpeningHours } from '@/shared/utils/opening-hours';
import type { ParsedOpeningHours } from '@/shared/utils/opening-hours';
@@ -224,8 +225,8 @@ export function listItemToPlace(
ldongRegnCd: str(item, 'lDongRegnCd'),
ldongSignguCd: str(item, 'lDongSignguCd'),
phone: htmlToText(item.tel),
imageUrl: str(item, 'firstimage'),
imageThumbUrl: str(item, 'firstimage2'),
imageUrl: preferHttps(str(item, 'firstimage')),
imageThumbUrl: preferHttps(str(item, 'firstimage2')),
imageLicense: (IMAGE_LICENSES as readonly string[]).includes(license ?? '')
? (license as ImageLicense)
: null,
@@ -0,0 +1,26 @@
import { preferHttps } from './image-url';
describe('preferHttps', () => {
it('관광공사 사진 서버의 http 주소를 https 로 바꾼다', () => {
expect(
preferHttps('http://tong.visitkorea.or.kr/cms/resource/a_image2_1.jpg'),
).toBe('https://tong.visitkorea.or.kr/cms/resource/a_image2_1.jpg');
expect(preferHttps('HTTP://Tong.VisitKorea.or.kr/a.jpg')).toBe(
'https://Tong.VisitKorea.or.kr/a.jpg',
);
});
it('이미 https 이거나 확인하지 않은 서버·빈 값은 그대로 둔다', () => {
expect(preferHttps('https://tong.visitkorea.or.kr/a.jpg')).toBe(
'https://tong.visitkorea.or.kr/a.jpg',
);
expect(preferHttps('http://www.kopis.or.kr/a.jpg')).toBe(
'http://www.kopis.or.kr/a.jpg',
);
expect(preferHttps('http://tong.visitkorea.or.kr.evil.example/a.jpg')).toBe(
'http://tong.visitkorea.or.kr.evil.example/a.jpg',
);
expect(preferHttps(null)).toBeNull();
expect(preferHttps('')).toBe('');
});
});
+18
View File
@@ -0,0 +1,18 @@
/**
* 사진 주소 정리 (순수 함수).
*/
/**
* 같은 파일을 https 로도 주는 것을 확인한 사진 서버.
* 2026-11-04 대구 관광공사 장소 사진 1,059건 중 780건은 https, 279건은 http 였다(같은 서버).
* https 페이지(웹)에서는 http 사진이 혼합 콘텐츠로 막히므로 저장할 때 https 로 맞춘다.
*/
const HTTPS_IMAGE_HOSTS = new Set(['tong.visitkorea.or.kr']);
/** 확인한 서버의 http 사진 주소를 https 로 바꾼다. 다른 서버·형식은 그대로 둔다 */
export function preferHttps(url: string | null): string | null {
if (!url) return url;
const m = /^http:\/\/([^/?#:]+)/i.exec(url);
if (!m || !HTTPS_IMAGE_HOSTS.has(m[1].toLowerCase())) return url;
return `https://${url.slice('http://'.length)}`;
}