블로그 프로젝트 v1 - 회원가입 구현하기 Repository

Feb 21, 2024
블로그 프로젝트 v1 - 회원가입 구현하기 Repository

1. UserRepository 만들기

package shop.mtcoding.blog.user; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @Repository // IoC에 new하는 방법 public class UserRepository { // DB에 접근할 수 있는 매니저 객체 // 스프링이 만들어서 IoC에 넣어둔다. // DI에서 꺼내 쓰기만 하면된다. private EntityManager em; // 생성자 주입 (DI 코드) public UserRepository(EntityManager em) { this.em = em; } @Transactional // db에 write 할때는 필수 public void save(UserRequest.JoinDTO requestDTO){ Query query = em.createNativeQuery("insert into user_tb(username, password, email, created_at) values(?,?,?, now())"); query.setParameter(1, requestDTO.getUsername()); query.setParameter(2, requestDTO.getPassword()); query.setParameter(3, requestDTO.getEmail()); query.executeUpdate(); } }

Repository = DAO 만들기 (+EntityManager)

notion image
notion image
Repository는 데이터베이스와 관련된 작업을 수행하는 클래스로, 일반적으로 DAO(Data Access Object)라고도 불린다. @Repository를 쓰면 스프링은 해당 클래스의 인스턴스를 자동으로 생성하고 관리 (=new 함) 지금 UserRepository라는 클래스는 내가 만든 클래스지만, IoC 컨테이너에 넣어서 사용하고 싶기 때문에 (=new를 니가 해줘) @Repository를 써줬다 필요할 때마다 내가 new를 띄워서 가져오는 것보단 IoC 컨테이너에 있는걸 넣었다 빼서 쓰는게 new도 안하고 훨씬 편하기 때문?
스프링에서 @Repository 어노테이션이 적용된 클래스는 일반적으로 기본 생성자가 필요! 그러나 매개변수가 있는 생성자만 존재하는 경우에도 스프링은 자동으로 인스턴스를 생성할 수 있다. 스프링은 @Repository 어노테이션이 붙은 클래스의 인스턴스를 관리하고 필요한 곳에 주입한다. 기본 생성자가 있는 경우에는 그대로 인스턴스를 생성하고, 매개변수가 있는 생성자만 존재하는 경우에는 해당 생성자에 필요한 매개변수를 자동으로 주입하여 인스턴스를 생성한다. (=의존 관계인데, 내가 안넣고 스프링이 알아서 의존성을 자동으로 해결해줌) 그런데 왜... EntityManager를 생성자로 주입해 준 걸까? (아래에)
💡
@Entity는 테이블을 만들어주는 거지 new 해주는게 아니다!! @Controller, @Repository → IoC로 제어되는 = 스프링이 new 해주는
 

[ EntityManager ]

데이터베이스와 상호작용하기 위해서는 JPA에서 제공하는 EntityManager를 사용해야 한다. EntityManager를 주입 받으면 UserRepository는 데이터베이스와 소통할 수 있는 능력을 갖게 된다. 즉, UserRepository가 데이터베이스와 상호작용하기 위해 필요한 도구를 받아오는게 EntitiyManager!! EntityManager와 UserRepository는 의존 관계! (= UserRepository에서 데이터베이스 기능을 사용하기 위해 EntityManager를 생성자 매개변수로 받아야 함!!) EntityManager를 필드로 받고, 생성자로 주입 (의존성 주입) 받는다. 이런 행위를 통해 EntityManager에 있는 메소드를 호출하거나 다른 기능들을 UserRepository 클래스에서 사용할 수 있는 것! (ex. UserRepository에서 데이터베이스에 사용자 정보를 저장하거나 조회하는 등의 작업을 EntityManager를 통해 수행할 수 있게 됨.)
 

 
notion image
UserRrepositoryd에 @Repository가 있으니까 new하려고 봤더니 엔티티가 있어야한다, 그래서 생성자로 주입해줌 → 의존성 주입 (Dependency Injection) EntityManager는 내가 안 띄워도 기존에 IoC에 떠있다. (JPA 라이브러리에서 제공하기 때문!) 그래서 쭉 스캔하면서 서로의(?) 짝을 찾아줌. 니가 이게 필요하네!? 하면서?!
 

2. UserController가 UserRepository 의존하기

notion image

의존성 주입 받아야 하는 것들은 모두 final 사용

final 키워드를 사용하여 필드를 선언하면 해당 필드는 반드시 초기화 되어야 한다. 따라서 의존성 주입을 받아야 하는 객체들은 final 키워드를 붙여서 선언하는 것이 좋다. (컴파일러가 해당 필드가 초기화되지 않은 상태에서 사용되는 것을 방지해주니까...)
notion image
notion image
💡
final을 쓸 때에는 꼭 @RequiredArgsConstructor 어노테이션을 붙여주자. @RequiredArgsConstructor는 final 상수만 생성자로 만든다!!
 

