국비학원 42일차 : Spring Boot_4

Digeut·2023년 4월 24일
0

국비학원

목록 보기
36/44

Service

비즈니스 계층

  • 상황에 따라 서비스 계층이라고도 한다.
  • 핵심 비즈니스 계층이라고도 한다.
  • 트랜잭션 처리나 유효성 검사 등의 작업도 수행한다.

RestApiService

public ⭐interface RestAPIService {
    
    public String getMethod();

    public String postMethod();
    public String patchMethod();
    public String deleteMethod();

    //기능에 대한걸 선언만 해두는것
    //구현은 Implements에 진행하게 된다.
    //반환되어야 할 인풋과 아웃풋만 정의해서 정의를 해준다. 
    //서비스를 구현하고 독립적으로 진행되게 된다.
    //서비스나 레포지토리 만들때는 인터페이스 만들어서 적용해준다.
}

RestApiServiceImplements

//@Component //Ioc 이용한 DI사용가능하다
@Service // Component와 동일한데 이름을 정확하게 지정해주는것
public class RestApiServiceImplement implements RestAPIService { //구현체
    
    public String getMethod(){
        return "Return to Service Rayer";
    }
    public String postMethod(){
        return "Return to Service Rayer";
    }
    public String patchMethod(){
        return "Return to Service Rayer";
    }
    public String deleteMethod(){
        return "Return to Service Rayer";
    }
}

RestApiController

public class RestAPIController {

    // private RestApiServiceImplement restApiService =
    //     new RestApiServiceImplement(); 
    //의존성을 컨트롤러에 직접 만들어 사용, RestAPIController이 종속되어 버린다. 
    //의존성이 이렇게 직접 만들어져있으면 하나의 서비스만 잘못되도 
    //다른 서비스들 다 사용이 불가하다 Ioc 주입해서 사용하기
    
    //@Autowired
    private RestAPIService  restApiService; 
    //이렇게 만들면 무조건 🌷@Autowired붙여야함 , 안적으면 적용안된다.

