[Spring Boot] MongoDB 연동 (+ Docker)

늦잠·2024년 6월 12일
0

목표 : Spring Boot 프로젝트에 MongoDB 연동.
+추가 목표: Docker로 Mongo DB 컨테이너 동작시키기.

대표적인 NoSQL 중 하나인 MongoDB를 프로젝트와 연동해 본다.

NoSQLNot only SQL이란 뜻으로, SQL만을 사용하지 않는 모든 DBMS를 일컫는 말이다. 따라서 NoSQL끼리도 각양각색이다.



MongoDB 설치

MongoDB Comunity Server를 설치한다.

링크 : https://www.mongodb.com/try/download/community

과정 중 MongoDB Compass도 설치할 수 있다.

MongoDB Compass

Compass 설치

우선 MongoDB를 쉽게 사용하기 위한 GUI인 MongoDB Compass를 설치한다.
링크 : https://www.mongodb.com/ko-kr/products/tools/compass

혹은 바로 Docker 컨테이너로 구현해볼 수도 있다.

Connection

설치한 compass를 열고 connection을 생성한다. 기본적으로 root 사용자가 생성되는 MySQL과 달리, 사용자 없이 접속 가능하다.

따로 사용자와 역할 등을 추가하여 사용할 수 있다.


Database 및 Collection 생성

Connect를 눌러 접속에 성공했다면, Databases 옆 + 버튼을 눌러 database 생성해보자.
(collection = MySQL의 테이블)

데이터 넣기

테스트를 위해 simplemongodb라는 database를 만들고, animals라는 collection을 만들었다.
Add data를 눌러 파일이나 json 방식으로 데이터를 넣을 수 있다.

일반적인 관계형 데이터베이스와 다른 NoSQL의 특징을 더 살펴보기 위해, 안에 들어가는 값을 조금 복잡하게 만들었다.

데이터는 animal_type이란 문자열 값을 갖고, 또 data라는 다른 오브젝트가 안에 있다. data 안에는 animal_name이라는 문자열 배열이 들어간다.

_id는 자동생성되는 데이터의 ObjectID이다. 데이터가 생성되는 시간을 기반으로 여러가지 요소로 생성되기 때문에 짧은 시간안에 동시에 데이터가 생성될 경우 낮은 확률로 중복될 가능성이 있다.



Spring Boot에서 연동

의존성

우선 의존성에 MongoDB와의 연결에 필요한 드라이버를 추가한다.

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

아 프로젝트는 uild.gradle 사용하므로 다음을 dependencies에 추가했고,

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <version>3.3.0</version>
</dependency>

maven을 사용할 경우 이런 방식으로 코드를 추가한다.

환경

spring :
	data:
    	mongodb:
      		uri: mongodb://localhost:27017/[db이름]

application.yml에서 다음 코드를 입력해 연결할 mongodb의 uri를 명시한다. 기본적으로 포트 번호 27071에 연결되어 있을 것이다.

spring :
	data:
    	mongodb:
   			port: 27017
      		host: localhost
      		database: simplemongodb

이런 방식으로도 쓸 수 있다.

