JavaProject/Spring Boot

Spring Boot(JPA dummy 데이터로 insert 테스트하기)

devel0per 2022. 9. 9. 14:16

# 1

com.cos.blog.test 패키지 속에 예제를 진행하게 될 DummyControllerTest 클래스를 만들고

어떤 페이지로 이동할 것이 아니라 데이터만 리턴받을 것이기 때문에 @RestController 어노테이션을 사용한다.

회원가입(insert) 예제를 할 것이기 때문에 @PostMapping으로 Post방식을 사용할 것이고, PostMan을 활용해서 몇개의 더미 데이터를 insert 해보고 결과를 살펴볼 것이다.

 

com.cos.blog.test > DummyControllerTest.java

package com.cos.blog.java;

// 어떤 페이지로 이동하는 것이 아니라, 데이터를 리턴받을 것 이기때문에 @RestController 사용
@RestController
public class DummyControllerTest{
	
    // Http 메소드중 Post 방식으로 Mapping
    @PostMapping("dummy/join")
    public String join(){
    	
    }
}

Id, Role, createdTime 데이터는 기본값으로 들어가니 username, password, email 값만 post send


# 2

join() 메소드에 매개변수로 username, password, email의 값을 전달 받고, 그것이 제대로 전달 받아지는지 먼저 Test를 해보려고 한다.

package com.cos.blog.java;

// 어떤 페이지로 이동하는 것이 아니라, 데이터를 리턴받을 것 이기때문에 @RestController 사용
@RestController
public class DummyControllerTest{
	
    // Http 메소드중 Post 방식으로 Mapping
    @PostMapping("dummy/join")
    public String join(String username, String password, String email){
    	
        System.out.println("username : " + username);
        System.out.println("password : " + password);
        System.out.println("email : " + email);
        
        return "회원가입이 완료되었습니다."
    	
    }
}

 

PostMan으로 확인해보면, 데이터들이 적절하게 이동한 것을 볼 수 있다.

 

다음은 object 형식으로 데이터들을 받아보려고 한다.

 

package com.cos.blog.java;

// 어떤 페이지로 이동하는 것이 아니라, 데이터를 리턴받을 것 이기때문에 @RestController 사용
@RestController
public class DummyControllerTest{
	
    // Http 메소드중 Post 방식으로 Mapping
    @PostMapping("dummy/join")
    public String join(User user){
    	
        System.out.println("username : " + user.getUsername());
        System.out.println("password : " + user.getPassword());
        System.out.println("email : " + user.getEmail());
        
        return "회원가입이 완료되었습니다."
    	
    }
}

이것도 마찬가지로 PostMan으로 확인해보면 데이터가 잘 이동하는 것을 확인할 수 있습니다.

 


# 3

 

Post 형식으로 데이터들이 제대로 이동하는 것을 확인했으니, 이제는 DB 테이블에 Insert를 해주도록 하겠다. Insert를 위해서는 com.cos.blog.repository 패키지를 하나 생성 후, 그 속에 UserRepository 인터페이스를 하나 생성 후에, JpaRepository를 상속받고 제네릭으로<User, Integer>을 사용해주면 된다. 여기서 <User, Integer>로 설정하는 이유가 User 테이블에서 Integer을 Primary key로 설정되어 있기 때문이다. JpaRepository는 findall()이라는 함수를 내장하고 있는데, findall()은 User 테이블의 모든 것을 return 받는 함수이다.

 

com.cos.blog.repository > UserRepository(interface)

 

package com.cos.blog.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.cos.blog.model.User;

public interface UserRepository extends JpaRepository<User, Integer>{

}

# 4

DummyControllerTest 에서 UserRepository의 형태를 지니고 있는 userRepository를 선언해준다.

Spring boot에서 @RestController를 인식하고 DummyControllerTest를 메모리에 띄워줄 때, userRepository는 NULL값으로 존재한다. 하지만 여기서 @AutoWired 라는 어노테이션을 붙혀주면 DummyControllerTest 가 메모리에 뜰 때, userRepository도 메모리에 동시에 같이 뜬다. 그러면 우리는 자유롭게 userRepository를 사용하기만 하면 되는 것이다. 이것을 의존성 주입(DI)라고 한다.

 

userRepository에 존재하는 save() 메소드를 이용해서 데이터를 user 테이블에 주입해보면, 모든 데이터가 전부 들어가지만 role 데이터는 들어가지 않는 것을 확인할 수 있다. 왜 그럴까?

package com.cos.blog.java;

// 어떤 페이지로 이동하는 것이 아니라, 데이터를 리턴받을 것 이기때문에 @RestController 사용
@RestController
public class DummyControllerTest{
	
    @AutoWired
	private UserRepository userRepository;
	
