점프 투 스프링부트 2장 (01~04)

이동원·2024년 4월 9일

2-01 스프링 부트 프로젝트의 구조 이해하기

1) src->main->java 디렉터리

  • 자바 파일을 저장하는 공간이다
  • com.example.sbb : SBB의 자바 파일을 저장하는 공간이다
    • 컨트롤러는 URL 요청 처리하고, 폼은 사용자 입력에대해 검증을한다.
  • SbbApplication.java 파일 : 프로그램의 시작을 담당하는 파일

2) src->main->resources 디렉터리

  • 자바 파일을 제외한 HTML, CSS, 자바스크립트, 환경 파일 등 저장함
  • templates 디렉터리 : 템플릿 파일을 저장
    • 템플릿 파일 : 자바 코드를 삽입할 수 있는 HTML 형식의 파일로, 스프링 부트에서 생성한 자바 객체를 HTML 형태로 출력
  • static 디렉터리 : css파일, js파일, 이미지 파일 등을 저장
  • application.properties 파일 : sbb 프로젝트의 환경 설정 (변수,db 설정 예를 들어server.port=8088 설정 등)

3) src/test/java 디렉터리

  • sbb 프로젝트에서 작성한 파일을 테스트하는 코드를 저장하는 공간
  • build.gradle 파일 : 그레들이 사용하는 환경 파일, 프로젝트에 필요한 플러그인과 라이브러리를 설치하기 위한 내용 작성
    • 그레들 : 그루비(Groovy)를 기반으로 한 빌드 도구로 Ant, Maven과 같은 이전 세대의 단점을 보완하고 장점을 취합하여 만듦

2-02 간단한 웹 프로그램 만들기

1) URL 매핑과 컨트롤러 이해하기

  • URL 매핑 : URL과 컨트롤러의 메서드를 일대일로 연결하는 것 (일치 시키는것)
  • 브라우저와 같은 클라이언트의 페이지 요청이 발생하면 스프링 부트는 가장 먼저 컨트롤러에 등록된 URL 매핑을 찾고, 해당 URL 매핑을 발견하면 URL 매핑과 연결된 메서드를 실행
package com.example.sbb;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MainController {
    @GetMapping("/sbb")
    @ResponseBody
    public String index(){
        return "index";
    }
}
  • @Controller : 시작점
  • @GetMapping : 요청된 URL(/sbb)과의 매핑을 담당
  • @ResponseBody : URL 요청에 대한 응답으로 문자열을 리턴하라는 의미

2-03 JPA로 데이터베이스 사용하기

  • 데이터베이스(database, DB) : 데이터를 모으고 관리하는 저장소
  • ORM(Object Relational Mapping)
  • SQL을 사용하지 않고 데이터베이스를 관리할 수 있는 도구
  • DBMS(database management system) : 데이터베이스를 관리하는 소프트웨어
  • JPA(Java Persistence API) : 인터페이스(서로 다른 시스템이나 요소들이 함께 작동할 수 있도록 연결는것) 모음이므로, 이 인터페이스를 구현한 실제 클래스가 필요
    • 하이버네이트(Hibernate) : JPA의 인터페이스를 구현한 실제 클래스이자 자바의 ORM 프레임워크

1) H2 데이터베이스 설치하기

  • build.gradle 에서 라이브러리 설치 : runtimeOnly 'com.h2database:h2'추가

  • src->main->resources -> application.properties 에서 설정 추가

spring.h2.console.enabled=true
// h2 콘솔에 접속 여부 묻는 항목.
// h2 콘솔 = h2 데이터베이스를 웹 UI로 보여준다
spring.h2.console.path=/h2-console
// h2 콘솔로 접속하기 위한 경로
spring.datasource.url=jdbc:h2:~/local
// DB 접속 경로
spring.datasource.driverClassName=org.h2.Driver
// DB 접속할 때 쓰는 드라이버 클래스명
spring.datasource.username=sa
// DB 사용자 명
spring.datasource.password=
// DB 비밀번호

2) JPA 환경 설정하기

  • JPA 라이브러리 설치
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 추가
  • implementation : 필요한 라이브러리 설치를 위해 가장 일반적으로 사용하는 설정
    • 특징 : 해당 라이브러리가 변경되더라도 이 라이브러리와 연관된 모든 모듈을 컴파일하지 않고 변경된 내용과 관련이 있는 모듈만 컴파일하므로 프로젝트를 리빌드(rebuild)하는 속도가 빠르다.
  • application.properties 파일 수정
