diff --git a/.jules/palette.md b/.jules/palette.md
index bd0f73248..be35271c6 100644
--- a/.jules/palette.md
+++ b/.jules/palette.md
@@ -57,3 +57,6 @@
## 2026-07-30 - Add window.confirm for destructive actions
**Learning:** Destructive actions like deleting groups and edge relationships previously occurred immediately without user confirmation.
**Action:** Always wrap delete operations with window.confirm() dialogs and ensure corresponding tests successfully mock window.confirm.
+## 2026-08-25 - [Table Modal Action Context]
+**Learning:** 모달 창 내의 액션 버튼(예: '복제', '테이블 삭제')이 단순히 동작 이름만 가지고 있으면, 스크린 리더 사용자는 어떤 대상을 복제하거나 삭제하는지 맥락을 잃을 수 있습니다.
+**Action:** 현재 선택된 컨텍스트(예: 테이블 이름)를 포함하는 명시적인 `aria-label`을 액션 버튼에 추가하여, 시각적 정보 없이도 동작의 대상을 명확히 알 수 있도록 합니다.
diff --git a/frontend/src/components/modals/EditTableModal.test.tsx b/frontend/src/components/modals/EditTableModal.test.tsx
index 1a8c9af5e..cd52e9d0f 100644
--- a/frontend/src/components/modals/EditTableModal.test.tsx
+++ b/frontend/src/components/modals/EditTableModal.test.tsx
@@ -44,6 +44,8 @@ describe('EditTableModal', () => {
expect(screen.getByRole('textbox', { name: 'test_col 데이터 타입' })).toBeInTheDocument();
expect(screen.getByRole('checkbox', { name: 'test_col PK 설정' })).toBeInTheDocument();
expect(screen.getByRole('checkbox', { name: 'test_col NN 설정' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: 'test_table 테이블 삭제' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: 'test_table 테이블 복제' })).toBeInTheDocument();
});
it('returns null if not open or no editingNode', () => {
@@ -170,7 +172,7 @@ describe('EditTableModal', () => {
render();
const user = userEvent.setup();
- await user.click(screen.getByRole('button', { name: '복제' }));
+ await user.click(screen.getByRole('button', { name: 'test_table 테이블 복제' }));
expect(setNodesMock).toHaveBeenCalled();
expect(onEditTableCancelMock).toHaveBeenCalled();
diff --git a/frontend/src/components/modals/EditTableModal.tsx b/frontend/src/components/modals/EditTableModal.tsx
index 998929d44..153407008 100644
--- a/frontend/src/components/modals/EditTableModal.tsx
+++ b/frontend/src/components/modals/EditTableModal.tsx
@@ -191,6 +191,7 @@ export function EditTableModal({
type="button"
onClick={onDeleteTable}
style={{ color: "#b91c1c", borderColor: "#fca5a5" }}
+ aria-label={`${editingNode.data.title} 테이블 삭제`}
>
테이블 삭제
@@ -218,6 +219,7 @@ export function EditTableModal({
onEditTableCancel();
}}
style={{ color: "#034ea2", borderColor: "#93c5fd" }}
+ aria-label={`${editingNode.data.title} 테이블 복제`}
>
복제
diff --git a/frontend/src/components/modals/ModalCoverage.test.tsx b/frontend/src/components/modals/ModalCoverage.test.tsx
index 8732f7efa..1553eb059 100644
--- a/frontend/src/components/modals/ModalCoverage.test.tsx
+++ b/frontend/src/components/modals/ModalCoverage.test.tsx
@@ -183,8 +183,8 @@ describe('modal behavior coverage', () => {
expect(deleteEditing(tableNode)?.data.columns).toHaveLength(1)
fireEvent.submit(document.getElementById('editTableForm')!)
- fireEvent.click(screen.getByRole('button', { name: '테이블 삭제' }))
- fireEvent.click(screen.getByRole('button', { name: '복제' }))
+ fireEvent.click(screen.getByRole('button', { name: 'public.users 테이블 삭제' }))
+ fireEvent.click(screen.getByRole('button', { name: 'public.users 테이블 복제' }))
const duplicate = setNodes.mock.calls[2]?.[0] as (nodes: Node[]) => Node[]
const duplicated = duplicate([tableNode])[1]!
expect(duplicated).toMatchObject({