본문 바로가기
Spring boot/스프링 부트 3 백엔드 개발자 되기(자바편)

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

by 리버🐦‍🔥 2023. 7. 25.

<핵심 키워드>

- 프레젠테이션 계층

- 비즈니스 계층

- 퍼시스턴스 계층

 

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

    3.1.1 계층 이해

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

        - 프레젠테이션 계층

            - HTTP 요청을 받고 이 요청을 비즈니스 계층으로 전송하는 계층 (컨트롤러가 프레젠테이션 계층 역할)

        - 비즈니스 계층

            - 서비스를 만들기 위한 비즈니스 로직을 처리하기 위한 계층 (서비스)

        - 퍼시스턴스 계층

            - 데이터베이스 관련 로직을 처리하기 위한 계층 (리포지토리)

        -> 계층은 개념의 영역이고, 컨트롤러, 서비스, 리포지토리는 실제 구현을 위한 영역이다.

 

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

        - main : 실제 코드를 작성하는 공간

        - test : 프로젝트 소스 코드를 테스트 할 목적의 코드나 리소스 파일이 들어있는 공간

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

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

 

    3.1.3 main 디렉토리 구성하기

        - templates : HTML과 같은 뷰 관련 파일을 저장

        - static : JS, CSS, 이미지와 같은 정적 파일을 저장

        - application.yml : 스프링 부트 설정을 하는 파일

▲ main 디렉토리 구성

 

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

    3.2.1 bulild.gradle에 의존성 추가하기

        1단계. build.gradle에 의존성 추가 (데이터베이스의 테이블을 객체로 바꿔서 가져오게 하는 도구정도...)

// build.gradle
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.2'   // 스프링 부트 플러그인
    id 'io.spring.dependency-management' version '1.1.0'    // 스프링 의존성 자동 관리 플러그인
}

group 'me.kyungsoolee'  // 그룹 이름
version '1.0'   // 버전
sourceCompatibility = '17'  // 자바 버전

repositories {  // 의존성을 받을 저장소
    mavenCentral()
}

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 {
    useJUnitPlatform()
}

▲ build.gradle에 필요한 의존성을 추가

        2단계. 새로고침을 눌러 의존성 다운로드

 

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

        1단계. 프레젠테이션 계층 (TestService 빈 주입) 코드 작성

// TestController
package me.kyungsoolee.springbootdeveloper;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @Autowired  // TestService 빈 주입
    TestService testService;

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

        2단계. 비즈니스 계층 (TestService) 코드 작성

// TestService
package me.kyungsoolee.springbootdeveloper;

import org.springframework.beans.factory.annotation.Autowired;

@Service
public class TestService {

    @Autowired
    MemberRepository memberRepository;  // 1. 빈 주입

    public List<Member> getAllMembers() {
        return memberRepository.findAll();  // 2. 멤버 목록 얻기
    }
}

        3단계. 퍼시스턴스 계층 코드 작성 (member라는 이름의 테이블에 접근하는데 사용할 객체)

// Member
package me.kyungsoolee.springbootdeveloper;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@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' 컬럼과 매칭
}

        4단계. 인터페이스 코드 작성 (DB에서 데이터를 가져오는 퍼시스턴스 계층 역할)

            - member라는 이름의 테이블에 접근해서 Member 클래스에 매핑하는 구현체(정도로 이해)

// MemberRepository
package me.kyungsoolee.springbootdeveloper;

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

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

        3.2.3 임포트 오류 처리하기

            - 빨간 오류가 발생한 곳에(맥 기준) ⌥ + enter를 눌러 import 해준다.

            - 위 방법이 아닌 github를 통해 처리하는 방법도 존재한다.

        3.2.4 작동 확인하기

            1단계. data.sql 생성 (애플리케이션 실행시 저장할 더미데이터를 넣을 SQL)

// data.sql
INSERT INTO member (id, name) VALUES (1, 'name 1')
INSERT INTO member (id, name) VALUES (2, 'name 2')
INSERT INTO member (id, name) VALUES (3, 'name 3')

            2단계. application.yml 파일에서 옵션 설정

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

                - defer-datasource-initialization : 애플리케이션을 실행할 때 테이블을 생성하고 data.sql의 쿼리를 실행하는 옵션

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

            3단계. 테이블 생성이 잘 되었는지 확인

▲ ⌥ + F를 통해 CREATE TABLE을 검색하여 잘 만들어졌는지 확인

            4단계. 포스트맨을 통해 확인

▲ 결과가 잘 나온 모습

 

<3장 핵심요약>
-> 일반적으로 스프링 부트 프로젝트는 4개 계층으로 이루어진다.

- 프레젠테이션 계층 : HTTP 요청을 받고 비즈니스 계층으로 전송
- 비즈니스 계층 : 모든 비즈니스 로직을 처리. 퍼시스턴스 계층에서 제고하는 서비스를 사용할 수도 있고, 권한을 부여하거나 유효성 검사를 하기도 한다.
- 퍼시스턴스 계층은 모든 스토리지 관련 로직을 처리한다. 이 과정에서 데이터베이스에 접근하기 위한 객체인 DAO를 사용할 수도 있다.
- 데이터베이스