BackEnd/DB

[몽고DB, 스프링부트] Springboot, MongoDB 연동

PgmJUN 2023. 1. 22. 20:51

 

스프링부트 몽고DB 연결

 

 

 

이번 포스팅에선 스프링부트에 스프링 데이터 몽고디비를 사용하여 DB를 연결하고, 간단한 api를 구현하여 연결이 잘 되었는지 테스트해보는 내용에 대해 다뤄보겠습니다.

 

아직 몽고DB에 관하여 공부가 더 필요하기 때문에 우선 간단한 내용과 연결 방법을 소개하고 다음 포스팅에서 몽고디비에 관한 내용만을 다루는 포스팅을 작성하겠습니다.

 

바로 시작하겠습니다.

 

:: Mongo DB ::

 

MongoDB의 기본적인 데이터 구조는 데이터베이스, 컬렉션, 도큐먼트 단위로 관리된다.

 

 

MongoDB 장점

  • Schema-less 구조
    - 다양한 형태의 데이터 저장 가능
    - 데이터 모델의 유연한 변화 가능(데이터 모델 변경, 필드 확장 용이)
  • Read/Write 성능이 뛰어남
  • Scale Out 구조
    - 많은 데이터 저장이 가능
    - 장비 확장이 간단함
  • JSON 구조 :  데이터를 직관적으로  이해 가능 (JSON 형식의 데이터 구조로 문서(Document)에 저장한다.)
  • 사용 방법이 쉽고, 개발이 편리함

 

JSON 구조로 이루어진 MongoDB 데이터

위는 몽고DB에 저장된 예시 데이터의 JSON구조이다.

 

 

MongoDB 단점

  • 데이터 업데이트 중 장애 발생 시, 데이터 손실 가능
  • 많은 인덱스 사용 시, 충분한 메모리 확보 필요
  • 데이터 공간 소모가 RDBMS에 비해 많은(비효율적인 Key 중복 입력)
  • 복잡한 JOIN 사용시 성능 제약이 따름
  • 트랜잭션 지원이 RDBMS 대비 미약함
  • 제공되는 MapReduce 작업이 Hadoop에 비해 성능이 떨어짐

 

 

:: 몽고DB 설치(MacOS) ::

$ brew update # homebrew 업데이트

$ brew tap mongodb/brew # mongoDB 설치 공간 확보

$ brew install mongodb-community # mongoDB 최신버전 설치

$ brew services start mongodb-community # mongoDB 실행

# mongoDB Compass 설치
$ brew --cask install mongodb-compass (만약 cask가 설치가 안되었다면 "$ brew install cask" 수행)

 

 

:: 몽고DB & 스프링부트 연결 ::

 

1. MongoDB 연결

이 글은 로컬 환경(localhost)을 기준으로 설명한다.

MongoDB Compass를 실행후 다음과 같은 URI를 입력해준 후 좌측 하단에 Connect 버튼을 클릭하여 DB에 연결한다.

 

좌측 Databases의 + 버튼을 클릭하여 사용할 Database를 만든다.

 

사용할 DB이름과 기본 컬렉션(테이블)을 입력하여 하나의 데이터베이스를 생성한다.

 

그럼 이렇게 customer라는 컬렉션을 가진 test 데이터베이스가 만들어진다.

이제 Spring에 연결해보자

 

 

2. application.yml 설정

 

spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      authentication-database: admin
      database: test
#uri: mongodb://localhost:27017/test
  • mogodb.host : 접속할 db의 ip 주소
  • mongodb.port : 접속할 db의 port 번호
  • mongodb.authentication-database : 접속할 계정이 위치한 db의 이름
  • mongodb.database : 접속할 database 이름
  • mongodb.username : 접속할 계정 이름
  • mongodb.password : 접속할 계정 비밀번호

 

 

3. build.grade Implement

 

mongoDB만 사용할 때

implementation 'org.springframework.boot:spring-boot-starter-data-mongodb

 

mongoDB 외에 다른 db도 사용하고 싶다면

implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive

 

주의점!!

mongoDB만 사용할 때 mongodb-reactive를 사용하면 스프링 빈 생성 오류가 발생할 수 있다.

 

 

4. Test를 위한 Collection, Controller, Service, Repository 생성

 

 

4-1. Model 객체 생성

 

유저의 성(firstName)과 이름(lastName)을 갖는 Customer 도큐먼트를 정의합시다. DB에 저장될 document의 이름은 @Documemt 애노테이션을 통하여 지정해줍니다. MongoDB의 모든 도큐먼트는 반드시 _id라는 주키를 갖게 됩니다.  @Id 애노테이션은 해당 필드에 대해 주키로 지정하겠다는 의미를 가집니다.

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import studymongodbnosql.springmongo.dto.CustomerResponseDto;

@Document(collection = "customer")
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Customer {

    @Id
    private String id;
    private String firstName;
    private String lastName;

    public Customer(StringfirstName, StringlastName) {
        this.firstName =firstName;
        this.lastName =lastName;
    }

    public CustomerResponseDto toDto() {
        return new CustomerResponseDto(id, firstName, lastName);
    }
}

Spring-Data-JPA 사용 시 @Entity, @Table(name = "테이블명")를 통해 Table과 연결하였지만

Spring-Data-MongoDB 사용 시 @Document(collection= "컬렉션명") 을 통해 Collection과 연결한다.

 

이번 과정에선 아까 MongoDB Compass에서 Database생성 시 collection명을 customer로 생성했기 때문에 collection=”customer” 로 설정한다.

 

 

4-2. DTO 생성

 

CustomerRequestDto

@Getter
@Setter
@AllArgsConstructor
public class CustomerRequestDto {
    private String firstName;
    private String lastName;

    public Customer toEntity() {
        return new Customer(firstName, lastName);
    }
}

 

CustomerResponseDto

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
public class CustomerResponseDto {
    private String id;
    private String firstName;
    private String lastName;
}

아무리 테스트이지만 역할을 확실히 분리하여 구현하기 위해 DTO도 구현해주었다.

DTO를 사용하는 이유

 

 

5. Repository 클래스 생성

 

CustomerRepository

import org.springframework.data.mongodb.repository.MongoRepository;
import studymongodbnosql.springmongo.domain.Customer;

import java.util.List;

public interface CustomerRepository extends MongoRepository<Customer, String> {
    List<Customer> findByFirstName(String firstName);
}

 

MongoTemplate와 MongoRepository

몽고DB는 MongoTemplate 또는 MongoRepository를 사용하여 연동할 수 있다.

MongoTemplate는 MongoRepository보다 더 세부적인 질의가 가능하지만

현재 프로젝트에선 편의성을 고려하여 MongoRepository를 사용하여 구현한다.

 

MongoRepository 인터페이스

생성한 Repository 인터페이스에 MongoRepository<T, ID> 를 extends한다.

제네릭을 뜻하는 T에는 레포지토리와 연결할 Class가 들어가고, ID는 컬렉션에 @Id로 설정한 변수의 자료형이 들어가는데 몽고DB의 Key,Value는 JSON형태로 이루어져 있어서 평균적으로 String이 사용된다.

JpaRepository와 마찬가지로 extends 시에 자동으로 Bean에 등록되기 때문에 @Repository 애노테이션이 필요하지 않다.

DB select 테스트를 위해 MongoRepository의 메서드 naming convention에 맞춰 findByFirstName 메서드를 구현하였다.

 

 

6. Service 클래스 생성

 

CustomerService 객체

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import studymongodbnosql.springmongo.domain.Customer;
import studymongodbnosql.springmongo.dto.CustomerRequestDto;
import studymongodbnosql.springmongo.dto.CustomerResponseDto;
import studymongodbnosql.springmongo.repository.CustomerRepository;

import java.util.ArrayList;
import java.util.List;

@RequiredArgsConstructor
@Service
public class CustomerService {
    private final CustomerRepository customerRepository;

