본문 바로가기

Backend/Spring

Spring Boot 패키지 구조 @Controller @Service - (2)

Spring Boot 내의 패키지 구조를 어떻게 설계할지에 대해서 이야기해볼게요. (Controller - Service - DAO)

그리고 JPA를 사용하여 데이터베이스 CRUD (Select, Insert, Update, Delete) 를 해볼거에요.

그림과 같이 파일을 생성하시고, 설명에 따라 내용을 작성해주시면 됩니다.

 

build.gradle

레파지토리는 mavenCentral이 아닌 jcenter로 변경할게요.

jcenter는 CDN을 통해 라이브러리를 제공해서 속도가 빨라요. (체감으로는 못느끼겠지만...)

JPA, Lombok, H2 Database를 사용해서 비즈니스 로직을 작성할거에요.

관련된 기능을 사용하기 위해 Dependencies를 추가해줍니다.

 

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

group = 'me.hong'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
	jcenter()
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	runtimeOnly 'com.h2database:h2'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

application.yml

데이터베이스를 별도로 사용하지 않을 거라 H2 인메모리 데이터베이스를 사용할거에요.

단, 스프링 부트를 종료하면 데이터는 모두 초기화되요.

 

spring:
  datasource:
    driver-class-name: org.h2.Driver
  jpa:
    open-in-view: false
    show-sql: true
    hibernate:
      ddl-auto: update

UserEntity

데이터베이스 테이블의 스키마라고 보면 되요.

디테일엔 설정은 다 빼버렸어요.

 

@Entity
@Table(name = "user")
@Getter
@Setter
public class UserEntity {
	
	@Id
	private String userId;
	
	private String password;
	
	private String userNm;

}

UserRepository

JpaRepository<T, ID> 인터페이스를 상속받을거에요.

T에는 미리 만들어놓은 엔티티를 넣고, ID에는 타입을 넣어주면되요.

이러면 UserRepository 인터페이스로 기본적으로 미리 만들어진 데이터베이스 API를 사용할 수 있게 되요.

미리 생성된 API를 사용함으로써 직접 쿼리를 작성할 일이 줄어듭니다.

 

@Repository
public interface UserRepository extends JpaRepository<UserEntity, String> {

}

UserService

getUser 메서드는 아이디로 User 테이블을 조회하여 정보를 리턴할거구요.

setUser 메서드는 User 테이블에 데이터를 저장하는 기능을 수행할겁니다.

 

@Service
public class UserService {
	
	@Autowired
	private UserRepository userRepository;
	
	public UserEntity getUser(String userId, String password) {
		return userRepository.findById(userId).get();
	}
	
	public UserEntity setUser(UserEntity user) {
		return userRepository.save(user);
	}

}

UserController

데이터를 어떤 형태의 자료구조로 받을지는 의견이 상당히 분분해요.

우선, 튜토리얼에서는 별다른 데이터 처리를 하지 않기 위해 Entity 로 받았어요.

아래와 같이 작성하면, 클라이언트에서 body 안에 userId, password, userNm 필드를 보내면 받아지게 되겠죠?

 

@RestController
@RequestMapping("user")
public class UserController {
	
	@Autowired
	private UserService userService;
	
	@PostMapping("signin")
	public UserEntity signin(@RequestBody UserEntity reqBody) {
		String userId = reqBody.getUserId();
		String password = reqBody.getPassword();
		UserEntity user = userService.getUser(userId, password);
		return user;
	}
	
	@PostMapping("signup")
	@ResponseStatus(HttpStatus.CREATED)
	public UserEntity signup(@RequestBody UserEntity reqBody) {
		UserEntity user = userService.setUser(reqBody);
		return user;
	}
	
}

 

서버를 실행해볼게요.

Entity에 정의한 이름대로 테이블이 자동 생성되었네요.

application.yml에서 spring.jpa.hibernate.ddl-auto를 update로 주면 없는 테이블은 CREATE하고, 있는 테이블을 ALTER합니다.

 

 

처음이니깐 테스트까지 해볼게요. 툴은 Postman을 사용했습니다.

 

/user/signup API를 호출하여 사용자 정보를 생성합니다.

 

 

/user/signin API를 호출하여 사용자 정보를 가져옵니다.

 

 

잘못된 정보를 요청하면 에러가 나네요.

 

 

콘솔 로그를 확인해볼게요.

application.yml에서 spring.jpa.show-sql: true로 주면 JPA를 호출하면 수행한 쿼리를 확인할 수 있어요.

우리는 이미 위에서 설정했기 때문에 아래와 같이 쿼리를 확인할 수 있어요.

 

 

너무 대충 작성해서 예외처리도 안되있네요.

없는 정보를 호출해서 발생한 오류에요.

다음 장에서는 예외처리를 해볼게요.

https://gofnrk.tistory.com/17

 

Spring Boot 예외처리 - (3)

Rest API를 개발할 때 제가 사용하는 아주 간단한 예외처리 방법을 소개해드릴게요. 클라이언트에게 상태코드로 예외의 성격을 알리고 body에 예외 상황에 대한 메시지를 알려줄거에요. 파일 두 개만 추가해주면..

gofnrk.tistory.com