회원 가입 및 로그인 코드 정리
1. DTO(Data Transfer Object) 설계
회원가입과 로그인을 처리하기 위해 DTO를 사용합니다.
회원가입 DTO (SignUpDTO)
package com.tenco.bank.dto;
import com.tenco.bank.repository.model.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SignUpDTO {
private String username;
private String password;
private String fullname;
// DTO -> User 객체 변환
public User toUser() {
return User.builder()
.username(this.username)
.password(this.password)
.fullname(this.fullname)
.build();
}
}
- 회원가입 시 username, password, fullname을 입력받음.
- toUser() 메서드를 통해 User 객체로 변환하여 DB에 저장.
로그인 DTO (SignInDTO)
package com.tenco.bank.dto;
import com.tenco.bank.repository.model.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SignInDTO {
private String username;
private String password;
public User toUser() {
return User.builder()
.username(this.username)
.password(this.password)
.build();
}
}
- 로그인 시 username, password를 입력받음.
- 마찬가지로 toUser() 메서드를 통해 User 객체 변환.
2. 사용자 컨트롤러 (UserController)
회원가입 및 로그인 요청을 처리하는 컨트롤러입니다.
package com.tenco.bank.controller;
import com.tenco.bank.dto.SignInDTO;
import com.tenco.bank.dto.SignUpDTO;
import com.tenco.bank.handler.exception.DataDeliveryException;
import com.tenco.bank.repository.model.User;
import com.tenco.bank.service.UserService;
import com.tenco.bank.utils.Define;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequiredArgsConstructor
@RequestMapping("/user")
public class UserController {
private final UserService userService;
private final HttpSession session;
// 회원가입 페이지
@GetMapping("/sign-up")
public String signUpPage() {
return "/user/signUp";
}
// 회원가입 처리
@PostMapping("/sign-up")
public String signProc(SignUpDTO dto) {
if(dto.getUsername() == null || dto.getUsername().isEmpty()) {
throw new DataDeliveryException("username을 입력하세요", HttpStatus.BAD_REQUEST);
}
if(dto.getPassword() == null || dto.getPassword().isEmpty()) {
throw new DataDeliveryException("password를 입력하세요", HttpStatus.BAD_REQUEST);
}
if(dto.getFullname() == null || dto.getFullname().isEmpty()) {
throw new DataDeliveryException("fullname을 입력하세요", HttpStatus.BAD_REQUEST);
}
userService.createUser(dto);
return "redirect:/user/sign-in";
}
// 로그인 페이지
@GetMapping("/sign-in")
public String signInPage() {
return "/user/signIn";
}
// 로그인 처리
@PostMapping("/sign-in")
public String signProc(SignInDTO dto) {
if(dto.getUsername() == null || dto.getUsername().isEmpty()) {
throw new DataDeliveryException(Define.ENTER_YOUR_USERNAME, HttpStatus.BAD_REQUEST);
}
if(dto.getPassword() == null || dto.getPassword().isEmpty()) {
throw new DataDeliveryException(Define.ENTER_YOUR_PASSWORD, HttpStatus.BAD_REQUEST);
}
User principal = userService.readUser(dto);
session.setAttribute(Define.PRINCIPAL, principal);
return "redirect:/account/list";
}
// 로그아웃 처리
@GetMapping("/logout")
public String logout() {
session.invalidate();
return "redirect:/user/sign-in";
}
}
- signProc()에서 유효성 검사 후 UserService를 호출하여 회원가입 및 로그인 수행.
- 로그인 성공 시 session에 사용자 정보 저장.
- logout()에서는 session.invalidate()를 호출하여 로그아웃 처리.
3. 사용자 서비스 (UserService)
회원가입과 로그인을 처리하는 서비스 계층입니다.
package com.tenco.bank.service;
import com.tenco.bank.dto.SignInDTO;
import com.tenco.bank.dto.SignUpDTO;
import com.tenco.bank.handler.exception.DataDeliveryException;
import com.tenco.bank.handler.exception.RedirectException;
import com.tenco.bank.repository.interfaces.UserRepository;
import com.tenco.bank.repository.model.User;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
@Transactional
public void createUser(SignUpDTO dto) {
try {
int result = userRepository.insert(dto.toUser());
if (result != 1) {
throw new DataDeliveryException("회원 가입 실패", HttpStatus.INTERNAL_SERVER_ERROR);
}
} catch (DataAccessException e) {
throw new DataDeliveryException("잘못된 처리입니다", HttpStatus.INTERNAL_SERVER_ERROR);
} catch (Exception e) {
throw new RedirectException("알 수 없는 오류", HttpStatus.SERVICE_UNAVAILABLE);
}
}
public User readUser(SignInDTO dto) {
User user = userRepository.findByUsernameAndPassword(dto.getUsername(), dto.getPassword());
if(user == null) {
throw new DataDeliveryException("아이디 혹은 비밀번호가 틀렸습니다.", HttpStatus.BAD_REQUEST);
}
return user;
}
}
- createUser()에서 예외 처리 및 트랜잭션 처리 추가.
- readUser()에서 로그인 실패 시 DataDeliveryException 발생.
4. 사용자 리포지토리 (UserRepository)
MyBatis를 사용하여 데이터베이스와 연결합니다.
package com.tenco.bank.repository.interfaces;
import com.tenco.bank.repository.model.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface UserRepository {
int insert(User user);
int updateById(User user);
int deleteById(Integer id);
List<User> findAll();
User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
}
- insert(), updateById(), deleteById() 등을 포함한 CRUD 메서드 정의.
- findByUsernameAndPassword()로 사용자 조회.
5. 회원가입 및 로그인 SQL
<mapper namespace="com.tenco.bank.repository.interfaces.UserRepository">
<insert id="insert">
insert into user_tb (username, password, fullname, created_at)
values (#{username}, #{password}, #{fullname}, now())
</insert>
<select id="findByUsernameAndPassword" resultType="com.tenco.bank.repository.model.User">
select * from user_tb where username = #{username} and password = #{password}
</select>
</mapper>
- 회원가입 (insert) 쿼리와 로그인 시 사용자 조회 (findByUsernameAndPassword) 쿼리 정의.
DTO를 활용하여 회원가입 및 로그인 데이터를 전달.
UserController에서 요청을 받아 UserService를 통해 처리.
\UserRepository를 통해 MyBatis로 DB와 연동.
session을 활용하여 로그인 상태 관리.
유효성 검사 및 예외 처리를 적용하여 안정적인 회원 관리 기능 구현.