개발자 취업준비/springboot

스프링부트 계층구조 구현하여 프로젝트를 구성해보기

naspeciallist 2025. 1. 29. 16:25


이 글은 스프링부트3 백엔드 개발자 되기 책을 바탕으로 공부한 내용을 정리한 게시글 입니다.

 

 

스프링 부트는 클라이언트로부터 요청을 받으면, 각 계층에서 해당 요청을 처리한 후 응답을 반환하는 구조로 이루어져 있습니다. 각 계층은 자신의 역할을 수행한 뒤, 다음 계층으로 요청을 전달합니다.

 

스프링부트에 계층구조에 대한 자세한 내용은 여기를 참고해 주세요.

 

그럼 스프링부트의 계층구조를 코드로 구성을 해보겠습니다.

 

 

1. 각 코드 작성(프레젠테이션 계층, 비즈니스 계층, 퍼시스턴 계층)


 

우선 프레젠테이션 계층 입니다.

프레젠테이션 계층은 주로 컨트롤러(Controller) 형태로 구현됩니다.

 

그럼 Controller를 구성해 보겠습니다.

org.zerock.springbootdeveloper 패키지 안에 controller라는 패키지를 만든 뒤 안에 TestController라는 클래스를 만들어 작성하겠습니다.

@RestController
public class TestController {

    @Autowired
    TestService testService;

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

}

 

컨트롤러를 통해 클라이언트의 요청을 받아들입니다. 그 후 해당 요청을 처리하기 위해 서비스 계층과 상호 작용한 후, 받은 응답을 클라이언트에게 반환하게 됩니다.

 

이제 이어서 비즈니스계층인 서비스 코드를 구성해보겠습니다.똑같이 Controller패키지 위치에 Service 패키지를 만든 뒤 그 안에 TestService.java라는 파일을 만들어 준 뒤 아래와 같이 코드를 작성하겠습니다.

@Service
public class TestService {
    @Autowired
    MemberRepository memberRepository; //빈 주입

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

 


MemberRepository라는 빈을 주입받은 후에 findAll(  ) 메서드를 호출해 멤버 테이블에 저장된 멤버 목록을 모두 가져옵니다. 지금까지 작성한 코드를 그림으로 표현하면 다음과 같습니다. 

 

이제는 데이터를 실제로 저장하고 관리하는 계층이 필요합니다. 이제 Persistent Layer를 구성하여 데이터베이스와 직접 상호작용하는 방식을 살펴보겠습니다.

 

퍼시스턴스 계층 코드를 작성해보겠습니다. DB에 접근 할 때 사용할 객체은 MemberDAO를 생성하고 실제 DB에 접근하는 코드를 작성합니다. 같은 위치에 dao 패키지를 만들어 주고 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;
    @Column(name = "name", nullable = false)
    private String name;
}

 

이제는 실제로 member 테이블과 Merber클래스를 매핑하는 코드를 작성합니다.

 

매핑작업에는 인터페이스 파일이 필요합니다. repository패키지를 만든 뒤 MerberRepository.java인터페이스 파일을 새로 생성해 필요한 코드를 작성해 보겠습니다.

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

 

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

 

이제 모든 계층을 구현 하였습니다. 오류로 빨간줄이 뜨는것들이 몇개 있을 겁니다. 그런건 아마 대부분 임포트에 관련된 오류 일 겁니다. build.gadle에 의존성을 추가하지 않아서 생기는 문제가 대부분일겁니다. 

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

의존성을 이렇게 구성해주시면 됩니다.

 

이제 프로젝트의 작동을 확인하겠습니다.

 

먼저 인메모리데이터베이스인 H2를 추가하겠습니다.

build.gradle에 방금 추가했던 의존성에다가 아래와 같은 의존성이 있는지 확인해 주시면 됩니다.

runtimeOnly 'com.h2database:h2'

 

H2 인메모리 데이터 베이스는 애플리케이션을 새로 실행할 때마다 데이터가 사라진다는 단점이 있습니다. 

이를 해결하기 위해 애플리케이션을 실행할 때 원하는 데이터를 자동으로 넣는 작업을 하겠습니다.

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')

 

그 다음에는 aplication.yml파일을 만든 뒤 아래처럼 코드를 작성해 줍니다. yml파일도 똑같이 resources 디렉터리에 만들어 주시면 됩니다.

spring:
  jpa:
    #전송쿼리 확인
    show-sql: true
    properties:
      hibernate:
        format_sql: true

    #테이블 생성 후에 data.sql 쿼리 실행
    defer-datasource-initialization: true

 

yaml파일은 들여쓰기를 통해 계층 구조를 나타냅니다. 들여쓰기는 일관되어야 하며 보통 공백 2개나 4개를 이용합니다.

 

이제 서버를 실행해봅니다.

콘솔창을 확인해보면 테이블이 생성 된 것을 확인 할 수 있습니다.

 

이제 HTTP요청을 시도해보겠습니다. 포스트맨이라는 프로그램을 통해 요청을 해보겠습니다.

 

포스트맨을 켜고 HTTP메서드를 [GET]으로 URL에 http://localhost:8080/test을 입력한 뒤 [Send] 버튼을 눌러 스프링 부트 서버에 HTTP 요청을 전송하세요 그러면 좀 전에 data.sql파일로 작성해 저장한 데이터를 포스트맨, 즉 클라이언트에서 확인 할 수 있습니다.

 

포스트맨에서 데이터를 보기까지는 다음 그림과 같은 과정을 거칩니다. 계층과 파일을 맞춰서 과정을 한번 확인해보면

이런 과정으로 스프링이 동작한다는 걸 확인 할 수 있습니다.