임동욱 임동욱 09-04
feat: 앱 메뉴 등록·수정에서 메뉴설명 칸을 뺀다
칸과 함께 도메인 필드·검증·저장 파라미터·응답 매핑까지 걷어낸다 — 그리는 곳이 이 칸뿐이라
남겨 두면 죽은 데이터가 된다.

MENU_EXPLAN 컬럼은 백엔드에 그대로 있다. update가 동적 SET()
이라 보내지 않으면 기존 값이 유지되고, 신규는 NULL로 들어간다 — 메뉴권한(roleId)과 같은
방식이다.

Co-Authored-By: Claude Opus 5 
@124ebcfef2fb000e196ac9547df0187587c89722
app/(protected)/(basic)/system/menus/_actions.ts
--- app/(protected)/(basic)/system/menus/_actions.ts
+++ app/(protected)/(basic)/system/menus/_actions.ts
@@ -64,7 +64,6 @@
     sortOrder: parseFormNumber(formData, 'sortOrder'),
     isTopActive: readString(formData, 'isTopActive') === 'Y',
     url: readString(formData, 'url'),
-    description: readString(formData, 'description'),
     largeIconId: await resolveIconId(formData, 'largeIcon', 'largeIconId'),
     smallIconId: await resolveIconId(formData, 'smallIcon', 'smallIconId'),
     isActive: readString(formData, 'isActive') === 'Y',
app/(protected)/(basic)/system/menus/_components/menu-form-modal.tsx
--- app/(protected)/(basic)/system/menus/_components/menu-form-modal.tsx
+++ app/(protected)/(basic)/system/menus/_components/menu-form-modal.tsx
@@ -18,7 +18,6 @@
   type SystemMenuNode,
 } from '@/lib/domain/system-menu';
 import {
-  DESCRIPTION_MAX_LENGTH,
   INITIAL_SYSTEM_MENU_FORM_STATE,
   NAME_MAX_LENGTH,
   URL_MAX_LENGTH,
@@ -192,20 +191,6 @@
           <FoxHelperText
             type="information"
             message="저장되지 않는 항목입니다. 백엔드에 컬럼이 추가되면 연결됩니다."
-          />
-        </div>
-
-        <div className={styles.field}>
-          <FoxInput
-            size="md"
-            name="description"
-            label="메뉴설명"
-            requirement="required"
-            defaultValue={menu?.description ?? ''}
-            placeholder="메뉴설명을 입력하세요."
-            maxLength={DESCRIPTION_MAX_LENGTH}
-            invalid={Boolean(errors.description)}
-            message={errors.description}
           />
         </div>
 
lib/data/repositories/system-menu-repository.ts
--- lib/data/repositories/system-menu-repository.ts
+++ lib/data/repositories/system-menu-repository.ts
@@ -64,7 +64,6 @@
       isActive: parseYesNo(raw.useYn),
       isTopActive: parseYesNo(raw.topYn),
       isDefault: parseYesNo(raw.defaultYn),
-      description: readString(raw, 'menuExplan'),
       largeIconId: readString(raw, 'atchFileId'),
       largeIconName: readString(raw, 'fileNm'),
       // 미리보기 주소는 서버에서 만든다 — 주소 조립기가 server-only라 화면이 부를 수 없다.
@@ -100,8 +99,8 @@
 
 /**
  * 새창여부는 보내지 않는다 — 저장할 컬럼이 없다(파일 상단 ⚠️ 3).
- * 메뉴권한(roleId)도 화면에서 빠져 보내지 않는다 — update는 동적 SET이라 기존 값이 유지되고,
- * 신규는 NULL로 들어간다(권한 없는 메뉴는 원래도 있다).
+ * 메뉴권한(roleId)과 메뉴설명(menuExplan)도 화면에서 빠져 보내지 않는다 — update는 동적
+ * SET(`<if test="… != null">`)이라 기존 값이 유지되고, 신규는 NULL로 들어간다.
  */
 function toWriteParams(values: SystemMenuValues) {
   return {
@@ -109,7 +108,6 @@
     sortOrdr: values.sortOrder,
     topYn: values.isTopActive ? 'Y' : 'N',
     menuUrl: values.url,
-    menuExplan: values.description,
     useYn: values.isActive ? 'Y' : 'N',
   };
 }
lib/domain/system-menu-form.ts
--- lib/domain/system-menu-form.ts
+++ lib/domain/system-menu-form.ts
@@ -1,6 +1,5 @@
 export const NAME_MAX_LENGTH = 100;
 export const URL_MAX_LENGTH = 300;
-export const DESCRIPTION_MAX_LENGTH = 300;
 export const SORT_ORDER_MAX = 9999;
 
 export interface SystemMenuValues {
@@ -11,7 +10,6 @@
   sortOrder: number;
   isTopActive: boolean;
   url: string;
-  description: string;
   largeIconId: string;
   smallIconId: string;
   isActive: boolean;
@@ -19,7 +17,7 @@
 
 export type SystemMenuFormErrors = Partial<
   Record<
-    'name' | 'sortOrder' | 'url' | 'description' | 'largeIconId' | 'smallIconId',
+    'name' | 'sortOrder' | 'url' | 'largeIconId' | 'smallIconId',
     string
   >
 >;
@@ -69,15 +67,6 @@
     errors.url = url.error;
   }
 
-  const description = validateText(
-    values.description,
-    DESCRIPTION_MAX_LENGTH,
-    '메뉴설명'
-  );
-  if (description.error) {
-    errors.description = description.error;
-  }
-
   if (!Number.isInteger(values.sortOrder) || values.sortOrder < 1) {
     errors.sortOrder = '메뉴순번은 1 이상의 숫자로 입력해 주세요.';
   } else if (values.sortOrder > SORT_ORDER_MAX) {
@@ -94,7 +83,6 @@
       ...values,
       name: name.value,
       url: url.value,
-      description: description.value,
     },
   };
 }
lib/domain/system-menu.ts
--- lib/domain/system-menu.ts
+++ lib/domain/system-menu.ts
@@ -9,7 +9,6 @@
   isActive: boolean;
   isTopActive: boolean;
   isDefault: boolean;
-  description: string | null;
   largeIconId: string | null;
   largeIconName: string | null;
   largeIconUrl: string | null;
Add a comment
List