    public CustomerResponseDto saveCustomer(CustomerRequestDtocustomerRequestDto) {
        CustomersavedCustomer= customerRepository.save(customerRequestDto.toEntity());
        returnsavedCustomer.toDto();
    }

    public List<CustomerResponseDto> findCustomerByFirstName(StringfirstName) {
        List<Customer>customerList= customerRepository.findByFirstName(firstName);
        List<CustomerResponseDto>result= new ArrayList<>();
customerList.stream().forEach(c-> {
result.add(c.toDto());
        });

        returnresult;
    }
}

 

DB에 Customer를 저장하는 saveCustomer 메서드와

FirstName으로 Customer를 select하는 findCustomerByFirstName 메서드를 구현하였다.

save 메서드는 MongoRepository에서 기본적으로 지원한다.

컨트롤러에서 클라이언트에게 데이터를 전달할 때 DTO로 전달해야하기 떄문에 Customer 컬렉션에 toDto 메서드를 구현하여 쉽게 ResponseDto로 변환할 수 있도록 하였다.

 

 

7. Controller 클래스 구현

 

CustomerController 객체

import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import studymongodbnosql.springmongo.dto.CustomerRequestDto;
import studymongodbnosql.springmongo.dto.CustomerResponseDto;
import studymongodbnosql.springmongo.service.CustomerService;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/customer")
public class CustomerController {
    private final CustomerService customerService;

    @PostMapping("/save")
    public ResponseEntity<?> saveCustomer(@RequestBody CustomerRequestDtocustomerRequestDto) {
        try {
            System.out.println("customerRequestDto = " +customerRequestDto.getFirstName());
            CustomerResponseDtocustomerResponseDto= customerService.saveCustomer(customerRequestDto);
            return new ResponseEntity<>(customerResponseDto, HttpStatus.OK);
        } catch (Exceptione) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
    }

    @GetMapping("/find/{firstName}")
    public ResponseEntity<?> findCustomerByFirstName(@PathVariable StringfirstName) {
        try {
            List<CustomerResponseDto>customerResponseDtoList= customerService.findCustomerByFirstName(firstName);
            return new ResponseEntity<>(customerResponseDtoList, HttpStatus.OK);
        } catch (Exceptione) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
    }

}

 

위 코드로 컨트롤러를 통해 save와 find RestAPI를 구현하였다.

 

 

8. PostMan으로 Test

 

save API 테스트

Postman 테스트
DB에 저장된 데이터

db에 확실히 저장된 것을 확인할 수 있다.

 

 

select API 테스트

Postman 테스트

firstName을 통해 방금 insert한 데이터를 불러온 것을 확인할 수 있다.

 

 

 

 

 

 

references

https://ckddn9496.tistory.com/100

 

MongoRepository를 이용한 MongoDB와 Spring boot 연동

SpringBoot와 MongoDB를 연결하고 MongoRepository를 사용해보자. 의존성 주입 pom.xml에 spring-boot-starter-data-mongodb를 추가합니다. org.springframework.boot spring-boot-starter-data-mongodb MongoDB 접속 정보 세팅 application.ym

ckddn9496.tistory.com

https://freedeveloper.tistory.com/341

 

[MongoDB] 카카오와 MongoDB 내용 정리

MongoDB tv.kakao.com/v/414072595 MongoDB 특징 신뢰성(Reliability): 서버 장애에도 서비스는 계속 동작 Primary 와 Secondry로 구성된 ReplicaSet 구조로 고가용성을 지원 확장성(Scalability): 데이터와 트래픽 증가에

freedeveloper.tistory.com

https://tychejin.tistory.com/349

 

[MongoDB] MongoDB 장점/단점

MongoDB 장점 Schema-less 구조 - 다양한 형태의 데이터 저장 가능 - 데이터 모델의 유연한 변화 가능(데이터 모델 변경, 필드 확장 용이) Read/Write 성능이 뛰어남 Scale Out 구조 - 많은 데이터 저장이 가능

tychejin.tistory.com