
이제 글쓰기 작성을 위한 post 프로젝트를 생성할 것이다.
현재 스프링 클라우드에 대한 내용을 실습하고 있지만
서비스 로직 작성하는 부분이 대부분이기에
조금 더 흐름을 익히고 정리하기 위한 포스트가 될 것 같다.
언어들을 학습하고 실습하면서 가장 기본이 되는 것은 프로젝트 생성이다. 언제 어디서든 뚝딱! 프로젝트를 만드는게 가장 쉽지만 어려운 부분이라 생각한다.
local yml 파일에는 그 전과 같이 서버, 데이터소스, jpa, 유레카 내용이 포함된다.
@EnableDiscoveryClient
@EnableFeignClients
유레카 서버와 openFeign과 관련된 애노테이션을 꼭 추가해주어야 한다.
post 프로젝트의 주 기능은 글쓰기 기능, 댓글 기능이다.
작성할 로직은 크게 다음과 같다.
헤더유틸, 엔티티, 레파지토리, dto, 서비스, 컨트롤러.
제일 먼저 작성할 코드는 제목과 같다. 이 클래스에서 게이트웨이에서 넘어온 헤더 정보를 꺼내는 역할을 하게된다. 보통, 사용자 정보를 읽어온다.
X-Auth-UserId
X-Auth-Client-Device
X-Auth-Client-Address
값을 뽑아 오는 함수들과 예외로 구성되어 있다. 순서대로
getUserId()
getClientDevice()
getClientAddress() 메서드가 있고, 각 ThrowException()로 감싸져 있다.
따라서 다른 클래스에서 이 클래스를 사용할 때, GatewayRequestHeaderUtils.getUserIdOrThrowException() 이렇게 사용하게 된다.
포스팅, 댓글 엔티티를 작성할 것이고 포스팅 하나에 댓글이 여러개 달릴 수 있으므로 1 : N의 관계이다. 그러므로 댓글 엔티티 쪽에 ManyToOne 애노테이션이 들어가고 포스팅 쪽에도 댓글을 사용하므로 OneToMany 애노테이션을 달아 둔다.
public void addComment(PostComment comment) {
comment.setPost(this);
this.comments.add(comment);
}
setPost와 댓글 엔티티 쪽에 @Setter
private Post post; 연결 된다.
포스팅, 댓글 생성 dto.
주의할 사항은 파라미터 userId 같은 정보를 직접적으로 가져오면 보안적으로 치명적인 문제 가 된다.
엔티티를 만드는 것이 목표! -> post, comment 리턴.
대표로 post dto만 자세히 살펴보자.
@Getter
@Setter
public class PostCreateDto {
@NotBlank(message = "타이틀을 입력하세요.")
private String title;
@NotBlank(message = "본문을 입력하세요.")
private String content;
public Post toEntity() {
Post post = new Post();
post.setUserId(GatewayRequestHeaderUtils.getUserIdOrThrowException());
post.setPost(this.title, this.content);
return post;
}
}
✅ entity에서 title, content가
nullable = false 옵션이 있기 때문에 @NotBlank를 사용했다.
Dto로 요청을 받고 entity로 변환하는 역할을 하는 메서드이다.
이 메서드를 사용함으로써 DTO와 Entity의 책임 분리, 코드의 일관성, 유지보수, 보안 등의 장점을 얻을 수 있다.
서비스에서 구현할 가능은 포스팅 생성, 댓글 추가이다. 트랜잭션 안에서 save 하도록 한다.
postCommentRepository.save(postComment); -> 새로운 댓글이 생성된 상태
post.addComment(postComment); -> addComment를 해서 setPost를 통해 댓글과 포스트 사이에 연관 관계가 맺어지고 (화살표 같이) comment.add를 함으로써 post 안에 댓글이 최종 추가된다.
@Transactional
public void createPost(PostCreateDte create Dto) {
Post post = createDto.toEntity();
postRepository.save(post)
-> db에 저장
- id: backend-post
uri: lb://backend-post
predicates: # 라우팅 조건
- Path=/api/post/**
filters:
- AddAuthenticationHeader
먼저 회원 등록, 로그인을 한 후 발행되는 토큰을 Bearer Token에 넣고, 바디를 넣은 후 post요청을 보내면 아래 사진 처럼 db에 잘 등록이 됨을 알 수 있다.


이제, 포스트 댓글이 달리면 알림 메시지 로그 전송하는 것을 구현할 것이다. 이번엔 아날로그로 구현하고 다음 포스트에는 kafka를 이용할 것 같다.
유저의 핸드폰 번호로 전송한다는 컨셉이므로, post 프로젝트에 userInfoDto를 먼저 작성한다.
@Getter
@Setter
public class SiteUserInfoDto {
private String userId;
private String phoneNumber;
}
유저 프로젝트 컨트롤러
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "backend/user/v1", produces = MediaType.APPLICATION_JSON_VALUE)
public class BackendUserController {
private final SiteUserService siteUserService;
@GetMapping(value = "/user/{userId}")
public ApiResponseDto<SiteUserInfoDto> userInfo(@PathVariable String userId) {
SiteUserInfoDto userInfoDto = siteUserService.userInfo(userId);
return ApiResponseDto.createOk(userInfoDto);
}
}
post 프로젝트 유저 서비스
@FeignClient(name = "backend-user", path = "backend/user/v1")
public interface RemoteUserService {
@GetMapping(value = "/user/{userId}")
public ApiResponseDto<SiteUserInfoDto> userInfo(@PathVariable String userId);
}
-> openFeign을 이용하여 RestTemplate 없이 유저 서비스의 api를 호출할 수 있게 해준다.
이 후에는 알림을 받을 dto, 알림 서비스(전송 api)를 작성한다.
마찬가지로 openFeign을 이용해 알림 서비스의 api를 사용한다.
[댓글 작성 요청] →
[PostService] →
① PostRepository에서 게시글 조회 →
② PostCommentRepository에 댓글 저장 →
③ RemoteUserService 통해 작성자 정보 조회 →
④ RemoteAlimService 통해 SMS 전송
최종적으로 알림서비스 로그에 sms 알림 문구가 찍히게 된다.