POST /projects
토큰과 프로젝트 이름을 보내지만, owner 값은 직접 믿지 않습니다.
Controller는 HTTP 모양을 받고, Service는 프로젝트와 파일 권한을 판단하며, Repository와 DB 제약은 중복 이름과 소유권 불일치를 마지막 경계에서 막습니다.
토큰과 프로젝트 이름을 보내지만, owner 값은 직접 믿지 않습니다.
생성된 id, name, timestamps만 받도록 화면 계약을 작게 둡니다.
Param, Body, Request user를 분리해 Service 호출 인자로 정리합니다.
예외는 필터에서 상태 코드로 바뀌고, 성공 응답은 DTO로 줄입니다.
인증 실패, 빈 이름, 잘못된 파일 경로는 비즈니스 로직 전에 탈락합니다.
trim, 길이 제한, enum 변환처럼 저장 전 형태를 일정하게 맞춥니다.
프로젝트 소유자와 파일 부모 폴더를 확인한 뒤 변경 명령을 만듭니다.
파일 생성과 메타데이터 갱신이 함께 성공하거나 함께 실패합니다.
userId 조건을 빠뜨리지 않도록 조회 메서드 이름에 소유권을 드러냅니다.
같은 폴더의 같은 파일명은 애플리케이션과 DB 제약에서 같이 막습니다.
FK, unique, not null은 동시에 들어온 요청의 마지막 방어선입니다.
createdBy, updatedAt을 남겨 협업 기능으로 확장할 때 충돌을 추적합니다.
목록, 상세, 수정, 삭제 라우트가 모두 userId 또는 멤버십 조건을 타는지 같은 테스트 데이터로 확인합니다.
ValidationError, NotFound, Conflict가 화면에서 구분 가능한 응답 메시지로 변환되는지 봅니다.
같은 이름의 파일을 동시에 만들 때 Service 검사와 unique 제약이 같은 결론으로 수렴해야 합니다.