4/7 - trakingId
@UuidGenerator
@JdbcTypeCode(Types.VARCHAR)
@Column(length = 36, nullable = false, unique = true)
private UUID trackingId;
4/8 도메인 에러코드 정의 (예제 코드입니다.)
@RequiredArgsConstructor
@Getter
public enum ExampleCode implements BaseError {
EXAMPLE_CODE1(HttpStatus.BAD_REQUEST, 200, "성공적으로 처리되었습니다."),
EXAMPLE_CODE2(HttpStatus.BAD_REQUEST, 201, "성공적으로 생성되었습니다."),
EXAMPLE_CODE3(HttpStatus.BAD_REQUEST, 202, "이미 존재하는 리소스입니다."),
;
private final HttpStatus status;
private final Integer code;
private final String message;
}
4/8 도메인 익셉션 정의 (권고:필수는아니지만 하는걸 추천함) (예제 코드입니다.)
public class ExampleException extends BaseException {
public ExampleException(ExampleCode exampleCode) {
super(exampleCode);
}
}
4/18 카프카 consumer 처리를 하니 kafka-ui가 뻑나간 사건에 대하여…
아래와 같이 Docker-compose를 구성하면 해결된다
kafka internal, external 설정을 해주어야 인식을 한다.
version: '3.8'
services:
mysql:
image: mysql:latest
container_name: mysql_db_chat
environment:
MYSQL_ROOT_PASSWORD: moimserver
MYSQL_DATABASE: chat
MYSQL_USER: chat
MYSQL_PASSWORD: moimserver
ports:
- "3313:3306"
volumes:
- mysql-data-chat:/var/lib/mysql
networks:
- app-network
phpmyadmin:
image: phpmyadmin:latest
container_name: phpmyadmin_chat
environment:
PMA_HOST: mysql
PMA_PORT: 3306
PMA_USER: chat
PMA_PASSWORD: moimserver
ports:
- "18087:80"
depends_on:
- mysql
networks:
- app-network
mongodb:
image: mongo:latest
container_name: mongodb_chat
environment:
MONGO_INITDB_ROOT_USERNAME: chat
MONGO_INITDB_ROOT_PASSWORD: moimserver
ports:
- "27017:27017"
volumes:
- mongodb-data-chat:/data/db
networks:
- app-network
mongo-express:
image: mongo-express:latest
container_name: mongo_express_chat
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: chat
ME_CONFIG_MONGODB_ADMINPASSWORD: moimserver
ME_CONFIG_MONGODB_SERVER: mongodb
ME_CONFIG_BASICAUTH_USERNAME: admin
ME_CONFIG_BASICAUTH_PASSWORD: moimserver
ports:
- "18081:8081"
depends_on:
- mongodb
networks:
- app-network
zookeeper:
image: bitnami/zookeeper:3.9
container_name: zookeeper
ports:
- "2181:2181"
volumes:
- zookeeper-data-chat:/bitnami/zookeeper # ZooKeeper 데이터 지속성을 위해 볼륨 추가
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
networks:
- app-network
kafka:
image: bitnami/kafka:3.6
container_name: kafka
ports:
- "9092:9092" # 외부 접근용 (localhost:9092)
- "29092:29092" # 내부 접근용 (kafka:29092)
environment:
- KAFKA_BROKER_ID=1
- KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
# 두 개의 리스너 구성
- KAFKA_LISTENERS=EXTERNAL://0.0.0.0:9092,INTERNAL://0.0.0.0:29092
- KAFKA_ADVERTISED_LISTENERS=EXTERNAL://localhost:9092,INTERNAL://kafka:29092
- KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=EXTERNAL:PLAINTEXT,INTERNAL:PLAINTEXT
- KAFKA_INTER_BROKER_LISTENER_NAME=INTERNAL
- ALLOW_PLAINTEXT_LISTENER=yes
volumes:
- kafka-data-chat:/bitnami/kafka
depends_on:
- zookeeper
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "kafka-topics --bootstrap-server localhost:9092 --list || exit 1"]
interval: 10s
timeout: 5s
retries: 5
kafka-ui:
image: provectuslabs/kafka-ui:v0.7.1
container_name: kafka-ui
ports:
- "19092:8080"
environment:
- KAFKA_CLUSTERS_0_NAME=local
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:29092
# - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181
# - DYNAMIC_CONFIG_ENABLED=true
depends_on:
- kafka
# - zookeeper
networks:
- app-network
volumes:
mysql-data-chat:
mongodb-data-chat:
kafka-data-chat:
zookeeper-data-chat:
networks:
app-network:
driver: bridge
package com.sparta.moim.common.response;
import java.util.Optional;
import java.util.function.Predicate;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
@Getter
@RequiredArgsConstructor
public enum Code {
/**
* 성공
* 200번대
*/
SUCCESS(HttpStatus.OK, 200, "성공적으로 처리되었습니다."),
CREATED(HttpStatus.CREATED, 201, "성공적으로 생성되었습니다."),
ALREADY_EXISTS(HttpStatus.OK, 202, "이미 존재하는 리소스입니다."),
/**
* 500번대
*/
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 500, "예기치 못한 서버 오류가 발생했습니다."),
INTERNAL_SERVER_MINIO_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 500, "Minio 서버 오류가 발생했습니다."),
;
private final HttpStatus status;
private final Integer code;
private final String message;
public String getMessage(Throwable e) {
return this.getMessage(this.getMessage() + " - " + e.getMessage());
// 결과 예시 - "Validation error - Reason why it isn't valid"
}
public String getMessage(String message) {
return Optional.ofNullable(message)
.filter(Predicate.not(String::isBlank))
.orElse(this.getMessage());
}
public String getDetailMessage(String message) {
return this.getMessage() + " : " + message;
}
}