Docker를 사용하여 MySQL 설치하고 접속하기

Danny·2023년 10월 23일
1

ASAC

목록 보기
3/8
  • Docker 를 통해 데이터베이스 가동
  • DBeaver 를 통해 가동된 데이터베이스 접근 및 SQL 쿼리 수행
  • Spring 예시 프로젝트를 통해 API 테스트
  • API 개발 및 Spring Annotation 설명

1. Docker 설치 (Docker 를 통해 데이터베이스 가동)

2. MySQL Docker 이미지 다운로드

다음 명령어로 MySQL Docker 이미지를 다운로드한다. 태그에 버전을 지정하지 않으면 최신 버전을 다운로드한다.

docker pull mysql

Using default tag: latest
latest: Pulling from library/mysql
bb79b6b2107f: Pull complete
49e22f6fb9f7: Pull complete
842b1255668c: Pull complete
9f48d1f43000: Pull complete
c693f0615bce: Pull complete
8a621b9dbed2: Pull complete
0807d32aef13: Pull complete
a56aca0feb17: Pull complete
de9d45fd0f07: Pull complete
1d68a49161cc: Pull complete
d16d318b774e: Pull complete
49e112c55976: Pull complete
Digest: sha256:8c17271df53ee3b843d6e16d46cff13f22c9c04d6982eb15a9a47bd5c9ac7e2d
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest

2.1 Docker 생성 명령어

docker run --name erd-coupang \
  -e MYSQL_ROOT_PASSWORD=root \
  -e MYSQL_USER=3rdasac \
  -e MYSQL_PASSWORD=3rdasac \
  -e MYSQL_DATABASE=erd-coupang \
  -p 3306:3306 -d mysql:8

3. Docker Container MySql 접속

docker exec -it test-mysql bash

mysql -u root -p

이후 위에서 지정했던 root 비밀번호를 입력해준다.

4. Database 생성 후 확인

create database erd-coupang;
show databases;

5. DBeaver로 접속하기 (DBeaver 를 통해 가동된 데이터베이스 접근 및 SQL 쿼리 수행)

  1. mysql 선택

  2. 접속 비밀번호 , 포트 설정(Spring 에서 설정한 포트)

6. 좌측 아래 Test Connection 눌러서 확인

7. DB 연결 확인

7.1 생성된 DB에 데이터 추가

SQL 누른후 스크립트 작성

-- USER 테이블
CREATE TABLE USER (
    id int unsigned NOT NULL AUTO_INCREMENT,
    email varchar(50) NOT NULL,
    password varchar(200) NOT NULL,
    name varchar(50),
    created timestamp DEFAULT CURRENT_TIMESTAMP,
    updated timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    status varchar(10) DEFAULT 'ACTIVE',
    CONSTRAINT USER_PK PRIMARY KEY(id)
);

-- 예제 데이터 추가
INSERT INTO USER(email, password, name) VALUES('email1@naver.com', '1234', 'name1');
INSERT INTO USER(email, password, name) VALUES('email2@naver.com', '1234', 'name2');
INSERT INTO USER(email, password, name) VALUES('email3@naver.com', '1234', 'name3');

-- MEMO 테이블
CREATE TABLE MEMO (
    id int unsigned NOT NULL AUTO_INCREMENT,
    memo varchar(100) NOT NULL,
    created timestamp DEFAULT CURRENT_TIMESTAMP,
    updated timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    state varchar(10) DEFAULT 'ACTIVE',
    CONSTRAINT TEST_PK PRIMARY KEY(id)
);

8. Spring에서 접속하기(Spring 예시 프로젝트를 통해 API 테스트)

8.1 Application.yml 설정

  • MySql의 com.mysql.cj.jdbc.Driver에 빨간줄 오류가 생길 수 있다.
  • Unknown database 'erd-coupang'
    • 대부분 포트 , datasource 의 url 부분에서 오타 의심
server:
  port: 9000

spring:
  application:
    name: demo

  datasource:
    url: jdbc:mysql://localhost:3309/erd-coupang?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&serverTimezone=Asia/Seoul
    username: root
    password:  password
    driver-class-name: com.mysql.cj.jdbc.Driver # mysql 8버전
    # driver-class-name: com.mysql.jdbc.Driver # mysql 5버전
  sql:
    init:
      platform: mysql
datasource:
    url: jdbc:mysql://localhost:3309/erd-coupang?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&serverTimezone=Asia/Seoul
    
  • "useSSL=false&allowPublicKeyRetrieval=true"
    • 스프링에서 접근하기 위함.

8.2 연결성공!

9. 디렉토리 구조


10. API 테스트(Spring 예시 프로젝트를 통해 API 테스트)

POSTMAN 사용

package com.example.demo.src.user;


import lombok.RequiredArgsConstructor;
import com.example.demo.common.BaseException;
import com.example.demo.common.BaseResponse;
import com.example.demo.src.user.model.*;
import org.springframework.web.bind.annotation.*;

