본문 바로가기
Backend/<스프링 부트 3 백엔드 개발자 되기>

03장 스프링 부트 3 구조 이해하기

by ccooll 2023. 10. 29.

3.1 스프링 부트 3 구조 살펴보기

1. 카페와 빵집으로 이해하는 계층

스프링 부트에는 프레젠테이션, 비즈니스, 퍼시스턴스 계층이 있으며 이 계층이 서로 통신하며 프로그램을 구성함

 

프레젠테이션 계층(컨트롤러) ↔ 비즈니스 계층(서비스) ↔ 퍼시스턴스 계층(리포지토리) ↔ 데이터베이스

 

- 프레젠테이션 (Controller)

: HTTP 요청을 받고 이 요청을 비즈니스 계층으로 전송하는 역할. 컨트롤러가 바로 프레젠테이션 계층의 역할을 함. 컨트롤러는 스프링 부트 내에 여러 개가 있을 수 있음

 

- 비즈니스 계층 (Service)

: 모든 비즈니스 로직 처리. 

※ 비즈니스 로직 : 서비스를 만들기 위한 로직, 서비스가 비즈니스 계층의 역할을 함.

ex) 주문 서비스 - 주문 개수 등의 데이터를 처리하기 위한 로직, 주문 처리를 하다가 발생하는 예외 처리 로직, 주문을 받거나 취소하는 프로세스 구현 로직

 

- 퍼시스턴스 계층 (Repository)

: 모든 데이터베이스 관련 로직 처리. 이 과정에서 데이터베이스에 접근하는 DAO 객체를 사용할 수 있음. 리포지토리가 퍼시스턴스 계층의 역할을 함

※ DAO : 데이터베이스 계층과 상호작용하기 위한 객체

 

 

2. 스프링 부트 프로젝트 디렉터리 구성하며 살펴보기

- main : 프로젝트 실행에 필요한 소스 코드나 리소스 파일

- test : 프로젝트의 소스 코드를 테스트 할 목적의 코드나 리소스 파일

- build.gradle : 빌드를 설정하는 파일, 의존성이나 플러그인 설정 등과 같이 빌드에 필요한 설정을 할 때 사용함

- setting.gradle : 빌드할 프로젝트의 정보를 설정하는 파일

 

 

3. main 디렉터리

main → java, resources

 

resources → templates, static(JS, CSS 이미지와 같은 정적 파일 넣을 디렉터리)

 

application.yml : 스프링 부트 서버가 실행되면 자동으로 로딩되는 파일, 데이터베이스의 설정 정보, 로깅 설정 정보 등이 들어갈 수도 있고, 직접 설정을 정의할 때 사용하기도 함.

 

 

 

3.2 스프링 부트 3 프로젝트 발전시키기

1. build.gradle에 의존성 추가하기

dependencies {
    // 생략
    
    // 스프링 데이터 JPA
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    
    // 인메모리 데이터베이스
    runtimeOnly 'com.h2database:h2'
    
    // 롬복
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
}

데이터베이스의 테이블을 객체로 바꿔서 가져오게 하는 도구들

 

 

2. 프레젠테이션, 서비스, 퍼시스턴스 계층 만들기

1. main/java/me/springbootdeveloper/controller/TestController.java

@RestController
public class TestController {

    @Autowired	// TestService 빈 주입
    TestService testService;

    @GetMapping("/test")
    public List<Member> getAllMembers() {
        List<Member> members = testService.getAllMembers();
        return members;
    }
}

 

2. main/java/me/springbootdeveloper/controller/TestService.java

@Service
public class TestService {
    @Autowired	// MemberRepository 빈 주입
    MemberRepository memberRepository;
	
    // 멤버 목록 얻기
    public List<Member> getAllMembers() {
        return memberRepository.findAll();
    }
}

MemberRepository라는 빈을 주입 받음

findAll() 메서드를 호출해 멤버 테이블에 저장된 멤버 목록을 모두 가져옴

 

HTTP 요청(url:/test) → TestController.java(프레젠테이션 계층) ↔ TestService.java(비즈니스 계층)

 

 

3. main/java/me/springbootdeveloper/controller/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' 컬럼과 매칭
}

DB에 접근할 때 사용할 객체인 Member DAO를 생성하고 실제 DB에 접근하는 코드

Member라는 이름의 테이블에 접근하는 데 사용할 객체

 

 

4. main/java/me/springbootdeveloper/controller/MemberRepository.java

@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
}

이 인터페이스는 DB에서 데이터를 가져오는 퍼시스턴트 계층 역할을 함

member라는 이름의 테이블에 접근해서 Member클래스에 매핑하는 구현체

 

 

3. 임포트 오류 처리

Alt + Enter

 

 

4. 작동 확인하기

1. mail/resources/data.sql

INSERT INTO member (id, name) VALUES (1, '이름1')
INSERT INTO member (id, name) VALUES (2, '이름2')
INSERT INTO member (id, name) VALUES (3, '이름3')

 

 

2. mail/resources/application.yml

spring:
  jpa:
    # 전송 쿼리 확인
    show-sql: true
    properties:
      hibernate:
        format_sql: true
        
    # 테이블 생성 후에 data.sql 실행
    defer-datasource-initialization: true

show-sql, format-sql : 애플리케이션 실행 과정에 데이터베이스에 쿼리를 할 일이 있으면 실행 구문을 모두 보여주는 옵션

defer-datasource-initialization : 애플리케이션을 실행할 때 테이블을 생성하고 data.sql 파일에 있는 쿼리를 실행하도록 함

 

 

HTTP 요청 → TestController.java ↔ TestService.java ↔ MemberRepository.java ↔ 데이터베이스

 (url:/test)        프레젠테이션 계층       비즈니스 계층            퍼시스턴스 계층

 

 

3.3 스프링 부트 요청-응답 과정 한 방에 이해하기

1. 포스트맨에서 톰캣/test GET 요청, 이 요청은 스프링 부트 내로 이동

2. 이때 스프링 부트의 디스패처 서블릿이라는 녀석이 URL 분석, 이 요청을 처리할 수 있는 컨트롤러를 찾음, TestController가 /test라는 패스에 대한 GET 요청을 처리할 수 있는 getAllMembers() 메서드를 가지고 있으므로 디스패처 서블릿은 TestController에게 /test GET 요청을 전달함

3. /test GET 요청을 처리할 수 있는 getAllMembers() 메서드와 이 요청이 매칭됨. 그리고 getAllMembers() 메서드에서는 비즈니스 계층과 퍼시스턴스 계층을 통하면서 필요한 데이터를 가져옴

4. 뷰 리졸버템플릿 엔진을 사용해 HTML 문서를 만들거나 JSON, XML 등의 데이터를 생성함

5. 그 결과 members를 return하고 그 데이터를 포스트맨에서 볼 수 있게 됨.

 

 

 

 

** 핵심 요약 **

더보기

1. 프레젠테이션 계층은 HTTP 요청을 받고 비즈니스 계층으로 전송

2. 비즈니스 계층은 모든 비즈니스 로직을 처리함. 퍼시스턴스 계층에서 제공하는 서비스를 사용할 수도 있고, 권한을 부여하거나 유효성 검사를 하기도 함

3. 퍼시스턴스 계층은 모든 스토리지 관련 로직을 처리함. 이 과정에서 데이터베이스에 접근하기 위한 객체인 DAO를 사용할 수도 있음.