    public RestAPIController(RestAPIService restApiService){ 
    //RestApiServiceImplements가 아니고 RestAPIService을 참조하게함
        this.restApiService = restApiService; 
        //Autowired 지우고 생성자에 주입하는 방법. 
        //@Autowired가 필수로 적어야할 필요가없다
        //의존성 주입해준다. // 내용물이 만들어지지 않으면 우리가 쓸수 없다. 
        //문제가 발생하면 실행이 안되게된다.
        //그래서 참조파일을 implement가 아닌
        //interface로 적용시킨다. (의존성 역전의 원칙 적용)
    }

@Service

해당 클래스를 Spring Bean으로 생성해주는 어노테이션이다. @Component로 사용되긴 하지만 해당 클래스가 Service를 담당한다는 것을 직접적으로 보여주기 위하여 Service라는 이름을 사용한다.

@Autowired

Spring context에 등록한 Spring Bean을 IoC를 통해 DI를 수행하는 어노테이션이다.

→ 🌷어노테이션 지정하지 않을 경우에는 실행이 되지 않는다.

Parameter 0 of constructor in com.**.firstproject.controller
.RestAPIController required a bean of type 'com.**.firstproject.service
.implement.RestApiServiceImplement' that could not be found.

이런 오류 뜨면 내가 어노테이션 입력하지 않은거라고 생각하고 수정하기

어노테이션 입력하지 않았을 경우 오류화면

인터페이스로 작성한 후 상위 모듈에서 인터페이스를 참조하는 이유

객체지향 5원칙 (SOLID) 중 DIP (Dependency Inversion Principle, 의존성 역전의 원칙)을 수행하기 위하여 인터페이스를 참조하도록 한다. DIP는 높은 수준의 모듈이 낮은 수준의 모듈에 직접 의존하는 것을 방지하고, 추상화를 통해 의존하도록 함으로써, 소프트웨어 구성 요소 사이의 결합도를 낮추는 작업이다.

이를 적용함으로써 낮은 결합도, 재사용성 향상, 유지보수성 향상을 구축할 수 있다. 즉, 구체적인 구현 대신 인터페이스를 정의하고, 상위 수준의 모듈이 인터페이스를 통해 하위 수준의 모듈과 상호작용할 수 있도록 한다. 이를 통해, 하위 수준 모듈의 변경이 상위 수준 모듈에 영향을 미치지 않게 할 수 있다.

높은 수준의 모듈이 낮은 수준의 모듈을 직접 의존하지 못하도록 막는것. 그래서 추상화를 통해서 의존하도록 하고 결합도는 낮추도록하는것

JPA & Repository

서버 올려서 다른 클라이언트로부터 입력받아 회원가입 만든다고 할때
입력을 받아서 데이터베이스에 저장을 해야한다.
DB에 저장을 하려면 was가 DB랑도 연결이 되야한다.
→ 이런 작업을 도와주는게 ORM

ORM

ORM은 "객체-관계 매핑(Object-Relational Mapping)"의 약자로, 객체 지향 프로그래밍과 관계형 데이터베이스 간의 상호 작용을 처리하는 프로그래밍 기술입니다. 자바와 같은 객체지향 언어에서 의미하는 객체와 RDBMS의 테이블을 자동으로 매핑하는 방법입니다.

ORM은 객체 지향 프로그래밍에서 사용되는 클래스, 객체, 메서드 등의 개념을 사용하여 데이터베이스를 조작할 수 있도록 합니다. 즉, 개발자는 SQL 쿼리를 작성하고 데이터베이스 스키마를 설계하는 번거로운 작업을 하지 않아도 됩니다. DB의 테이블과 자바의 class를 동일시 시켜줍니다.
클래스는 데이터베이스의 테이블과 매핑하기 위해 만들어진 것이 아니기 때문에 RDBMS의 테이블과 불일치가 발생하는데, ORM은 이러한 불일치와 제약사항을 해결하는 기능을 제공해 줍니다.

ORM을 사용하면 데이터베이스에서 데이터를 가져오는 것이 간단하고, 개발자는 객체를 사용하여 데이터를 조작할 수 있습니다. 또한 ORM은 데이터베이스와 애플리케이션 코드 사이의 인터페이스를 제공하여 데이터베이스 변경에 대한 코드 변경을 최소화할 수 있습니다.

ORM은 다양한 프로그래밍 언어에서 사용될 수 있으며, 대표적인 예로는 Java에서는 Hibernate, Python에서는 Django ORM, Ruby에서는 ActiveRecord 등이 있습니다.

ORM 장점

  • 개발 속도 향상: ORM은 데이터베이스와 객체 간의 매핑을 자동화하므로, 개발자는 SQL 쿼리를 작성하지 않아도 되어 개발 속도를 향상 시킬수 있다.

  • 코드 재사용성: ORM을 사용하면 데이터 접근 코드를 모듈화하여 재사용할 수 있다. 이를 통해 코드 중복을 제거하고 유지보수를 용이하게 할 수 있다.

  • 데이터베이스 추상화: ORM은 데이터베이스 시스템 간의 차이를 추상화하여, 애플리케이션을 다양한 데이터베이스에서 사용할 수 있게 한다.

  • 객체지향적 설계: ORM을 사용하면 객체지향적 설계 원칙에 따라 데이터 모델을 작성할 수 있다. 이는 코드의 가독성과 유지보수성을 향상시킨다.
    → 객체지향의 특징까지 가져간다

다른 DB를 사용하게 되면 클래스를 바꿀 필요없이 db만 바꾸면 되게 된다.

ORM 단점

  • ⚠️성능 저하: ORM은 추상화 계층을 추가하므로, SQL 쿼리보다 더 많은 오버헤드가 발생할 수 있다. 이로 인해 성능이 저하될 수 있다.

  • 복잡한 쿼리 제한: ORM은 일반적인 CRUD 작업에 최적화되어 있지만, 복잡한 쿼리나 데이터베이스 특화 기능에 대한 지원이 제한적이다. 추가적인 연산작업을 할수 없게된다

  • 학습 곡선: 개발자는 ORM 도구의 사용 방법과 동작 원리를 익혀야 한다. 이로 인해 학습에 많은 시간을 투자해야 한다.