(application.properties의 경우 spring.data.mongodb.uri=mongodb://localhost:27017/[db이름] )


코드

Document

MongoDB의 document는 MySQL의 Entity에 해당된다.

@Data
@Document(collection = "animals")
public class Animal {
    @Id
    private String id;
    @Field("animal_type")
    private String animalType;
    private SpecificAnimal data;


    public static class SpecificAnimal{
        public List<String> animal_name;
    }
}

animals collection과 매핑될 클래스, Animal이다.

  • @Document 어노테이션을 사용하여 이 클래스가 MongoDB의 collection매핑됨을 표시한다. 괄호 안에 매핑되는 collection 이름을 명시할 수 있다.

  • @Id 어노테이션이 붙은 값은 ObjectID이다. 사용할 수 있는 다른 표현이 몇 개 있는 것 같지만 String id로 쓰는게 가장 간단하니 이걸로 사용하자.

  • @Field 어노테이션을 활용해 매핑되는 필드값의 타입이나 이름을 지정할 수 있다.

collection을 만들 때 보았듯, 데이터 안에 또다른 객체 데이터를 넣어두었다.
이 데이터가 매핑될 클래스 SpecificAnimal도 만든다.

Repository

쿼리를 사용하는 방법 중 가장 간단한 Repository를 이용한 방법을 살펴보자.

public interface AnimalRepository extends MongoRepository<Animal, String> {
    List<Animal> findAnimalsByAnimalType(String animalType);
}

인터페이스를 만들고, MongoRepository를 상속한다. 뒤에 들어가는 <Animal, String>은 각각 매핑되는 document 클래스, ObjectID의 타입이다.

findAnimalsByAnimalType라는 메서드는 animalType으로 검색을 실행한다.
이렇게 메서드의 이름을 통해 쿼리를 실행하게 되는데, 세세한 사용법에 대해선 생략하겠다.

@Query 어노테이션을 통해 보다 직접적인 쿼리도 가능한데, 머리가 아파오므로 나중에 볼 경우를 대비해 링크만 남겨둔다. : https://docs.spring.io/spring-data/data-mongodb/reference/mongodb/repositories/query-methods.html

Service

	public List<String> searchAnimalsByType(String animalType){

        List<String> ret = new ArrayList<>();
        try{
            List<Animal> animals = animalRepository.findAnimalsByAnimalType(animalType);
            for(Animal animal : animals){
                 for(String name : animal.getData().animal_name){
                     ret.add(name);
                 }
            }
        } catch(Exception e){
            e.printStackTrace();
        }
        return ret.size() > 0? ret : null;
    }

Controller

	@GetMapping("/mongodb/search/{animaltype}")
    public ResponseEntity<List<String>> findAnimalsByType(@PathVariable String animaltype){
        List<String> ret = simpleService.searchAnimalsByType(animaltype);

        if(ret == null){
            return ResponseEntity.status(400).body(null);
        }
        return ResponseEntity.status(200).body(ret);
    }

서비스와 컨트롤러에도 코드를 추가해, 입력받은 동물 종류를 검색하여 해당되는 동물 이름을 가져오는 기능을 구현하였다.

테스트 시 잘 실행되는 것을 확인할 수 있다.



Docker 컨테이너

이번엔 MongoDB를 직접 설치해서 사용하지 말고, Docker 컨테이너로 구현해 보자.

docker/docker desktop 설치에 관해서 예전에 썼던 글로 대체한다.

docker desktop을 반드시 설치할 필요는 없다.

우선 기존에 실행되고 있는 MongoDB를 중지해야 된다.
Window를 사용한다면 시작 창 - 서비스에서 MongoDB Server를 찾아 중지한다.

(이제 프로젝트를 실행해 보면 MongoDB와 연결할 수 없다고 에러가 난다.)

컨테이너 생성

docker desktop이 없을 경우

docker search mongo

search로 이미지를 검색할 수 있다.

docker run --name [컨테이너 이름] -d -p 27017:27017 mongo

다음 명령문으로 mongo 컨테이너를 생성 및 실행한다.

  • --name : 컨테이너 이름
  • -d : 백글라운드 실행
  • -p : 컨테이너와 연결할 포트 번호
  • mongo : 이미지 이름.

db의 데이터를 컨테이너 밖에 저장해 두고 싶은 경우 -v 옵션으로 디렉토리를 마운트 해둔다.

docker desktop이 있을 경우

docker desktop이 설치되어 있다면 mongo를 검색하고 pull 버튼을 눌러 이미지를 다운받는다.

images 탭에서 다운받은 mongo 이미지를 실행하여 컨테이너를 생성한다.
컨테이너의 이름을 적고, 컨테이너와 연결될 포트 번호를 지정한다.

컨테이너 접속

MySQL 때와는 달리, 데이터베이스를 생성하지 않고 컨테이너만 실행해도 프로젝트는 잘 실행된다.

테스트를 위해 컨테이너에 접속한다.

docker desktop의 경우, 컨테이너에서 open in terminal을 통해 터미널로 접속할 수 있다.

docker exec it [컨테이너 이름] bash

없을 경우 다음 명령문으로 컨테이너에 접속할 수 있다.

1) mongodb 접속

mongosh

2) 데이터베이스 접속

use [데이터베이스 이름]

3) 컬렉션에서 모든 데이터 탐색

db.[collection 이름].find()

컨테이너에 접속한 후, 다음 명령문으로 데이터를 탐색할 수 있다.

테스트 코드로 데이터를 db에 삽입한 후, db에서 데이터가 잘 들어간 것을 확인했다.

docker로 mongodb 구현 끝!


참고

profile
피카

0개의 댓글