프로젝트 실행하면 (readme에 실행 방법 기재해둠)
-> 참고로 간혹 빌드가 잘 안될 때 있는데, 그럴땐 걍 down하고, 재 빌드 하면 됨.
docker-compose -f docker-compose.local.yml down
docker-compose -f docker-compose.local.yml build
docker-compose -f docker-compose.local.yml up -d

이런 식으로 에러 뜨는거는 그냥 포트 번호 수정해주면 됨.
이미 3306 포트를 다른 프로세스(예: 로컬 MySQL 서버)가 점유 중이라서 Docker가 사용할 수 없다는 뜻

이런 식으로 뜨는데, 이건
failed to solve: eclipse-temurin:17-jdk-alpine: no match for platform in manifest...
현재 사용하는 Docker Desktop (예: Apple Silicon 기반 맥) 환경과 이미지가 호환되지 않아서 발생한 문제.
즉, eclipse-temurin:17-jdk-alpine 이미지가 ARM64 (예: M1/M2 Mac) 플랫폼을 지원하지 않거나, 해당 플랫폼에 대한 manifest가 등록되어 있지 않아서 생기는 문제입니다.
해결 방법
방법 1: 이미지 변경
# Dockerfile에서
# FROM eclipse-temurin:17-jdk-alpine
FROM eclipse-temurin:17-jdk # <- alpine 제거
# alpine 버전은 용량은 작지만, ARM 호환성 문제가 자주 발생함.
# 일반 jdk 버전은 호환성이 더 좋음.
방법 2: 플랫폼 설정
방법 3: 대체 이미지 사용
이렇게 방법이 있지만 저는 맥북이 요즘 너무 렉이 심해서 그냥 윈도우 환경에서 진행하겠습니다.

이해하기 쉽게 static과 non-static ?
간단히 생각하면, 직렬화 불가능한 필드를 들고 있는 직렬화 가능한 클래스가 되면서 SonarQube가 경고를 낸 거라서 직렬화를 해주면 됩니다.
참고 1, 2,
더 쉽게 검색을 하라면 지금 우측 하단에 보시면 빨간색 Maintainablitiy 우측에 java:S1948이 있는데 이것을 검색하면 스택오버플로우 등 다양한 자료를 확인 할 수 있어 유용합니다.
재 부팅 후, docke up

왜 Exited (137)인가?
Exited (137)은 시스템에 의해 강제 종료됨을 의미 (예: 메모리 부족, 수동 강제종료 등)
과거 실행되고 있었으나 docker-compose에 의해 관리되지 않아 따로 종료되지 않고 남아 있는 것
재 부팅하고 키바나에서 테스트하려 했는데, 이렇게 뜸.
Kibana만 docker-compose.local.yml에 포함되어 있지 않기 때문에 down 명령어의 대상이 아니었고, 따라서 지워지지 않고 남아 있는 것 같은데..흠.
컨테이너 직접 제거
docker rm kibana
이렇게 하면 dangling(고아) 상태의 Kibana 컨테이너가 삭제됩니다.
Kibana를 docker-compose.local.yml에 추가한 다음 함께 관리
(제 프로젝트는 배포되었으므로 함부러 yml 수정 불가능해서 추후 팀원과 상의 예정)
version: "3.9"
services:
mysql:
image: mysql:latest
container_name: mysql-container
ports:
- "3307:3306"
environment:
- MYSQL_ROOT_USERNAME=root
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
- MYSQL_DATABASE=testdb
networks:
- local-test
elastic-search:
container_name: elasticsearch
build:
context: .
dockerfile: Dockerfile.elastic
ports:
- "9200:9200"
networks:
- local-test
kibana:
image: kibana:8.18.0
container_name: kibana
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elastic-search
networks:
- local-test
elastic-logstash:
container_name: logstash-container
image: logstash:8.18.0
ports:
- "5044:5044"
networks:
- local-test
redis:
container_name: redis-container
image: redis
networks:
- local-test
spring:
container_name: spring-container
build:
context: .
dockerfile: Dockerfile
environment:
- SPRING_PROFILE=dev
env_file:
- .env
ports:
- "8080:8080"
networks:
- local-test
networks:
local-test:
driver: bridge



