Skip to content
Open
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.

94 changes: 21 additions & 73 deletions infra/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,14 @@ resource "aws_security_group" "sg_1" {
cidr_blocks = ["0.0.0.0/0"]
}

# MySQL (port 3306)
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

# 아웃바운드 모든 프로토콜
egress {
from_port = 0
Expand Down Expand Up @@ -322,6 +330,18 @@ docker run -d \
-v /dockerProjects/npm_1/volumes/etc/letsencrypt:/etc/letsencrypt \
jc21/nginx-proxy-manager:latest

# MySQL 설치
docker run -d \
--name mysql_1 \
--network common \
-e MYSQL_ROOT_PASSWORD=root_pass \
-e MYSQL_DATABASE=${var.db_name} \
-e MYSQL_USER=${var.db_username} \
-e MYSQL_PASSWORD=${var.db_password} \
-p 3306:3306 \
-v mysql_data:/var/lib/mysql \
mysql:8.0

# ghcr.io 로그인
echo "${var.github_access_token_1}" | docker login ghcr.io -u ${var.github_access_token_1_owner} --password-stdin

Expand Down Expand Up @@ -408,78 +428,6 @@ output "coturn_server_public_ip" {
value = aws_instance.coturn_server.public_ip
}

# RDS용 Security Group
resource "aws_security_group" "rds_sg_1" {
name = "team5-rds-sg-1"
description = "Allow All"
vpc_id = aws_vpc.vpc_1.id

ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "all"
cidr_blocks = ["0.0.0.0/0"]
}

tags = {
Key = "TEAM"
Value = "devcos-team05"
Name = "team5-rds-sg-1"
}
}

# RDS Subnet Group
resource "aws_db_subnet_group" "db_subnet_group" {
name = "team5-db-subnet-group"
subnet_ids = [aws_subnet.subnet_2.id, aws_subnet.subnet_3.id]

tags = {
Key = "TEAM"
Value = "devcos-team05"
Name = "team5-db-subnet-group"
}
}

resource "aws_db_instance" "mysql" {
identifier = "team5-mysql"
engine = "mysql"
engine_version = "8.0"
instance_class = "db.t3.micro"
allocated_storage = 20
storage_type = "gp2"

db_name = "catfe"
username = "catfe_user"
password = "catfe_pass"

db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name
vpc_security_group_ids = [aws_security_group.rds_sg_1.id]

# RDS 퍼블릭 액세스 허용
publicly_accessible = true

multi_az = false

# 자동 백업 보관 기간
backup_retention_period = 1

# 삭제 시 최종 스냅샷 생성 여부
skip_final_snapshot = true

tags = {
Key = "TEAM"
Value = "devcos-team05"
Name = "team5-mysql"
}
}

# EC2 역할에 AmazonS3FullAccess 정책을 부착
resource "aws_iam_role_policy_attachment" "s3_full_access" {
role = aws_iam_role.ec2_role_1.name
Expand Down Expand Up @@ -522,7 +470,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);
});
}
}
Loading