    // Http 메소드중 Post 방식으로 Mapping
    @PostMapping("dummy/join")
    public String join(User user){
    	
        System.out.println("username : " + user.getUsername());
        System.out.println("password : " + user.getPassword());
        System.out.println("email : " + user.getEmail());
        
        userRepository.save(user);
        return "회원가입이 완료되었습니다."
    	
    }
}

# 5

id값은 auto_increment의 형식으로 순서대로 자동으로 잘 들어갈 것이고 createDate 값은 @CreationTimestamp의 어노테이션 덕분에 java에서 알아서 잘 import를 해줘서 상관이 없다. 근데 왜 role의 데이터는 null 값으로 들어가는 것일까?

쿼리문을 살펴보자.

console 창을 살펴보면 현재 쿼리문이

INSERT INTO User(createDate, email, password, role, username) VALUES(?, ?, ?, ?, ?) 이런식으로 작동하고 있다.

지금 role 같은 경우는 @ColumnDefault("user")로 설정해뒀으니 실제로 쿼리값이 명시적 NULL 방식으로 들어가고 있는 것이다.

우리가 원하는 값을 대입하고 싶으면 쿼리문이 INSERT INTO User(createDate, email, password, username) VALUES(?, ?, ?, ?)

이런식으로 작동해야 NULL값이 적용되지 않고 DEFAULT값으로 "user"라는 데이터가 들어갈 것이다. 그럼 어떻게 해야할까?

필자는 2가지 방식으로 설명한다.


# 5 - 1

@DynamicInsert insert 어노테이션을 사용하기.

어노테이션을 사용하면 insert시, null인 필드를 자동으로 제외시켜주는 역할을 한다.

어노테이션이 분명 지금의 우리가 원하는 적절한 일을 해주긴 하지만, 이러한 어노테이션을 하나하나 붙이게 되면 나중에는 끝도 없어진다.

그럼 또 다른 방법을 알아보자.

 


# 5 - 2

또 다른 방법은 @columndefault 어노테이션을 빼서, userRepository.save(user) 하기 전에 user 객체의 Role의 값을 지정해주는것이다. 즉 user.setRole("user"); 로 설정해준다.

여기서 하나 문제가 되는 것은 개발자들이 개발을 진행할 때, "user"라는 데이터 대신 실수로 "user2"라는 데이터를 삽입할 수 있다는 것이다. 여기서 문제를 방지하기 위해 Enum을 사용해서 RoleType을 하나 만들어서 USER,ADMIN 2가지를 정의해준다.

package com.cos.blog.model;

public enum RoleType {
	USER,ADMIN

}

이제 user 객체에서 private String role의 형태를 private RoleType role로 바꿔줘서 ADMIN과 USER만 사용할 수 있게 설정해두고

데이터베이스에는 RoleType이라는 것이 없기 때문에 @Enumerated(EnumType.STRING)을 사용해서 형을 보존해줘야 한다.

@Enumerated(EnumType.STRING)
	private RoleType role;

이제 Role에 데이터를 넣을 때, RoleType만 넣을 수 있으니 RoleType.USER을 사용해서 넣게 만들어두면 개발자들이 실수할일이 없을 것이다.

user.setRole(RoleType.USER);

# 6

모든 준비를 마쳤으니, Insert를 해보도록 하겠다.

package com.cos.blog.java;

// 어떤 페이지로 이동하는 것이 아니라, 데이터를 리턴받을 것 이기때문에 @RestController 사용
@RestController
public class DummyControllerTest{
	
    @AutoWired
	private UserRepository userRepository;
	
    // Http 메소드중 Post 방식으로 Mapping
    @PostMapping("dummy/join")
    public String join(User user){
    	
        System.out.println("username : " + user.getUsername());
        System.out.println("password : " + user.getPassword());
        System.out.println("email : " + user.getEmail());
        
        user.setRole(RoleType.USER);
        userRepository.save(user);
        return "회원가입이 완료되었습니다."
    	
    }
}

 

username, password, email 삽입
제대로 들어가 있는것을 확인~

 


# 주요 개념

- enum을 활용한 강제성 설정 : Data의 domain을 만들 때 사용(데이터의 범위)

- 의존성 주입(DI) : @AutoWired을 이용한 의존성 주입 . . . . 설명에서 @RestController를 인식한 Spring이 해당 클래스를 메모리에 띄워줄 때, @AutoWired를 달고 있는 어떠한 객체..? 인터페이스..?도 같이 메모리에 띄워줘서, 개발자가 맘대로 사용할 수 있는 상태를 만들어준다는데 사실 100% 이해되지는 않지만, 뭔가 감이 닿는 느낌... 이랄까.. 해당 부분에 대해서는 좀 더 공부해봐야겠다.