project

[나만의 웹사이트를 만들어보자] 4. PostgreSQL을 Spring Boot와 연동하기 (Spring Boot + React + PostgreSQL)

나홀로전세집 2024. 6. 25. 21:59
728x90
반응형

안녕하세요 나홀로전세집입니다.

 

지난 시간에는 PostgreSQL을 설치을 해봤습니다.

이번 시간에는 PostgreSQL을 Spring Boot와 연동해보겠습니다.

 

PostgreSQL을 Spring Boot와 연동하기 위해서 JPA와 JDBC를 사용할 것 입니다.

 

JPA 란?

JPA는 Java Persistence API의 줄임말로 자바 애플리케이션에서 데이터베이스와의 상호작용을 표준화하는 API입니다.

 

JDBC 란?

JDBC는 Java Database Connectivity의 줄임말로 자바에서 데이터베이스에 연결하고 SQL 쿼리를 실행할 수 있게 하는 API입니다.

 

Spring Boot 에서 JPA와 JDBC를 사용하는 법

Spring Boot 에서 JPA와 JDBC를 사용하는 방법은 간단합니다. 

build.gradle의 dependencies 부분에 필요한 의존성을 추가하면 됩니다.

https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa - JPA

https://mvnrepository.com/artifact/org.postgresql/postgresql - JDBC

 

아래 링크로 들어가면 다음과 같은 화면이 나오게 됩니다.

본인이 사용하려는 버전을 선택합니다. 저는 3.3.1 버전을 사용했습니다.

 

Gradle(Short) 를 클릭한 후 아래 implementation로 시작하는 문장을 복사합니다.

 

그 후 프로젝트의 build.gradle의 dependencies 에 추가해줍니다.

JDBC도 같은 방법으로 하시면 됩니다.

 

저는 lombok 이란 의존성도 추가해줬습니다.

lombok 이란?

lombok은 반복되는 코드인 getter, setter, 생성자, toString, 등을 자동으로 생성해줍니다.

lombok을 통해 나중에 사용 할 getter, setter 코드 반복을 줄여줄 것 입니다.

 

다음과 같이 의존성을 추가했습니다.

 

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
	
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.3.1' // JPA를 사용하기 위한 의존성
    implementation 'org.postgresql:postgresql:42.7.3' // PostgreSQL JDBC 드라이버 의존성

	implementation 'org.projectlombok:lombok:1.18.32' // Lombok 의존성 버전 명시
    annotationProcessor 'org.projectlombok:lombok:1.18.32' // Lombok 어노테이션 프로세서 버전 명시

    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
 	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

 

여기서 어노테이션은 처음 들어보는 단어일 수 있습니다.

 

어노테이션이란?

어노테이션은 코드에 대한 추가 정보를 제공하는 특수한 형태의 주석입니다. 어노테이션을 사용하여 컴파일러에게 정보를 제공하거나 런타임 시 특정 동작을 수행하도록 지시할 수 있습니다. 자바에서 @Override 가 어노테이션 중 하나입니다.

 

lombok 어노테이션을 사용하여 getter와 setter를 자동으로 만들 수 있게 할 수 있습니다.

 

 

지금까지 Spring Boot가 PostgreSQL을 접근할 수 있게 했습니다.

Spring Boot가 어디에 있는 PostgreSQL에 접근할 지 설정줘야 합니다.

 

PostgreSQL의 위치는 application.properties 에 작성하게 됩니다.

 

다음과 같이 추가하면 됩니다.

 

데이터베이스에 잘 접근했는지 확인하기 위해서는 MVC 패턴을 사용하여 확인하면 됩니다.

 

MVC 패턴은 https://na-hollo.tistory.com/15 에서 확인할 수 있습니다.

 

Spring Boot에서 MVC 패턴을 사용하기 위해선 

컨트롤러 (controller)

서비스 (service)

리포지토리 (repository)

엔티티 (entity)

가 필요합니다.

 

Spring Boot 폴더에 다음과 같은 폴더와 파일을 만들어주면 됩니다.