?? 엔티티 확인해보니까 SELECT * FROM refresh_tokens; 로 해야했는데 s를 빼먹었음
-> 정상 동작 확인.
@Column(name = "deleted_at")
private LocalDateTime deletedAt;
public void softDelete() {
this.deletedAt = LocalDateTime.now();
}
public boolean isDeleted() {
return this.deletedAt != null;
}
혼자 드는 생각.
Book은 soft delete 대상이 아닌데, BaseEntity에 deleted 필드를 올리면 Book에도 생기게 되는데, 과연 그게 좋은 설계일까 ??
판단 기준
💡 지금 나의 상황
soft delete 하면 안됨.❌soft delete O→ 따라서 지금은 BaseEntity에 deleted를 넣지 않는 게 맞는 것 같음.
결론
항목 선택
deleted를 BaseEntity로 올리기 → ❌ 지금은 부적절 (Book 등 예외 존재)❌
deleted를 Entity별로 개별 선언 → 현 상황에 가장 안전하고 깔끔한 설계라고 판단.
따라서 필요한 도메인에 개별로 선언해서 사용할 예정.
Entity, Repository, Service, Controller 수정 -> Test 코드 수정


Order 도메인 수정했는데, 밤샘 이슈로 깜빡하고 재빌드를 안해줌..
./gradlew clean compileQuerydsl

build.gradle 일부 수정으로 정상 동작 확인.

이젠 review 수정해줬고, 역시 Qclass 반영 안됨.
이 오류는 정확히 말하면 QReview 클래스가 deletedAt 필드를 모르고 있다는 거.
즉, Review 엔티티에는 deletedAt이 분명히 선언되어 있지만, QueryDSL의 Q클래스를 regenerate 하지 않아서 QReview에 반영이 안 된 거.
Q클래스를 재생성하기.
1. 먼저 clean
./gradlew clean
./gradlew compileQuerydsl
만약 위 태스크가 안 보인다면, build.gradle에 QueryDSL 설정을 다시 확인해야함.

이래도 안되면 ./gradlew clean compileQuerydsl 입력.
원인
IntelliJ가 Q 클래스 변경사항을 인식 못함
기존 QReview 클래스가 오래된 상태로 캐시됨
QueryDSL이 Review 클래스의 변경을 감지 못하고 다시 생성 안 함
해결법 (지난번과 동일)
rm -rf ./build/generated/querydsl
또는 IntelliJ에서 수동으로 Q파일 삭제
./gradlew clean build
build만 해도 Q 클래스가 재생성됨. compileQuerydsl 없어도 됨 (우리는 JavaCompile에 annotationProcessorDirectory 설정해놨기 때문)
CDN을 도입해서 이미지 로딩 속도를 빠르게 하려는 목적이고, 이를 위해
현재 구조 정리
S3Upload 클래스에서 이미지 업로드 후 S3 URL을 반환 중
s3Client.utilities().getUrl(...).toString()
개선 목표
CDN 도입 시, 사용자는 https://cdn.example.com/profile/UUID_filename.png 처럼 접속해야 하므로
📌 변경 전
return s3Client.utilities().getUrl(GetUrlRequest.builder()
.bucket(bucket)
.key(fileName)
.build()).toString();
📌 변경 후
.yml에 CDN 도메인 추가 후, 아래처럼 수정
cloud:
aws:
s3:
bucket: your-bucket-name
cdn-url: https://cdn.example.com # 추가
@Value("${cloud.aws.s3.cdn-url}")
private String cdnUrl;
...
return cdnUrl + "/" + fileName;
이렇게 하면 반환되는 URL이 S3 자체 링크가 아닌 CDN 경유 링크가 된다.
예시로 바뀌는 URL