  • 결합도 증가: ORM을 사용하면 데이터 모델과 데이터베이스 구조 간의 결합도가 증가한다. 이는 데이터베이스 구조 변경과 같은 작업에 제약이 따를 수 있다. 애초에 맵핑시켜 결합하는거라 결합도가 증가할수 밖에 없고 둘 중에 하나라도 오타가 있으면 안된다 데이터 타입바꾸거나 이름살짝 바꾸는게 어려워지게 된다. DB만 바꿨는데 서버가 다운되는경우가 생기게된다.

❔이런 단점에도 불구하고 왜 사용하는가
개발 속도 향상이라는 장점이 매우 크기때문에 사용하게 된다. 성능 저하의 문제도 복잡한 SQL구문을 쓰는 경우가 거의 없기때문에 크게 와닿지 못하고, 결합도 증가의 문제는 DB구조와 테이블의 필드명 등은 한번 설정하면 바꾸지 않는게 좋도록 설계를 하기때문에 이 문제 또한 생길일이 줄어들게 된다.

JPA

java에서 제공해주는 ORM = JPA

Java Persistence API로 사용하여 관계형 데이터베이스의 데이터에 접근하고 조작할 수 있는 기능을 제공한다. Java에서 ORM을 구현하는 표준 '인터페이스' Hibernate와 같은 구현체를 사용할 수 있다. Spring Data JPA는 개발자가 데이터 액세스 계층을 손쉽게 구현할 수 있도록 지원한다. 우리가 구현하지는 않고 선언만 하게된다!

저장소 인터페이스 추상화: 개발자는 간단한 인터페이스를 정의하고, Spring Data JPA가 이를 구현하여 기본 CRUD 작업을 처리한다. 이를 통해 개발자는 반복적인 코드 작성을 피할 수 있다.

쿼리 메서드: 저장소 인터페이스에 메서드를 정의하고, 메서드 이름을 통해 쿼리를 생성할 수 있다. 이를 통해 간단한 데이터베이스 검색 작업을 수행할 수 있다.

페이징 및 정렬: Spring Data JPA는 쿼리 결과의 페이징 및 정렬을 쉽게 처리할 수 있는 기능을 제공한다.

JPA 구현체와의 통합: Spring Data JPA는 Hibernate, EclipseLink 등 다양한 JPA 구현체와 통합할 수 있다.

트랜잭션 관리: Spring 프레임워크의 트랜잭션 관리 기능과 결합하여, 데이터베이스 트랜잭션을 간편하게 관리할 수 있다.

Hibernate

Java 객체와 관계형 데이터베이스 간의 매핑을 처리하는 JPA 구현체이다.

Persistence (구현 해놓은게 DB)

지속성이라는 뜻으로, 데이터를 영구적으로 저장하고, 애플리케이션의 실행이 종료된 후에도 사용 가능한 상태로 유지하는 것을 의미한다.

//JPA gradle 의존성 주입
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

JPA gradle 의존성 주입까지만 하고 나서의 오류

JPA는 DB에 연결이 된상태로 해야하는데 그게 지금 연결이 되어있지않아서 연결을 실패했다고 뜨는것. 서버를 가동하는 순간부터 정상DB에 연결을 해야한다!

//MySQL Connector gradle 의존성 주입
runtimeOnly 'com.mysql:mysql-connector-j'

이것까지 입력하면 mySQL에서 연결할수있게된다. 이렇게만 지정해둬도 쓸수있게된다. 하지만 이렇게 해도 실행은 안된다. 어떤 DB에 연결할지 어떤 서버에 어떤 이름으로 어떤 pw로 접근해야하는지 명시를 해줘야한다!



application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://호스트:포트(DB의)
		/데이터베이스이름?serverTimezone=UTC&characterEncoding=UTF-8
spring.datasource.username=아이디
spring.datasource.password=비밀번호

DB를 만들기 전에 나타나는 오류 문구

MySQL에 DB를 만들어주게된다.

Entity

(SQL의 테이블과 연결을 하는 방법)
JPA를 사용하고자 할때 데이터베이스 테이블과 매핑되는 Java객체이다. 각 Entity 인스턴스는 데이터베이스 테이블의 하나의 레코드에 해당하며, 이를 통해 데이터베이스와 객체지향 프로그래밍 사이의 데이터 변환을 처리한다. Entity 클래스는 JPA를 사용하여 데이터베이스와의 상호 작용을 추상화하고, 데이터베이스의 테이블과 객체지향 코드를 쉽게 연결할 수 있다.

생성한 SQL 데이터베이스, 테이블

ExampleEntity

@AllArgsConstructor
@NoArgsConstructor
@Entity(name="Example") 
//name을 이 이름으로 사용할수 있게 지정, DB에서는 해당테이블 못찾는다..! 
//테이블 어노테이션 추가
@Table(name="Example") //테이블 찾아오게 함
//DB의 여러 제약조건에서 기본키는 만드시 있어야한다! → 지정하는 어노테이션이 따로 있다.
//java에서는 보통 카멜케이스로 네이밍규칙. 띄어쓰기다음에 오면 대문자로 함 
// db에서는 띄어쓰기 _로하고 소문자로해야 서로 인식함!
public class ExampleEntity { 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    //다른 제약조건을 설정하려면 @Column사용해서 지정함
    @Column(name="example_column1", nullable = false, unique = true)
    private int pk; 
    private String exampleColumn2;
    private boolean exampleColumn3;
}

@Entity

Java 클래스를 JPA Entity로 표시하여 해당 클래스를 데이터베이스의 테이블과 매핑할 수 있도록 한다. ORM을 설정해주는것이다. 이를 이용해서 두 프로그램사이의 데이터를 하나로 정의해줄수 있다.

@Table

JPA Entity 클래스와 데이터베이스 테이블간의 매핑을 설정하거나 수정할 때 사용된다. 기본적으로 JPA는 Entity 클래스의 이름을 사용하여 데이터베이스 테이블 이름을 유추하지만 @Table 어노테이션을 이용하면 Entity와 Table을 명시적으로 지정할 수 있다. 직접 지칭해서 가져오라고 할 수 있다.

@Table 속성

name: 엔티티와 매핑할 데이터베이스 테이블의 이름을 지정합니다.

schema: 테이블이 속한 스키마를 지정합니다. 이 속성은 선택 사항이며, 데이터베이스에서 스키마를 사용하는 경우에만 필요합니다.

spring.datasource.url=jdbc:mysql://localhost:3306/⭐DB명serverTimezone=UTC&characterEncoding=UTF-8

//⭐이 부분 DB명 지정하지 않고 사용시 특정 스키마를 지정해줘야한다

catalog: 테이블이 속한 카탈로그를 지정합니다. 이 속성은 선택 사항이며, 데이터베이스에서 카탈로그를 사용하는 경우에만 필요합니다.

uniqueConstraints: 테이블에 적용할 고유 제약 조건을 지정합니다. 이 속성은 선택 사항이며, 고유 제약 조건이 필요한 경우에만 사용합니다.

@Id

JPA Entity 클래스에서 Primary Key에 해당하는 필드를 표시하는 데 사용된다. Entity 클래스에 필수로 하나 이상 포함해야 한다.

@GeneratedValue

Primary Key는 데이터베이스에서 자동으로 생성되는 경우가 있는데, 이를 위해 @GeneratedValue 어노테이션을 함께 사용할 수 있다. @GeneratedValue은 GenerationType 열거형을 사용하여 기본 키 값 생성 전략을 지정할 수 있다.

GenerationType의 주요 전략

GenerationType.AUTO: JPA 프로바이더가 자동으로 값을 생성한다. 이 전략은 데이터베이스에 따라 적절한 전략을 선택한다(예: 시퀀스, IDENTITY, 테이블 등). auto_inclement 적용시킬때 사용한다.

⭐GenerationType.IDENTITY: 데이터베이스의 IDENTITY 열을 사용하여 값을 생성한다. 데이터베이스가 자동 증가 열을 지원하는 경우 이 전략이 사용된다.

GenerationType.SEQUENCE: 데이터베이스의 시퀀스를 사용하여 값을 생성한다. 이 전략은@SequenceGenerator 어노테이션을 사용하여 시퀀스 이름과 초기값 등을 설정할 수 있다.

GenerationType.TABLE: 키 생성 테이블을 사용하여 값을 생성한다. 이 전략은 @TableGenerator 어노테이션을 사용하여 키 생성 테이블, 초기값 등을 설정할 수 있다. 키 생성시 테이블 참조해서 만들도록 한다.

@Column

Entity 클래스의 필드와 데이터베이스 테이블의 필드간의 매핑을 설정하거나 수정하는 데 사용된다. 기본적으로 JPA는 엔티티 클래스의 필드 이름을 사용하여 데이터베이스 테이블의 열 이름을 자동으로 유추하지만, @Column 어노테이션을 사용하면 클래스의 필드와 데이터베이스 테이블의 필드 간의 매핑을 명시적으로 지정하거나 필드의 속성을 변경할 수 있다. 찾아올때 네이밍규칙따라서 작성해야하는데 이걸 사용하면 규칙무시하고 다 가져올수 있다.

@Column 속성

name nullable unique 정도만 사용하게 된다

