몽고디비 (2)

이번 프로젝트에서는 Java + SpringBoot + Mongo DB 로 구현할 예정입니다.

각각 사용할 버전은 다음과 같습니다.

 

- Java 8 (오라클jdk가 상용목적으로는 유료화되어 추후 코틀린으로 변경하는 프로젝트를 진행해봐야겠네요)

- Springboot 2.4.0 (20년 11월 현재 최신버전)

- Mongo DB 4.4.2 Community Server (20년 11월 현재 최신버전)

 

몽고디비 설치 관련해서는 몽고DB 최신버전 설치하기 포스팅을 참고하시면 됩니다.

설치 후 사용자 계정 생성 및 데이터 베이스 생성 관련해서는 [몽고DB] 기본명령어 포스팅을 참고해주세요.

 

이제 그래들 자바 프로젝트를 하나 생성하여 Blog > 다이어리 메뉴에서 사용할 CRUD를 순서대로 작성해보겠습니다.

가장 먼저 프로젝트 구성을 한번 살펴보겠습니다.

블로그 만들기 백엔드 프로젝트

 

우선 build.gralde파일을 아래와 같이 작성했습니다.

plugins {
    id "org.springframework.boot" version "2.4.0"
    id 'java'
}

group 'com.keichee'
version '1.0-SNAPSHOT'
sourceCompatibility = "1.8"

repositories {
    jcenter()
}

ext {
    springVersion = '2.4.0'
}

dependencies {
    testImplementation group: 'junit', name: 'junit', version: '4.12'

    implementation 'org.mongodb:mongodb-driver-sync:4.1.1'
    testImplementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'

    implementation "org.springframework.boot:spring-boot-starter-web:$springVersion"
    testImplementation("org.springframework.boot:spring-boot-starter-test:$springVersion") {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }

    compileOnly 'org.projectlombok:lombok:1.18.16'
    annotationProcessor 'org.projectlombok:lombok:1.18.16'

    testCompileOnly 'org.projectlombok:lombok:1.18.16'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.16'

    implementation "io.springfox:springfox-boot-starter:3.0.0"
    implementation 'io.springfox:springfox-swagger-ui:3.0.0'

    implementation 'com.google.guava:guava:30.0-jre'
}

test {
    useJUnitPlatform()
}

 

mongodb-driversync 4.1.1 을 사용했습니다.

로깅을 위해서 logback-classic을 추가했고 

api 를 쉽게 만들 수 있도록 spring-boot-starter-web을 추가

getter, setter 등의 어노테이션 사용을 위해 lombok 라이브러리를 추가하였고

스웨거 문서를 사용하려고 springfox 라이브러리들도 추가했습니다.

 

이제 몽고DB와 연결을 위한 설정을 아래와 같이 해줍니다.

@Configuration
public class MongoConfig {

    private static final String host = "localhost";
    private static final int port = 27017;
    private static final String database = "blogapp";

    @Bean
    public MongoDatabase blogAppDatabase() {
        MongoClient client = MongoClients.create(
                MongoClientSettings.builder()
                        .applyToClusterSettings(builder ->
                                builder.hosts(Collections.singletonList(new ServerAddress(host, port))))
                        .build());
        return client.getDatabase(database);
    }
}

 

컨트롤러에는 딱 4개의 Restful API를 만들었습니다.

@Slf4j
@RestController
@RequestMapping("/diary/life")
@AllArgsConstructor
public class DiaryLifeController {

    private final DiaryLifeService diaryLifeService;

    @ApiOperation("전체 목록 조회")
    @GetMapping
    public Response<List<Post>> getPosts() {
        log.info("전체 목록 조회");

        return new Response<>(diaryLifeService.getPosts(null));
    }

    @ApiOperation("다이어리 포스팅 신규생성")
    @PostMapping
    public Response<Void> savePost(@RequestBody Post post) {
        validatePostInput(post);
        diaryLifeService.createPost(post);
        return new Response<>();
    }

    @ApiOperation("다이어리 포스팅 업데이트")
    @PutMapping
    public Response<Void> updatePost(@RequestBody Post post) {
        validatePostInput(post);
        diaryLifeService.updatePost(post);
        return new Response<>();
    }

    @ApiOperation("다이어리 포스팅 삭제")
    @DeleteMapping
    public Response<Void> deletePost(@RequestParam String _id) {
        diaryLifeService.deletePost(_id);
        return new Response<>();
    }

    private void validatePostInput(Post post) {
        if (ObjectUtils.isEmpty(post.getTitle())) {
            throw new BadRequestException("No TITLE exists.");
        }
        if (ObjectUtils.isEmpty(post.getContent())) {
            throw new BadRequestException("No CONTENT exists.");
        }
    }

