fix(테이블타입): bug hunt 발견 6건 수정 (B1~B6)

review 4명 (debugger + security-reviewer + architect + code-reviewer) 발견:

- B1 [CRITICAL]: DdlService.convertToInputType 에 file/image/numbering case 추가
  - 사용자가 파일/이미지/채번 선택해도 silent text 저장되던 버그
  - 박창현 image 2 의 8개 중 3개가 운영에서 작동 안 함
- B2 [MAJOR]: TableManagementService.updateColumnSettings null check
  - settings 에 input_type 키만 있고 값 null 일 때 500 에러 방지
- B3 [MAJOR]: TableSettingModal.tsx 'direct' default → 'text'
  - 운영의 bom.status 같은 컬럼이 UI 에 'direct' 표시되던 원인 제거
- B4 [MINOR/UX]: TypeOverviewStrip 에 Legacy 합산 칩 추가
  - V0 의 legacy 1,209 row (category 888 외) 가 strip 에서 보이도록 amber 칩 + 도넛 호
- B5 [DRY]: USER_SELECTABLE_INPUT_TYPES 공통 상수 추출
  - TableManagementService:30 + DdlService:43 중복 → InputTypeConstants 신설
- B6 [type safety]: context flag enum 화
  - 'user-insert'/'user-update-type'/'user-update-other'/'system-normalize' string → InputTypeContext enum
  - typo silent fail 차단

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 18:07:19 +09:00
parent 0328f618b9
commit 420b92bc7b
5 changed files with 82 additions and 18 deletions
@@ -0,0 +1,13 @@
package com.erp.constants;
import java.util.Set;
public final class InputTypeConstants {
private InputTypeConstants() {}
/** 사용자가 직접 선택 가능한 INPUT_TYPE 8종 (INSERT/UPDATE-type 검증용) */
public static final Set<String> USER_SELECTABLE_INPUT_TYPES = Set.of(
"text", "number", "date", "code", "entity",
"numbering", "file", "image"
);
}
@@ -0,0 +1,8 @@
package com.erp.constants;
public enum InputTypeContext {
USER_INSERT,
USER_UPDATE_TYPE,
USER_UPDATE_OTHER,
SYSTEM_NORMALIZE
}
@@ -1,6 +1,7 @@
package com.erp.service;
import com.erp.common.BaseService;
import com.erp.constants.InputTypeConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
@@ -39,12 +40,6 @@ public class DdlService extends BaseService {
"id", "created_date", "updated_date", "company_code"
);
/** 사용자가 신규 추가하는 컬럼에 허용되는 INPUT_TYPE 8종 (백엔드 백스톱) */
private static final Set<String> USER_SELECTABLE_INPUT_TYPES = Set.of(
"text", "number", "date", "code", "entity",
"numbering", "file", "image"
);
public DdlService(JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager) {
this.jdbcTemplate = jdbcTemplate;
this.transactionTemplate = new TransactionTemplate(transactionManager);
@@ -146,9 +141,9 @@ public class DdlService extends BaseService {
transactionTemplate.execute(status -> {
jdbcTemplate.execute(ddlQuery);
String inputType = convertToInputType(column);
if (!USER_SELECTABLE_INPUT_TYPES.contains(inputType)) {
if (!InputTypeConstants.USER_SELECTABLE_INPUT_TYPES.contains(inputType)) {
throw new IllegalArgumentException(
"INPUT_TYPE 은 다음 8개 중 하나여야 합니다: " + USER_SELECTABLE_INPUT_TYPES
"INPUT_TYPE 은 다음 8개 중 하나여야 합니다: " + InputTypeConstants.USER_SELECTABLE_INPUT_TYPES
+ " (받은 값: " + inputType + ")"
);
}
@@ -421,9 +416,9 @@ public class DdlService extends BaseService {
for (int i = 0; i < columns.size(); i++) {
Map<String, Object> col = columns.get(i);
String inputType = convertToInputType(col);
if (!USER_SELECTABLE_INPUT_TYPES.contains(inputType)) {
if (!InputTypeConstants.USER_SELECTABLE_INPUT_TYPES.contains(inputType)) {
throw new IllegalArgumentException(
"INPUT_TYPE 은 다음 8개 중 하나여야 합니다: " + USER_SELECTABLE_INPUT_TYPES
"INPUT_TYPE 은 다음 8개 중 하나여야 합니다: " + InputTypeConstants.USER_SELECTABLE_INPUT_TYPES
+ " (받은 값: " + inputType + ")"
);
}
@@ -532,6 +527,9 @@ public class DdlService extends BaseService {
case "radio" -> "radio";
case "code" -> "code";
case "entity" -> "entity";
case "file" -> "file";
case "image" -> "image";
case "numbering" -> "numbering";
default -> "text";
};
}