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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ bin/
.DS_Store

.env
.env.aws
.env.prod
.claudeignore
.claude
.mcp.json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,26 @@ public List<BlockedUserResponse> getBlockedUsers(Long blockerUserId) {
public Set<Long> getBlockedUserIds(Long blockerUserId) {
String cacheKey = BLOCK_CACHE_KEY_PREFIX + blockerUserId;

Set<Long> cachedBlockedIds = (Set<Long>) redisTemplate.opsForValue().get(cacheKey);
if (cachedBlockedIds != null) {
return cachedBlockedIds;
Object cachedValue = redisTemplate.opsForValue().get(cacheKey);

if (cachedValue != null) {
// Redis 직렬화(JSON) 과정에서 Set이 List(Array)로 변환되어 저장된 경우 처리
if (cachedValue instanceof java.util.List) {
return new java.util.HashSet<>((java.util.List<Long>) cachedValue);
}
// 설정에 따라 Set 타입 그대로 복원된 경우
if (cachedValue instanceof Set) {
return (Set<Long>) cachedValue;
}
// 그 외의 타입이 들어있다면 무시하고 DB 조회로 넘어갑니다.
}

// DB 조회 로직 (기존과 동일)
Set<Long> blockedUserIds = userBlockRepository.findByBlockerUserId(blockerUserId).stream()
.map(UserBlock::getBlockedUserId)
.collect(Collectors.toSet());

// 캐시 저장
redisTemplate.opsForValue().set(cacheKey, blockedUserIds, CACHE_TTL);

return blockedUserIds;
Expand Down
42 changes: 42 additions & 0 deletions chat-service/src/main/resources/application-aws.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# AWS 환경 설정 - Docker 컨테이너 간 통신용
server:
port: 9003

spring:
application:
name: chat-service

data:
mongodb:
host: mongodb
port: 27017
database: comatching_chat
auto-index-creation: true

kafka:
bootstrap-servers: kafka:29092
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
consumer:
group-id: chat-service-group
auto-offset-reset: latest
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

cloud:
aws:
credentials:
access-key: ${AWS_ACCESS_KEY}
secret-key: ${AWS_SECRET_KEY}
region:
static: ap-northeast-2
s3:
bucket: ${AWS_S3_BUCKET}

jwt:
secret: ${JWT_SECRET}
access-token:
expiration: ${ACCESS_TOKEN_EXP:86400000}
refresh-token:
expiration: ${REFRESH_TOKEN_EXP:604800000}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ public static ResponseCookie createAccessTokenCookie(String accessToken) {
return ResponseCookie.from("accessToken", accessToken)
.path("/")
.httpOnly(true)
.secure(false) // HTTPS 환경에서는 true
.secure(false)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The secure flag for authentication cookies is set to false. This allows sensitive tokens (accessToken and refreshToken) to be transmitted over unencrypted HTTP connections, making them vulnerable to interception via Man-in-the-Middle (MitM) attacks. It is highly recommended to set this to true for production environments.

.maxAge(Duration.ofDays(1).toSeconds())
.sameSite("Lax")
// .domain("comatching.site")
.build();
}

Expand All @@ -25,9 +26,10 @@ public static ResponseCookie createRefreshTokenCookie(String refreshToken) {
return ResponseCookie.from("refreshToken", refreshToken)
.path("/api/auth")
.httpOnly(true)
.secure(false) // HTTPS 환경에서는 true
.secure(false)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The secure flag for the refresh token cookie is set to false. This should be set to true to ensure the token is only transmitted over HTTPS, preventing exposure over unencrypted connections. It is strongly recommended to configure such sensitive cookie attributes dynamically via application.yml using environment-specific profiles and inject them with the @Value annotation, rather than hardcoding secure(false).

.maxAge(Duration.ofDays(7).toSeconds())
.sameSite("Lax")
.domain("comatching.site")
.build();
}

Expand All @@ -36,7 +38,8 @@ public static ResponseCookie createExpiredCookie(String cookieName) {
return ResponseCookie.from(cookieName, "")
.path(cookieName.equals("accessToken") ? "/" :"/api/auth")
.httpOnly(true)
.maxAge(0) // 즉시 만료
.maxAge(0)
.domain("comatching.site")
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.comatching.gateway;

import org.redisson.spring.starter.RedissonAutoConfigurationV2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
Expand All @@ -12,7 +15,10 @@
@SpringBootApplication(
exclude = {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
HibernateJpaAutoConfiguration.class,
RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class,
RedissonAutoConfigurationV2.class
}
)
@ComponentScan(
Expand Down
100 changes: 100 additions & 0 deletions gateway-service/src/main/resources/application-aws.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# AWS 환경 설정 - Docker 컨테이너 간 통신용
server:
port: 8080

spring:
application:
name: gateway-service

cloud:
gateway:
server:
webflux:
# CORS 설정
globalcors:
cors-configurations:
'[/**]':
allowedOrigins:
- "https://comatching.site"
- "http://localhost:3000"
- "http://localhost:5173"
allowedMethods: [GET, POST, PUT, DELETE, OPTIONS]
allowedHeaders: "*"
allowCredentials: true

# 라우팅 규칙 - 컨테이너 이름 사용
routes:
- id: user-service-public
uri: http://user-service:9000
predicates:
- Path=/api/auth/login, /api/auth/signup, /api/auth/signup/nickname/availability, /api/auth/participants, /api/auth/email/**, /oauth2/**, /login/**, /default-ui.css

- id: user-service-protected
uri: http://user-service:9000
predicates:
- Path=/api/auth/signup/profile, /api/auth/logout, /api/auth/reissue, /api/auth/password/**, /api/auth/withdraw, /api/members/**, /api/internal/users/**
filters:
- AuthorizationHeaderFilter

- id: user-service-swagger
uri: http://user-service:9000
predicates:
- Path=/user-doc/**
filters:
- RewritePath=/user-doc/(?<segment>.*), /$\{segment}

- id: matching-service
uri: http://matching-service:9001
predicates:
- Path=/api/matching/**, /api/internal/matching/**
filters:
- AuthorizationHeaderFilter

- id: matching-service-swagger
uri: http://matching-service:9001
predicates:
- Path=/matching-doc/**
filters:
- RewritePath=/matching-doc/(?<segment>.*), /$\{segment}

- id: chat-service
uri: http://chat-service:9003
predicates:
- Path=/api/chat/**, /api/internal/chat/**, /ws/**
filters:
- AuthorizationHeaderFilter

- id: chat-service-swagger
uri: http://chat-service:9003
predicates:
- Path=/chat-doc/**
filters:
- RewritePath=/chat-doc/(?<segment>.*), /$\{segment}

- id: item-service
uri: http://item-service:9006
predicates:
- Path=/api/items/**, /api/internal/items/**
filters:
- AuthorizationHeaderFilter

- id: notification-service
uri: http://notification:9005
predicates:
- Path=/api/fcm/**
filters:
- AuthorizationHeaderFilter

default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST

jwt:
secret: ${JWT_SECRET}
access-token:
expiration: ${ACCESS_TOKEN_EXP:86400000}
refresh-token:
expiration: ${REFRESH_TOKEN_EXP:604800000}

logging:
level:
org.springframework.cloud.gateway: INFO
18 changes: 2 additions & 16 deletions gateway-service/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ spring:
- id: user-service-public
uri: http://localhost:9000
predicates:
- Path=/api/auth/login, /api/auth/signup, /api/auth/email/**, /oauth2/**, /login/**, /default-ui.css
- Path=/api/auth/login, /api/auth/signup, /api/auth/signup/nickname/availability, /api/auth/participants, /api/auth/email/**, /oauth2/**, /login/**, /default-ui.css

- id: user-service-protected
uri: http://localhost:9000
Expand Down Expand Up @@ -71,24 +71,10 @@ spring:
filters:
- RewritePath=/chat-doc/(?<segment>.*), /$\{segment}

- id: payment-service
uri: http://localhost:9004
predicates:
- Path=/api/payment/**
filters:
- AuthorizationHeaderFilter

- id: payment-service-swagger
uri: http://localhost:9004
predicates:
- Path=/payment-doc/**
filters:
- RewritePath=/payment-doc/(?<segment>.*), /$\{segment}

- id: item-service
uri: http://localhost:9006
predicates:
- Path=/api/items/**, /api/internal/items/**
- Path=/api/items/**, /api/internal/items/**, /api/v1/**
filters:
- AuthorizationHeaderFilter

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.comatching.item.domain.dto;
package com.comatching.item.domain.item.dto;

import java.time.LocalDateTime;
import com.comatching.item.domain.entity.ItemHistory;
import com.comatching.item.domain.item.entity.ItemHistory;
import com.comatching.common.domain.enums.ItemType;
import com.comatching.item.domain.enums.ItemHistoryType;
import com.comatching.item.domain.item.enums.ItemHistoryType;

public record ItemHistoryResponse(
Long historyId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.comatching.item.domain.dto;
package com.comatching.item.domain.item.dto;

import java.time.LocalDateTime;

import com.comatching.common.domain.enums.ItemType;
import com.comatching.item.domain.entity.Item;
import com.comatching.item.domain.item.entity.Item;

public record ItemResponse(
Long itemId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.comatching.item.domain.entity;
package com.comatching.item.domain.item.entity;

import java.time.LocalDateTime;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.comatching.item.domain.entity;
package com.comatching.item.domain.item.entity;

import java.time.LocalDateTime;

import com.comatching.item.domain.enums.ItemHistoryType;
import com.comatching.item.domain.item.enums.ItemHistoryType;
import com.comatching.common.domain.enums.ItemType;

import jakarta.persistence.Column;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.comatching.item.domain.enums;
package com.comatching.item.domain.item.enums;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.comatching.item.domain.repository;
package com.comatching.item.domain.item.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -8,8 +8,8 @@
import org.springframework.stereotype.Repository;

import com.comatching.common.domain.enums.ItemType;
import com.comatching.item.domain.entity.ItemHistory;
import com.comatching.item.domain.enums.ItemHistoryType;
import com.comatching.item.domain.item.entity.ItemHistory;
import com.comatching.item.domain.item.enums.ItemHistoryType;

@Repository
public interface ItemHistoryRepository extends JpaRepository<ItemHistory, Long> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.comatching.item.domain.repository;
package com.comatching.item.domain.item.repository;

import java.util.List;

Expand All @@ -10,7 +10,7 @@
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.comatching.item.domain.entity.Item;
import com.comatching.item.domain.item.entity.Item;
import com.comatching.common.domain.enums.ItemType;

import jakarta.persistence.LockModeType;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.comatching.item.domain.service;
package com.comatching.item.domain.item.service;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import com.comatching.common.dto.response.PagingResponse;
import com.comatching.item.domain.dto.ItemHistoryResponse;
import com.comatching.item.domain.enums.ItemHistoryType;
import com.comatching.item.domain.item.dto.ItemHistoryResponse;
import com.comatching.item.domain.item.enums.ItemHistoryType;
import com.comatching.common.domain.enums.ItemType;

public interface ItemHistoryService {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.comatching.item.domain.service;
package com.comatching.item.domain.item.service;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -7,10 +7,10 @@

import com.comatching.common.domain.enums.ItemType;
import com.comatching.common.dto.response.PagingResponse;
import com.comatching.item.domain.dto.ItemHistoryResponse;
import com.comatching.item.domain.entity.ItemHistory;
import com.comatching.item.domain.enums.ItemHistoryType;
import com.comatching.item.domain.repository.ItemHistoryRepository;
import com.comatching.item.domain.item.dto.ItemHistoryResponse;
import com.comatching.item.domain.item.entity.ItemHistory;
import com.comatching.item.domain.item.enums.ItemHistoryType;
import com.comatching.item.domain.item.repository.ItemHistoryRepository;

import lombok.RequiredArgsConstructor;

Expand Down
Loading