html CSS 는 현재 피그마에맞게

아키텍처 원칙

로그인

User

DTO 분리 (목적별)

원칙: 왠만하면 매 요청/응답마다 DTO 분리. 공통 DTO 지양.

DTO 역할 사용 위치
SessionUserDTO 세션 저장용 사용자 정보 (id, username, nickname, email, roles) CustomUserAccount 내부, 세션
로그인 요청 DTO username, password (현재는 @RequestParam으로 처리) Security가 자동 처리
회원가입 요청 DTO username, password, nickname, email UserController (현재는 @RequestParam)

※ Security 적용 전에는 LoginUserDTO였으나, 목적이 “로그인”이 아니라 “세션 저장”이므로
SessionUserDTO로 명확히 분리. 이것이 “매 요청/응답마다 DTO 분리” 원칙.

Spring Security — 세션 방식 적용

개발자가 만드는 것 (2가지 + 설정)

| 파일 | 역할 | |——|——| | SecurityConfig | URL 접근 권한, 로그인/로그아웃 URL, PasswordEncoder Bean 등록 | | CustomUserAccount | UserDetails 구현 — SessionUserDTO 재사용 (composition) + password 추가 | | CustomUserDetailsService | UserDetailsService 구현 — username으로 DB 조회 후 UserDetails 반환 |

Entity → DTO 변환 원칙 준수:
CustomUserAccount는 필드를 직접 선언하지 않고 SessionUserDTO를 composition으로 갖는다.
CustomUserAccount.from(entity) → 내부에서 SessionUserDTO.from(entity) 재사용 + password 추가.
Controller에서 Entity 사용 금지 원칙 준수.

로그인 흐름 (Security가 자동 처리)

사용자가 username/password 입력 → /loginProc POST
  ↓ Security가 요청 가로챔 (UsernamePasswordAuthenticationFilter)
  ↓ CustomUserDetailsService.loadUserByUsername(username) 자동 호출
  ↓ DB에서 사용자 조회 → CustomUserAccount로 감싸서 반환
  ↓ Security가 BCrypt로 password 비교
  ↓ 성공 → Authentication 생성 → 세션에 저장 / 실패 → /login?error 리다이렉트

SecurityConfig URL 접근 규칙

permitAll()           → "/", "/login", "/signup"  (비로그인 허용)
hasAuthority("ADMIN") → "/admin"                  (ADMIN만)
hasAnyAuthority()     → "/mypage"                  (ADMIN 또는 USER)
anyRequest()          → permitAll()                (나머지 허용)

Controller에서 로그인 정보 사용

// @AuthenticationPrincipal로 CustomUserAccount 주입 → model에 담아서 HTML에서 사용
@GetMapping("/mypage")
public String mypage(@AuthenticationPrincipal CustomUserAccount userDetails, Model model) {
    model.addAttribute("user", userDetails);  // id, username, nickname, email, role 사용 가능
}

Thymeleaf에서 사용

<!-- 로그인/비로그인 분기 — sec 태그 사용 -->
<div sec:authorize="isAuthenticated()">로그인 상태</div>
<div sec:authorize="isAnonymous()">비로그인 상태</div>
<div sec:authorize="hasAuthority('ADMIN')">관리자 전용</div>

<!-- 사용자 정보 표시 — model에 담은 CustomUserAccount(user)를 일반 EL로 사용 -->
<span th:text="${user.nickname}">닉네임</span>     <!-- getNickname() -->
<span th:text="${user.username}">아이디</span>      <!-- getUsername() -->
<span th:text="${user.email}">이메일</span>         <!-- getEmail() -->
<span th:text="${user.roles}">USER</span>            <!-- getRoles() -->

sec:authentication="principal.nickname" 방식도 가능하지만,
model에 담아서 ${user.nickname}으로 쓰는 것이 기존 Thymeleaf와 같아서 직관적.
이 프로젝트에서는 model 방식을 사용한다.

UserEntity 변경사항

초기 데이터 (DataInitializer)

🗄️ JPA 설계

연관관계 원칙