θ Spring Boot 예제1 (회원관리)

프로젝트 생성 & 회원 가입 & 로그인 정리!

  • 사용 IDE : IntelliJ IDEA Ultimate
  • 사용 DB : MySQL
  • 사용 언어 & SDK : Java & Amazon correto 11
  • thymeleaf 사용을 가급적 줄인 예제입니다.
  • 정리본입니다 참고용으로만 봐주세요 :D
  • 회원가입부터 로그인까지 정리본

프로젝트 생성

  • Project Name : MemberProject

  • pakage : com.icia.member

  • dependency는 아래와 같이 설정.

설정 후 생성

  • 생성 후 가장 먼저 할 설정

  • Annotation Processors에 들어가 Enable anootation processing 체크 후 Apply

  • 프로젝트마다 개별 설정이기 때문에 프로젝트를 생성할 때 마다 이를 설정해줘야함.

  • 역할 : 어노테이션이 역할을 수행할 수 있게 해줌.


yml파일 설정

주의할점!!

  • 들여쓰기는 반드시 지켜주세요. 오류납니다.
  • 아래와 같이 들여쓰기를 해줘야합니다.
# 포트 설정, port는 server안에서 들여써주세요.
server:
  port: 8093

# DB접속 정보 MySQL에서 사용할 DB와 username 및 pw 설정
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springbootclass?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
    username: bootuser
    password: 1234
  # Run시 cache값을 사용하지 않겠다는 의미 (완벽하진 않지만 오류 방지)
  thymeleaf:
    cache: false

  # JPA 관련 설정, datasource: 위치와 같은 위치에 작성해줘야함.
  # JPA를 사용하겠다는 코드
  jpa:
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    show-sql: true
    hibernate:
      ddl-auto: update
      # create : 실행할 때 마다 전체 재시작
      # update : table을 drop하지 않고 계속해서 사용하겠다는 의미

build.gradle 설정

  • 프로젝트 생성할 때 추가하지 못한 Dependency를 추가할 수 있게 해주는 파일

  • Dependency 추가 후 우측 팝업에 코끼리 모양을 눌러줘야 추가한 Dependency가 적용됨.

