일반공고 sirsoft-board 정책 제한값 하드코딩 문제
페이지 정보

조회 25회 작성일 26-07-18 18:09
본문
게시판부분만 점검해 봤습니다. 전체적으로 점검해봐야할 문제라 생각 됩니다.
# sirsoft-board 정책 제한값 하드코딩 1차 감사 보고서
> 제안 이슈 제목: `[sirsoft-board] 설정 제한값 하드코딩과 정책 불일치로 검증·서비스·UI 계약이 분리됨`
## 결론
**첨부파일 최대 20개 한 건의 문제가 아니라, 설정 가능한 정책값이 검증 요청, 서비스, JSON UI, 다국어 문구, API 문서에 중복 하드코딩되어 실제 계약이 분리된 구조적 결함입니다.**
**본 보고서는 확인된 제한값 관련 경로를 대상으로 한 일부 감사입니다. 이번 결과만으로 `sirsoft-board` 전체 또는 그누보드7 전체에 하드코딩 문제가 없다고 판단할 수 없으며, 정식 출시 전 별도의 전수 감사가 필요합니다.**
중앙 설정이 일부 존재하지만 적용 범위가 일관되지 않아 다음 문제가 이미 발생하고 있습니다.
확인된 핵심 위험은 다음과 같습니다.
| 우선순위 | 문제 | 현재 영향 |
|---|---|---|
| 높음 | 대댓글 저장 깊이가 서비스에서 `5`로 고정됨 | 설정값 `6~10`에서 깊이 제한과 계층 표현이 깨짐 |
| 높음 | 중앙 길이 제한과 관리자 기본설정 API의 검증값이 다름 | UI가 허용하는 `0`을 저장 API가 거부함 |
| 높음 | 비동기 첨부 연결 경로에 게시판별 개수 상한이 없음 | `max_file_count`를 초과한 첨부 연결 가능 |
| 중간 | 자동 숨김 `0=비활성` 정책과 UI 최소값이 다름 | API는 `0`을 허용하지만 관리자 UI는 입력을 막음 |
| 중간 | 답변 깊이 상한이 코드와 문서에서 `10`과 `5`로 분리됨 | 관리자 안내와 API 계약이 실제 검증 규칙과 다름 |
| 낮음 | 표시용 깊이와 첨부 안내 문구가 숫자를 직접 보유함 | 정책 변경 시 화면과 번역 리소스가 다시 어긋날 수 있음 |
최대 첨부 개수 `20`이라는 정책 자체가 결함인 것은 아닙니다. 문제는 이 값을 한 곳에서 변경해도 모든 검증과 UI가 함께 변경되지 않으며, 일부 실제 처리 경로는 해당 정책을 강제하지 않는 구조입니다.
## 감사 범위와 추가 필요성
이번 감사는 `sirsoft-board`에서 제한값 불일치가 확인된 게시판 설정, 댓글·답변 깊이, 첨부파일, 신고·스팸 설정과 직접 연결된 코드만 우선 대조한 1차 표본 감사입니다.
다음 범위는 전수 확인하지 않았으므로 추가 감사가 필요합니다.
- `sirsoft-board` 전체 Controller, Request, Service, Repository, Listener, Job, migration, JSON UI 및 문서
- 숫자 제한 외 상태값, 문자열 Enum, 기본값, 캐시 TTL, 페이지 크기, 재시도 횟수와 배치 크기
- 코어와 다른 번들 모듈·플러그인의 설정값 중복 및 모듈 간 계약 불일치
- 환경설정 변경 시 API, 관리자 UI, 사용자 UI, CLI·Queue가 동일하게 반영되는지에 대한 경계값 테스트
따라서 본 보고서의 확인 항목을 수정하는 것과 별개로, 저장소 전체를 대상으로 정책값 출처와 소비 지점을 자동 대조하는 전수 감사 작업을 진행해야 합니다.
## 확인 기준
| 항목 | 값 |
|---|---|
| 그누보드 버전 | `7.0.4` |
| 원본 게시판 모듈 버전 | `sirsoft-board 1.1.3` |
| 확인 커밋 | `348efa2e98df22b00d30d3a4e267d0305f201758` |
| 확인일 | `2026-07-17` |
| 분석 범위 | 확인된 제한값 관련 config, defaults, FormRequest, Service/Rule, JSON UI, lang, API 문서의 일부 경로 |
현재 작업트리의 별도 첨부 개선 코드와 버전 변경은 원본 결함 근거에서 제외하고, 위 커밋의 원본 코드만 대조했습니다. 본 보고서는 정적 소스 감사 결과이며 원본 코드는 수정하지 않았습니다.
## 상세 결과
### H-01. 대댓글 깊이가 서비스에서 5로 고정됨
중앙 설정은 대댓글 깊이를 `0~10`으로 정의하고 기본값도 `10`으로 지정합니다.
- `modules/_bundled/sirsoft-board/config/board.php:151`
- `modules/_bundled/sirsoft-board/config/settings/defaults.json:18`
검증 규칙도 게시판의 `max_comment_depth`를 사용합니다.
- `modules/_bundled/sirsoft-board/src/Rules/CommentValidationRule.php:114`
그러나 실제 저장 깊이는 다음 서비스 코드에서 `5`로 잘립니다.
```php
$data['depth'] = min(($parentComment->depth ?? 0) + 1, 5);
```
- `modules/_bundled/sirsoft-board/src/Services/CommentService.php:257`
이 때문에 설정값이 `6~10`이면 검증은 더 깊은 대댓글을 허용해도 저장된 `depth`는 계속 5가 됩니다. 이후 검증 역시 부모의 저장 깊이 5를 기준으로 판단하므로 설정 상한이 사실상 무력화될 수 있습니다.
### H-02. 중앙 길이 제한과 관리자 기본설정 API가 불일치함
중앙 제한값은 최소 제목 및 최소 댓글 길이에 `0`을 허용합니다.
```php
'min_title_length_min' => 0,
'min_comment_length_min' => 0,
```
- `modules/_bundled/sirsoft-board/config/board.php:121`
- `modules/_bundled/sirsoft-board/config/board.php:133`
게시판 생성·수정 요청과 관리자 JSON UI는 이 중앙 값을 사용합니다.
- `modules/_bundled/sirsoft-board/src/Http/Requests/StoreBoardRequest.php:116`
- `modules/_bundled/sirsoft-board/src/Http/Requests/UpdateBoardRequest.php:95`
- `modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_board_settings_post.json:120`
- `modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_board_settings_comment.json:372`
반면 관리자 기본설정 저장 요청은 두 최소값을 직접 `1`로 고정합니다.
```php
'basic_defaults.min_title_length' => ['nullable', 'integer', 'min:1', 'max:200'],
'basic_defaults.min_comment_length' => ['nullable', 'integer', 'min:1', 'max:1000'],
```
- `modules/_bundled/sirsoft-board/src/Http/Requests/Admin/StoreBoardSettingsRequest.php:151`
- `modules/_bundled/sirsoft-board/src/Http/Requests/Admin/StoreBoardSettingsRequest.php:155`
동일한 설정값이 화면에서는 유효하지만 저장 API에서는 422가 되는 계약 불일치입니다.
### H-03. 첨부 개수 정책이 중복되고 비동기 연결 경로에서는 강제되지 않음
게시판 설정의 허용 범위는 중앙 config에 `1~20`으로 정의되어 있습니다.
- `modules/_bundled/sirsoft-board/config/board.php:141`
게시판 생성·수정 요청은 중앙 상한을 사용하지만, 관리자 기본설정 저장 요청은 `20`을 다시 직접 보유합니다.
```php
'basic_defaults.max_file_count' => ['nullable', 'integer', 'min:1', 'max:20'],
```
- `modules/_bundled/sirsoft-board/src/Http/Requests/Admin/StoreBoardSettingsRequest.php:159`
더 큰 문제는 실제 게시글 저장 API의 비동기 첨부 경로입니다. 원본 요청 검증은 `attachment_ids`가 배열과 정수인지 확인할 뿐 게시판의 `max_file_count`를 적용하지 않습니다.
- `modules/_bundled/sirsoft-board/src/Http/Requests/StorePostRequest.php:89`
- `modules/_bundled/sirsoft-board/src/Http/Requests/UpdatePostRequest.php:64`
- `modules/_bundled/sirsoft-board/src/Http/Requests/User/StorePostRequest.php:109`
- `modules/_bundled/sirsoft-board/src/Http/Requests/User/UpdatePostRequest.php:74`
단일 파일 업로드 요청도 파일 크기와 확장자만 검증하며 누적 개수는 확인하지 않습니다.
- `modules/_bundled/sirsoft-board/src/Http/Requests/UploadAttachmentRequest.php:42`
서비스는 전달받은 ID 또는 같은 `temp_key`의 첨부를 개수 확인 없이 연결합니다.
- `modules/_bundled/sirsoft-board/src/Services/PostService.php:830`
- `modules/_bundled/sirsoft-board/src/Services/PostService.php:844`
- `modules/_bundled/sirsoft-board/src/Services/AttachmentService.php:184`
따라서 UI의 `FileUploader` 제한을 우회한 API 요청에서는 게시판별 최대 첨부 개수가 서버의 최종 불변조건으로 보장되지 않습니다.
### M-01. 자동 숨김 비활성 값이 UI와 백엔드에서 다름
백엔드 검증은 `auto_hide_threshold`에 `0~100`을 허용합니다.
- `modules/_bundled/sirsoft-board/src/Http/Requests/Admin/StoreBoardSettingsRequest.php:178`
서비스와 테스트는 `0`을 자동 숨김 비활성 값으로 명시합니다.
- `modules/_bundled/sirsoft-board/src/Services/ReportService.php:732`
- `modules/_bundled/sirsoft-board/tests/Feature/Admin/AutoHideTest.php:184`
그러나 관리자 JSON UI는 최소값을 `1`로 고정합니다.
```json
"min": 1,
"max": 100
```
- `modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_report_policy.json:81`
결과적으로 지원되는 비활성 설정을 관리자 화면에서 정상적으로 입력할 수 없습니다.
### M-02. 답변 깊이 계약이 코드와 문서에서 10과 5로 분리됨
현재 검증 상한은 config 기준 `10`이며, 관련 회귀 테스트도 10을 기대합니다.
- `modules/_bundled/sirsoft-board/config/board.php:148`
- `modules/_bundled/sirsoft-board/tests/Feature/Admin/BoardSettingsControllerTest.php:427`
- `modules/_bundled/sirsoft-board/tests/Playwright/specs/admin/board-settings-range-hints.spec.ts:48`
하지만 다음 원본 자료는 여전히 `1~5`로 안내합니다.
- `modules/_bundled/sirsoft-board/database/migrations/2026_04_01_000002_create_boards_table.php:32`
- `modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin.json:905`
- `modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin.json:977`
- `modules/_bundled/sirsoft-board/resources/lang/partial/en/admin.json:977`
- `modules/_bundled/sirsoft-board/docs/api/boards.md:60`
API 문서 안에서도 요청 검증 상한과 응답 필드 설명이 서로 다를 수 있어 외부 클라이언트가 어느 값을 계약으로 따라야 하는지 불명확합니다.
### M-03. 중앙 목록에 없는 운영 정책값이 백엔드와 JSON UI에 반복됨
`new_display_hours`, 신고 정책, 스팸 제한값은 운영자가 변경하는 설정이지만 `config('sirsoft-board.limits')`에 포함되지 않습니다. 같은 숫자가 FormRequest와 JSON UI에 각각 반복됩니다.
대표 사례:
| 설정 | 백엔드 | JSON UI |
|---|---|---|
| 신규 표시 시간 | `1~720` | `1~720` |
| 일일 신고 제한 | `0~100` | `0~100` |
| 신고 거절 횟수 | `0~50` | `0~50` |
| 신고 거절 기간 | `1~365` | `1~365` |
| 글·댓글·신고 쿨다운 | `0~3600` | `0~3600` |
| 조회수 캐시 TTL | `60~604800` | `60~604800` |
근거:
- `modules/_bundled/sirsoft-board/src/Http/Requests/Admin/StoreBoardSettingsRequest.php:168`
- `modules/_bundled/sirsoft-board/src/Http/Requests/Admin/StoreBoardSettingsRequest.php:178`
- `modules/_bundled/sirsoft-board/src/Http/Requests/Admin/StoreBoardSettingsRequest.php:211`
- `modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_board_settings_post.json:581`
- `modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_report_policy.json:223`
- `modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_spam_security.json:73`
현재 값이 일치하더라도 어느 한쪽만 수정하면 즉시 계약이 분리됩니다. M-01은 이 구조가 이미 실제 오류로 이어진 사례입니다.
### L-01. 표시 상한과 정적 안내 문구도 정책 숫자를 직접 보유함
댓글과 답변글 들여쓰기는 화면에서 깊이를 `10`으로 직접 제한합니다.
- `templates/_bundled/sirsoft-basic/layouts/partials/board/show/_comment_item.json:11`
- `templates/_bundled/sirsoft-basic/layouts/partials/board/types/basic/index.json:281`
- `modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_detail/_comments.json:72`
현재 서버 상한과는 일치하지만 상한을 변경하면 데이터 깊이와 화면 표현이 분리됩니다. 표시 상한이 의도된 별도 UX 정책이라면 이름 있는 설정으로 분리해야 합니다.
또한 현재 레이아웃 사용처는 확인되지 않았지만 다국어 리소스에는 여전히 `최대 5개, 10MB` 문구가 남아 있습니다.
- `modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin.json:723`
- `modules/_bundled/sirsoft-board/resources/lang/partial/en/admin.json:722`
사용되지 않는 문구라도 다시 참조되면 게시판별 설정과 다른 안내가 노출될 수 있으므로 제거하거나 동적 치환 방식으로 통일해야 합니다.