Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/기능-구현.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: 기능 구현
about: '기능 설명 및 구현 '
title: "[FEAT]"
title: "[FEAT] "
labels: "\U0001F6E0️ FEAT"
assignees: ''

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/기능-수정.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: 기능 수정
about: 리팩토링 목적이 아닌 기능 수정
title: "[FIX} "
title: "[FIX] "
labels: "\U0001F527 FIX"
assignees: ''

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/기타-수정.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: 기타 수정
about: '작은 부분 수정 '
title: "[CHORE]"
title: "[CHORE] "
labels: "\U0001F3B5 CHORE"
assignees: ''

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/문서-작업-.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: '문서 작업 '
about: 문서작업 내용
title: ''
title: '[Docs] '
labels: "\U0001F4DC DOC"
assignees: ''

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/오류수정.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: 오류수정
about: '오류 설명 및 수정 '
title: "[DEBUG]"
title: "[DEBUG] "
labels: "\U0001F577️ BUG"
assignees: ''

Expand Down
12 changes: 12 additions & 0 deletions .github/ISSUE_TEMPLATE/테스트-작성.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: '테스트 작성'
about: 테스트 코드 작성
title: '[Test] '
labels: "🧪 TEST"
assignees: ''

---

## 🔑 테스트 내용

<br>
4 changes: 3 additions & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
else
echo "DOCKER_TAG=staging" >> $GITHUB_OUTPUT
fi


- name: Build with Gradle
run: |
Expand Down Expand Up @@ -71,7 +72,7 @@ jobs:
envs: >-
DB_PASSWORD,GCS_BUCKET,
KAKAO_CLIENT_ID,KAKAO_CLIENT_SECRET,KAKAO_REDIRECT_URI_PROD,KAKAO_REDIRECT_URI_STAGING,KAKAO_ADMIN_KEY,
JWT_SECRET_KEY
JWT_SECRET_KEY,FIREBASE_SERVICE_ACCOUNT_KEY
script: |
chmod +x /home/ubuntu/cockple/scripts/deploy.sh
bash /home/ubuntu/cockple/scripts/deploy.sh \
Expand All @@ -86,3 +87,4 @@ jobs:
KAKAO_REDIRECT_URI_STAGING: ${{ secrets.KAKAO_REDIRECT_URI_STAGING }}
KAKAO_ADMIN_KEY: ${{ secrets.KAKAO_ADMIN_KEY }}
JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }}
FIREBASE_SERVICE_ACCOUNT_KEY: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_KEY }}
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ jobs:
echo "${{ secrets.APPLICATION_STAGING }}" > src/main/resources/application.yml
fi

- name: Create Firebase Key File
run: |
mkdir -p src/main/resources/firebase
echo '${{ secrets.FIREBASE_SERVICE_ACCOUNT_KEY }}' > src/main/resources/firebase/cockple-1a83e-firebase-adminsdk-fbsvc-212ce01565.json

- name: Grant execute permission for Gradle
run: chmod +x gradlew

Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,7 @@ application-dev.yml
terraform/.terraform/
terraform/terraform.tfstate
terraform/terraform.tfstate.backup
terraform/terraform.tfvars
terraform/terraform.tfvars

