카테고리 없음

one프로젝트 오류보고서2(Report 생성 시 userId가 null로 전달되어 신고 등록 실패)

sooho93 2024. 12. 19. 14:19

개요

  • 사용자가 댓글을 신고하려고 시도할 때, 백엔드에서 userId가 null로 전달되어 IllegalArgumentException이 발생합니다. 이로 인해 신고가 정상적으로 등록되지 않습니다.

3. 환경

  • 프론트엔드: React.js, Axios
  • 백엔드: Spring Boot, Spring Security, JPA/Hibernate
  • 데이터베이스: (사용 중인 DB 종류 기재)
  • 버전:
    • Spring Boot: 2.x 또는 3.x (정확한 버전 기재)
    • React: 17.x 또는 18.x (정확한 버전 기재)
    • 기타 관련 라이브러리 버전

4. 재현 단계

  1. 사용자가 특정 댓글에 대해 신고를 시도 (ReportModal 사용).
  2. 프론트엔드에서 ReportService.createReport(commentId, reason) 호출.
  3. 백엔드에서 /api/report 엔드포인트로 POST 요청 전송.
  4. 백엔드 로그 확인 시 userId=null로 로그가 출력됨.
  5. userRepository.findById(null) 호출로 인해 IllegalArgumentException 발생.

5. 실제 결과

  • 백엔드 로그:
    sql
    코드 복사
    INFO c.e.o.service.ReportServiceImpl : Attempting to create report for userId=null, commentId=1 ERROR o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() ... IllegalArgumentException: The given id must not be null
  • 프론트엔드 콘솔:
    java
    코드 복사
    신고 등록 중 오류 발생: TypeError: Cannot read properties of undefined (reading 'id') at handleSubmit (ReportModal.jsx:17:1)

6. 예상 결과

  • userId가 올바르게 전달되어 신고가 정상적으로 등록되고, 프론트엔드에서 성공 메시지가 표시됨.

7. 원인 분석

  • 현재 ReportServiceImpl에서 ReportDTO의 userId를 프론트엔드로부터 받아 처리하고 있으나, userId가 null로 전달되고 있음.
  • JwtAuthorizationFilter를 통해 SecurityContextHolder에서 인증된 사용자 정보를 추출하려고 시도했으나, 여전히 userId가 null로 남아있음.
  • 프론트엔드 ReportService.js에서 createReport 호출 시 userId를 전달하지 않거나, 백엔드에서 userId를 추출하는 로직이 제대로 작동하지 않음.

8. 시도한 해결 방법

  1. 백엔드 변경 사항:
    • ReportServiceImpl.createReport에서 SecurityContextHolder를 사용하여 인증된 사용자의 username을 추출하고, 이를 통해 User 엔티티를 조회하도록 수정.
    • ReportDTO에서 userId 필드 제거.
    • 예외 처리 개선 및 로그 추가.
  2. 프론트엔드 변경 사항:
    • ReportService.js에서 createReport 메서드에 userId 전달을 제거.
    • ReportModal.jsx에서 createReport 호출 시 commentId와 reason만 전달하도록 수정.
  3. JWT 필터 및 보안 설정 검토:
    • JwtAuthorizationFilter가 올바르게 등록되고, JWT 토큰이 Authorization 헤더를 통해 전달되는지 확인.
    • SecurityConfig에서 /api/report 엔드포인트에 대해 인증된 사용자만 접근할 수 있도록 설정.

9. 현재 상태

  • 백엔드에서 여전히 userId=null로 로그가 출력되어 findById(null) 호출 시 예외 발생.
  • 프론트엔드에서는 백엔드 오류로 인해 response.data가 undefined여서 추가적인 TypeError 발생.

