From ed46b01a08b99d3ab53722107285494039bd30a2 Mon Sep 17 00:00:00 2001 From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:59:17 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20useShortcut=20=ED=9B=85=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=8B=A8=EC=B6=95=ED=82=A4=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/hooks/common/useShortcut.ts | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 app/hooks/common/useShortcut.ts diff --git a/app/hooks/common/useShortcut.ts b/app/hooks/common/useShortcut.ts new file mode 100644 index 0000000..8713432 --- /dev/null +++ b/app/hooks/common/useShortcut.ts @@ -0,0 +1,41 @@ +import { useEffect } from 'react'; + +interface useShortcutProps { + onShortcutAction: () => void; + keys: string[]; +} + +const useShortcut = ({ onShortcutAction, keys }: useShortcutProps) => { + useEffect(() => { + const handler = (e) => { + const isPressed = keys?.every((key) => { + if (key === 'Alt') { + return e.altKey; + } else if (key === 'Control' || key === 'Ctrl') { + return e.ctrlKey; + } else if (key === 'Shift') { + return e.shiftKey; + } else if (key === 'Meta') { + return e.metaKey; + } + return e.key.toLowerCase() === key.toLowerCase(); + }); + if (isPressed) { + if (onShortcutAction) { + onShortcutAction(); + } + } + }; + + if (window) { + document.addEventListener('keydown', handler); + } + return () => { + document.removeEventListener('keydown', handler); + }; + }, [onShortcutAction, keys]); + + return; +}; + +export default useShortcut; From b8ab6b23bf3d2ce160c57214dcf2ed5141ce336f Mon Sep 17 00:00:00 2001 From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com> Date: Fri, 8 Aug 2025 17:59:28 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=EB=A9=94=EC=9D=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EA=B8=80=EC=93=B0?= =?UTF-8?q?=EA=B8=B0=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=ED=95=98=EB=8A=94=20=EB=8B=A8=EC=B6=95=ED=82=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/page.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/page.tsx b/app/page.tsx index 3e6a96f..f85126c 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -16,10 +16,13 @@ import useToast from '@/app/hooks/useToast'; import useDataFetch from '@/app/hooks/common/useDataFetch'; import { Post } from '@/app/types/Post'; import ErrorBox from '@/app/entities/common/Error/ErrorBox'; +import { useRouter } from 'next/navigation'; +import useShortcut from '@/app/hooks/common/useShortcut'; export default function Home() { const { fingerprint } = useFingerprint(); const toast = useToast(); + const router = useRouter(); const fetchConfig = { method: 'GET' as const, @@ -41,6 +44,13 @@ export default function Home() { } }, [fingerprint]); + const goToWritePage = () => { + toast.success('글쓰기 페이지로 이동합니다...'); + router.push('/admin/write'); + }; + + useShortcut({ onShortcutAction: goToWritePage, keys: ['Alt', 'N'] }); + return (
From fe1ee62073cb1fdf298763ab2a954dabd91603a7 Mon Sep 17 00:00:00 2001 From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:09:33 +0900 Subject: [PATCH 3/8] =?UTF-8?q?feat:=20=EB=A9=94=EC=9D=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EB=B8=94=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=8B=A8=EC=B6=95=ED=82=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/page.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/page.tsx b/app/page.tsx index f85126c..e0bb20c 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -49,7 +49,13 @@ export default function Home() { router.push('/admin/write'); }; + const goToPostsPage = () => { + toast.success('모든 글 목록 페이지로 이동합니다...'); + router.push('/posts'); + }; + useShortcut({ onShortcutAction: goToWritePage, keys: ['Alt', 'N'] }); + useShortcut({ onShortcutAction: goToPostsPage, keys: ['Ctrl', ';'] }); return (
From 3d7a1439ec58ad56fcbade3a2938b43ad8e59387 Mon Sep 17 00:00:00 2001 From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:11:39 +0900 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20=EB=8B=A8=EC=B6=95=ED=82=A4=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=A0=84=EC=97=AD=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=84=A4=EC=A0=95=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=EC=98=B5=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/hooks/common/useShortcut.ts | 11 ++++++++++- app/page.tsx | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/hooks/common/useShortcut.ts b/app/hooks/common/useShortcut.ts index 8713432..acae430 100644 --- a/app/hooks/common/useShortcut.ts +++ b/app/hooks/common/useShortcut.ts @@ -3,9 +3,14 @@ import { useEffect } from 'react'; interface useShortcutProps { onShortcutAction: () => void; keys: string[]; + isGlobal?: boolean; } -const useShortcut = ({ onShortcutAction, keys }: useShortcutProps) => { +const useShortcut = ({ + onShortcutAction, + keys, + isGlobal, +}: useShortcutProps) => { useEffect(() => { const handler = (e) => { const isPressed = keys?.every((key) => { @@ -30,6 +35,10 @@ const useShortcut = ({ onShortcutAction, keys }: useShortcutProps) => { if (window) { document.addEventListener('keydown', handler); } + if (isGlobal) { + window.addEventListener('keydown', handler); + } + return () => { document.removeEventListener('keydown', handler); }; diff --git a/app/page.tsx b/app/page.tsx index e0bb20c..395b3d1 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -55,7 +55,11 @@ export default function Home() { }; useShortcut({ onShortcutAction: goToWritePage, keys: ['Alt', 'N'] }); - useShortcut({ onShortcutAction: goToPostsPage, keys: ['Ctrl', ';'] }); + useShortcut({ + onShortcutAction: goToPostsPage, + keys: ['Ctrl', ';'], + isGlobal: true, + }); return (
From 956f7b398508c766a3e2ee658818c58eacd4afa8 Mon Sep 17 00:00:00 2001 From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:13:13 +0900 Subject: [PATCH 5/8] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/hooks/common/useShortcut.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/hooks/common/useShortcut.ts b/app/hooks/common/useShortcut.ts index acae430..3810344 100644 --- a/app/hooks/common/useShortcut.ts +++ b/app/hooks/common/useShortcut.ts @@ -31,18 +31,21 @@ const useShortcut = ({ } } }; + // 고민 + // 다른 페이지로 먼저 접근하면 전역 이벤트가 설정되지 않는다. + // 생각나는 해결방법: layout.tsx 에서 useShortcut 훅을 사용하여 전역 이벤트를 설정한다. + // 이렇게 할 경우 어떤 페이지로 접근하든 전역 이벤트를 설정 할 수 있다. - if (window) { - document.addEventListener('keydown', handler); - } if (isGlobal) { window.addEventListener('keydown', handler); + } else if (window) { + document.addEventListener('keydown', handler); } return () => { document.removeEventListener('keydown', handler); }; - }, [onShortcutAction, keys]); + }, [onShortcutAction, keys, isGlobal]); return; }; From 333ee7d1e878bb4fac6dd7b9e69635096e0b8b59 Mon Sep 17 00:00:00 2001 From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:13:48 +0900 Subject: [PATCH 6/8] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A1=B0=EA=B1=B4=EB=AC=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/hooks/common/useShortcut.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/hooks/common/useShortcut.ts b/app/hooks/common/useShortcut.ts index 3810344..953752f 100644 --- a/app/hooks/common/useShortcut.ts +++ b/app/hooks/common/useShortcut.ts @@ -26,9 +26,7 @@ const useShortcut = ({ return e.key.toLowerCase() === key.toLowerCase(); }); if (isPressed) { - if (onShortcutAction) { - onShortcutAction(); - } + onShortcutAction(); } }; // 고민 From 0aa39b5590954562b849c4f755bbed6103fd3502 Mon Sep 17 00:00:00 2001 From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:18:16 +0900 Subject: [PATCH 7/8] =?UTF-8?q?refactor:=20=EB=A7=A4=EA=B0=9C=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=9C=A0=ED=98=95=20=EA=B0=9D=EC=B2=B4=20=EB=8C=80?= =?UTF-8?q?=EC=8B=A0=20=EA=B0=9C=EB=B3=84=EC=A0=81=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B0=9B=EA=B8=B0=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/hooks/common/useShortcut.ts | 16 +++++----------- app/page.tsx | 8 ++------ 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/app/hooks/common/useShortcut.ts b/app/hooks/common/useShortcut.ts index 953752f..8d0ea96 100644 --- a/app/hooks/common/useShortcut.ts +++ b/app/hooks/common/useShortcut.ts @@ -1,16 +1,10 @@ import { useEffect } from 'react'; -interface useShortcutProps { - onShortcutAction: () => void; - keys: string[]; - isGlobal?: boolean; -} - -const useShortcut = ({ - onShortcutAction, - keys, - isGlobal, -}: useShortcutProps) => { +const useShortcut = ( + onShortcutAction: () => void, + keys: string[], + isGlobal: boolean +) => { useEffect(() => { const handler = (e) => { const isPressed = keys?.every((key) => { diff --git a/app/page.tsx b/app/page.tsx index 395b3d1..c058ceb 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -54,12 +54,8 @@ export default function Home() { router.push('/posts'); }; - useShortcut({ onShortcutAction: goToWritePage, keys: ['Alt', 'N'] }); - useShortcut({ - onShortcutAction: goToPostsPage, - keys: ['Ctrl', ';'], - isGlobal: true, - }); + useShortcut(goToWritePage, ['Alt', 'N'], true); + useShortcut(goToPostsPage, ['Ctrl', ';'], true); return (
From 0dc6489dab999cb8aebfa092d6a1b67de9e055b8 Mon Sep 17 00:00:00 2001 From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:32:05 +0900 Subject: [PATCH 8/8] =?UTF-8?q?fix:=20type=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/hooks/common/useShortcut.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/hooks/common/useShortcut.ts b/app/hooks/common/useShortcut.ts index 8d0ea96..f532a50 100644 --- a/app/hooks/common/useShortcut.ts +++ b/app/hooks/common/useShortcut.ts @@ -6,7 +6,7 @@ const useShortcut = ( isGlobal: boolean ) => { useEffect(() => { - const handler = (e) => { + const handler = (e: KeyboardEvent) => { const isPressed = keys?.every((key) => { if (key === 'Alt') { return e.altKey;