  • name: 매핑할 데이터베이스 열의 이름을 지정합니다.
  • nullable: 열이 NULL 값을 허용하는지 여부를 지정합니다. 기본값은 true입니다.
  • unique: 열 값이 고유해야 하는지 여부를 지정합니다. 기본값은 false입니다.
  • insertable: 열이 INSERT 문에 포함되어야 하는지 여부를 지정합니다. 기본값은 true입니다.
  • pdatable: 열이 UPDATE 문에 포함되어야 하는지 여부를 지정합니다. 기본값은 true입니다.
  • columnDefinition: 데이터베이스 열의 DDL 정의를 지정할 수 있습니다. 이 속성은 데이터베이스 벤더에 따라 다르게 해석될 수 있습니다.
  • length: 문자열 열의 최대 길이를 지정합니다. 기본값은 255입니다.
  • precision과 scale: 숫자 열에 대한 정밀도와 스케일을 지정합니다. 이러한 속성은 주로 BigDecimal 필드에 사용됩니다.

Repository

Repository 레이어는 Spring 레이어드 아키텍처에서 데이터 접근 영역에 해당한다. DB에 접근해서 작업하는것들을 이곳에서 작업한다. CRUD작업 또는 쿼리문 실행을 하게 된다

ExampleRepoistory

@Repository
public interface ExampleRepository ⭐extends 
					JpaRepository<ExampleEntity, Integer>{
    							//Entity Class , data Type
    //메서드 정의하는 공간에 규칙만 잘 따라서 작성하면 쿼리문 생성없이 바로 할 수있다.
}

Repository에 대한 구현체(implements)는 생성하지 않는다. jpa가 알아서 만들기 때문에! jpa 라이브러리를 구현 말고 상속을 해서 사용해야한다!!

@Repository

해당 클래스를 Spring Bean으로 생성해주는 어노테이션이다. @Component로 사용되긴 하지만 해당 클래스가 Repository를 담당한다는 것을 직접적으로 보여주기 위하여 Repository라는 이름을 사용한다.

JpaRepository 인터페이스

JPA 기반 Repository를 구현하는 데 사용되는 주요 인터페이스이다. PagingAndSortingRepository
및 CrudRepository 인터페이스를 확장하고, 추가적으로 JPA 관련 기능들을 제공한다. Repository를 생성할 때 필수로 상속 받아 작성해준다.

JpaRepository 인터페이스의 주요 기능

기본 CRUD 연산: 저장, 검색, 업데이트 및 삭제 기능을 포함하여 일반적인 데이터 액세스 작업을 수행할 수 있는 메서드를 제공합니다.

페이징 및 정렬: 페이징 및 정렬 기능을 지원하여 대량 데이터 집합을 관리할 수 있는 메서드를 제공한다.

JPA 관련 추가 기능: 엔티티 관리자, 플러시 모드, 트랜잭션 등과 같은 JPA 관련 설정 및 기능에 대한 액세스를 제공한다.

ORM의 가장 좋은 장점 = 쿼리문을 작성하지 않아도 된다.

JpaRepository 인터페이스 상속 방법

  • 특정 Entity에서 사용할 Repository 인터페이스를 생성하고 JpaRepository를 상속받는다.

  • JpaRepository 인터페이스의 제너릭 유형에 첫번 째 매개타입으로 엔터티 클래스, 두 번째 매개타입으로 해당 엔터티의 기본키 타입을 지정한다.

profile
개발자가 될 거야!

0개의 댓글