mysql, redis 설정
먼저 mysql과 redis를 도커 컨테이너로 띄우기 위해 docker-compose를 작성해 주자.
//docker-compose.yml
version: '3.7'
services:
redis:
container_name: coupon-redis
image: redis:7.2-alpine
command: redis-server --port 6380
labels:
- "name=redis"
- "mode=standalone"
ports:
- 6380:6380
mysql:
container_name: coupon-mysql
image: ubuntu/mysql:edge
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --explicit_defaults_for_timestamp=1
ports:
- 3306:3306
environment:
- MYSQL_DATABASE=coupon
- MYSQL_USER=abcd
- MYSQL_PASSWORD=1234
- MYSQL_ROOT_PASSWORD=1234
- TZ=UTC
volumes:
- ./mysql/init:/docker-entrypoint-initdb.d
이제 해당 디렉토리로 이동해서 다음과 같이 명령어를 입력하면 mysql과 redis 컨테이너가 올라간다.
$ docker-compose up -d
[+] Building 0.0s (0/0)
[+] Running 3/3
✔ Network mycoupon_default Created 0.0s
✔ Container coupon-mysql Started 0.5s
✔ Container coupon-redis Started
다음 명령어를 통해서 올라간 컨테이너가 확인 가능하다.
$ docker ps
이제 redis와 mysql를 사용 가능하도록 설정해주자.
mycoupon
제일 바깥의 root 디렉토리의 build.gradle 에 다음과 같은 dependency 들을 추가해주자.
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.3'
id 'io.spring.dependency-management' version '1.1.4'
}
bootJar.enabled = false
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
subprojects {
apply plugin: "java"
apply plugin: "io.spring.dependency-management"
apply plugin: "org.springframework.boot"
repositories {
mavenCentral()
}
// 관리하는 모듈에 공통 dependencies
dependencies {
/** 새로 추가 **/
implementation "org.springframework.boot:spring-boot-starter-data-jpa" // jpa 를 사용하기 위해서
implementation "org.springframework.boot:spring-boot-starter-data-redis" // redis 사용을 위해서
runtimeOnly "com.h2database:h2" // h2db 사용을 위해서
runtimeOnly "com.mysql:mysql-connector-j" // mysql driver 를 사용하기 위해서
implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta" // querydsl 사용을 위해
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" // querydsl 사용을 위해
/** // 새로 추가 **/
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compileOnly "org.projectlombok:lombok"
annotationProcessor "org.projectlombok:lombok"
implementation "org.springframework.boot:spring-boot-starter"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
testImplementation "org.springframework.boot:spring-boot-starter-test"
}
}
tasks.named('test') {
useJUnitPlatform()
}
mycoupon-core
mycoupon-core 의 application.yml 정보를 다음과 같이 수정해주자.
//application-core.yml
spring:
config:
activate:
on-profile: local
datasource:
hikari:
jdbc-url: jdbc:mysql://localhost:3306/coupon?useUnicode=yes&characterEncoding=UTF-8&rewriteBatchedStatements=true
driver-class-name: com.mysql.cj.jdbc.Driver
# maximum-pool-size: 30000
# max-lifetime: 3000
username: abcd
password: 1234
jpa:
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate:
format_sql: true
data:
redis:
host: localhost
port: 6380
---
spring:
config:
activate:
on-profile: test
datasource:
url: jdbc:h2:mem:test;
driverClassName: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
data:
redis:
host: localhost
port: 6380
공통 dependency 영역이 추가되었기 때문에 전체 gradle reload를 한번 해준다.
이제 다시 앱을 기동해보면 잘 되는것을 확인해 볼 수 있다.
mysql과 redis가 잘 붙었는지 확인해 보려면 올라오는 log를 확인해 보면 알 수 있다.
db, redis 연결
먼저 crate ddl 문을 다음과 같은 위치에 넣어두자.
CREATE TABLE `coupon`.`coupons`
(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL COMMENT '쿠폰명',
`coupon_type` VARCHAR(255) NOT NULL COMMENT '쿠폰 타입 (선착순 쿠폰, ..)',
`total_quantity` INT NULL COMMENT '쿠폰 발급 최대 수량',
`issued_quantity` INT NOT NULL COMMENT '발급된 쿠폰 수량',
`discount_amount` INT NOT NULL COMMENT '할인 금액',
`min_available_amount` INT NOT NULL COMMENT '최소 사용 금액',
`date_issue_start` datetime(6) NOT NULL COMMENT '발급 시작 일시',
`date_issue_end` datetime(6) NOT NULL COMMENT '발급 종료 일시',
`date_created` datetime(6) NOT NULL COMMENT '생성 일시',
`date_updated` datetime(6) NOT NULL COMMENT '수정 일시',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT '쿠폰 정책';
CREATE TABLE `coupon`.`coupon_issues`
(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`coupon_id` BIGINT(20) NOT NULL COMMENT '쿠폰 ID',
`user_id` BIGINT(20) NOT NULL COMMENT '유저 ID',
`date_issued` datetime(6) NOT NULL COMMENT '발급 일시',
`date_used` datetime(6) NULL COMMENT '사용 일시',
`date_created` datetime(6) NOT NULL COMMENT '생성 일시',
`date_updated` datetime(6) NOT NULL COMMENT '수정 일시',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT '쿠폰 발급 내역';
insert into coupons (title, coupon_type, total_quantity, issued_quantity, discount_amount, min_available_amount,
date_issue_start, date_issue_end, date_created, date_updated)
values ('선착순 쿠폰 이벤트','FIRST_COME_FIRST_SERVED',500,0,100000,10000,now(),now(),now(),now());
만약에 intelliJ 를 사용 중이라면 datagrip을 통해서 db에 붙을 수가 있다.
꼭 datagrip 이 아니더라도 db 툴로는 dbeaver, Heidsql 등등 많으니 알아보고 각자가 쓰기 편한 것을 쓰면 될 것 같다.
설정 내용은 다음과 같이 하였다.
연결이 잘 되었다면 아까 작성했던 쿼리를 실행해주자.
그럼 다음과 같이 table이 생성되고, 하나의 더미 데이터가 들어가는 것을 볼 수 있다.
같은 방법으로 redis도 연결하면 된다.
엔터티 작성
이제 본격적으로 코딩을 해보자.
각 도메인별로 엔터티를 작성해주기 전에 공통으로 상속받는 엔터티를 하나 만들어 주자.
이걸 상속받는 엔터티들은 자동으로 생성 시간과 수정 시간을 자동으로 BaseTimeEntity
가 주입해준다.
package com.example.mycouponcore.model;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDate;
@Getter
@MappedSuperclass //다른 entity 에서 상속할 것이기 때문에
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {
@CreatedDate
private LocalDate dateCreated;
@LastModifiedDate
private LocalDate dateUpdated;
}
제대로 작동하기 위해서는 메인 class에 @EnableJpaAuditing
달아주어야 한다.
//MyCouponCoreConfiguration
package com.example.mycouponcore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@EnableAutoConfiguration
@ComponentScan
@EnableJpaAuditing //추가
public class MyCouponCoreConfiguration {
}
다음으로 coupon 도메인에 대한 엔터티를 작성해주자.
package com.example.mycouponcore.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Table(name = "coupons")
public class Coupon extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(nullable = false)
@Enumerated(value = EnumType.STRING)
private CouponType couponType;
private Integer totalQuantity;
@Column(nullable = false)
private int issuedQuantity;
@Column(nullable = false)
private int discountAmount;
@Column(nullable = false)
private int minAvailableAmount;
@Column(nullable = false)
private LocalDateTime dateIssueStart;
@Column(nullable = false)
private LocalDateTime dateIssueEnd;
}
coupon의 종류가 다를 수 있기 때문에 enum 타입의 CouponType을 따로 선언해 주자.
package com.example.mycouponcore.model;
public enum CouponType {
FIRST_COME_FIRST_SERVED, //선착순 쿠폰
DISCOUNT_COUPON
}
마지막으로 coupon_issues 엔터티를 작성해주자.
package com.example.mycouponcore.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import java.time.LocalDateTime;
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Table(name = "coupon_issues")
public class CouponIssue extends BaseTimeEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private Long couponId;
@Column(nullable = false)
private Long userId;
@Column(nullable = false)
@CreatedDate
private LocalDateTime dateIssued;
private LocalDateTime dateUsed;
}
내용이 너무 길어져서 Mysql 기반 선착순 쿠폰 발급 기능 개발 (2) 에서 이어서 작성하겠다.
'토이프로젝트 > 선착순 이벤트 쿠폰 시스템' 카테고리의 다른 글
Mysql 기반 선착순 쿠폰 발급 기능 개발 (4) (0) | 2024.04.30 |
---|---|
Mysql 기반 선착순 쿠폰 발급 기능 개발 (3) (0) | 2024.04.18 |
Mysql 기반 선착순 쿠폰 발급 기능 개발 (2) (0) | 2024.04.16 |
2. 프로젝트 환경 설정 (0) | 2024.04.06 |
1. 요구사항 분석 및 도메인 설계 (0) | 2024.04.02 |