티스토리 뷰
[Spring] 스프링부트 + JPA + thymeleaf + Spring Security로 회원가입 + 게시판(수정, 삭제, 등록, 조회, 댓글, 좋아요) + 로그인 구현하기 #4회원 가입
poopooreum 2024. 8. 29. 20:07✏️ 회원가입 로직
기본적인 로직은 클라이언트 요청 → 컨트롤러 → 서비스 → 리포지토리 방식으로 작업이 이루어진다
- 회원가입 입력창에서 id, name, password, confirmpassword를 입력함
- 컨트롤러는 SignUpDTO를 통해서 입력값을 전달받음
- 컨트롤러는 멤버서비스의 메소드를 통해, id가 중복되지는 않았는지 password와 confirm메소드가 같은지 확인을 한다.
- 모두 이상이 없으면 다시 멤버서비스를 호출해서 SignUpDTO의 값을 Member db에 save하고 로그인 창으로 이동한다.
- 이상이 있으면 로그 에러를 찍어주고 회원가입 화면을 다시 띄어준다.
✏️ Member 클래스
package hello.hello_spring.domain.member;
import hello.hello_spring.domain.board.Board;
import jakarta.persistence.*;
import lombok.*;
import java.util.*;
@Getter
@Entity
@Builder
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Member {
@Id
@Column(name = "id", nullable = false, length = 20)
private String id;
@Column(name = "name", nullable = false, length = 20)
private String name;
@Column(name = "password", nullable = false, length = 20)
private String password;
@OneToMany(mappedBy = "member")
private List<Board> boards = new ArrayList<>();
@Enumerated(EnumType.STRING)
@Column(name = "role", nullable = false)
private MemberRole role;
}
DB에 있는 Member와 똑같은 구조로, 인텔리제이에 db를 연결하고 table명을 우클릭 후 Create JPA Entites From DB를 누르시면 인텔리제이가 알아서 멤버 클래스를 만들어준다.
@ID는 primary key를 나타냄
✏️ SignUp DTO 클래스
@Getter
@Setter
public class SignUpDTO {
private String name;
private String id;
private String password;
private String confirmPassword;
}
회원가입 시 입력 값을 받아올 클래스이다.
✏️ signup.html 생성
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" th:href="@{/css/main.css}">
</head>
<body>
<h1>회원가입</h1>
<form method="post" action="/member/signup">
<table class="table">
<tr><td>아이디: <input type="text" name="id" required/></td></tr>
<tr><td>이름: <input type="text" name="name" required/></td></tr>
<tr><td>비밀번호: <input type="text" name="password" required/></td></tr>
<tr><td>비밀번호 확인: <input type="text" name="confirmPassword" required/></td> </tr>
</table>
<input type="submit" value="가입하기" />
<a href="http://localhost:8080">돌아가기</a>
</form>
</body>
</html>
✏️ Api Controller 클래스
@Controller
@RequestMapping("/member")
@RequiredArgsConstructor
@Slf4j
public class ApiController {
@PostMapping("/signup")
public String signup(SignUpDTO signUpDTO) {
boolean isMemberExist = memberService.checkMemberExist(signUpDTO.getId());
if (isMemberExist) { // 안 되었으므로 다시 회원가입 화면
log.error("회원가입 실패");
return "redirect:/signup";
}
boolean isSignUpSamePassword = memberService.checkSignUpSamePassword(signUpDTO);
if(!isSignUpSamePassword) {
log.error("회원가입 실패");
return "redirect:/signup";
}
memberService.save(signUpDTO);
log.info("signup success");
return "redirect:/login";
}
}
✏️ WebController 클래스
@Controller
@RequiredArgsConstructor
public class WebController {
@GetMapping("/signup") // 회원가입
public String signup(HttpServletRequest httpServletRequest) {
HttpSession session = httpServletRequest.getSession();
Optional<Object> idOptional =Optional.ofNullable(session.getAttribute("userId"));
if(idOptional.isPresent()){
return "redirect:/member/list";
}
return "signup";
}
}
ApiController는 GetMapping을 처리해주는 컨트롤러이다. 쉽게 생각해서 우리가 회원가입 버튼을 누르면 회원가입 화면을 띄어주는 역할을 해준다고 생각하면 된다.
@Controller 어노테이션을 사용해서 스프링이 이 클래스가 컨트롤러임을 알 수 있도록 해주기
@RequiredArgsConstructor 어노테이션을 사용해서 final이나 @NonNull인 필드 값만 파라미터로 받는 생성자를 생성할 수 있도록 하자
✏️ MemberRepository 인터페이스
@Repository
public interface MemberRepository extends JpaRepository<Member, String> {
}
MemberRepository 인터페이스에서 JpaRepository를 상속받아서 JPA를 사용할 수 있도록 한다.
JpaRepository<데이터베이스명, 프라이머리 키의 변수 타입>으로 선언하면 된다.
어노테이션 @Repository를 선언해서 스프링이 리포지토리임을 알 수 있도록 하자
✏️ MemberService 인터페이스
public interface MemberService {
boolean checkMemberExist(String id);
void save(SignUpDTO signUpDTO);
boolean checkSignUpSamePassword(SignUpDTO signUpDTO);
}
멤버 서비스 인터페이스를 만들어서 필요한 메소드를 선언만 해주기
✏️ MemberServiceImpl 클래스
@RequiredArgsConstructor
@Service
@Slf4j
public class MemberServiceImp implements MemberService {
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
@Override
public boolean checkMemberExist(String id) {
Optional<Member> memberOptional = memberRepository.findById(id);
if(memberOptional.isPresent()){
log.error("동일한 아이디가 존재");
return true;
}
else {
log.info("동일한 아이디 없음");
return false;
}
}
@Override
public boolean checkSignUpSamePassword(SignUpDTO signUpDTO) {
if (!(signUpDTO.getConfirmPassword()).equals(signUpDTO.getPassword())) {
log.error("비밀번호를 다시 입력해 주세요");
return false;
}
else {
log.info("비빌먼호 일치");
return true;
}
}
@Override
public void save(SignUpDTO signUpDTO) {
String encodingPassword = passwordEncoder.encode(signUpDTO.getPassword());
signUpDTO.setPassword(encodingPassword);
log.info("로그인한 ID{}", signUpDTO.getId());
Member member = Member.builder()
.id(signUpDTO.getId())
.name(signUpDTO.getName())
.password(encodingPassword)
.role(MemberRole.USER)
.build();
memberRepository.save(member);
}
}
MemberService 인터페이스들에 선언되어 있는 메소드들을 구현하는 구현체
어떤 작업을 수행하는데에 있어서 핵심적인 비즈니스 로직이라고 할 수 있음
@Service 어노테이션을 사용해서 스프링이 이 클래스가 서비스임을 인식할 수 있도록 하기 @Slf4j 어노테이션은 로그를 찍을 때 사용하는 어노테이션
✏️ PasswordEncoder 메소드
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
비밀번호를 암호화 하는 방법중에 BCrypt라는 방식이 있는데 이를 이용해서 비밀번호를 암호화 해줌
아래와 같은 방식으로 비밀번호가 저장이 된다
'Web > Spring' 카테고리의 다른 글
- Total
- Today
- Yesterday
- 백준 풀이
- 자바
- 자바스크립트
- 에라토스테네스의 체
- 유클리드 호제법
- 알고리즘
- CSS
- DP
- DFS
- 자료구조
- 스프링 부트 crud 게시판 구현
- 카운팅 정렬
- 반복문
- 세그먼트 트리
- 우선순위 큐
- BFS
- c++ string
- html
- 스택
- 이분 매칭
- 유니온 파인드
- C++ Stack
- 알고리즘 공부
- Do it!
- java
- 투 포인터
- HTML5
- js
- C++
- 백준
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |