1, 스프링 부트 3 구조 살펴보기
프레젠테이션 계층
HTTP 요청을 받고 이 요청을 비즈니스 계층으로 전송하는 역할
>> 컨트롤러가 프레젠테이션 계층의 역할을 함
컨트롤러는 스프링 부트 내에 여러 개가 있을 수 있다.
비즈니스 계층
모든 비즈니스 로직을 처리하는 역할
비즈니스 로직? : 서비스를 만들기 위한 로직
>> 서비스가 비즈니스 계층의 역할을 함
ex) 주문 서비스라고 한다면 주문 개수, 가격 등의 데이터를 처리하기 위한 로직, 주문 처리를 하다가 발생하는 예외 처리 로직, 주문을 받거나 취소하는 것 같이 프로세스를 구현하기 위한 로직
퍼시스턴스 계층
모든 데이터베이스 관련 로직을 처리하는 역할
이 과정에서 데이터베이스에 접근하는 DAO 객체를 사용할 수도 있다.
DAO? : 데이터베이스 계층과 상호작용하기 위한 객체
>> 리포지토리가 퍼시스턴스 계층의 역할을 함
2. main 디렉터리 구성하기
main 디렉터리를 펼치면 java와 resources로 구성되어 있다.
resources의 디렉터리에 다음과 같이 추가한다.
1. templates 디렉터리
HTML과 같은 뷰 관련 파일을 넣음
2. static 디렉터리
JS, CSS, 이미지와 같은 정적 파일을 넣음
3. application.yml
- 스프링 부트 서버가 실행되면 자동으로 로딩되는 파일
- 데이터베이스의 설정 정보, 로깅 설정 정보가 들어감
3. 프로젝트 계층 구조화
3-1. build.gradle에 의존성 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// 스프링 데이터 JPA
implementation 'org.springframework.boot:spring-boot-stater-data-jpa'
runtimeOnly 'com.h2database:h2' // 인메모리 데이터베이스
compileOnly 'org.projectlombok:lombok' // 롬복
annotationProcessor 'org.projectlombok:lombok'
}
- 스프링 부트용 JPA인 스프링 데이터 JPA 추가
- 로컬 환경과 테스트 환경에서 사용할 인메모리 데이터베이스인 H2 추가
- 반복 메서드 작성 작업을 줄여주는 라이브러리 롬복을 추가
3-2. 프레젠테이션, 서비스, 퍼시스턴스 계층 만들기
위와 같은 구조로 코드를 구조화할 것이다.
3-2-1. 프레젠테이션 계층 - TestController.java
@RestController
public class TestController {
@Autowired
TestService testService;
@GetMapping("/test")
public List<Member> getAllMembers(){
List<Member> members = testService.getAllMembers();
return members;
}
}
- 프레젠테이션 계층은 라우터의 역할이므로 @RestController 애너테이션을 정의해 준다.
- 비즈니스 계층인 TestService의 로직을 가져다가 쓸 것이므로 @Autowired로 TestService 빈 주입을 한다.
- Restful API를 사용하므로 /test의 경로로 get 요청을 보냈을 때,
TestService의 getAllMembers() 함수를 불러와 member의 리스트를 return 시켜 사용자에게 보여준다.
* TestService에서 gettAllMembers()로 member의 데이터베이스에서 전체 리스트를 불러오는 것을 구현해 보자.
3-2-2. 비즈니스 계층 - TestService.java
@Service
public class TestService {
@Autowired
MemberRepository memberRepository; // 빈 주입
public List<Member> getAllMembers(){
return memberRepository.findAll(); // 멤버 목록 얻기
}
}
- 비즈니스 계층은 Service의 역할이므로 @Service 애너테이션을 정의해 준다.
- 비즈니스 계층은 퍼시스턴스 계층인 MemberRepository와 통신해야 하므로
@Autowired를 통해 MemberRepository 빈을 주입한다. - 프레젠테이션 계층에서 사용할 데이터베이스의 전체 리스틀 불러오는 getAllMembers() 함수를 정의해 준다.
그럼 이제, member라는 이름의 table에 접근할 수 있도록 퍼시스턴스 계층을 구성해 보자.
3-3-3. 퍼시스턴스 계층 - Member.java
DB에 접근할 때, 사용할 객체인 Member DAO를 생성하고 실제 DB에 접근하도록 코드 작성
@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' 컬럼과 매칭
}
- @NoArgsConstructor(access = AccessLevel.PROTECTED)
- 역할 :
매개변수가 없는 기본 생성자를 생성하는 애너테이션 (protected로 정의하여 외부에서 호출하지 못하도록 함) - 이유 :
JPA는 프록시를 통해 엔터티 클래스를 인스턴스화할 때 기본 생성자를 필요로 하기 때문에 사용함
- 역할 :
- @AllArgsConstructor
- 역할 :
모든 필드를 인수로 받는 생성자를 생성한다. - 이유 :
자동으로 모든 필드를 초기화할 수 있는 생성자를 제공하여 객체를 쉽게 생성할 수 있음 - 예시 :
- 역할 :
public Member(Long id, String name) {
this.id = id;
this.name = name;
}
- @Getter
- 역할:
롬복 라이브러리를 사용하여, get메소드들이 자동으로 생성된다. -> 엔터티의 필드 값에 쉽게 접근 가능 - 예시:
- 역할:
public Long getId() {
return id;
}
public String getName() {
return name;
}
- @Entity
- 역할:
JPA에서 제공하며, 해당 클래스가 JPA 엔터티임을 나타낸다.
>> @Entity 애너테이션을 사용하면 JPA가 해당 클래스를 데이터베이스 테이블과 매핑하여 관리한다.
- 역할:
- @ID
해당 필드가 데이터베이스 테이블의 기본 키임을 나타낸다. - @GeneratedValue(strategy = GenerationType.IDENTITY)
기본 키 값을 자동으로 생성하도록 설정 - @Column(name="", updatable = false, nullable = false)
- name : 필드를 데이터베이스 테이블의 컬럼과 매핑하고, column의 이름을 name으로 설정
- updatable : 수정 가능 여부
- nullable : null 값 여부
3-2-4. 인터페이스 파일 - MemberRepository.java
매핑 작업에는 인터페이스 파일이 필요하다.
member라는 이름의 테이블에 접근해서 Member 클래스에 매핑하는 구현체
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
}
- DB에서 데이터를 가져오는 퍼시스턴스 계층 역할 -> @Repository 애너테이션 정의
- JpaRepository 인터페이스를 상속받는 이유는 JPA(Java Persistence API) 기반의 데이터 접근 계층을 구현할 때 여러 유용한 기능을 제공
기능 | 종류 |
CRUD |
|
Paging & Sorting |
|
쿼리 메소드 자동 생성 |
|
3-3. 작동 확인하기
3-3-1. 데이터베이스 쿼리 작성
resources 디렉터리에 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');
위와 같이 쿼리문 작성하기
3-3-2. SQL 쿼리 코드에 적용하기 - 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 파일에 있는 쿼리를 실행하도록 하는 옵션
이제, 앱을 실행시키면 콘솔창에 위와 같이 table이 잘 만들어짐을 알 수 있다.
3-3-3. HTTP 요청
마지막으로 우리가 설정한 API인 /test의 경로로 HTTP요청을 하면
다음과 같이 sql의 쿼리문대로 member의 테이블에 데이터가 잘 들어감을 확인할 수 있고
프레젠테이션 계층도 잘 작동하여 화면에 띄워짐을 확인할 수 있다.
'JAVA > SpringBoot 3' 카테고리의 다른 글
[스프링 부트 3] 블로그 만들기 - 1 (블로그 글 작성 API 구현) (4) | 2024.08.07 |
---|---|
[스프링 부트 3] ORM, JPA, 하이버네이트 (0) | 2024.07.30 |
[스프링 부트 3] 테스트 코드란? / 테스트 코드 작성하기 (0) | 2024.07.29 |
[스프링 부트 3] 초기 세팅 (IntelliJ) & Hello World 출력하기 (1) | 2024.07.24 |
[스프링 부트] 기본 개념 (IoC, DI, 빈, 컨테이너, AOP, PSA) (2) | 2024.07.22 |