티스토리 뷰

Project 댕린이집

[게시판] 게시글 작성

xoo | 수진 2024. 6. 18. 23:54

게시판 작성 기능은 로그인한 회원만 사용할 수 있게 구현할 생각입니다.

 

1. 먼저 로그인을 한 상태라면? 게시글 작성 버튼을 누를시 작성 화면으로 이동
2. 로그인을 안 한 상태라면? 로그인이 필요하다는 알림을 띄우고 로그인 화면으로 이동
3. 현재 로그인한 사용자의 정보를 가져오기
4. 새로운 게시글 생성: 클라이언트로부터 받은 DTO를 ENTITY로 변환하고 필요한 필드 설정
5. Repository를 이용해 entity를 저장
6. 클라이언트로 응답을 보내기 위해 ENTITY를 다시 DTO로 변환하여 리턴

 

처음에는 일반적인 로직을 구현을 했는데요

나중에 유틸리티 메소드를 사용하여 리팩토링 했습니다.

현재 인증된 사용자를 가져오는 작업은 거의 모듈마다 다 필요로 하다고 생각되어 보안 컨텍스트에서 사용자 ID를 가져오는 코드를 SecurityUtil 클래스의 getCurrentUserId 메서드로 통합하여 코드의 중복을 줄이고 유지보수를 용이하게 했습니다.

그 과정을 기록해보겠습니다!

 

 


 

 [ 서버 ] 

1. Spring Security 설정

2. SecurityConfig 클래스 생성

여기까지는 이미 되어있는 상태입니다.

이제 SecurityUtil.java 클래스를 생성해줍니다.

 

3. SecurityUtil 클래스 생성 ⭐⭐⭐

현재 로그인한 사용자의 ID를 가져오기 위한 SecurityUtil 클래스를 만듭니다.

[ 패키지 선언 ]
저의 경우엔 시큐리티 클래스가 있는 config 패키지 안에 생성하였습니다.

[ import ]
SecurityUtile 클래스 내에서 사용되는 스프링 시큐리티 프레임워크의 클래스를 임포트 합니다.

[ getCurrentUserId() 메소드 선언 ]
유저의 아이디를 반환하는 public static 메소드 입니다.

[ 인증 객체 가져오기 ]
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();​

 

SecurityContextHolder는 현재 인증되고 있는 사용자의 세부 정보를 보유하는 보안 컨텍스트에 접근할 수 있게 하는데요, 이를 사용하여 현재 인증 객체를 가져옵니다.

[ 인증 확인 ]
인증 객체 authentication이 null이 아니고 인증된 사용자를 나타내는지 확인합니다.

[ principal 가져오기 ]
Object principal = authentication.getPrincipal();​

인증된 사용자와 연관된 principal 객체를 가져옵니다.

[ 사용자 ID 반환 ]

if (principal instanceof UserDetails) {
    return ((UserDetails) principal).getUsername();
} else {
    return principal.toString();
}

가져온 principal 객체가 UserDetails의 인스턴스인지 확인합니다 ( 사용자 세부 정보 )
- 인스턴스라면?  principal을 UserDetails로 캐스트하고 사용자 이름을 반환합니다.
- 아니라면? principal의 문자여 표현을 반환합니다.

 

 

4. UserRepository

UserEntity findByUserId(String userId);

 

 

 

5. BoardService

현재 로그인한 사용자의 정보를 가져와 게시글에 설정하는 로직을 추가합니다.

[ 게시글 작성 메소드 ]
게시글을 작성하는 역할을 하는 createBoard를 만들어줍니다.
이 메소드는 BoardDTO를 매개변수로 받아서 새로운 게시글을 생성하고 반환합니다.

[ 현재 사용자의 ID 가져오기 ]
String currentUserId = SecurityUtil.getCurrentUserId();​

만들어뒀던 SecurityUtil 클래스를 써먹을 차례 입니다.
SecurityUtil 클래스의 getCurrentUserId(); 메서드를 사용하여 인증된 사용자의 ID를 얻습니다.


