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
388 changes: 0 additions & 388 deletions commits.txt

This file was deleted.

8 changes: 4 additions & 4 deletions infra/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,9 @@ resource "aws_db_instance" "mysql" {
allocated_storage = 20
storage_type = "gp2"

db_name = "catfe"
username = "catfe_user"
password = "catfe_pass"
db_name = "${var.db_name}"
username = "${var.db_username}"
password = "${var.db_password}"

db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name
vpc_security_group_ids = [aws_security_group.rds_sg_1.id]
Expand Down Expand Up @@ -522,7 +522,7 @@ POLICY

# S3 인스턴스 생성
resource "aws_s3_bucket" "s3_1" {
bucket = "team5-s3-1"
bucket = "catfe-s3-1"
tags = {
Key = "TEAM"
Value = "devcos-team05"
Expand Down
21 changes: 1 addition & 20 deletions src/main/java/com/back/domain/board/post/entity/Post.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,6 @@ public void update(String title, String content, String thumbnailUrl) {
this.thumbnailUrl = thumbnailUrl;
}

/** 카테고리 일괄 업데이트 */
public void updateCategories(List<PostCategory> newCategories) {
List<PostCategory> currentCategories = this.getCategories();

// 제거 대상
List<PostCategoryMapping> toRemove = this.getPostCategoryMappings().stream()
.filter(mapping -> !newCategories.contains(mapping.getCategory()))
.toList();

// 추가 대상
List<PostCategory> toAdd = newCategories.stream()
.filter(category -> !currentCategories.contains(category))
.toList();

// 실행
toRemove.forEach(this::removePostCategoryMapping);
toAdd.forEach(category -> new PostCategoryMapping(this, category));
}

/** 좋아요 수 증가 */
public void increaseLikeCount() {
this.likeCount++;
Expand Down Expand Up @@ -156,7 +137,7 @@ public void decreaseCommentCount() {
// -------------------- 헬퍼 메서드 --------------------
/** 게시글에 연결된 카테고리 목록 조회 */
public List<PostCategory> getCategories() {
return postCategoryMappings.stream()
return this.postCategoryMappings.stream()
.map(PostCategoryMapping::getCategory)
.toList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ public PostCategory(String name, CategoryType type) {
public void addPostCategoryMapping(PostCategoryMapping mapping) {
this.postCategoryMappings.add(mapping);
}

public void removePostCategoryMapping(PostCategoryMapping mapping) {
this.postCategoryMappings.remove(mapping);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ public PostCategoryMapping(Post post, PostCategory category) {
post.addPostCategoryMapping(this);
category.addPostCategoryMapping(this);
}

// -------------------- 헬퍼 메서드 --------------------
/** 매핑 삭제 시 연관관계 정리 */
public void remove() {
this.post.removePostCategoryMapping(this);
this.category.removePostCategoryMapping(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.back.domain.board.post.repository;

import com.back.domain.board.post.entity.PostCategoryMapping;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PostCategoryMappingRepository extends JpaRepository<PostCategoryMapping, Long> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import com.back.domain.board.post.entity.PostCategory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface PostCategoryRepository extends JpaRepository<PostCategory, Long> {
boolean existsByName(String name);
List<PostCategory> findAllByNameIn(List<String> categoryNames);

@Query("SELECT c.id FROM PostCategory c WHERE c.name IN :names")
List<Long> findIdsByNameIn(@Param("names") List<String> names);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.back.domain.board.post.service;

import com.back.domain.board.post.entity.Post;
import com.back.domain.board.post.entity.PostCategory;
import com.back.domain.board.post.entity.PostCategoryMapping;
import com.back.domain.board.post.repository.PostCategoryMappingRepository;
import com.back.domain.board.post.repository.PostCategoryRepository;
import com.back.global.exception.CustomException;
import com.back.global.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
@Transactional
public class PostCategoryMappingService {
private final PostCategoryMappingRepository postCategoryMappingRepository;
private final PostCategoryRepository postCategoryRepository;

/**
* 게시글 생성 시 카테고리 매핑 등록
* - 카테고리 ID 유효성 검증 후 매핑 엔티티 생성
*
* @param post 게시글 엔티티
* @param categoryIds 카테고리 ID 리스트
*/
public void createMappings(Post post, List<Long> categoryIds) {
if (categoryIds == null || categoryIds.isEmpty()) return;

// 카테고리 유효성 검증
List<PostCategory> categories = postCategoryRepository.findAllById(categoryIds);
if (categories.size() != categoryIds.size()) {
throw new CustomException(ErrorCode.CATEGORY_NOT_FOUND);
}

// 매핑 생성
categories.forEach(category -> {
PostCategoryMapping mapping = new PostCategoryMapping(post, category);
postCategoryMappingRepository.save(mapping);
});
}

/**
* 게시글의 카테고리 매핑을 갱신
* - 기존 매핑 제거 및 신규 매핑 추가 처리
*
* @param post 게시글 엔티티
* @param categoryIds 카테고리 ID 리스트
*/
public void updateMappings(Post post, List<Long> categoryIds) {
// null 또는 빈 리스트면 → 모든 매핑 제거
if (categoryIds == null || categoryIds.isEmpty()) {
deleteMappings(post);
return;
}

List<PostCategory> newCategories = postCategoryRepository.findAllById(categoryIds);
if (newCategories.size() != categoryIds.size()) {
throw new CustomException(ErrorCode.CATEGORY_NOT_FOUND);
}

List<PostCategoryMapping> currentMappings = post.getPostCategoryMappings();
List<PostCategory> currentCategories = post.getCategories();

// 제거 대상
List<PostCategoryMapping> toRemove = currentMappings.stream()
.filter(mapping -> !newCategories.contains(mapping.getCategory()))
.toList();

// 추가 대상
List<PostCategory> toAdd = newCategories.stream()
.filter(category -> !currentCategories.contains(category))
.toList();

// 제거 수행
toRemove.forEach(mapping -> {
mapping.remove();
postCategoryMappingRepository.delete(mapping);
});

// 추가 수행
toAdd.forEach(category -> {
PostCategoryMapping mapping = new PostCategoryMapping(post, category);
postCategoryMappingRepository.save(mapping);
});
}

/**
* 게시글의 모든 카테고리 매핑을 삭제
*
* @param post 게시글 엔티티
*/
public void deleteMappings(Post post) {
List<PostCategoryMapping> existingMappings = post.getPostCategoryMappings();
existingMappings.forEach(mapping -> {
mapping.remove();
postCategoryMappingRepository.delete(mapping);
});
}
}
99 changes: 9 additions & 90 deletions src/main/java/com/back/domain/board/post/service/PostService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@

import com.back.domain.board.common.dto.PageResponse;
import com.back.domain.board.post.entity.Post;
import com.back.domain.board.post.entity.PostCategory;
import com.back.domain.board.post.dto.PostDetailResponse;
import com.back.domain.board.post.dto.PostListResponse;
import com.back.domain.board.post.dto.PostRequest;
import com.back.domain.board.post.dto.PostResponse;
import com.back.domain.board.post.entity.PostCategoryMapping;
import com.back.domain.board.post.repository.PostBookmarkRepository;
import com.back.domain.board.post.repository.PostCategoryRepository;
import com.back.domain.board.post.repository.PostLikeRepository;
import com.back.domain.board.post.repository.PostRepository;
import com.back.domain.file.entity.AttachmentMapping;
Expand Down Expand Up @@ -38,8 +35,7 @@ public class PostService {
private final PostLikeRepository postLikeRepository;
private final PostBookmarkRepository postBookmarkRepository;
private final UserRepository userRepository;
private final PostCategoryRepository postCategoryRepository;
private final FileAttachmentRepository fileAttachmentRepository;
private final PostCategoryMappingService postCategoryMappingService;
private final AttachmentMappingRepository attachmentMappingRepository;
private final AttachmentMappingService attachmentMappingService;

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

// Category 매핑
if (request.categoryIds() != null) {
List<PostCategory> categories = validateAndFindCategories(request.categoryIds());
categories.forEach(category -> new PostCategoryMapping(post, category));
}
// Category 매핑 생성
postCategoryMappingService.createMappings(post, request.categoryIds());

// AttachmentMapping 매핑
List<FileAttachment> attachments = List.of();
if (request.imageIds() != null && !request.imageIds().isEmpty()) {
attachments = validateAndFindAttachments(request.imageIds());
for (FileAttachment attachment : attachments) {
attachmentMappingRepository.save(new AttachmentMapping(attachment, EntityType.POST, post.getId()));
}
}
// Attachment 매핑 생성
List<FileAttachment> attachments =
attachmentMappingService.createAttachments(EntityType.POST, post.getId(), userId, request.imageIds());

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

// Category 매핑 업데이트
List<PostCategory> categories = validateAndFindCategories(request.categoryIds());
post.updateCategories(categories);
postCategoryMappingService.updateMappings(post, request.categoryIds());

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

return PostResponse.from(post, attachments);
}

/**
* 첨부 이미지 매핑 갱신
* - 이미지 변경 없음 → 유지
* - 변경 있음 → 기존 파일 및 매핑 삭제 후 새로 저장
* - 새로 추가됨 → 새 매핑 생성
* - 제거됨 → 기존 매핑 삭제
*/
private List<FileAttachment> updatePostAttachments(Post post, List<Long> newImageIds, Long userId) {
List<Long> newIds = (newImageIds != null) ? newImageIds : List.of();

// 기존 매핑 조회
List<AttachmentMapping> existingMappings =
attachmentMappingRepository.findAllByEntityTypeAndEntityId(EntityType.POST, post.getId());
List<Long> existingIds = existingMappings.stream()
.map(m -> m.getFileAttachment().getId())
.toList();

// 변경 없음 → 유지
if (existingIds.equals(newIds)) {
return existingMappings.stream()
.map(AttachmentMapping::getFileAttachment)
.toList();
}

// 기존 중 newIds에 없는 첨부만 삭제
attachmentMappingService.deleteRemovedAttachments(EntityType.POST, post.getId(), userId, newIds);

// 새로 추가된 첨부만 매핑 생성
List<Long> addedIds = newIds.stream()
.filter(id -> !existingIds.contains(id))
.toList();

if (!addedIds.isEmpty()) {
List<FileAttachment> newAttachments = validateAndFindAttachments(addedIds);
newAttachments.forEach(attachment ->
attachmentMappingRepository.save(new AttachmentMapping(attachment, EntityType.POST, post.getId()))
);
}

// 최신 매핑 다시 조회
return attachmentMappingRepository.findAllByEntityTypeAndEntityId(EntityType.POST, post.getId())
.stream()
.map(AttachmentMapping::getFileAttachment)
.toList();
}

/**
* 게시글 삭제 서비스
*
Expand Down Expand Up @@ -232,26 +173,4 @@ public void deletePost(Long postId, Long userId) {
post.remove();
postRepository.delete(post);
}

/**
* 카테고리 ID 유효성 검증 및 조회
*/
private List<PostCategory> validateAndFindCategories(List<Long> categoryIds) {
if (categoryIds == null || categoryIds.isEmpty()) return List.of();
return categoryIds.stream()
.map(id -> postCategoryRepository.findById(id)
.orElseThrow(() -> new CustomException(ErrorCode.CATEGORY_NOT_FOUND)))
.toList();
}

/**
* 첨부 파일 ID 유효성 검증 및 조회
*/
private List<FileAttachment> validateAndFindAttachments(List<Long> imageIds) {
if (imageIds == null || imageIds.isEmpty()) return List.of();
return imageIds.stream()
.map(id -> fileAttachmentRepository.findById(id)
.orElseThrow(() -> new CustomException(ErrorCode.FILE_NOT_FOUND)))
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@

import com.back.domain.file.entity.AttachmentMapping;
import com.back.domain.file.entity.EntityType;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

public interface AttachmentMappingRepository extends JpaRepository<AttachmentMapping, Long> {
@EntityGraph(attributePaths = "fileAttachment")
List<AttachmentMapping> findAllByFileAttachmentIdIn(List<Long> attachmentIds);

@EntityGraph(attributePaths = "fileAttachment")
List<AttachmentMapping> findAllByEntityTypeAndEntityId(EntityType entityType, Long entityId);

Optional<AttachmentMapping> findByEntityTypeAndEntityId(EntityType entityType, Long entityId);

void deleteAllByEntityTypeAndEntityId(EntityType entityType, Long entityId);
Expand Down
Loading