본문 바로가기
SPRING

[Spring] JPA를 활용한 회원가입 구현

by 킹명주 2022. 7. 14.

앞서 MyBatis를 활용해서 DB와 연결하고 Login을 구현했다. 그러나 요즘은 JPA가 대세라 무조건 한 번은 경험하고 넘어가야 한다. 그래서 JPA를 활용해서 회원가입을 구현해보고자 한다.

JPA

 

JPA는 Java Persistence API의 약자이며 자바의 ORM을 위한 표준 기술이다.

ORM(Object-Relational Mapping)이란 자바의 객체와 관계형 DB를 맵핑하는 것으로 DB의 특정 테이블이 자바의 객체로 맵핑되어 SQL문을 일일이 작성하지 않고 객체로 구현할 수 있도록 하는 프레임워크를 말한다. 특히, JPA의 장점을 뽑자면 SQL 위주의 Mybatis 프로젝트와 비교하여 쿼리를 하나하나 작성할 필요도 없어 코드 볼륨이 적고 객체 위주로 코드가 작성되다 보니 가독성도 좋다. 

이전 강의부터 MySQL을 다운받아 사용하고 있기 때문에 MySQL Driver를 추가했다. 다른 DB를 사용하면 그에 맞는 dependencies를 추가해서 진행하면 된다. 이렇게 프로젝트를 생성하면 build.gradle 설정은 완료된 것이다.


회원가입 구현

 

가장 먼저 application.properties를 설정해준다.

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/{your_database}?serverTimezone=UTC&userUnicode=true&characterEncoding=utf8&userSSL=false";
spring.datasource.username=root
spring.datasource.password=your_password
sprint.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update

2 ~ 4번째 줄만 환경에 맞게 변경하면 된다. {your_database}에는 스키마 주소인데, mysql에서는 database의 이름과 동일하다.

spring.jpa.show-sql 콘솔에 JPA 실행 쿼리를 출력한다.
spring.jap.generate-ddl true로 설정 시, @Entity이 명시된 클래스를 찾아서 ddl을 생성하고 실행한다.
spring.jpa.hibernate.ddl-auto 데이터베이스 초기화를 설정한다.
1. none : 아무것도 실행하지 않는다.
2. create : 기존테이블을 삭제 후 다시 생성한다.
3. create-drop: 시작할 때 테이블을 생성하고 종료할 때 테이블을 삭제한다.
4. update : 변경된 스키마만 반영한다.
5. validate : 엔티티와 테이블이 정상적으로 매핑되었는지 확인한다.

 

그 다음으로 프로젝트 구조이다.

각각에 대해 코드 리뷰를 통해 상세하게 살펴볼 예정이다.

 

1. Controller

package com.example.jpa_practice.controller;

import com.example.jpa_practice.domain.Member;
import com.example.jpa_practice.service.JpaService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
@RequiredArgsConstructor
public class JpaController {
    private final JpaService jpaService;
    @RequestMapping(value="/login", method= RequestMethod.GET)
    public String login(@RequestParam(value="id")String id, @RequestParam(value="pwd")String pwd){
        Member member=new Member(id,pwd);
        jpaService.joinUser(member);
        return "가입 success";
    }
}
@Controller Controller 선언
@RequiredArgsConstructor final, @NotNull이 붙은 필드의 생성자를 자동으로 생성해주는 lombok annotation이다.
(@RequiredArgsConstructor와 비교하기 위해 넣음)
@NoArgsConstructor
파라미터가 없는 생성자를 자동으로 생성해주는 lombok annotation
(참고하면 좋은 것)
@Autowired
의존성 주입을 할 때 사용하는 Annotation으로 의존 객체의 타입에 해당하는 bean을 찾아 주입하는 역할을 한다. 생성자, Setter, 필드 위에 사용 가능하다. 
@Autowired
JpaService jpaService;
형태로 사용 가능하다. 
@RequestsMapping 요청을 어디에 mapping할 것인지 정한다.
@RequestParam 프론트에서 어떤 parameter를 받아올 것인지 정한다.

 

2. Domain

package com.example.jpa_practice.domain;

import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Data
@Entity
@Table(name="test2")
public class Member {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String email;
    private String password;
    public Member(String email, String password){
        this.email=email;
        this.password=password;
    }
}
@Data @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 모두 포함한 것이다.
@Entity JPA에서 엔티티란 쉽게 생각하면, DB 테이블에 대응하는 하나의 클래스라고 생각할 수 있다. @Entity가 붙은 클래스는 JPA가 관리해주며, @Entity를 꼭 붙여야만 매핑이 된다. 
  • 기본 생성자(파라미터가 없는 생성자)필수, 접근 제어자는 public 혹은 protected 이어야 함.
  • 저장할 필드에는 final을 붙이면 안된다. 즉 final을 붙이면 테이블에 매핑되지 않는다.
@Table 엔티티와 매핑이 진행 될 테이블을 지정한다.
@Id 테이블의 primary key를 지정한다.
@GeneratedValue primary key 값을 자동 생성 등을 명시하는데 사용한다.

option
strategy = GenerationType.
1. AUTO : DB에 맞게 자동 선택
2. IDENTITY : DB의 identity 컬럼 이용
3. SEQUENCE : DB의 시퀀스 컬럼 이용
4. TABLE : 유일성이 보장된 테이블 이용

id를 primary key로 지정하고, 입력하지 않은 경우 자동으로 할당할 수 있도록 설계했다. 그리고 이메일과 비밀번호를 입력하여 회원가입이 진행될 수 있도록 각각 속성을 지정했다.

3. Repository

package com.example.jpa_practice.repository;

import com.example.jpa_practice.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

public interface MemberRepository extends JpaRepository<Member, Long> {
    /*
        save() : 레코드 저장 (insert, update)
        findOne() : primary key로 레코드 한건 찾기
        findAll() : 전체 레코드 불러오기. 정렬(sort), 페이징(pageable) 가능
        count() : 레코드 갯수
        delete() : 레코드 삭제
        findBy : 쿼리를 요청하는 메서드 임을 알림
        counyBy : 쿼리 결과 레토드 수를 요청하는 메서드 임을 알림
   */
}

사용할 수 있는 함수는 위 코드 블럭에 나타냈다. JpaRepository는 <Entity_Type, PK_Type>를 환경에 맞게 입력해주어 사용하면 된다.

4. Service

package com.example.jpa_practice.service;

import com.example.jpa_practice.domain.Member;
import com.example.jpa_practice.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class JpaService {
    private final MemberRepository memberRepository;
    public void joinUser(Member member){
        memberRepository.save(member);
    }
}

front로 부터 email, password 정보를 받아 저장하는 것이다.


결과

 

성공적으로 test2 table에 입력한 정보를 저장하는 것을 확인할 수 있다.