각 폴더는 ~~~Application.java와 같은 위치에 만들면 됩니다.

 

 

각각의 계층이 무엇을 하는지 설명해드리겠습니다.

컨트롤러 (Controller)

컨트롤러는 클라이언트의 요청을 받아서 처리하는 계층입니다. 주로 HTTP 요청을 받아서 

적절한 서비스를 호출하고, 그 결과를 클라이언트에게 반환합니다.
컨트롤러를 사용하면 웹 요청과 비즈니스 로직을 분리할 수 있습니다. 

이렇게 하면 웹 요청 처리와 비즈니스 로직이 독립적으로 관리될 수 있어 유지보수가 쉬워집니다.

서비스 (Service)

서비스는 비즈니스 로직을 처리하는 계층입니다. 컨트롤러가 요청을 받으면, 그 요청을 처리하기 위해 

필요한 비즈니스 로직을 실행합니다. 서비스는 리포지토리와 상호작용하여 데이터를 가져오거나 저장합니다.
서비스 계층을 사용하면 비즈니스 로직을 독립적으로 관리할 수 있습니다. 

이렇게 하면 비즈니스 로직이 복잡해지더라도 코드의 가독성과 유지보수성이 향상됩니다.

리포지토리 (Repository)

리포지토리는 데이터베이스와의 직접적인 상호작용을 담당하는 계층입니다. 

JPA 리포지토리를 사용하면 데이터베이스 CRUD(Create, Read, Update, Delete) 작업을 쉽게 수행할 수 있습니다.
리포지토리를 사용하면 데이터 접근 로직을 독립적으로 관리할 수 있습니다.

이렇게 하면 데이터베이스 변경이 발생해도 비즈니스 로직에 미치는 영향을 최소화할 수 있습니다.

엔티티 (Entity)

엔티티는 데이터베이스 테이블과 매핑되는 클래스입니다. 주로 데이터베이스 테이블의 구조를 정의하고, 

테이블의 각 행을 객체로 표현합니다.
엔티티를 사용하면 객체 지향 프로그래밍 언어의 객체를 데이터베이스 테이블에 매핑할 수 있습니다. 

이렇게 하면 데이터베이스 작업이 더욱 직관적이고 쉽게 이루어질 수 있습니다.

DTO (Data Transfer Object)

DTO는 계층 간 데이터 전송을 위해 사용하는 객체입니다. 주로 컨트롤러와 서비스 간 또는 서비스와

외부 API 간의 데이터를 주고받을 때 사용됩니다.

DTO는 엔티티와 달리 데이터베이스의 구조와 무관하게 필요한 데이터만을 포함합니다.

 

현재 만들고 있는 프로젝트의 구조를 그림으로 보여드리겠습니다.

컨트롤러는 클라이언트의 HTTP 요청을 받습니다.
컨트롤러는 서비스를 호출하여 비즈니스 로직을 처리합니다.
서비스는 리포지토리를 호출하여 데이터베이스와 상호작용합니다.
리포지토리는 엔티티를 사용하여 데이터베이스의 테이블과 상호작용합니다.
결과가 서비스를 통해 컨트롤러로 반환되고, 컨트롤러는 이를 클라이언트에게 반환합니다.

 

 

오늘 간단하게 구현할 컨트롤러, 서비스, 리포지토리에는 DTO를 사용하지 않을 것 입니다.

그림에는 DTO가 있는데 현재 만들어진 프로젝트에 DTO가 없는 이유에 대해 설명해드리겠습니다.

 

현재 DTO를 사용하지 않은 이유는 데이터 전송 과정이 간단하고, 추가 처리가 필요없기 때문입니다. 그렇기 때문에 엔티티를 직접 사용하는 로직으로 구현했습니다.

추후에 데이터 유효성 검사가 필요할 때 DTO를 사용해보겠습니다.

 

아래에서 각각의 컨트롤러, 엔티티, 리포지토리, 서비스 코드를 보여드리겠습니다.

 

 

TempController.java

