Wanna be Brilliant Full-Stack Developer

2/16 SpringBoot 포토리스트 API 만들기 본문

Back-End/Spring Boot

2/16 SpringBoot 포토리스트 API 만들기

Flashpacker 2022. 2. 16. 11:13


목표

포토리스트 API 만들기

Ajax로 포토 리스트 가져오기

페이징 처리하기

 

유저정보와 이미지 정보만 들고와서 리턴을 해보는 로직을 만들어보자! 

어떤 유저와 어떤 이미지 정보인지 데이터베이스에 쿼리를 적어보자! 

 

자기가 올린 이미지는 스토리에서 볼필요가 없다! 

내가 만약에 지금 2번으로 로그인했을떄 피드에 어떤 이미지가 나와야하냐면 

userId = 1, 3 이 피드에 나와야한다. 
SELECT * FROM image WHERE userId IN (1,3); 이런 쿼리로 

이런 결과가 나오는데 1, 3 과 같이 상수로 적을수 없으니 

SELECT toUserId FROM subscribe WHERE fromUserId = 2; 이 두명의 이미지만 보면되니 

SELECT * FROM image WHERE userId IN (SELECT toUserId FROM subscribe WHERE fromUserId = 2);  와 같은 스칼라 서브쿼리를 사용해야한다 

2번 계정과 3번 계정도 사진을 업로드하고 쿼리를 다시 실행하면? 

이렇게 나오는것을 보면 쿼리가 잘나왔다는 것이다.

이정보로 셀렉트하여 이미지를 가져왔다 하면 . Image.java 를 보면 id, caption 포스트이미지 URL, 유저정보 를 가져오는데 유저 정보를 가지러가면 다시 애가 그 해당 유저가 올린 images를 가져오게된다! 우리는 유저정보까지만 필요하지 그 유저가 올린 이미지까지는 가져올필요가 없기떄문에

 

@JsonIgnoreProperties({"images}) 를 추가한다

package com.cos.photogramstart.domain.image;

import java.time.LocalDateTime;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PrePersist;

import com.cos.photogramstart.domain.subscribe.Subscribe;
import com.cos.photogramstart.domain.user.User;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Image { // N, 1
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY) 
	private int id;
	private String caption; // 설명 
	private String postImageUrl; // 사진을 전송받아서 그 사진을 서버에 특정 폴더에 저장 - DB에 그 저장된 경로를 insert\

	@JsonIgnoreProperties({"images"})
	@JoinColumn(name = "userId")
	@ManyToOne
	private User user;// 1, 1
	
	//이미지 좋아요
	
	// 댓글 
	
	private LocalDateTime createDate;
	
	@PrePersist
	public void createDate() {
		this.createDate = LocalDateTime.now();
	}

		// 오브젝트를 콘솔에 출력할 때 문제가 될 수 있어서 User 부분을 출력 되지 않게 함.
//	@Override
//	public String toString() {
//		return "Image [id=" + id + ", caption=" + caption + ", postImageUrl=" + postImageUrl 
//				+ ", createDate=" + createDate + "]";
//	}

}

이 쿼리를 또한 작동시키리면 imageRepository에 하나 만들어야한다. 

package com.cos.photogramstart.domain.image;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface ImageRepository extends JpaRepository<Image, Integer> {

	@Query(value = "SELECT * FROM image WHERE userId IN (SELECT toUserId FROM subscribe WHERE fromUserId = :principalId);", nativeQuery = true)
	List<Image> mStory(int principalId);
}

애를 호출하는 API를 만들어야한다

package com.cos.photogramstart.web.api;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cos.photogramstart.service.ImageService;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
public class ImageApiController {

	private final ImageService imageService;
	
	@GetMapping("/api/image")
	public ResponseEntity<?> imageStory(){
		return null;
	}
}

만들었으면 서비스를 호출해야한다! 

 

@Transactional(readOnly = true) 이것을 하면 좋은점은 데이터베이스에 영속성 컨텍스트 변경 감지를 해서, 더티체킹, flush(반영) 하는것을 안하고 좀더 좋아진다! 

이것을 걸어서 세션을 컨트롤러 단까지 끌고 오는것은 중요하다 

 

package com.cos.photogramstart.service;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cos.photogramstart.config.auth.PrincipalDetails;
import com.cos.photogramstart.domain.image.Image;
import com.cos.photogramstart.domain.image.ImageRepository;
import com.cos.photogramstart.web.dto.image.ImageUploadDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Service		
public class ImageService {
	
	private final ImageRepository imageRepository;
	
	@Transactional(readOnly = true) // 영속성 컨텍스트 변경 감지를 해서, 더티체킹, flush(반영) 
	public List<Image> 이미지스토리(int principalId) {
		List<Image> images = imageRepository.mStory(principalId);
		return images;
	}
	
	
	@Value("${file.path}")
	private String uploadFolder;
	
	@Transactional
	public void 사진업로드(ImageUploadDto imageUploadDto, PrincipalDetails principalDetails) {
		UUID uuid  = UUID.randomUUID();	 // uuid
		String imageFileName = uuid+ "_" + imageUploadDto.getFile().getOriginalFilename(); // 1.jpg
		System.out.println("이미지 파일이름: "+ imageFileName);
		
		Path imageFilePath = Paths.get(uploadFolder+imageFileName);
		
		//통신, I/O -> 예외 
		try {
			Files.write(imageFilePath, imageUploadDto.getFile().getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		// image 테이블에 저장
		Image image = imageUploadDto.toEntity(imageFileName, principalDetails.getUser()); // acc21c4e-947a-475d-9220-6117b0d4efa8_BB1eWj3u.jfif 
		 imageRepository.save(image);
		
		//System.out.println(imageEntity.toString());
	}
}
package com.cos.photogramstart.web.api;

import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cos.photogramstart.config.auth.PrincipalDetails;
import com.cos.photogramstart.domain.image.Image;
import com.cos.photogramstart.service.ImageService;
import com.cos.photogramstart.web.dto.CMRespDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
public class ImageApiController {

	private final ImageService imageService;
	
	@GetMapping("/api/image")
	public ResponseEntity<?> imageStory(@AuthenticationPrincipal PrincipalDetails principalDetails){
		List<Image>	images = imageService.이미지스토리(principalDetails.getUser().getId());
		return new ResponseEntity<>(new CMRespDto<>(1,"성공",images), HttpStatus.OK);
	}
}

API컨트롤러 다 만들었으니 POSTMAN으로 테스트 해보려고한다! 

http://localhost:8080/api/image 로 get방식으로 불러오면 

 

 

 

 

 

 

 

 

 

 

 

이제 어느정도 완성했으니 Javscript에 불러 오기만 하면된다!