SOLUX-완숙이

Access token으로 사용자 정보 가져오기

leeeehhjj 2022. 1. 28. 17:49

댓글과 멤버 클래스를 N:1 연관관계로 설정하면서

댓글을 작성했을 때 따로 프론트에서 로그인 정보를 받지 않아도

헤더에 있는 access token으로 로그인 된 사용자의 정보를 가져와 자동으로 댓글의 작성자를 설정해주는 코드를 구현해봤다.

또, 댓글을 저장하면서 어떤 게시글의 댓글인지 정보를 받아 연관 관계를 맺는 코드도 구현했다.

 

1. Comment 클래스

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import solux.wansuki.OurNeighbor_BE.domain.Gathering.Gathering;
import solux.wansuki.OurNeighbor_BE.domain.Member.Member;
import solux.wansuki.OurNeighbor_BE.domain.RecommendPost.RecommendPost;
import solux.wansuki.OurNeighbor_BE.domain.UsedGoods.UsedGoods;

import javax.persistence.*;

@Getter
@NoArgsConstructor
@Entity
public class Comment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "comment_id")
    private Long id;

    private String content;

    @JsonIgnore
    @ManyToOne
    @JoinColumn(name = "member_id")
    private Member member;

    @JsonIgnore
    @ManyToOne
    @JoinColumn(name = "gathering_id")
    private Gathering gathering;

    @Builder
    public Comment (String content) {
        this.content = content;
    }

    public void setMember(Member member) {
        this.member = member;
        if (!member.getComments().contains(this))
            member.getComments().add(this);
    }

    public void setGathering(Gathering gathering) {
        this.gathering = gathering;
        if (!gathering.getComments().contains(this))
            gathering.getComments().add(this);
    }
}

2. Member 클래스

@OneToMany(mappedBy = "member")
private List<Comment> comments = new ArrayList<>();

public void addComment(Comment comment) {
    this.comments.add(comment);
    if (comment.getMember() != this)
        comment.setMember(this);
}

-> 이렇게 댓글과 멤버를 N:1 양방향 관계로 설정해준다.

 

3. Comment Controller

@PostMapping("/comment/{postId}")
public Long saveComment(@RequestBody CommentSaveDto saveDto,
                        @PathVariable Long postId, @AuthenticationPrincipal User user) {
    return commentService.save(saveDto, postId, user);
}

@AuthenticalPrincipal : UserDetailsService에서 return 한 객체를 파라미터로 직접 받아 사용할 수 있도록 하는 어노테이션 -> 이 어노테이션을 사용하면 헤더에 첨부되어 있는 access token에서 로그인 된 사용자의 정보를 받아와 사용할 ㅅ ㅜ있다.

 

4. CommentSaveDto

@Getter
@NoArgsConstructor
public class CommentSaveDto {

    private String content;

    private String postCategory;

    @Builder
    public CommentSaveDto(String content) {
        this.content = content;
        this.postCategory = getPostCategory();
    }

    public Comment toEntity() {
        return Comment.builder()
                .content(content)
                .build();
    }
}

 다음과 같이 내용과 함께 postCategory라는 항목도 같이 프론트에서 받아오도록 했다.

 

5. Comment service

@Transactional
public Long save(CommentSaveDto saveDto, Long postId, User user) {
    Long id = commentRepository.save(saveDto.toEntity()).getId();
    Member member = memberRepository.findByLoginId(user.getUsername())
            .orElseThrow(()->new IllegalArgumentException("해당 유저 없음"));
    member.addComment(commentRepository.findById(id).orElseThrow());
    if (saveDto.getPostCategory().equals("gathering")) {
        Gathering gathering = gatheringRepository.findById(postId).orElseThrow();
        gathering.addComment(commentRepository.findById(id).orElseThrow());
    }
    else if (saveDto.getPostCategory().equals("recommend")) {
        RecommendPost recommendPost = recommendPostRepository.findById(postId).orElseThrow();
        recommendPost.addComment(commentRepository.findById(id).orElseThrow());
    }
    else if (saveDto.getPostCategory().equals("usedGoods")) {
        UsedGoods usedGoods = usedGoodsRepository.findById(postId).orElseThrow();
        usedGoods.addComment(commentRepository.findById(id).orElseThrow());
    }
    return id;
}

@AuthenticalPrincipal 을 이용해 받아온 user 객체를 통해 user.getUsername으로 사용자의 로그인 아이디를 가져와서 멤버 객체를 찾는다. 그 후 멤버와 댓글을 연관 지어준다.

 

6. Comment repository

public interface CommentRepository extends JpaRepository<Comment,Long> {
    List<Comment> findByGatheringId(Long gatheringId);
    List<Comment> findByRecommendPostId(Long recommendPostId);
    List<Comment> findByUsedGoodsId(Long usedGoodsId);
}

이처럼 JpaRepository를 extends하면 findBy 뒤에 GatheringId를 써서 gathering 클래스의 id 값을 통해 Comment의 리스트를 반환받을 수 있다.

 

7. Gathering service

public List<CommentResponseDto> getComment(Long id) {
    List<CommentResponseDto> responseDtos = new ArrayList<>();
    List<Comment> comments = commentRepository.findByGatheringId(id);
    for (Comment comment : comments) {
        CommentResponseDto commentResponseDto = CommentResponseDto.builder()
                .commentId(comment.getId())
                .content(comment.getContent())
                .userNickName(comment.getMember().getNickName())
                .build();
        responseDtos.add(commentResponseDto);
    }
    return responseDtos;
}

이 메소드를 통해 프론트가 gatheringId를 전송하면 그 게시글에 있는 댓글들을 모두 반환받을 수 있다.