ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 6월 29일 목요일 TIL 회고록
    카테고리 없음 2023. 6. 29. 22:52

    어제 TIL을 쓰려했는데 티스토리 블로그 및 사이트를 들어가면 Http 400 에러가 나와서 티스토리 서버가 잠시 터진 줄 알았는데..

    오늘도 쓰려하니 똑같이 400에러가 나와서 혹시나 하고 구글링을 해보니 티스토리 쿠키를 지우면 해결된다고 해서 쿠키를 지워봤더니 

    잘 들어가진다 ㅋㅋㅋ..

     

    어제는 사이트를 꾸며봤다. 검색창이 맨 밑에 있어서 크롬 확대/축소를 75%까지 내려야 검색창이 보였는데 정말 불편해서 수정했다.

    검색창을 위로 올리고 가운데에 정렬했다. 지도 및 스카이뷰도 오른쪽으로 옮겼다.

    위로 올릴때는 비교적 쉬웠는데 가운데로 옮기려고 참 애먹었다.. 프론트는 오랜만에 만져봐서..

    display: flex, justify-content: center 를 사용해서 가운데로 옮겼다.

    <div id="search" style="display: flex;justify-content:center;">

    카카오 지도도 정렬해주었다.

    100vh를 사용했다.

    <div id="map" style="width:100%;height:100vh;position:relative;overflow:hidden;"></div>

    이제 해야할 것은.. 아이콘 변경 등등 할게 많이 남았다..


    프로필을 조회하고 수정하는 코드를 만들었다. 아직 조회 및 수정은 이름밖에 안된다.

     

    프로필 조회 Controller

      // 프로필 조회
      @GetMapping("/user/me/profile")
      public ProfileResponse getUserProfile(@AuthenticationPrincipal UserDetailsImpl userDetails) {
        return userService.getUserProfile(userDetails.getUserId());
      }

    프로필 조회 Service

      // 프로필 조회
      @Override
      @Transactional(readOnly = true)
      public ProfileResponse getUserProfile(Long userId) {
        User user = userRepository.findById(userId).orElseThrow(
            () -> new CustomException(ExceptionStatus.NOT_FOUND_USER)
        );
    
        return ProfileResponse.builder()
            .nickname(user.getUsername())
            .build();
      }

    어려운 부분은 딱히 없고 UserDetailsImpl userDetails를 매개변수로 받아 userDetails.getUserId()로 유저 닉네임을 조회한다.

     

    실행 결과

     

    프로필 수정 Controller

    // 프로필 (이름 수정)
      @PutMapping("/user/me/profile")
      public ResponseEntity<String> updateUserProfile(
          @AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody
      ProfileRequest request) {
        userService.updateUserProfile(userDetails.getUserId(), request);
        return new ResponseEntity<>("프로필 수정 완료!", HttpStatus.OK);
      }

     

    프로필 수정 Service

      // 프로필 수정
      @Override
      @Transactional
      public void updateUserProfile(Long userId, ProfileRequest request) {
        User user = userRepository.findById(userId).orElseThrow(
            () -> new CustomException(ExceptionStatus.NOT_FOUND_USER)
        );
    
        user.updateProfile(request.getUsername());
        userRepository.save(user);
      }

     

    실행 결과

    그 다음 게시글을 작성할 때 이미지를 넣을 수 있게 multipartFiles를 사용해봤다.

     

    먼저 보드 엔티티에 BoardImage 클래스를 만들었다.

     

    BoardImage.class

    @Getter
    @Entity
    @NoArgsConstructor(force = true, access = AccessLevel.PROTECTED)
    public class BoardImage {
    
      @Column(nullable = false)
      private final String imagePath;
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      @Column(name = "IMAGE_ID")
      private Long Id;
      @Column(nullable = false)
      private String originalName;
    
      private Long fileSize;
    
      @ManyToOne
      @JoinColumn(name = "BOARD_ID")
      private Board board;
    
      @Builder
      public BoardImage(Long id, String originalName, Long fileSize, String imagePath) {
        this.originalName = originalName;
        this.fileSize = fileSize;
        this.imagePath = imagePath;
      }
    
      // Board 정보 저장
      public void setBoard(Board board) {
        this.board = board;
    
        // 게시글에 현재 파일이 존재하지 않으면
        if (!board.getBoardImageList().contains(this)) {
          // 파일 추가
          board.getBoardImageList().add(this);
        }
      }
    }

    하나의 게시글에 여러개의 사진을 추가할 수 있으므로 ManyToOne 어노테이션을 사용해서 BoardImage와 Board 연관관계를 매핑해줬다.

     

    보드 엔티티에도 OneToMany 어노테이션을 사용해서 Board와 BoardImage 연관관계를 매핑해줬다.

     

    Board.class

    @OneToMany(
          mappedBy = "board",
          cascade = {CascadeType.PERSIST, CascadeType.REMOVE},
          orphanRemoval = true
      )
      private List<BoardImage> boardImageList = new ArrayList<>();
    
      // Board에서 파일 처리 위함
      public void addBoardImage(BoardImage boardImage) {
        this.boardImageList.add(boardImage);
    
        // 게시글에 파일이 저장되어있지 않은 경우
        if (boardImage.getBoard() != this) {
          // 파일 저장
          boardImage.setBoard(this);
        }

    그 후 BoardImageRepository 인터페이스를 만들어 준 후 JpaRepository를 상속받았다.

    게시글 작성 컨트롤러에 List<MutilpartFile> mutilpartFiles를 매개변수로 받도록 추가해주었다.

    기존에는 RequestBody를 사용했는데 RequestPart를 사용하게 만들었다.

     

    BoardController.class

      // 게시글 작성
      @PostMapping("/basic-boards")
      public ResponseEntity<String> createBasicBoard(
          @AuthenticationPrincipal UserDetailsImpl userDetails,
          @RequestPart("request") @Valid BasicBoardRequest request,
          @RequestPart(required = false, name = "images") List<MultipartFile> multipartFiles)
          throws java.io.IOException {
        basicBoardService.createBasicBoard(userDetails.getUser(), request, multipartFiles);
        return new ResponseEntity<>("게시글 작성 완료!", HttpStatus.CREATED);
      }

     

    BasicBoardServiceImpl 클래스에 파일 업로드를 위한 upload 메서드를 만들었다.

    // 이미지 업로드
      public List<BoardImage> upload(List<MultipartFile> multipartFiles, BasicBoard basicBoard)
          throws java.io.IOException {
    
        // 반환을 할 파일 리스트
        List<BoardImage> uploadImagePaths = new ArrayList<>();
    
        // 파일이 빈 것이 들어오면 빈 것을 반환
        if (multipartFiles.isEmpty()) {
          return uploadImagePaths;
        }
    
        // 파일 이름을 업로드 한 날짜로 바꾸어서 저장할 것이다.
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        String current_date = simpleDateFormat.format(new Date());
    
        // 프로젝트 폴더에 저장하기 위해 절대 경로를 설정
        String absolutePath = new File("").getAbsolutePath() + "\\";
    
        // 경로를 저장하고 저장한다.
        String path = "images/" + current_date;
        File file = new File(path);
        // 저장할 위치의 디렉토리가 존재하지 않을 경우
        if (!file.exists()) {
          // mkdir() 함수와 다른 점은 상위 디렉토리가 존재하지 않을 때 그것까지 생성
          file.mkdirs();
        }
    
        for (MultipartFile multipartFile : multipartFiles) {
          // 파일이 비어 있지 않을 때 작업을 시작해야 오류가 나지 않는다.
          if (!multipartFile.isEmpty()) {
            // jpeg, png, gif 파일들알 받아서 처리할 예정
            String contentType = multipartFile.getContentType();
            String originalFileExtension;
            // 확장자 명이 없으면 잘못된 파일이므로 break 발생
            if (ObjectUtils.isEmpty(contentType)) {
              break;
            } else {
              if (contentType.contains("/image/jpeg")) {
                originalFileExtension = ".jpg";
              } else if (contentType.contains("/image/png")) {
                originalFileExtension = ".png";
              } else if (contentType.contains("image/gif")) {
                originalFileExtension = ".gif";
              } else {
                // 다른 파일 명이면 break 발생
                break;
              }
            }
            String newFileName = System.nanoTime() + originalFileExtension;
            BoardImage boardImage = BoardImage.builder()
                .originalName(multipartFile.getOriginalFilename())
                .imagePath(path + File.separator + newFileName)
                .fileSize(multipartFile.getSize())
                .build();
    
            uploadImagePaths.add(boardImage);
    
            file = new File(absolutePath + path + "/" + newFileName);
            multipartFile.transferTo(file);
    
          }
        }
        return uploadImagePaths;
      }

     

    게시글 작성 메서드에 upload 메서드를 사용해서 수정해주었다.

    // 게시글 작성
      @Transactional
      @Override
      public BasicBoard createBasicBoard(User user, BasicBoardRequest request,
          List<MultipartFile> multipartFiles) throws java.io.IOException {
        BasicBoard basicBoard = BasicBoard.builder()
            .content(request.getContent())
            .title(request.getTitle())
            .boardSort(request.getBoardSort())
            .user(user)
            .build();
    
        List<BoardImage> boardImageList = upload(multipartFiles, basicBoard);
    
        // 파일이 존재할 때에만 처리
        if (!boardImageList.isEmpty()) {
          for (BoardImage boardImage : boardImageList) {
            // 파일을 DB에 저장
            basicBoard.addBoardImage(boardImageRepository.save(boardImage));
          }
        }
    
        boardRepository.save(basicBoard);
    
        return basicBoard;
      }

     

    포스트맨으로 테스트 해보려고 하면 415 에러가 나오면서 작성이 안된다.

    form-data로 키-밸류 값을 잘 준거 같은데 에러가 나온다 ㅠㅠ.. 내일 고쳐봐야겠다..

Designed by Tistory.