Skip to content

Commit 6fda242

Browse files
namgigunloseminhojoyewon0705
authored
deploy: 최신 개발 내용 운영 반영
* Hotfix/loseminho : terminated 상태 조회 제거 (#314) * refactor: 스더티룸 권한에 대한 로직 개선 * fix: ci에서 통과 못한 테스트코드 수정 * fix:rest api와 웹소켓 중간 경로 통합 * fix:rest api와 웹소켓 중간 경로 통합 * fix: 에러 확인을 위한 통합테스트 추가, Room.create()메서드 수정 * refactor, feat : 조회 분할 * refactor: redis 로직 최적화 및 중복 검증 로직 제거 * fix: 에러 번호 수정 * feat: 스터디룸 방 비밀번호 변경 및 삭제 기능 구현 * fix:app-dev 제거 * feat: 웹소켓 기반 소극적 하트비트 * feat: 스터디룸 썸네일 기능 추가 및 webrtc 설정 변경에서 주석처리 * fix:소극적 하트비트 사용 주석처리 * Feat: 스터디 룸 내에 고양이 아바타 시스템과 프로필 이미지 url 연동 * fix: 기존 작성되어있던 test 코드 수정 * test: 아바타 테스트 코드 완료 * refactor: 프론트엔드 요청 사항에 따른 스터디룸 조회 마스킹 제거 * feat: 스터디룸 방 초대 코드 시스템 * Infra: main branch 로컬 환경과 운영 환경 동기화 * Infra: docker-compose 파일 수정 - Redis 버전 업그레이드 기존: 6.2 -> 변경: 7.0 * Fix: 백엔드 CD 파일 수정 - 자동화 시, 잘못된 도메인으로 호스트 ID 검증하는 오류 해결 * Infra: EC2 환경변수 수정 - 잘못 표기한 도메인 네임 변경 * Chore: CD 파일 수정 - Github Actions commandLine 인식 문제로 인해 set -Eeuo pipefail 줄바꿈 * Chore: 백엔드 CD 파일 수정 - 인스턴스 ID 체크 삭제 * Infra: 백엔드 CD 파일 수정 - .env 파일 추가시, $DOT_ENV_PROD -> $DOT_ENV 로 변경 * Infra: 도커 컴포즈 수정 - mysql 사용자 정보 변경 * Infra: 운영환경 설정 - application-prod.yml 과 application.yml 동기화 * Fix: SecurityConfig 수정 - H2 DB 허용 X * test,fix: 방 초대에 대한 테스트 코드 작성 및 에러 수정 * fix: 스터디룸 파일 업로드 맵핑 형식으로 변환 * fix: 병합충돌 제어 수정 * fix: 병합충돌 제어 * fix: 스터디 룸 내 프론트엔드 요구 사항 및 오류사항 수정 * feat: 방 즐겨찾기, 방 공지사항 구현 * fix: mockbean 수정 * fix: 테스트에서 빠진 비로그인 사용자 추가 * hotfix: 누락된 사용자 추방에 대한 컨트롤러 추가 * hotfix: VISITOR도 추방 가능하도록 수정 * fix: 누락된 테스트코드 추가 및 테스트코드 로직 수정 * refactor: 아바타 시스템 db와 분리 및 테스트 코드 수정 * fix: 턴서버 dev에 맞춤 * hotfix: 추방 후 추방당한 유저에게 개인 메시지 전송 로직 추가 * fix: 웹소켓 메세지 전송 * fix: 병합 오류 제어 * test: 테스트코드 수정 * refactor: 스터디룸 파일 업로드 s3 + fileAttachment + Mapping 제거 방식으로 수정 * feat: 방 내 방명록 기능 추가 * hotfix:로젝 내 웹소켓 세션 제거 * hotfix: 방 조회 시 terminated 상태는 조회 안되도록 --------- Co-authored-by: namgigun <[email protected]> * Refactor: PostService 구조 개선 및 매핑 로직 분리 (#298) (#316) * Ref: PostService 개선 * Test: 테스트 작성 * Infra: 기존 AWS 계정 → 신규 계정 리소스 마이그레이션 * Infra: RDS 설정 변경 - db 관련정보 하드 코딩 -> 변수화 * Infra: S3 인스턴스 설정 변경 S3 버킷명 변경 - team5-s3-1 -> catfe-s3-1 --------- Co-authored-by: loseminho <[email protected]> Co-authored-by: joyewon0705 <[email protected]>
1 parent 6cd3aba commit 6fda242

File tree

19 files changed

+482
-605
lines changed

19 files changed

+482
-605
lines changed

commits.txt

Lines changed: 0 additions & 388 deletions
This file was deleted.

infra/terraform/main.tf

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,9 @@ resource "aws_db_instance" "mysql" {
455455
allocated_storage = 20
456456
storage_type = "gp2"
457457

458-
db_name = "catfe"
459-
username = "catfe_user"
460-
password = "catfe_pass"
458+
db_name = "${var.db_name}"
459+
username = "${var.db_username}"
460+
password = "${var.db_password}"
461461

462462
db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name
463463
vpc_security_group_ids = [aws_security_group.rds_sg_1.id]
@@ -522,7 +522,7 @@ POLICY
522522

523523
# S3 인스턴스 생성
524524
resource "aws_s3_bucket" "s3_1" {
525-
bucket = "team5-s3-1"
525+
bucket = "catfe-s3-1"
526526
tags = {
527527
Key = "TEAM"
528528
Value = "devcos-team05"

src/main/java/com/back/domain/board/post/entity/Post.java

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -98,25 +98,6 @@ public void update(String title, String content, String thumbnailUrl) {
9898
this.thumbnailUrl = thumbnailUrl;
9999
}
100100

101-
/** 카테고리 일괄 업데이트 */
102-
public void updateCategories(List<PostCategory> newCategories) {
103-
List<PostCategory> currentCategories = this.getCategories();
104-
105-
// 제거 대상
106-
List<PostCategoryMapping> toRemove = this.getPostCategoryMappings().stream()
107-
.filter(mapping -> !newCategories.contains(mapping.getCategory()))
108-
.toList();
109-
110-
// 추가 대상
111-
List<PostCategory> toAdd = newCategories.stream()
112-
.filter(category -> !currentCategories.contains(category))
113-
.toList();
114-
115-
// 실행
116-
toRemove.forEach(this::removePostCategoryMapping);
117-
toAdd.forEach(category -> new PostCategoryMapping(this, category));
118-
}
119-
120101
/** 좋아요 수 증가 */
121102
public void increaseLikeCount() {
122103
this.likeCount++;
@@ -156,7 +137,7 @@ public void decreaseCommentCount() {
156137
// -------------------- 헬퍼 메서드 --------------------
157138
/** 게시글에 연결된 카테고리 목록 조회 */
158139
public List<PostCategory> getCategories() {
159-
return postCategoryMappings.stream()
140+
return this.postCategoryMappings.stream()
160141
.map(PostCategoryMapping::getCategory)
161142
.toList();
162143
}

src/main/java/com/back/domain/board/post/entity/PostCategory.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,8 @@ public PostCategory(String name, CategoryType type) {
3737
public void addPostCategoryMapping(PostCategoryMapping mapping) {
3838
this.postCategoryMappings.add(mapping);
3939
}
40+
41+
public void removePostCategoryMapping(PostCategoryMapping mapping) {
42+
this.postCategoryMappings.remove(mapping);
43+
}
4044
}

src/main/java/com/back/domain/board/post/entity/PostCategoryMapping.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,11 @@ public PostCategoryMapping(Post post, PostCategory category) {
3030
post.addPostCategoryMapping(this);
3131
category.addPostCategoryMapping(this);
3232
}
33+
34+
// -------------------- 헬퍼 메서드 --------------------
35+
/** 매핑 삭제 시 연관관계 정리 */
36+
public void remove() {
37+
this.post.removePostCategoryMapping(this);
38+
this.category.removePostCategoryMapping(this);
39+
}
3340
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.back.domain.board.post.repository;
2+
3+
import com.back.domain.board.post.entity.PostCategoryMapping;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.stereotype.Repository;
6+
7+
@Repository
8+
public interface PostCategoryMappingRepository extends JpaRepository<PostCategoryMapping, Long> {
9+
}

src/main/java/com/back/domain/board/post/repository/PostCategoryRepository.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22

33
import com.back.domain.board.post.entity.PostCategory;
44
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
6+
import org.springframework.data.repository.query.Param;
57
import org.springframework.stereotype.Repository;
68

79
import java.util.List;
810

911
@Repository
1012
public interface PostCategoryRepository extends JpaRepository<PostCategory, Long> {
1113
boolean existsByName(String name);
12-
List<PostCategory> findAllByNameIn(List<String> categoryNames);
14+
15+
@Query("SELECT c.id FROM PostCategory c WHERE c.name IN :names")
16+
List<Long> findIdsByNameIn(@Param("names") List<String> names);
1317
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package com.back.domain.board.post.service;
2+
3+
import com.back.domain.board.post.entity.Post;
4+
import com.back.domain.board.post.entity.PostCategory;
5+
import com.back.domain.board.post.entity.PostCategoryMapping;
6+
import com.back.domain.board.post.repository.PostCategoryMappingRepository;
7+
import com.back.domain.board.post.repository.PostCategoryRepository;
8+
import com.back.global.exception.CustomException;
9+
import com.back.global.exception.ErrorCode;
10+
import lombok.RequiredArgsConstructor;
11+
import org.springframework.stereotype.Service;
12+
import org.springframework.transaction.annotation.Transactional;
13+
14+
import java.util.List;
15+
16+
@Service
17+
@RequiredArgsConstructor
18+
@Transactional
19+
public class PostCategoryMappingService {
20+
private final PostCategoryMappingRepository postCategoryMappingRepository;
21+
private final PostCategoryRepository postCategoryRepository;
22+
23+
/**
24+
* 게시글 생성 시 카테고리 매핑 등록
25+
* - 카테고리 ID 유효성 검증 후 매핑 엔티티 생성
26+
*
27+
* @param post 게시글 엔티티
28+
* @param categoryIds 카테고리 ID 리스트
29+
*/
30+
public void createMappings(Post post, List<Long> categoryIds) {
31+
if (categoryIds == null || categoryIds.isEmpty()) return;
32+
33+
// 카테고리 유효성 검증
34+
List<PostCategory> categories = postCategoryRepository.findAllById(categoryIds);
35+
if (categories.size() != categoryIds.size()) {
36+
throw new CustomException(ErrorCode.CATEGORY_NOT_FOUND);
37+
}
38+
39+
// 매핑 생성
40+
categories.forEach(category -> {
41+
PostCategoryMapping mapping = new PostCategoryMapping(post, category);
42+
postCategoryMappingRepository.save(mapping);
43+
});
44+
}
45+
46+
/**
47+
* 게시글의 카테고리 매핑을 갱신
48+
* - 기존 매핑 제거 및 신규 매핑 추가 처리
49+
*
50+
* @param post 게시글 엔티티
51+
* @param categoryIds 카테고리 ID 리스트
52+
*/
53+
public void updateMappings(Post post, List<Long> categoryIds) {
54+
// null 또는 빈 리스트면 → 모든 매핑 제거
55+
if (categoryIds == null || categoryIds.isEmpty()) {
56+
deleteMappings(post);
57+
return;
58+
}
59+
60+
List<PostCategory> newCategories = postCategoryRepository.findAllById(categoryIds);
61+
if (newCategories.size() != categoryIds.size()) {
62+
throw new CustomException(ErrorCode.CATEGORY_NOT_FOUND);
63+
}
64+
65+
List<PostCategoryMapping> currentMappings = post.getPostCategoryMappings();
66+
List<PostCategory> currentCategories = post.getCategories();
67+
68+
// 제거 대상
69+
List<PostCategoryMapping> toRemove = currentMappings.stream()
70+
.filter(mapping -> !newCategories.contains(mapping.getCategory()))
71+
.toList();
72+
73+
// 추가 대상
74+
List<PostCategory> toAdd = newCategories.stream()
75+
.filter(category -> !currentCategories.contains(category))
76+
.toList();
77+
78+
// 제거 수행
79+
toRemove.forEach(mapping -> {
80+
mapping.remove();
81+
postCategoryMappingRepository.delete(mapping);
82+
});
83+
84+
// 추가 수행
85+
toAdd.forEach(category -> {
86+
PostCategoryMapping mapping = new PostCategoryMapping(post, category);
87+
postCategoryMappingRepository.save(mapping);
88+
});
89+
}
90+
91+
/**
92+
* 게시글의 모든 카테고리 매핑을 삭제
93+
*
94+
* @param post 게시글 엔티티
95+
*/
96+
public void deleteMappings(Post post) {
97+
List<PostCategoryMapping> existingMappings = post.getPostCategoryMappings();
98+
existingMappings.forEach(mapping -> {
99+
mapping.remove();
100+
postCategoryMappingRepository.delete(mapping);
101+
});
102+
}
103+
}

src/main/java/com/back/domain/board/post/service/PostService.java

Lines changed: 9 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@
22

33
import com.back.domain.board.common.dto.PageResponse;
44
import com.back.domain.board.post.entity.Post;
5-
import com.back.domain.board.post.entity.PostCategory;
65
import com.back.domain.board.post.dto.PostDetailResponse;
76
import com.back.domain.board.post.dto.PostListResponse;
87
import com.back.domain.board.post.dto.PostRequest;
98
import com.back.domain.board.post.dto.PostResponse;
10-
import com.back.domain.board.post.entity.PostCategoryMapping;
119
import com.back.domain.board.post.repository.PostBookmarkRepository;
12-
import com.back.domain.board.post.repository.PostCategoryRepository;
1310
import com.back.domain.board.post.repository.PostLikeRepository;
1411
import com.back.domain.board.post.repository.PostRepository;
1512
import com.back.domain.file.entity.AttachmentMapping;
@@ -38,8 +35,7 @@ public class PostService {
3835
private final PostLikeRepository postLikeRepository;
3936
private final PostBookmarkRepository postBookmarkRepository;
4037
private final UserRepository userRepository;
41-
private final PostCategoryRepository postCategoryRepository;
42-
private final FileAttachmentRepository fileAttachmentRepository;
38+
private final PostCategoryMappingService postCategoryMappingService;
4339
private final AttachmentMappingRepository attachmentMappingRepository;
4440
private final AttachmentMappingService attachmentMappingService;
4541

@@ -59,20 +55,12 @@ public PostResponse createPost(PostRequest request, Long userId) {
5955
Post post = new Post(user, request.title(), request.content(), request.thumbnailUrl());
6056
postRepository.save(post);
6157

62-
// Category 매핑
63-
if (request.categoryIds() != null) {
64-
List<PostCategory> categories = validateAndFindCategories(request.categoryIds());
65-
categories.forEach(category -> new PostCategoryMapping(post, category));
66-
}
58+
// Category 매핑 생성
59+
postCategoryMappingService.createMappings(post, request.categoryIds());
6760

68-
// AttachmentMapping 매핑
69-
List<FileAttachment> attachments = List.of();
70-
if (request.imageIds() != null && !request.imageIds().isEmpty()) {
71-
attachments = validateAndFindAttachments(request.imageIds());
72-
for (FileAttachment attachment : attachments) {
73-
attachmentMappingRepository.save(new AttachmentMapping(attachment, EntityType.POST, post.getId()));
74-
}
75-
}
61+
// Attachment 매핑 생성
62+
List<FileAttachment> attachments =
63+
attachmentMappingService.createAttachments(EntityType.POST, post.getId(), userId, request.imageIds());
7664

7765
return PostResponse.from(post, attachments);
7866
}
@@ -149,62 +137,15 @@ public PostResponse updatePost(Long postId, PostRequest request, Long userId) {
149137
post.update(request.title(), request.content(), request.thumbnailUrl());
150138

151139
// Category 매핑 업데이트
152-
List<PostCategory> categories = validateAndFindCategories(request.categoryIds());
153-
post.updateCategories(categories);
140+
postCategoryMappingService.updateMappings(post, request.categoryIds());
154141

155-
// TODO: 리팩토링 필요
156142
// 첨부 이미지 갱신
157-
List<FileAttachment> attachments = updatePostAttachments(post, request.imageIds(), userId);
143+
List<FileAttachment> attachments =
144+
attachmentMappingService.updateAttachments(EntityType.POST, postId, userId, request.imageIds());
158145

159146
return PostResponse.from(post, attachments);
160147
}
161148

162-
/**
163-
* 첨부 이미지 매핑 갱신
164-
* - 이미지 변경 없음 → 유지
165-
* - 변경 있음 → 기존 파일 및 매핑 삭제 후 새로 저장
166-
* - 새로 추가됨 → 새 매핑 생성
167-
* - 제거됨 → 기존 매핑 삭제
168-
*/
169-
private List<FileAttachment> updatePostAttachments(Post post, List<Long> newImageIds, Long userId) {
170-
List<Long> newIds = (newImageIds != null) ? newImageIds : List.of();
171-
172-
// 기존 매핑 조회
173-
List<AttachmentMapping> existingMappings =
174-
attachmentMappingRepository.findAllByEntityTypeAndEntityId(EntityType.POST, post.getId());
175-
List<Long> existingIds = existingMappings.stream()
176-
.map(m -> m.getFileAttachment().getId())
177-
.toList();
178-
179-
// 변경 없음 → 유지
180-
if (existingIds.equals(newIds)) {
181-
return existingMappings.stream()
182-
.map(AttachmentMapping::getFileAttachment)
183-
.toList();
184-
}
185-
186-
// 기존 중 newIds에 없는 첨부만 삭제
187-
attachmentMappingService.deleteRemovedAttachments(EntityType.POST, post.getId(), userId, newIds);
188-
189-
// 새로 추가된 첨부만 매핑 생성
190-
List<Long> addedIds = newIds.stream()
191-
.filter(id -> !existingIds.contains(id))
192-
.toList();
193-
194-
if (!addedIds.isEmpty()) {
195-
List<FileAttachment> newAttachments = validateAndFindAttachments(addedIds);
196-
newAttachments.forEach(attachment ->
197-
attachmentMappingRepository.save(new AttachmentMapping(attachment, EntityType.POST, post.getId()))
198-
);
199-
}
200-
201-
// 최신 매핑 다시 조회
202-
return attachmentMappingRepository.findAllByEntityTypeAndEntityId(EntityType.POST, post.getId())
203-
.stream()
204-
.map(AttachmentMapping::getFileAttachment)
205-
.toList();
206-
}
207-
208149
/**
209150
* 게시글 삭제 서비스
210151
*
@@ -232,26 +173,4 @@ public void deletePost(Long postId, Long userId) {
232173
post.remove();
233174
postRepository.delete(post);
234175
}
235-
236-
/**
237-
* 카테고리 ID 유효성 검증 및 조회
238-
*/
239-
private List<PostCategory> validateAndFindCategories(List<Long> categoryIds) {
240-
if (categoryIds == null || categoryIds.isEmpty()) return List.of();
241-
return categoryIds.stream()
242-
.map(id -> postCategoryRepository.findById(id)
243-
.orElseThrow(() -> new CustomException(ErrorCode.CATEGORY_NOT_FOUND)))
244-
.toList();
245-
}
246-
247-
/**
248-
* 첨부 파일 ID 유효성 검증 및 조회
249-
*/
250-
private List<FileAttachment> validateAndFindAttachments(List<Long> imageIds) {
251-
if (imageIds == null || imageIds.isEmpty()) return List.of();
252-
return imageIds.stream()
253-
.map(id -> fileAttachmentRepository.findById(id)
254-
.orElseThrow(() -> new CustomException(ErrorCode.FILE_NOT_FOUND)))
255-
.toList();
256-
}
257176
}

src/main/java/com/back/domain/file/repository/AttachmentMappingRepository.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22

33
import com.back.domain.file.entity.AttachmentMapping;
44
import com.back.domain.file.entity.EntityType;
5+
import org.springframework.data.jpa.repository.EntityGraph;
56
import org.springframework.data.jpa.repository.JpaRepository;
67

78
import java.util.List;
89
import java.util.Optional;
910

1011
public interface AttachmentMappingRepository extends JpaRepository<AttachmentMapping, Long> {
12+
@EntityGraph(attributePaths = "fileAttachment")
13+
List<AttachmentMapping> findAllByFileAttachmentIdIn(List<Long> attachmentIds);
14+
15+
@EntityGraph(attributePaths = "fileAttachment")
1116
List<AttachmentMapping> findAllByEntityTypeAndEntityId(EntityType entityType, Long entityId);
17+
1218
Optional<AttachmentMapping> findByEntityTypeAndEntityId(EntityType entityType, Long entityId);
1319

1420
void deleteAllByEntityTypeAndEntityId(EntityType entityType, Long entityId);

0 commit comments

Comments
 (0)