# Conventions — bibimbap ## Mapper (MyBatis) - `@Mapper` 인터페이스 + 인라인 `@Select/@Insert/@Update/@Delete` (Java text block SQL). XML 매퍼·네임스페이스 없음. - SELECT 에서 snake_case 컬럼을 camelCase 로 alias (`g.user_id AS userId`). - 다중/명명 인자에 `@Param("x")`. 자동생성 PK: `@Options(useGeneratedKeys=true, keyProperty="id", keyColumn="id")`. - 모든 쿼리에 soft-delete 가드 `is_delete IS NOT TRUE` (조인 대상 포함). ## Controller - 생성자 주입(필드 `@Autowired` 미사용). - 페이지 `@Controller`: view-name String 반환 (`"recruit-list"`, `"redirect:/login"`). - JSON 엔드포인트: `ResponseEntity>` — `LinkedHashMap` 에 `{status, message, ...}`. 헬퍼 `response(HttpStatus, msg)`. - mutation(`@PostMapping`/`@DeleteMapping`)은 `@Transactional` + 표준 가드 순서: 1. `if (!CsrfTokens.isValid(request)) return 403 + CsrfTokens.errorBody()` 2. `sessionUserId(session)` null → 401 3. 소유권 불일치 → 403 - 입력 위생: `trimToNull`/`trimToEmpty` 헬퍼, 길이 상한 인라인 검사, `safeExternalUrl` 은 http/https 만 허용, 에셋 경로는 `/game/` 시작 + `..` 금지. ## 기타 - 사용자 노출 문자열 한국어. - `data/` POJO 는 수기 getter/setter. - soft-delete / 세션 인증 불변식은 `mem:core`.