    @ExceptionHandler
    public ResponseEntity<Response<String>> badRequest(BadRequestException e) {
        log.error("Bad request.., e-msg:{}", e.getMessage(), e);
        return ResponseEntity.badRequest().body(new Response<>(e.getMessage()));
    }
}

 

스웨거로 보면 다음처럼 나오게 됩니다.

다이어리 API 스웨거

 

스웨거를 이용해서 기능 테스트를 한번 해보겠습니다.

 

 

 

현재 구현된 기능은 모두 정상적으로 동작하는 것 까지 확인했습니다.

 

여기까지 작업하면서 쉽게 풀리지 않았던 부분은 몽고DB를 처음 사용하다보니 몽고DB 클라이언트를 이용한 CRUD만드는 부분이었습니다. 기존 RDS와는 다르게 ObjectID 로 핸들링을 해야하는 부분이 있었고, auto increment pk 설정을 따로 할 수 없었습니다. 만약 게시글의 번호가 필요하다면 어떻게 데이터를 저장해야할지 고민이 좀 되는 부분입니다. 각 게시글마다 시퀀스값을 넣어줘야하는데 구글링해서 나오는 것들은 synchronized 가 안될 것 처럼 보여서 테스트도 좀 해봐야 할 것 같습니다.

 

여기까지 백엔드의 기본적인 구현을 완료했습니다.

다음 포스팅에서는 프론트와 백엔드를 연결하는 부분에 대해서 올리겠습니다.

아래 링크로 들어가서 오른쪽 하단의 Download 버튼을 클릭하여 tgz 파일을 다운로드 받아 압축을 풀면 설치가 완료된다.

 

몽고DB 커뮤니티 서버 최신버전 다운로드

 

 

몽고디비 최신버전은 자바버전 8 이상이면 사용가능하다.

추가적인 호환성 여부는 몽고DB 공식사이트에서 확인가능하다.

현재 사용하고 있는 자바 버전이 8이 아니라면 업그레이드가 필요하다.

몽고DB 드라이버 호환성 여부
몽고DB 자바버전 호환성 여부


몽고DB서버 실행하기 공식문서를 보고 따라하면되는데 그대로 따라하면 중간에 오류가 발생한다.

아래 명령어를 보고 실행하되 경로는 본인의 입맛에 맞게 변경해주면 된다.

keichee:BlogApp KH$ sudo mkdir -p /usr/local/mongodb/data-v4.4
Password:
keichee:BlogApp KH$ sudo mkdir -p /usr/local/mongodb/log
keichee:BlogApp KH$ sudo chown KH /usr/local/mongodb/*
keichee:BlogApp KH$ touch /usr/local/mongodb/log/mongo.log

-- 몽고db bin 디렉토리로 이동 --
keichee:bin KH$ ./mongod --dbpath /usr/local/mongodb/data-v4.4 --logpath /usr/local/mongodb/log/mongo.log --fork
about to fork child process, waiting until server is ready for connections.
forked process: 38133
child process started successfully, parent exiting
keichee:bin KH$ 

 

이제 서버는 정상적으로 기동이 되었고, 실제로 접속해서 명령어를 입력하려면 mongo 명령어를 실행하면 됩니다.

keichee:bin KH$ ./mongo
MongoDB shell version v4.4.2
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("b8192555-a975-457e-ab16-2b2c7675c72a") }
MongoDB server version: 4.4.2
---
The server generated these startup warnings when booting: 
        2020-11-22T08:12:57.220+09:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
        2020-11-22T08:12:57.221+09:00: This server is bound to localhost. Remote systems will be unable to connect to this server. Start the server with --bind_ip <address> to specify which IP addresses it should serve responses from, or with --bind_ip_all to bind to all interfaces. If this behavior is desired, start the server with --bind_ip 127.0.0.1 to disable this warning
        2020-11-22T08:12:57.221+09:00: Soft rlimits too low
        2020-11-22T08:12:57.221+09:00:         currentValue: 10240
        2020-11-22T08:12:57.221+09:00:         recommendedMinimum: 64000
---
---
        Enable MongoDB's free cloud-based monitoring service, which will then receive and display
        metrics about your deployment (disk utilization, CPU, operation statistics, etc).

        The monitoring data will be available on a MongoDB website with a unique URL accessible to you
        and anyone you share the URL with. MongoDB may use this information to make product
        improvements and to suggest MongoDB products and deployment options to you.

        To enable free monitoring, run the following command: db.enableFreeMonitoring()
        To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
>