plugins {
	id 'org.springframework.boot' version '2.6.2'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.icia'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	// implementaion : 구현에 필요한 코드
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
    
	implementation 'org.springframework.boot:spring-boot-starter-validation'
	// 공백 체크 및 각종 체크를 도와주는 어노테이션을 사용할 수 있게 해주는 Dependency
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	// jpa를 사용하겠다는 Dependency
	
	runtimeOnly 'mysql:mysql-connector-java'
	// MySQL DB를 사용할 수 있게 해주는 Dependency
    
	// compileOnly : 컴파일에만 사용하는 코드
	compileOnly 'org.projectlombok:lombok'
    
	// annotationProcessor : 어노테이션 지정 코드
	annotationProcessor 'org.projectlombok:lombok'
    
	// testImplementation : 테스트시 사용
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

기본 주소 (index.html) 처리

  • src/java 안에 controller pakage 생성 & MainController 생성

  • MainController에 기본주소를 처리하는 메서드 생성

// 스프링 부트에서는 아래와 같은 방법으로 메서드 생성 가능.
// 기본주소 요청 시 index 페이지 출력
@GetMapping("/")
public String index() {
	return "index";
}
  • templeates 에 index.html 생성 및 회원가입, 로그인 주소 생성
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
	<h2>index.html</h2>
	<a href="/member/save">회원가입</a>
	<a href="/member/login">로그인</a>
</body>
</html>

Controller 생성

  • /member/*를 처리할 Controller 생성

  • 회원가입 페이지 요청 주소 및 저장 주소 생성

// 회원가입 페이지 요청
@GetMapping("save")
public String saveForm() {
	return "member/save";
}

Repository

  • 이제 각종 DB처리를 해주는 Repository를 생성합니다.

  • Repository는 Interface Class로 만들고 JpaRepository를 상속받는 클래스로 설정합니다.

  • 주의할점으로 Repository에는 @Repository를 붙이지 않게 주의합시다.

public interface MemberRepository extends JpaRepository<MemberEntity, Long> {

}

JPA는 maven클래스의 mybatis와 비슷한 역할을 수행하는 Java Class입니다.
mybatis처럼 직접 쿼리문을 작성하지 않아도 JpaRepository에 각종 쿼리문이 포함되어있어 호출만 해도 각종 CRUD를 처리할 수 있습니다.


회원가입 처리

  • templates 폴더 안에 member라는 폴더 생성

  • member 폴더 안에 save.html 생성

save.html

  • 회원가입을 받는 html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>

	<h2 class="mt-3 mb-3">회원가입</h2>

	<form action="/member/save" method="post">
		<input type="text" name="memberEmail" placeholder="이메일">
		<input type="password" name="memberPassword" placeholder="비밀번호">
		<input type="text" name="memberName" placeholder="이름">
		<input type="submit" value="회원가입">
	</form>
  
</body>
</html>

Save용 DTO 생성

@Data
@NoArgsConstructor // 기본 생성자 생성
@AllArgsConstructor // 모든 필드를 매개변수로 하는 생성자 생성
public class MemberSaveDTO {

    private String memberEmail;
    private String memberPassword;
    private String memberName;
    
}

정보 저장 구조

  • 순서

    1. html에서 Controller로 정보 전달

    2. Controller에서 정보를 받은 후 Service로 전달

    3. Service에서 Entity로 정보 전달

    4. Entity에서 DTO타입을 Entity타입으로 변환 후 Service에 전달

    5. Service에서 받은 후 Repository(JPA)로 전달

    6. 처리 완료 후 지정한 메서드 or 페이지로 이동


Controller

// 회원가입 정보 저장
@PostMapping("save")
public String save(@ModelAttribute MemberSaveDTO memberSaveDTO) {
	Long memberId = ms.save(memberSaveDTO);
	return "member/login";
}

Service

  • service pakage 생성 후 Service와 ServiceImpl 생성

  • Service : Interface Class로 생성

  • ServiceImpl : 일반 Java Class로 생성 및 implements 후 @Service 붙이기.

Service (Interface)

public interface MemberService {

   	Long save(MemberSaveDTO memberSaveDTO);

}

ServiceImpl

@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {

	// Repository 생성자 주입.
	private final MemberRepository mr;

	// 회원가입 정보 저장
	@Override
	public Long save(MemberSaveDTO memberSaveDTO) {
	// JPARepository는 무조건 Entity 타입만 받기 때문에 Entity 타입으로 바꿔줘야함.
	MemberEntity memberEntity = MemberEntity.saveMember(memberSaveDTO);
//        Long memberId = mr.save(memberEntity).getId();
//        return memberId;
	// 위 두줄과 아래 한줄은 같은 코드
	// 앞으로 이런식으로 줄여서 사용할 예정임.
	return mr.save(memberEntity).getId();
	}
}

Entity

  • entity pakage 생성 & Entity Class 생성

  • Entity는 Java Class입니다. 주의해주세요.

  • Entity의 역할 : JPA에 정보를 보내거나 받기 위해 사용.

  • 테이블명 및 컬럼을 선언하는 곳, 또한 데이터 타입을 Entity로 변환을 하는 곳.

@Entity // JPA를 사용하려면 Entity Class가 팔수적이다.
@Getter
@Setter
@Table(name="member_table")	// table 이름을 member_table로 지정.
public class MemberEntity {

	@Id // PK로 아래 컬럼을 사용하겠다는 뜻
	@GeneratedValue(strategy = GenerationType.IDENTITY) // auto_increment와 같은 역할
	@Column(name = "member_id") // 컬럼 이름을 member_id로 지정
	private Long id;

	@Column(length = 50, unique = true)  // varchar(50)에 unipue 속성을 부여
	private String memberEmail;
	// Entity에서는 _(언더바) 절대 금물. 차후에 오류 발생 가능성 높음.
	// 카멜케이스로 작성한 컬럼은 member_email로 자동으로 바뀜.

	@Column(length = 20)
	private String memberPassword;

	@Column() // 아무 지정을 안해주면 varchar(255) 크기로 생성됨.
	private String memberName;

	// MemberSaveDTO -> MemberEntity 객체로 변환하기 위한 메서드
	public static MemberEntity saveMember(MemberSaveDTO memberSaveDTO) {
		// MemberEntity타입의 객체를 보내기 위해 memberEntity라는 객체 선언
		MemberEntity memberEntity = new MemberEntity();

		// memberEntity 객체에 memberSaveDTO 객체 안에 담긴 각 요소를 담아줌.
		memberEntity.setMemberEmail(memberSaveDTO.getMemberEmail());
		memberEntity.setMemberPassword(memberSaveDTO.getMemberPassword());
		memberEntity.setMemberName(memberSaveDTO.getMemberName());

		// 변환이 완료된 memberEntity 객체를 넘겨줌
		return memberEntity;
	}

}

위 코드를 잘 따라왔다면 DB에 데이터가 잘 들어간 것을 확인할 수 있습니다.
thymeleaf를 사용한다면 공백체크 & 아이디중복체크도 수행할 수 있지만 여기서는 다루지 않고 차후에 다루겠습니다. 그럼 로그인으로 넘어가겠습니다 :D


login 처리

  • login을 만들어봅시다.

Controller

  • login 주소를 처리하는 메서드 생성
// 로그인 페이지 요청
@GetMapping("login")
public String loginForm() {
	return "member/login";
}

login.html 생성

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
	<h2>login.html</h2>
	<form action="/member/login" method="post">
		<input type="text" name="memberEmail" placeholder="이메일을 입력하세요">
		<input type="text" name="memberPassword" placeholder="비밀번호를 입력하세요">
		<input type="submit" value="로그인">
	</form>
</body>
</html>

Login용 DTO 생성

@Data
@NoArgsConstructor
@AllArgsConstructor
public class MemberLoginDTO {

    private String memberEmail;
    private String memberPassword;

}

로그인 저장 구조

  • 순서

    1. login.html에서 Controller로 정보 전달

    2. Controller에서 정보를 받은 후 Service로 정보 전달

    3. Service에서 Entity로 정보 전달

    4. Entity에서 DTO타입을 Entity 타입으로 변환 후 Service에 전달

    5. Service에서 받은 후 Repository(JPA)로 전달

    6. JPA에서 처리 후 Service에 전달

    7. Service에서 받은 후 null 체크 및 비밀번호 일치여부 확인

    8. 처리 결과를 Controller로 전달

    9. 사용자가 지정한 메서드 or 주소로 이동


Controller

// 로그인 성공여부 판별
@PostMapping("login")
public String login(@ModelAttribute MemberLoginDTO memberLoginDTO, HttpSession session) {
	if (ms.login(memberLoginDTO)) {
//	session.setAttribute("loginEmail",memberLoginDTO.getMemberEmail());
		// 아래처럼 상수를 선언해 사용할 수 있음, 아무거나 편한걸로 사용
		session.setAttribute(LOGIN_EMAIL,memberLoginDTO.getMemberEmail());
		return "redirect:/member/";
	} else {
		return "member/login";
	}
}

Service

Service

// 내용 추가
boolean login(MemberLoginDTO memberLoginDTO);

ServiceImple

  • jpa에서 지원하는 메서드 중 findBy~ 를 사용하므로 메서드 이름을 멋대로 바꾸면 오류생김.

  • findAll, findBy~ 등이 있음.

  • findBy~ : ~인 데이터를 찾겠다 라는 뜻으로 뒤에 각 컬럼을 넣어 사용할 수 있다.

@Override
public boolean login(MemberLoginDTO memberLoginDTO) {
	// MemberEntity타입의 객체 생성 후 jpa의 findBy 메서드 호출 및 정보 저장
	// MemberLoginDTO의 memberEmail을 보내 값을 memberEntity에 담는것임.
	MemberEntity memberEntity = mr.findByMemberEmail(memberLoginDTO.getMemberEmail());
	// 정보가 비어있으면 로그인시도를 한 email을 가진 데이터 자체가 없는 정보라는 뜻임.
	if (memberEntity!=null) {
		// 로그인을 시도한 데이터의 비밀번호와 jpa에서 받아온 데이터의 비밀번호를 비교
		if(memberEntity.getMemberPassword().equals(memberLoginDTO.getMemberPassword())) {
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}
}

Repository

Repository는 기본적으로 메서드를 생성할 일이 거의 없습니다.
하지만 PK가 아닌 값으로 CRUD를 수행하기 위해선 Repository에 메서드를 생성해줘야 합니다.
아까 만든 Repository는 Interface Class이므로 추상메서드로 작성해야합니다.

// Repository에 아래 코드 한줄 추가.
MemberEntity findByMemberEmail(String memberEmail);

여기까지 잘 따라오셨으면 회원가입부터 로그인까지 잘 될겁니다.
원래 이 게시글에서 끝내려고 했지만 길이가 너무 길어진 관계로
회원목록 조회 및 상세조회, 삭제 등은 다음 게시글에서 정리하겠습니다:D

좋은 웹페이지 즐겨찾기