Skip to content

Commit 4cc2bc0

Browse files
committed
feat: notion-to-utils formatNotionImageUrl 불필요 query 삭제
1 parent ad8c8eb commit 4cc2bc0

File tree

3 files changed

+77
-34
lines changed

3 files changed

+77
-34
lines changed

apps/storybook/src/sample-data/notionBlocks.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@
6868
"caption": [],
6969
"type": "file",
7070
"file": {
71-
"url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/566f127b-9e73-491d-bee6-5afd075653a2/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB4667ZOXY2Y6%2F20250319%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250319T125545Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEBwaCXVzLXdlc3QtMiJIMEYCIQCo971xkAkpOezG800JUV1AJkAZ1%2BJ4GHc%2BXUmLgc%2B5PwIhAIfB6MFIuO9ESgtes%2Bvf%2Fehjzj%2BkvnaSGdAaBVY138ooKv8DCHUQABoMNjM3NDIzMTgzODA1Igwi4apJDc%2Bqo22dqecq3AP%2BDHeGuvT8rmtUsxYlp9NJ6tFdB1ACasA9X5yJmZihnP9hSw3j%2FZA%2Fr8Z5GQ%2FhfYNLtPooN2yczm5Wv%2F7uCSjB2Fj8HL9InG3FkjuSxnBbktd80L0LNbmriYZhEwkcLJ3MtZCxy0IyGzu%2Bxobsj9QVKaaP7Tj716vfx19xo%2BBSqZ1vOelZgdKeQ0o1MiFYkwbZ9fWsTw8QklGdK5%2Bp840vrP2LUoU2sh0YsTLrgnVu2NdG18MKUCVUOL6yLb%2BxFFsvk%2Bff3vcO%2BHKQ7U2F%2FcZclBOgKfUOL0QUZRiYHJIcPq1XrkF8o2KkxKxkJfTeJMdyifwO0zIf9Dzzb6dLj6hfG6wJ1DwDJVCQKi9cIPrnDbcyBOJ7Z3PD7mme6jueP1anVq8%2FIt6uYD%2FKgE40FkJjFLCOPYdFAH1erRiwG3w2jxWq45bl2b29Qs7tMGmVuaync79S3F1RGLZdnLYGGJZYBCmRgua1wKaJ4P3dM0hniTkh8cWlkER6xZdu8Hs4akAuCs4ySm%2FRaBwow%2BspV%2BkZ%2F%2BwYE9dpTCGeRtAIPCvmVYSmuRPmKNPpX6gGmmQJwDzFLFPqALc3GLYxpryP%2Fjh%2Fgwqw%2Bog2%2BeSp6iDZ7rLkOPwZ4wk8h5PYSuWVhjDi4Oq%2BBjqkAUIe5ZKyHXXBq%2BiJp%2BU35TAMenQbIlEE6oJrqlwkBQ7nV4Mfbh8YxETPph9LetG8fm90uJmS9%2BbR73AP6LJYrcVWvrZp%2BcyBKtYFCa7TFD9luj7iSwL0C1rOukxu3VslsBc%2FWKnXlndYtCAT%2FumdsC9PH84%2B1QqruASGJZZ9R2a%2BqFRkCJg5maGTFkq30RZkW%2F9i7%2FLVSVp62IonNMyAocrnuO84&X-Amz-Signature=ec0b1f90dce03602b54b49c1459d830e8aef008221f67ff79439afe6364cd9c2&X-Amz-SignedHeaders=host&x-id=GetObject",
72-
"expiry_time": "2025-03-19T13:55:45.348Z"
71+
"url": "https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Fcd7314a5-d906-43b0-81e7-42eff82c02a3%2F566f127b-9e73-491d-bee6-5afd075653a2%2Fimage.png?table=block&id=17f9c6bf-2b17-8016-bf79-dc83ab79fb78&cache=v2",
72+
"expiry_time": "2025-03-19T14:54:05.767Z"
7373
}
7474
}
7575
},
@@ -845,7 +845,7 @@
845845
"page_id": "1239c6bf-2b17-8076-a838-d17ca1c89783"
846846
},
847847
"created_time": "2024-10-18T08:07:00.000Z",
848-
"last_edited_time": "2025-03-09T11:03:00.000Z",
848+
"last_edited_time": "2025-03-19T13:01:00.000Z",
849849
"created_by": {
850850
"object": "user",
851851
"id": "5146391e-8b65-47f2-83b6-2bfe81194f32"
@@ -4560,8 +4560,8 @@
45604560
"caption": [],
45614561
"type": "file",
45624562
"file": {
4563-
"url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/10d9f59d-d3e2-429a-ad72-c8b15b1f536b/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB4667ZOXY2Y6%2F20250319%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250319T125545Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEBwaCXVzLXdlc3QtMiJIMEYCIQCo971xkAkpOezG800JUV1AJkAZ1%2BJ4GHc%2BXUmLgc%2B5PwIhAIfB6MFIuO9ESgtes%2Bvf%2Fehjzj%2BkvnaSGdAaBVY138ooKv8DCHUQABoMNjM3NDIzMTgzODA1Igwi4apJDc%2Bqo22dqecq3AP%2BDHeGuvT8rmtUsxYlp9NJ6tFdB1ACasA9X5yJmZihnP9hSw3j%2FZA%2Fr8Z5GQ%2FhfYNLtPooN2yczm5Wv%2F7uCSjB2Fj8HL9InG3FkjuSxnBbktd80L0LNbmriYZhEwkcLJ3MtZCxy0IyGzu%2Bxobsj9QVKaaP7Tj716vfx19xo%2BBSqZ1vOelZgdKeQ0o1MiFYkwbZ9fWsTw8QklGdK5%2Bp840vrP2LUoU2sh0YsTLrgnVu2NdG18MKUCVUOL6yLb%2BxFFsvk%2Bff3vcO%2BHKQ7U2F%2FcZclBOgKfUOL0QUZRiYHJIcPq1XrkF8o2KkxKxkJfTeJMdyifwO0zIf9Dzzb6dLj6hfG6wJ1DwDJVCQKi9cIPrnDbcyBOJ7Z3PD7mme6jueP1anVq8%2FIt6uYD%2FKgE40FkJjFLCOPYdFAH1erRiwG3w2jxWq45bl2b29Qs7tMGmVuaync79S3F1RGLZdnLYGGJZYBCmRgua1wKaJ4P3dM0hniTkh8cWlkER6xZdu8Hs4akAuCs4ySm%2FRaBwow%2BspV%2BkZ%2F%2BwYE9dpTCGeRtAIPCvmVYSmuRPmKNPpX6gGmmQJwDzFLFPqALc3GLYxpryP%2Fjh%2Fgwqw%2Bog2%2BeSp6iDZ7rLkOPwZ4wk8h5PYSuWVhjDi4Oq%2BBjqkAUIe5ZKyHXXBq%2BiJp%2BU35TAMenQbIlEE6oJrqlwkBQ7nV4Mfbh8YxETPph9LetG8fm90uJmS9%2BbR73AP6LJYrcVWvrZp%2BcyBKtYFCa7TFD9luj7iSwL0C1rOukxu3VslsBc%2FWKnXlndYtCAT%2FumdsC9PH84%2B1QqruASGJZZ9R2a%2BqFRkCJg5maGTFkq30RZkW%2F9i7%2FLVSVp62IonNMyAocrnuO84&X-Amz-Signature=f4f7a75350d15a03ee3beaf213bda4485d8734443f3dcf1dfbb92b7a09ea6941&X-Amz-SignedHeaders=host&x-id=GetObject",
4564-
"expiry_time": "2025-03-19T13:55:45.591Z"
4563+
"url": "https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Fcd7314a5-d906-43b0-81e7-42eff82c02a3%2F10d9f59d-d3e2-429a-ad72-c8b15b1f536b%2Fimage.png?table=block&id=1809c6bf-2b17-8096-aaf4-d89c3850bed0&cache=v2",
4564+
"expiry_time": "2025-03-19T14:54:05.937Z"
45654565
}
45664566
}
45674567
},

packages/notion-to-utils/src/client/formatNotionImageUrl.ts

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,95 @@
11
/**
22
* 노션 이미지 URL을 깔끔한 형태로 변환하는 함수
3-
*
3+
*
44
* S3 URL 형식의 노션 이미지 URL을 notion.so/image/ 형식으로 변환합니다.
5-
*
5+
* AWS 인증 토큰 등의 복잡한 파라미터를 제거하고 기본 이미지 URL만 사용합니다.
6+
*
67
* @param url - 변환할 S3 이미지 URL
78
* @param blockId - 블록 ID (선택적)
89
* @param userId - 사용자 ID (선택적)
910
* @returns 변환된 노션 스타일 이미지 URL
10-
*
11+
*
1112
* @example
1213
* const formattedUrl = formatNotionImageUrl('https://prod-files-secure.s3.us-west-2.amazonaws.com/...');
1314
* // 결과: https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F...
1415
*/
1516
export const formatNotionImageUrl = (
16-
url: string,
17+
url: string | undefined,
1718
blockId?: string,
18-
userId?: string
19+
userId?: string | undefined
1920
): string => {
20-
// URL이 없거나 유효하지 않은 경우 원래 URL 반환
21-
if (!url || !url.startsWith('https://')) {
22-
return url;
21+
// URL이 없거나 유효하지 않은 경우 빈 문자열 또는 원래 URL 반환
22+
if (!url || typeof url !== 'string' || !url.startsWith('https://')) {
23+
return url ?? '';
2324
}
2425

2526
try {
2627
// 이미 notion.so 형식인 경우 그대로 반환
2728
if (url.includes('notion.so/image/')) {
28-
return url;
29+
return url; // 이미 노션 이미지 URL 형식인 경우 그대로 반환
2930
}
3031

31-
// URL 인코딩
32-
const encodedUrl = encodeURIComponent(url);
33-
32+
// S3 URL에서 AWS 인증 파라미터 제거 (? 이후 부분 제거)
33+
// 안전하게 URL 처리 - 항상 문자열 반환 보장
34+
// 이 시점에서 url은 string 타입이 보장됨
35+
const baseUrl = url.includes('?') ? url.split('?')[0] : url;
36+
37+
// URL 인코딩 (문자열만 인코딩 가능)
38+
// 타입 단언을 사용하여 TypeScript에게 baseUrl이 문자열임을 알림
39+
const encodedUrl = encodeURIComponent(baseUrl as string);
40+
3441
// 기본 노션 이미지 URL 형식
3542
let formattedUrl = `https://www.notion.so/image/${encodedUrl}`;
36-
43+
3744
// 추가 파라미터 설정
3845
const params: string[] = [];
39-
46+
4047
// 블록 ID가 있는 경우 추가
4148
if (blockId) {
4249
params.push(`table=block&id=${blockId}`);
4350
}
44-
45-
// 사용자 ID가 있는 경우 추가
46-
if (userId) {
47-
params.push(`userId=${userId}`);
48-
}
49-
51+
5052
// 추가 파라미터가 있는 경우 URL에 추가
5153
if (params.length > 0) {
5254
formattedUrl += `?${params.join('&')}`;
5355
}
54-
56+
5557
// 캐시 버스팅 파라미터 추가
5658
formattedUrl += formattedUrl.includes('?') ? '&' : '?';
5759
formattedUrl += 'cache=v2';
58-
60+
5961
return formattedUrl;
6062
} catch (error) {
6163
console.error('이미지 URL 변환 중 오류 발생:', error);
62-
return url; // 오류 발생 시 원래 URL 반환
64+
return url ?? ''; // 오류 발생 시 원래 URL 반환
6365
}
6466
};
6567

6668
/**
6769
* 노션 블록에서 이미지 URL을 추출하고 포맷팅하는 함수
68-
*
70+
*
6971
* @param block - 노션 블록 객체
7072
* @returns 포맷팅된 이미지 URL 또는 null
7173
*/
7274
export const getFormattedImageUrlFromBlock = (block: any): string | null => {
7375
if (!block) return null;
74-
76+
7577
try {
7678
// 이미지 블록인 경우
7779
if (block.type === 'image') {
7880
const imageData = block.image;
79-
const url = imageData.file?.url || imageData.external?.url;
80-
81+
const url = imageData?.file?.url || imageData?.external?.url;
82+
83+
// URL이 존재하는 경우 처리
8184
if (url) {
82-
return formatNotionImageUrl(url, block.id, block.last_edited_by?.id);
85+
// expiry_time 필드가 있는 경우에도 무시하고 URL만 사용
86+
// URL에서 기본 이미지 경로만 추출하여 사용
87+
const blockId = block.id;
88+
const userId = block.last_edited_by?.id;
89+
return formatNotionImageUrl(url, blockId, userId);
8390
}
8491
}
85-
92+
8693
return null;
8794
} catch (error) {
8895
console.error('블록에서 이미지 URL 추출 중 오류 발생:', error);

packages/notion-to-utils/src/client/getPageBlocks.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
BlockObjectResponse,
55
PartialBlockObjectResponse,
66
} from '@notionhq/client/build/src/api-endpoints';
7+
import { formatNotionImageUrl } from './formatNotionImageUrl';
78

89
// 블록 타입 정의
910
export type NotionBlock = BlockObjectResponse | PartialBlockObjectResponse;
@@ -54,6 +55,41 @@ async function fetchBlockChildren(
5455
...block,
5556
} as unknown as NotionBlockWithChildren;
5657

58+
// 이미지 블록인 경우 URL 포맷팅 처리
59+
if ('type' in block && block.type === 'image') {
60+
// 타입 안전성을 위해 any로 처리
61+
const imageBlock = block as any;
62+
63+
// 이미지 속성이 있는지 확인
64+
if (imageBlock.image) {
65+
// file URL 처리
66+
if (imageBlock.image.file && imageBlock.image.file.url) {
67+
const url = imageBlock.image.file.url;
68+
const userId = imageBlock.last_edited_by?.id;
69+
// 포맷팅된 URL로 교체
70+
imageBlock.image.file.url = formatNotionImageUrl(
71+
url,
72+
block.id,
73+
userId
74+
);
75+
}
76+
// external URL 처리
77+
else if (
78+
imageBlock.image.external &&
79+
imageBlock.image.external.url
80+
) {
81+
const url = imageBlock.image.external.url;
82+
const userId = imageBlock.last_edited_by?.id;
83+
// 포맷팅된 URL로 교체
84+
imageBlock.image.external.url = formatNotionImageUrl(
85+
url,
86+
block.id,
87+
userId
88+
);
89+
}
90+
}
91+
}
92+
5793
// 타입 가드를 사용하여 has_children 속성 확인
5894
if (hasChildren(block)) {
5995
// 하위 블록 가져오기

0 commit comments

Comments
 (0)