스프링 부트는 하나의 계층이 양 옆의 계층과 통신하는 구조
각 계층은 독립적이며 서로 소통할 수 있지만 다른 계층에 간섭하거나 영향을 줄 수 없다.
계층은 개념의 영역이고, 컨트롤러, 서비스, 리포지토리는 실제 구현을 위한 영역이다.
가장 우선적으로 HTTP의 요청을 받고 이 요청을 비즈니스 계층으로 전송하는 역할.
컨트롤러 = 프레젠테이션 계층
모든 비즈니스 로직을 처리. 비즈니스 로직이란 서비스를 만들기 위한 로직
웹 사이트에서 벌어지는 모든 작업(주문 서비스 -> 주문 개수, 가격 등)의 데이터를 처리하기 위한 로직, 예외 작업(주문처리 예외 작업)커피를 주문한다고 가정할 때, 프레젠테이션 계층에서 커피 주문을 접수하면 비즈니스 계층이 돈을 받아 계산하고, 커피를 만든다. 이때 커피 주문 취소 등의 다양한 작업도 가능하다.
모든 데이터베이스의 관련 로직을 처리한다. 데이터베이스에 접근하는
DAO
객체를 사용할 수 있다.DAO
는 데이터베이스 계층과 상호작용하기 위한 객체로 이해하자.리포지토리 = 퍼시스턴스 계층
main 디렉터리를 보면
java
와resources
가 있다.resources
디렉터리에 스프링 부트 프로젝트의 구성 요소를 하나씩 추가해보자.
(1) resources
디렉터리 밑에 templates
디렉터리를 생성한다.
(2) static
디렉터리를 생성 → JS
, CSS
, 이미지와 같은 정적 파일을 넣을 용도
(3) application.yml
파일을 생성 → 스프링 서버가 실행되면 자동으로 로딩되는 파일이다. 데이터베이스의 설정 정보, 로깅 설정 정보 등이 들어갈 수도 있고, 직접 설정을 정의할 때 사용되기도 한다.
가장 먼저 build.gradle 의존성을 추가한다.
스프링 부트용 JPA인 스프링 데이터 JPA, 로컬 환경과 테스트 환경에서 사용할 인메모리 데이터베이스인 H2, 반복 메서드 작성 작업을 줄여주는 라이브러리인 룸복을 추가한다.이 부분들은 데이터베이스의 테이블을 객체로 바꿔서 가져오게 하는 도구로 추후에 설명할 예정이다.
dependencies {
// 기존
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// 추가 (스프링 데이터 JPA)
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2' //인메모리 데이터베이스
compileOnly 'org.projectlombok:lombok' // 롬복
annotationProcessor 'org.projectlombok:lombok'
}
추가한 후 사진의 코끼리 모양을 누르면 추가한 의존성이 다운로드 된다.
프레젠테이션 계층은 컨트롤러라고 했습니다 :>
모든 서비스는 이 컨트롤러에서 처리하는데 기존의 test() 메서드를 삭제하고 코드를 작성해보겠습니다.
🔽 TestController.java
package org.example.SpringBootDevleoperApplication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class TestController {
@Autowired // TestService 빈 주입
TestService testService;
@GetMapping("/test")
public List<Member> getAllMembers() {
List<org.example.SpringBootDevleoperApplication.Member> members = testService.getAllMembers();
return members;
}
}
🔽 TestService.java
package org.example.SpringBootDevleoperApplication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TestService {
@Autowired
MemberRepository memberRepository; // 빈 주입
public List<Member> getAllMembers() {
return memberRepository.findAll(); // 멤버 목록 얻기
}
}
TestController
에서TestService
를Autowired
로Bean
을 주입 받는다.HTTP 요청(url: /test)
이 들어오면@GetMappin
어노테이션으로 요청을 처리하기 위해getAllMembers()
이 실행되어서 비즈니스 서비스 계층인TestService
가findAll()
메서드를 호출해 멤버 테이블에 저장된 멤버 목록을 모두 가져온다.프레젠테이션 로직은 `
TestController
에서 사용자에게 요청이 들어오면 관련된 부분을 라우팅해 처리해준다.비즈니스 로직
TestService
는MemberRepository
Bean
을 주입받은 후에findAll()
메서드를 호출해 멤버 테이블에 저장된 멤버 목록을 모두 가져온다.
DB에 접근할 때 사용할 객체인 Member DAO를 생성하고 실제 DB에 접근하는 코드를 작성
🔽 Member.java
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Getter
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false)
private Long id; // DB 테이블의 'id' 컬럼과 매칭
@Column(name = "name", nullable = false)
private String name; // DB 테이블의 'name' 컬럼과 매칭
}
매핑 작업에는 인터페이스 파일이 필요하다.
MemberRepository.java
인터페이스를 작성한다.이 인터페이스는 DB에서 데이터를 가져오는 퍼시스턴스 계층이다. 추후에 리포지토리를 만들 때 자세한 설명을 할 것이므로
지금은 간단히member
테이블에 접근해서Member
클래스에 매핑하는 구현체로 알아두자.
🔽MemberRository.java
package org.example.SpringBootDevleoperApplication;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
}
현재 실습한 결과물을 볼 수 있는 데이터가 DB에 하나도 입력되지 않은 상태이다. 이런 경우 실행 테스트를 하기 위해 애플리케이션을 실행할 때마다 SQL 문을 실행해 데이터베이스에 직접 데이터를 넣는다.
지금은 위에서 인메모리H2
를 사용하고 있기 때문에 애플리케이션을 새로 실행할 때마다 데이터가 사라진다. 이를 해결하기 위해 애플리케이션을 실행할 떄 원하는 데이터를 자동으로 넣어보자.
🔽application.yml
spring:
jpa:
# 전송 쿼리 확인
show-sql: true
properties:
hibernate:
format_sql: true
# 테이블 생성 후에 data.sql 실행
defer-datasource-initialization: true
실행해보면 아래처럼 실행창에 member 테이블이 만들어졌음을 확인할 수 있다.
postman으로 테스트해도 되고, 귀찮다면 인터넷 주소창에
http://localhost:8080/test
를 하게 되면 결과를 볼 수 있다.