[ 만약 디폴트 생성자와 매개변수가 있는 생성자가 둘 다 있는 경우 ]

디폴트 생성자가 때려진다. 모르겠으면 함 해보고 결과를 봐라
 

[ 내가 직접 생성자 만들어주기 ]

1. 롬북의 allArgumentsContstuctor 2. final의 @RequiredArgsConstructor 3. @Autowired 어노테이션이 붙은 필드나 생성자에 해당하는 의존성을 스프링 IoC 컨테이너에서 찾아서 자동으로 주입해준다. (= 붙이면 IoC에 있는거 가져와 줌)
 

3. save 함수 호출

@PostMapping("/join") public String join(UserRequest.JoinDTO requestDTO){ System.out.println(requestDTO); userRepository.save(requestDTO); // 모델에 위임하기 return "redirect:/loginForm"; }

save 함수 호출

notion image
이렇게 계속 UserRepository가 필요할 때마다 new해서 띄울 거야? 아니지? UserRepository를 IoC 컨테이너에 넣어놓는 작업이 필요하지? @Repository 붙이러 가자!
notion image
notion image
save 메서드는 실제로 데이터베이스에 사용자 정보를 저장하는 역할을 할 것. 컨트롤러에서는 UserRequest.JoinDTO 객체를 받아와서 UserRepository의 save 메서드를 호출하기만 하면 된다. save 메서드 호출이 되는지 확인하기 위해 회원가입을 했더니
notion image
호출됐다. 만약, 값이 null이면 호출 안 된다.
 

 
notion image
notion image
UserRepository에 매개변수가 있는 생성자가 적혀 있기 때문에 UserController에서 UserRepository를 사용하기 위해서는 UserRepository를 매개변수로 받는 생성자를 정의해야 한다. UserRepository가 먼저 new가 되어야 UserController가 때릴 수 있으니까 생성자 주입을 해줘야하는 듯...?
 

4. h2-console 가서 값 확인하기

notion image
notion image
 

DB Insert 코드를 작성해보자 (2가지 방법) +@Transactional

notion image
UserRepository에서 save 메소드를 작성해준다. UserController 쪽에서 생성자 매개변수로 IoC에 띄워진 UserRepository 객체를 받았으니 save 메소드를 잘 쳐줄거다.
notion image
notion image
?! 회원가입 했더니 터졌다 ㅠㅠ TransactionRequiredException....?
notion image
notion image
이게 뭔진 잘 모르겠지만 아무튼... save 메소드 위에 @Transactional 어노테이션을 추가하니 안터짐 (org꺼를 써야함)
💡
* @Transectional이란게 안붙으면 DB에 전송을 안함
* select할때는 @Transectinal 안붙여도 된다
notion image
H2 DB에서 조회해보면 회원 가입할 때 넣은 값이 나올거다. (확인 필요)
 

[ 어떤 클래스에 있는 값을 생성자를 통해서 옮길 것 ] - 2번째 방법 ㅎ…

notion image
통신으로 받은 requestDTO에 있는 정보를 User 클래스 (항아리)로 옮겨보자고요 (em = EnityManager)
notion image
User 클래스로 옮겨줄거니까... User 클래스를 enw 띄우고, user.setUsername--- 으로 항아리에 담긴 데이터들을 적용시킨다 하이버네이트 기술?? 다 적었으면 컨트롤러에서 호출해보자!
notion image
userRepository에 있는 saveV2 메소드를 호출! (requestDTO 객체를 DAO로 넘겨줘야 하니까... 아규먼츠가 requestDTO...?)
notion image
회원가입하니까 값 들어간거 콘솔창에 보이죠?
notion image
데이터베이스에도 들어왔죠?
 

TIP!

💡
IoC에 있는 걸 가져다 쓰자 → 의존성 주입
💡
@CreationTimeStamp : 자동으로 들어감
💡
@AllargConstructor는 생성자로 만들 필요가 없는 것까지도 만든다 (단순한 int 이런 거에도 생성자를 죄다 만들어버림…) @RequiredArgsConstructor는 final 상수만 생성자로 만든다
💡
세션은 스프링이 시작될 때 무조건 있는 영역
💡
[ f12 - 네트워크 - 리퀘스트 헤더 ] 에 쿠키 정보를 저장한다
유저 정보를 통째로 세션에 저장하는 방법은 일반적으로 사용되는 방식 중 하나. 유저의 고유한 식별값(예: 유저 이름, 아이디)을 키로 사용하여 해당 유저의 정보를 세션에 저장할 수 있다. = key에 내가 넣은 값(username 등)이 있을 때, 유저 정보를 통째로 넣어라. 그래야 편함
 
 
 
Share article

codingb