### firebase ###
src/main/resources/firebase/*.json
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ dependencies {
// redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'io.lettuce:lettuce-core'

// firebase
implementation 'com.google.firebase:firebase-admin:9.7.1'

// flyway
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql'
}

tasks.named('test') {
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ services:
KAKAO_REDIRECT_URI: ${KAKAO_REDIRECT_URI_PROD}
KAKAO_ADMIN_KEY: ${KAKAO_ADMIN_KEY}
JWT_SECRET_KEY: ${JWT_SECRET_KEY}
FIREBASE_SERVICE_ACCOUNT_KEY: ${FIREBASE_SERVICE_ACCOUNT_KEY}
depends_on:
mysql:
condition: service_healthy
Expand All @@ -85,6 +86,7 @@ services:
KAKAO_REDIRECT_URI: ${KAKAO_REDIRECT_URI_STAGING}
KAKAO_ADMIN_KEY: ${KAKAO_ADMIN_KEY}
JWT_SECRET_KEY: ${JWT_SECRET_KEY}
FIREBASE_SERVICE_ACCOUNT_KEY: ${FIREBASE_SERVICE_ACCOUNT_KEY}
depends_on:
mysql:
condition: service_healthy
Expand Down
7 changes: 5 additions & 2 deletions nginx/conf.d/prod.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ server {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;

proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}

location / {
proxy_pass http://cockple-app:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
}
}
3 changes: 3 additions & 0 deletions nginx/conf.d/staging.conf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;

proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}

location / {
Expand Down
4 changes: 4 additions & 0 deletions nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,9 @@ http {
keepalive_timeout 65;
client_max_body_size 30M;

gzip on;
gzip_types application/json application/javascript text/plain text/css;
gzip_min_length 256;

include /etc/nginx/conf.d/*.conf;
}
2 changes: 2 additions & 0 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ KAKAO_REDIRECT_URI_PROD=${KAKAO_REDIRECT_URI_PROD}
KAKAO_REDIRECT_URI_STAGING=${KAKAO_REDIRECT_URI_STAGING}
KAKAO_ADMIN_KEY=${KAKAO_ADMIN_KEY}
JWT_SECRET_KEY=${JWT_SECRET_KEY}
FIREBASE_SERVICE_ACCOUNT_KEY=${FIREBASE_SERVICE_ACCOUNT_KEY}
EOF
echo "${FIREBASE_SERVICE_ACCOUNT_KEY}" > /home/ubuntu/cockple/firebase-service-account.json

echo "=== 배포 전 상태 ==="
sudo docker ps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import umc.cockple.demo.domain.bookmark.dto.GetAllExerciseBookmarksResponseDTO;
import umc.cockple.demo.domain.bookmark.dto.GetAllPartyBookmarkResponseDTO;
import umc.cockple.demo.domain.exercise.domain.Exercise;
import umc.cockple.demo.domain.image.service.ImageService;
import umc.cockple.demo.domain.party.domain.Party;
import umc.cockple.demo.domain.party.domain.PartyLevel;
import umc.cockple.demo.domain.party.enums.ActivityTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import umc.cockple.demo.domain.bookmark.repository.ExerciseBookmarkRepository;
import umc.cockple.demo.domain.bookmark.repository.PartyBookmarkRepository;
import umc.cockple.demo.domain.exercise.domain.Exercise;
import umc.cockple.demo.domain.image.service.ImageService;
import umc.cockple.demo.domain.file.service.FileService;
import umc.cockple.demo.domain.member.domain.Member;
import umc.cockple.demo.domain.member.exception.MemberErrorCode;
import umc.cockple.demo.domain.member.exception.MemberException;
Expand Down Expand Up @@ -43,7 +43,7 @@ public class BookmarkQueryService {
private final MemberExerciseRepository memberExerciseRepository;
private final MemberRepository memberRepository;
private final BookmarkConverter bookmarkConverter;
private final ImageService imageService;
private final FileService fileService;

public List<GetAllExerciseBookmarksResponseDTO> getAllExerciseBookmarks(Long memberId, BookmarkedExerciseOrderType orderType) {
// 회원 조회하기
Expand Down Expand Up @@ -133,7 +133,7 @@ private ActivityTime makeActiveTime(Exercise exercise) {

private String getImageUrl(PartyImg partyImg) {
if (partyImg != null && partyImg.getImgKey() != null && !partyImg.getImgKey().isBlank()) {
return imageService.getUrlFromKey(partyImg.getImgKey());
return fileService.getUrlFromKey(partyImg.getImgKey());
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import umc.cockple.demo.domain.chat.dto.*;
import umc.cockple.demo.domain.chat.service.ChatCommandService;
import umc.cockple.demo.domain.chat.service.ChatFileService;
import umc.cockple.demo.domain.chat.service.ChatImageService;
import umc.cockple.demo.domain.chat.service.ChatQueryService;
import umc.cockple.demo.global.response.BaseResponse;
import umc.cockple.demo.global.response.code.status.CommonSuccessCode;
Expand All @@ -27,7 +26,6 @@ public class ChatController {
private final ChatQueryService chatQueryService;
private final ChatCommandService chatCommandService;
private final ChatFileService chatFileService;
private final ChatImageService chatImageService;

@GetMapping(value = "/parties")
@Operation(summary = "모임 채팅방 목록 조회", description = "회원이 자신의 모임 채팅방 목록을 조회합니다.")
Expand Down Expand Up @@ -139,33 +137,6 @@ public ResponseEntity<Resource> downloadFile(
return chatFileService.downloadFile(fileId, token);
}

//TODO: 파일 다운로드 토큰 발급 API와 통합
@PostMapping("/images/{imageId}/download-token")
@Operation(summary = "채팅 이미지 다운로드 토큰 발급", description = "채팅방에 업로드된 특정 이미지를 다운로드할 수 있는 일회용 토큰을 발급합니다.")
@ApiResponse(responseCode = "200", description = "토큰 발급 성공")
@ApiResponse(responseCode = "403", description = "이미지 접근 권한 없음")
@ApiResponse(responseCode = "404", description = "존재하지 않는 이미지")
public BaseResponse<ChatDownloadTokenDTO.Response> issueImageDownloadToken(
@PathVariable Long imageId
) {
Long memberId = SecurityUtil.getCurrentMemberId();
ChatDownloadTokenDTO.Response response = chatImageService.issueDownloadToken(imageId, memberId);
return BaseResponse.success(CommonSuccessCode.OK, response);
}

//TODO: 파일 다운로드 API와 통합
@GetMapping("/images/{imageId}/download")
@Operation(summary = "채팅 이미지 다운로드", description = "발급받은 다운로드 토큰을 검증하고, 유효할 경우 실제 이미지 데이터를 반환합니다.")
@ApiResponse(responseCode = "200", description = "이미지 다운로드 성공")
@ApiResponse(responseCode = "403", description = "유효하지 않거나 만료된 토큰")
@ApiResponse(responseCode = "404", description = "존재하지 않는 이미지")
public ResponseEntity<Resource> downloadImage(
@PathVariable Long imageId,
@RequestParam String token
) {
return chatImageService.downloadImage(imageId, token);
}

@GetMapping("/parties/{partyId}")
@Operation(summary = "모임 채팅방 ID 조회")
@ApiResponse(responseCode = "200", description = "채팅방 ID 조회 성공")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,14 @@ public List<DirectChatRoomCreateDTO.MemberInfo> toMemberInfo(List<ChatRoomMember

public WebSocketMessageDTO.MessageResponse toSendMessageResponse(
Long chatRoomId, String content,
List<ChatCommonDTO.ImageInfo> images,
List<WebSocketMessageDTO.MessageResponse.FileInfo> files,
List<ChatCommonDTO.FileInfo> files,
ChatMessage savedMessage, Member sender, String senderProfileImageUrl, int unreadCount) {
return WebSocketMessageDTO.MessageResponse.builder()
.type(WebSocketMessageType.SEND)
.chatRoomId(chatRoomId)
.messageId(savedMessage.getId())
.content(content)
.images(images)
.files(files)
.images(files)
.senderId(sender.getId())
.senderName(sender.getMemberName())
.senderProfileImageUrl(senderProfileImageUrl)
Expand Down Expand Up @@ -171,7 +169,7 @@ public ChatRoomDetailDTO.ChatRoomInfo toChatRoomDetailChatRoomInfo(
public ChatCommonDTO.MessageInfo toCommonMessageInfo(
ChatMessage message,
String senderProfileImageUrl,
List<ChatCommonDTO.ImageInfo> processedImages,
List<ChatCommonDTO.FileInfo> processedFiles,
boolean isMyMessage,
boolean isSenderWithdrawn) {

Expand All @@ -183,21 +181,21 @@ public ChatCommonDTO.MessageInfo toCommonMessageInfo(
.isSenderWithdrawn(isSenderWithdrawn)
.content(message.getContent())
.messageType(message.getType())
.images(processedImages)
.images(processedFiles)
.timestamp(message.getCreatedAt())
.isMyMessage(isMyMessage)
.build();
}

public ChatCommonDTO.ImageInfo toImageInfo(ChatMessageImg img, String imageUrl) {
return ChatCommonDTO.ImageInfo.builder()
.imageId(img.getId())
.imageUrl(imageUrl)
.imgOrder(img.getImgOrder())
.isEmoji(img.getIsEmoji())
.originalFileName(img.getOriginalFileName())
.fileSize(img.getFileSize())
.fileType(img.getFileType())
public ChatCommonDTO.FileInfo toFileInfo(ChatMessageFile file, String fileUrl) {
return ChatCommonDTO.FileInfo.builder()
.imageId(file.getId())
.imageUrl(fileUrl)
.imgOrder(file.getFileOrder())
.isEmoji(file.getIsEmoji())
.originalFileName(file.getOriginalFileName())
.fileSize(file.getFileSize())
.fileType(file.getFileType())
.build();
}

Expand Down
20 changes: 4 additions & 16 deletions src/main/java/umc/cockple/demo/domain/chat/domain/ChatMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ public class ChatMessage extends BaseEntity {
@Column(nullable = false)
private Boolean isDeleted;

@OneToMany(mappedBy = "chatMessage", cascade = CascadeType.ALL, orphanRemoval = true)
@Builder.Default
private List<ChatMessageImg> chatMessageImgs = new ArrayList<>();

@OneToMany(mappedBy = "chatMessage", cascade = CascadeType.ALL, orphanRemoval = true)
@Builder.Default
private List<ChatMessageFile> chatMessageFiles = new ArrayList<>();
Expand All @@ -61,11 +57,11 @@ public String getDisplayContent() {
return this.content;
}

if (this.chatMessageImgs != null && !this.chatMessageImgs.isEmpty()) {
ChatMessageImg firstImg = this.chatMessageImgs.get(0);
int count = this.chatMessageImgs.size();
if (this.chatMessageFiles != null && !this.chatMessageFiles.isEmpty()) {
ChatMessageFile firstFile = this.chatMessageFiles.get(0);
int count = this.chatMessageFiles.size();

if (firstImg.getIsEmoji()) {
if (firstFile.getIsEmoji()) {
return "이모티콘을 보냈습니다.";
} else {
return count > 1 ?
Expand All @@ -74,14 +70,6 @@ public String getDisplayContent() {
}
}

// 파일이 있는 경우
if (this.chatMessageFiles != null && !this.chatMessageFiles.isEmpty()) {
int fileCount = this.chatMessageFiles.size();
return fileCount > 1 ?
String.format("파일 %d개를 보냈습니다.", fileCount) :
"파일을 보냈습니다.";
}

return "메시지";
}
}
Loading
Loading