스프링 부트3 - 구조

김동헌·2023년 11월 6일
0

SpringBoot

목록 보기
4/19
post-thumbnail

📌 스프링 부트3 - 구조

스프링 부트는 하나의 계층이 양 옆의 계층과 통신하는 구조
각 계층은 독립적이며 서로 소통할 수 있지만 다른 계층에 간섭하거나 영향을 줄 수 없다.

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


🔨 프레젠테이션 계층

가장 우선적으로 HTTP의 요청을 받고 이 요청을 비즈니스 계층으로 전송하는 역할. 컨트롤러 = 프레젠테이션 계층


🔨 비즈니스 계층

모든 비즈니스 로직을 처리. 비즈니스 로직이란 서비스를 만들기 위한 로직
웹 사이트에서 벌어지는 모든 작업(주문 서비스 -> 주문 개수, 가격 등)의 데이터를 처리하기 위한 로직, 예외 작업(주문처리 예외 작업)

커피를 주문한다고 가정할 때, 프레젠테이션 계층에서 커피 주문을 접수하면 비즈니스 계층이 돈을 받아 계산하고, 커피를 만든다. 이때 커피 주문 취소 등의 다양한 작업도 가능하다.


🔨 퍼시스턴스 계층

모든 데이터베이스의 관련 로직을 처리한다. 데이터베이스에 접근하는 DAO 객체를 사용할 수 있다. DAO는 데이터베이스 계층과 상호작용하기 위한 객체로 이해하자. 리포지토리 = 퍼시스턴스 계층


📌 스프링부트 디렉터리 구성


☄️ main 디렉터리 구성

main 디렉터리를 보면 javaresources가 있다. resources 디렉터리에 스프링 부트 프로젝트의 구성 요소를 하나씩 추가해보자.

(1) resources 디렉터리 밑에 templates 디렉터리를 생성한다.

(2) static 디렉터리를 생성 → JS, CSS, 이미지와 같은 정적 파일을 넣을 용도

(3) application.yml 파일을 생성 → 스프링 서버가 실행되면 자동으로 로딩되는 파일이다. 데이터베이스의 설정 정보, 로깅 설정 정보 등이 들어갈 수도 있고, 직접 설정을 정의할 때 사용되기도 한다.


☄️ build.gradle 의존성 추가

가장 먼저 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에서 TestServiceAutowiredBean을 주입 받는다. HTTP 요청(url: /test)이 들어오면 @GetMappin어노테이션으로 요청을 처리하기 위해 getAllMembers()이 실행되어서 비즈니스 서비스 계층인 TestServicefindAll() 메서드를 호출해 멤버 테이블에 저장된 멤버 목록을 모두 가져온다.

프레젠테이션 로직은 `TestController에서 사용자에게 요청이 들어오면 관련된 부분을 라우팅해 처리해준다.

비즈니스 로직 TestServiceMemberRepository 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를 하게 되면 결과를 볼 수 있다.

profile
백엔드 기록 공간😁

0개의 댓글