10. 추가 정보

  • 프론트엔드 ReportService.js 코드:
    javascript
    코드 복사
    class ReportService { async createReport(commentId, reason) { try { const reportDTO = { commentId, reason }; console.log("Sending reportDTO:", reportDTO); // 디버그 로그 추가 const response = await axios.post(API_URL_COMMENT_REPORT, reportDTO, { headers: authHeader() }); return response.data; } catch (error) { console.error("Failed to create report:", error); throw error; } } async getReportsByComment(commentId) { try { const response = await axios.get(`${API_URL_ADMIN_REPORT}/${commentId}`, { headers: authHeader() }); return response.data; } catch (error) { console.error("Failed to get reports by comment:", error); throw error; } } } const reportService = new ReportService(); export default reportService;
  • 백엔드 ReportServiceImpl.java 코드:
    java
    코드 복사
    @Override public ReportDTO createReport(ReportDTO reportDTO) { Long commentId = reportDTO.getCommentId(); String reason = reportDTO.getReason(); // 현재 인증된 사용자 정보 획득 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String username = authentication.getName(); // 로그인한 사용자 이름 log.info("Creating report for user: " + username + ", commentId: " + commentId); User user = userRepository.findByUsername(username) .orElseThrow(() -> new RuntimeException("User not found")); Comment comment = commentRepository.findById(commentId) .orElseThrow(() -> new RuntimeException("Comment not found")); Report report = Report.builder() .user(user) .comment(comment) .reason(reason) .build(); report = reportRepository.save(report); log.info("Report created with ID: " + report.getId()); return toDTO(report); }
  • 백엔드 JwtAuthorizationFilter.java 디버그 로그 추가:
    java
    코드 복사
    @Override protected void doFilterInternal(HttpServletRequest request , HttpServletResponse response , FilterChain filterChain) throws ServletException, IOException { log.debug("JwtAuthorizationFilter: Checking JWT token"); Authentication authentication = jwtProvider.getAuthentication(request); if(authentication != null && jwtProvider.isTokenValid(request)){ log.debug("JwtAuthorizationFilter: JWT is valid, setting authentication for user: " + authentication.getName()); SecurityContextHolder.getContext().setAuthentication(authentication); } else { log.debug("JwtAuthorizationFilter: JWT is invalid or not present"); } filterChain.doFilter(request, response); }

11. 스크린샷 / 로그

  • 백엔드 로그:
    yaml
    코드 복사
    INFO c.e.o.service.ReportServiceImpl : Creating report for user: john_doe, commentId: 1 INFO c.e.o.service.ReportServiceImpl : Report created with ID: 100
    현재 문제 발생 시 로그:
    sql
    코드 복사
    INFO c.e.o.service.ReportServiceImpl : Attempting to create report for userId=null, commentId=1 ERROR o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() ... IllegalArgumentException: The given id must not be null

12. 제안된 해결 방안

  1. 백엔드 코드 재검토 및 동기화:
    • ReportServiceImpl에서 userId를 더 이상 사용하지 않고, SecurityContextHolder를 통해 username을 기반으로 User를 조회하는지 확인.
    • 모든 관련 클래스 (ReportDTO, 서비스 메서드 등)가 최신 코드로 업데이트 되었는지 확인.
    • 백엔드 서버를 재시작하여 변경 사항이 반영되었는지 확인.
  2. 프론트엔드 요청 검증:
    • ReportService.createReport 호출 시 userId를 전달하지 않고, commentId와 reason만 전달하는지 확인.
    • Axios 요청 시 Authorization 헤더에 올바른 JWT 토큰이 포함되어 있는지 확인.
  3. 로그 추가 및 디버깅 강화:
    • 백엔드에서 JwtAuthorizationFilter가 제대로 동작하고 있는지, Authentication 객체가 올바르게 설정되는지 로그를 통해 확인.
    • 프론트엔드에서 reportDTO가 올바르게 구성되어 전송되는지 로그 확인.
  4. Postman 등을 사용한 직접 테스트:
    • JWT 토큰을 포함한 POST 요청을 직접 보내어 백엔드가 올바르게 인증 정보를 처리하는지 테스트.
  5. 예외 처리 개선:
    • 구체적인 예외 (ResourceNotFoundException)를 사용하여 클라이언트에 명확한 에러 메시지 제공.

13. 참고 자료


추가 요청

  • 필요한 추가 정보가 있으면 알려주세요. 예를 들어, SecurityConfig 클래스 전체 코드, JwtProvider 구현 상세, 프론트엔드의 인증 로직 등 추가적인 코드나 설정이 필요할 수 있습니다.

감사합니다.