package com.nahollo.nahollo.Project.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.nahollo.nahollo.Project.entity.Temp;
import com.nahollo.nahollo.Project.service.TempService;

// 웹 요청을 처리하는 컨트롤러 클래스
@RestController
public class TempController {

    private final TempService tempService;

    // TempService를 주입받는 생성자
    @Autowired
    public TempController(TempService tempService) {
        this.tempService = tempService;
    }

    // HTTP GET 요청을 처리하는 메서드
    @GetMapping("/temp")
    // Temp 엔티티를 생성하고 저장한 후 반환
    public Temp createTemp() {
        return tempService.createTempRecord();
    }
}

 

Temp.java

package com.nahollo.nahollo.Project.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
// import lombok.Data;
import lombok.Data;

// 데이터베이스 테이블과 매핑되는 클래스
@Entity
// Data는 Lombok 어노테이션으로, 게터, 세터, toString, equals, hashCode 메서드를 자동으로 생성
@Data
public class Temp {
    // @Id: 기본 키(primary key)로 사용될 필드임을 나타냄
    // @GeneratedValue: 이 필드의 값을 자동으로 생성하도록 지정
    // strategy = GenerationType.IDENTITY: 데이터베이스의 IDENTITY 컬럼을 사용하여 기본 키 값을 자동 생성
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)

    // 데이터베이스의 id, confirm 컬럼과 매핑되는 필드
    private Long id;

    private Boolean confirm;

    // lombok을 사용하지 않으면 getter, setter을 생성해야됨.
}

 

TempRepository.java

package com.nahollo.nahollo.Project.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.nahollo.nahollo.Project.entity.Temp;

// JpaRepository를 상속받아 Temp 엔티티에 대한 CRUD 작업을 처리하는 리포지토리 인터페이스
public interface TempRepository extends JpaRepository<Temp, Long> {
}

 

TempService.java

package com.nahollo.nahollo.Project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.nahollo.nahollo.Project.entity.Temp;
import com.nahollo.nahollo.Project.repository.TempRepository;

// 서비스 계층을 나타내는 어노테이션
@Service
public class TempService {

    private final TempRepository tempRepository;

    // TempRepository를 주입받는 생성자
    @Autowired
    public TempService(TempRepository tempRepository) {
        this.tempRepository = tempRepository;
    }

    // Temp 엔티티를 생성 후 confirm 필드를 true로 저장
    public Temp createTempRecord() {
        Temp temp = new Temp();
        temp.setConfirm(true);
        return tempRepository.save(temp);
    }
}

 

 

다음과 같이 작성하면 됩니다.

 

코드리딩을 한번 해보시면 컨트롤러 ↔️ 서비스 ↔️ 리포지토리 인 것을 알 수 있을 것 입니다.

 

다음과 같이 작성 후 다시 서버를 켜보면

다음과 같이 서버가 잘 켜지는 것을 볼 수 있습니다.

 

이제 psql 을 사용해서 데이터베이스에 잘 접근을 하는지 확인해보겠습니다.

 

이 상태에서 \c temp 를 입력하여 temp 데이터베이스에 접근합니다.

 

접근이 되면 \dt 를 통해 temp 데이터베이스를 확인할 수 있습니다.

 

 

이 상태에서 서버가 켜져있을 때 크롬에서 http://localhost:8080/temp 를 입력하면 

 

다음과 같은 화면이 나옵니다. 

이 화면이 나오게 되면 데이터베이스에 값이 잘 전달이 된 것입니다.

다시 psql로 돌아가서

SELECT * from temp; 를 입력하면

temp 에 입력되어있는 값을 볼 수 있습니다.

방금 http://localhost:8080/temp에 접속한 것으로 id와 confirm 이 생긴 것입니다.

 

이렇게 되면 Spring Boot와 PostgreSQL이 연동된 것입니다.

다음 시간에는 React 템플릿을 가져와서 적용해보겠습니다.

 

오늘도 즐코딩 하시고 좋은 하루 되세요~

 

728x90
반응형