Photogram은 MSA 기반으로 구성되어 있으며, 게시글 관련 기능은 Post-service, 사용자 정보는 User-service에서 담당하고 있다.
게시글 상세 조회 API는 작성자의 정보가 필요하기 때문에, Post-service는 User-service에 사용자 정보를 요청하게 되어 있다.
현재 게시글을 조회하는 플로우는 다음과 같다:
- 사용자가 게시글 상세 조회 요청
- Post-service는 게시글 데이터 조회
- 작성자 정보를 위해 User-service 호출
- 사용자 정보를 포함한 게시글 응답 반환
그런데 이 구조에 문제가 있는데, 만약 User-service가 다운되거나 응답하지 않는 상황이 발생하면, 게시글 조회 API 자체가 실패한다.
즉, User-service의 문제로 Post-service도 함께 장애가 나는 전파 구조이다.
해결 방법: Redis + Resilience4j
이 문제를 해결하기 위해 Redis 캐싱과 Resilience4j의 CircuitBreaker, Fallback 패턴을 적용했다.
User 데이터 캐싱
- User-service에서 불러온 사용자 정보를 Redis에 캐싱한다.
- 이후 사용자 정보를 조회할 때는 1차적으로 Redis에서 조회하고, 없을 경우에만 User-service에 요청한다.
이 방법으로 User-service에 장애 상황이더라도 캐시 된 데이터로 응답이 가능하다.
CircuitBreaker & Fallback
- Redis에도 데이터가 없고, 동시에 User-service도 장애 상태라면 여전히 문제가 발생할 수 있다.
- 이 상황을 막기 위해 CircuitBreaker와 Fallback 메서드를 함께 적용했다.
CircuitBreaker는 일정 횟수 이상 실패하면 호출 자체를 차단하고,
Fallback에서는 작성자 정보를 비공개 사용자로 대체해서 응답하도록 구현했다.
Redis와 User-service 모두에서 사용자 정보를 가져올 수 없는 경우 빈 사용자 정보를 Post-service 자체에서 반환한다.
결과적으로 사용자는 작성자 정보는 볼 수 없지만, Post-service에 장애 전파는 막을 수 있게 되었다.
@Service
class UserClientService(
private val userClient: UserClient
) {
@CircuitBreaker(name = "userClient", fallbackMethod = "fallbackUser")
@Cacheable(cacheNames = ["post_userCache"], key = "#loginUserId + ':' + #writerId")
fun getUser(loginUserId: Long, writerId: Long): UserDto {
return userClient.getUser(loginUserId, writerId)
}
fun fallbackUser(loginUserId: Long, writerId: Long, ex: Throwable): UserDto {
ex.printStackTrace()
return UserDto.ofPrivate(writerId)
}
}
실제 코드에선 @CircuitBreaker, @Cacheable 어노테이션으로 쉽게 구현할 수 있었다.
GitHub - setung/photogram
Contribute to setung/photogram development by creating an account on GitHub.
github.com
'project > Photogram' 카테고리의 다른 글
Photogram Push 기반 피드 구현 (0) | 2025.04.14 |
---|---|
Photogram 태그 기반 게시글 검색 기능 (0) | 2025.04.13 |
Photogram 인증 구현하기 (1) | 2025.04.13 |
Photogram 아키텍처 (0) | 2025.04.13 |
댓글