import java.util.List;


import static com.example.demo.common.BaseResponseStatus.*;
import static com.example.demo.utils.ValidationRegex.isRegexEmail;

@RequiredArgsConstructor
@RestController
@RequestMapping("/app/users")
public class UserController {


    private final UserService userService;


    /**
     * 회원가입 API
     * [POST] /app/users
     * @return BaseResponse<PostUserRes>
     */
    // Body
    @ResponseBody
    @PostMapping("")
    public BaseResponse<PostUserRes> createUser(@RequestBody PostUserReq postUserReq) {
        // TODO: email 관련한 짧은 validation 예시입니다. 그 외 더 부가적으로 추가해주세요!
        if(postUserReq.getEmail() == null){
            return new BaseResponse<>(POST_USERS_EMPTY_EMAIL);
        }
        //이메일 정규표현
        if(!isRegexEmail(postUserReq.getEmail())){
            return new BaseResponse<>(POST_USERS_INVALID_EMAIL);
        }
        try{
            PostUserRes postUserRes = userService.createUser(postUserReq);
            return new BaseResponse<>(postUserRes);
        } catch(BaseException exception){
            return new BaseResponse<>((exception.getStatus()));
        }
    }

    /**
     * 회원 조회 API
     * [GET] /app/users
     * 회원 번호 및 이메일 검색 조회 API
     * [GET] /app/users? Email=
     * @return BaseResponse<List<GetUserRes>>
     */
    //Query String
    @ResponseBody
    @GetMapping("") // (GET) 127.0.0.1:9000/app/users
    public BaseResponse<List<GetUserRes>> getUsers(@RequestParam(required = false) String Email) {
        try{
            if(Email == null){
                List<GetUserRes> getUsersRes = userService.getUsers();
                return new BaseResponse<>(getUsersRes);
            }
            // Get Users
            List<GetUserRes> getUsersRes = userService.getUsersByEmail(Email);
            return new BaseResponse<>(getUsersRes);
        } catch(BaseException exception){
            return new BaseResponse<>((exception.getStatus()));
        }
    }

    /**
     * 회원 1명 조회 API
     * [GET] /app/users/:userId
     * @return BaseResponse<GetUserRes>
     */
    // Path-variable
    @ResponseBody
    @GetMapping("/{userId}") // (GET) 127.0.0.1:9000/app/users/:userId
    public BaseResponse<GetUserRes> getUser(@PathVariable("userId") int userId) {
        // Get Users
        try{
            GetUserRes getUserRes = userService.getUser(userId);
            return new BaseResponse<>(getUserRes);
        } catch(BaseException exception){
            return new BaseResponse<>((exception.getStatus()));
        }

    }



    /**
     * 유저정보변경 API
     * [PATCH] /app/users/:userId
     * @return BaseResponse<String>
     */
    @ResponseBody
    @PatchMapping("/{userId}")
    public BaseResponse<String> modifyUserName(@PathVariable("userId") int userId, @RequestBody User user){
        try {
            PatchUserReq patchUserReq = new PatchUserReq(userId,user.getName());
            userService.modifyUserName(patchUserReq);

            String result = "";
        return new BaseResponse<>(result);
        } catch (BaseException exception) {
            return new BaseResponse<>((exception.getStatus()));
        }
    }

    /**
     * 유저정보삭제 API
     * [DELETE] /app/users/:userId
     * @return BaseResponse<String>
     */
    @ResponseBody
    @DeleteMapping("/{userId}")
    public BaseResponse<String> deleteUser(@PathVariable("userId") int userId){
        try {
            userService.deleteUser(userId);

            String result = "";
            return new BaseResponse<>(result);
        } catch (BaseException exception) {
            return new BaseResponse<>((exception.getStatus()));
        }
    }


}


TIP 어노테이션 설명 (API 개발 및 Spring Annotation 설명)

  • @Entity
    • 테이블과의 매핑
    • @Entity가 붙은 클래스는 JPA가 관리하는 것으로, 엔티티라고 불림
  • @Table(name = "USER")
    • "내 테이블의 이름은 "USER"야"
    • 해당 어노테이션이 붙은 클래스를 테이블과 매핑한다는 뜻.
    • name 속성은 테이블의 이름으로 지정.
    • 생략하면 클래스의 이름으로 지정.
  • @Getter
    • User 클래스의 멤버변수의 getter 메서드를 생성
  • @Data
    • "난 Getter , Setter 모두 쓰기 귀찮아"
    • @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor 등이 모두 자동으로 생성
  • @NoArgsConstructor(access = AccessLevel.PROTECTED)
    • 기본 생성자를 생성하는 어노테이션
    • 기본 생성자에 접근 제어자를 설정하지 않으면 무분별하게 객체가 생성될 수 있기 때문에 access 속성을 통해 설정합니다.
  • @AllArgsConstructor
    • 모든 멤버변수를 가지고 있는 생성자를 생성합니다.

0개의 댓글