# JPA
// 스프링부트와 하이버네이트를 함께 사용할 때 필요한 설정 항목
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
// 엔티티를 기준으로 데이터의 테이블을 생성하는 규칙 설정
spring.jpa.hibernate.ddl-auto=update

2-04 엔티티로 테이블 매핑하기

  • 기본키(primary key) : 테이블의 데이터가 중복되어 저장되지 않게 한다. 어떤 열을 기본키로 설정하면 해당 열에는 동일한 값을 저장하지 못한다.
  • 엔티티(entity)(=모델,도메인 모델) : 데이터베이스 테이블과 매핑되는 자바 클래스
    즉 자바에서의 테이블
    ex) 질문과 답변 데이터를 저장할 데이터베이스 테이블과 매핑되는 질문과 답변 엔티티

1) 질문 엔티티 만들기

package com.example.sbb;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;

@Getter
@Setter
@Entity
public class Question {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(length = 200)
    private String subject;

    @Column(columnDefinition = "TEXT")
    private String content;

    private LocalDateTime createDate;
}
  • @Entity : 스프링 부트가 클래스를 엔티티로 인식
  • @Getter와 @Setter : 롬복의 기능으로 Getter, Setter 메서드를 자동으로 생성
  • @Id : id 속성을 기본키로 지정
    • 기본키 조건 : null x, 중복 x
  • @GeneratedValue : 데이터를 저장할 때 해당 속성에 값을 일일이 입력하지 않아도 자동으로 1씩 증가하여 저장
  • strategy = GenerationType.IDENTITY : 고유한 번호를 생성하는 방법을 지정하는 부분, 해당 속성만 별도로 번호가 차례대로 늘어나도록 할 때 사용
    • strategy 생략시, 순서가 일정한 고유 번호를 가질 수 없다 즉 순서가 달라질수 있다 .
    • 왜? @GeneratedValue 에 지정된 모든 속성에 번호를 차례대로 지정하므로
  • @Column : 열의 세부 설정
  • 엔티티의 속성은 테이블의 열 이름과 일치
    • length : 열의 길이
    • columnDefinition : 열 데이터의 유형이나 성격을 정의
    • TEXT : 열 데이터 ‘텍스트’, 글자 수 제한 X
    • @Transient : 엔티티의 속성을 테이블의 열로 만들지 않고 클래스의 속성 기능으로만 사용
      즉, @Transient를 사용하면 해당 속성은 데이터베이스 테이블에 영향을 주지 않고 엔티티 클래스의 일부로만 유지됩니다.
  • 엔티티에서 카멜표기법으로 속성의 이름을 쓰면, DB 테이블에서 언더바로 구분되어 열 이름으로 변환된다
    EX) createDate(java) > create_date(DB)
  • 엔티티를 만들때, Setter 메서드는 권장하지 않는다
    Setter는 DB와 바로 연결되므로 데이터를 자유롭게 변경할 수 있는 Setter 메서드를 허용하는 것은 안전하지 않다

2) 질문 엔티티 만들기

package com.example.sbb;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;
import java.util.List;

@Getter
@Setter
@Entity
public class Answer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(columnDefinition = "TEXT")
    private String content;

    private LocalDateTime createDate;

//    @ManyToOne
//    private Question question;


// answerList 를 Question 엔티티 속성으로 추가하고 @OneToMany 설정 
    @OneToMany(mappedBy = "question", cascade = CascadeType.REMOVE)
    private List<Answer> answerList;

}
  • question : 질문 엔티티 참조
  • @ManyToOne
    • N(답변):1(질문) 관계에 사용
    • question 속성에 추가하여 질문 엔티티와 연결
    • 질문 엔티티와 연결된 속성이라는 것을 답변 엔티티에 표시하는 역할
    • 부모 자식 관계를 갖는 구조에서 사용
      -부모 Question, 자식 Answer
  • @OneToMany
    • 1(질문) : N(답변) 관계에 사용
  • mappedBy : 참조 엔티티의 속성명
    • Answer 엔티티에서 Question 엔티티를 참조한 속성인 question을 mappedBy에 전달
  • CascadeType.REMOVE : 질문을 삭제하면 그에 달린 답변도 모두 삭제되도록 하는 기능

0개의 댓글