[ 인증된 사용자 확인 ]
if (currentUserId == null || "anonymousUser".equals(currentUserId)) {
    throw new RuntimeException("로그인한 사용자가 없습니다.");
}​

현재 로그인한 사용자가 없거나 익명 사용자인 경우 예외를 던집니다.

[ 사용자 정보 가져오기 ] 
현재 사용자의 ID를 사용하여 해당 사용자의 정보를 가져옵니다. 사용자가 존재하지 않으면 예외를 던집니다.
생각해보니...이 부분도 충분히 캡슐화할 수 있지 않나 하는 생각이 듭니다. 추후 리팩토링 해보겠습니다!

[ 게시글 Entity 생성 ]

BoardEntity boardEntity = BoardEntity.builder()
        .userId(userEntity.getId())  // 현재 사용자의 ID로 설정
        .title(boardDTO.getTitle())
        .content(boardDTO.getContent())
        .boardDate(Date.valueOf(LocalDate.now())) // 현재 날짜 설정
        .views(0) // 초기 조회수 설정
        .userLike(0) // 초기 좋아요 수 설정
        .build();

 

새로운 게시글 엔터티를 생성하고 필요한 필드들을 설정합니다.

[ 게시글 저장 ]
boardRepository.save(boardEntity);​
생성된 게시글 엔터티를 저장합니다.

[ DTO로 변환하여 반환 ]
return BoardMapper.instance.boardToDTO(boardEntity);​

mapstruct를 사용하여 저장된 게시글 entity를 DTO로 변환하여 반환해줬습니다.

 

 

 [ 클라이언트 ] 

서버에서만 처리를 해봤자 아무 소용 없습니다.

클라이언트 측에서 정보를 함께 보내줘야 합니다.

여태까지 했던 것처럼 상태변수로 쿠키를 가져와 헤더에 같이 전송해주면 됩니다!

 

1. 게시글 작성에 필요한 상태 변수들을 지정해줍니다.

  // 게시글 작성에 필요한 상태 변수들
  let [title, setTitle] = useState('');
  let [content, setContent] = useState('');

 

2. 게시글 작성 핸들러 메소드를 작성해줍니다. (axios)

 

3. 리턴문 작성

 

 


 

 

💻 [ 결과 ]  

로그인을 하고 글 작성을 하게되면

이렇게 작성자 ID가 저장되고 나타나게 됩니다.

BUT…

작성자의 아이디나 닉네임을 저장해야되는데

고유 번호인 id를 저장시켰네요…

 

 


 

 

💣 [ 트러블 슈팅 ] 

문제

작성자 란에 작성자의 아이디가 아닌 PK값인 id가 렌더링 되는 문제 입니다.

 

 

원인

user 필드가 없어서 렌더링이 안됩니다.

서버에서 데이터를 가져올 때 userIdboard 객체에 포함하도록 수정해야 합니다.

즉, 서버 측 코드에서 BoardDTO를 반환할 때 UserDTO를 포함하여 userId를 제공하도록 수정해야 합니다.

 

해결

서버 측 수정

BoardDTO.java 수정 - 먼저, 서버 측에서 BoardDTOuserId 필드를 추가하고 이를 반환하도록 수정합니다. - BoardDTO.of 메서드에서 StrUserId를 설정합니다.

 

BoardEntity 클래스에는 UserEntity가 필드로 포함되어 있는 것을 확인합니다.

 

BoardMapper.java MapStruct를 사용하여 매핑할 때 UserEntity의 user_Id 필드를 매핑하도록 설정합니다.

 

BoardService.java

 

 

React 코드 수정

BoardList.js 렌더링 되는 부분 board.user_id → board.user_Id 로 변경

 

BoardView.js 상세보기 화면에서도 board.user_id → board.user_Id 로 변경

 

결과

PK이 값이 아닌 아이디가 잘 렌더링 되는 것을 확인할 수 있습니다!

기본적인거 같은데도 실수가 잦네요 😓

추후, 아이디가 아닌 닉네임이나 강쥐 이름으로 변경할 수도…

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함