SNS 포토그램 만들기 (프로필 페이지)

송용준·2023년 6월 26일
0
post-thumbnail

Image 모델 만들기

Image이름으로 model과 repository를 만든다.
Model은

private int id;
	private String caption; 				// 오늘 나 너무 피곤해 !!
	private String postImageUrl;		// 사진을 전송받아서 그 사진을 서버에 특정 폴더에 저장 - DB에 그 저장된 경로를 insert

가 들어가야 하고 User는 @ManyToOne이다. 한 사람이 여러 사진을 올릴 수 있으나 여러사람이 하나의 사진을 올리진 않기 때문

Image 서버에 업로드하기

@AuthenticationPrincipal : 유저 정보를 받음
image 컨트롤러에선 업로드 후 다시 첫 화면으로 돌아가야한다.
UUID : 유일성이 보장되는 범용 고유 식별자. 사진을 저장할 때 이름이 덮어씌워지는것을 막기위해 구분
@Value("${file.path}") : yml에 넣은 경로

<form class="upload-form" action="/image" method="post" enctype="multipart/form-data">

enctype="multipart/form-data" : 여러타입의(사진 + 글)을 묶어서 전송

upload 폴더를 프로젝트 외부에 두는 이유

upload안에 jpg가 .class, 정적파일들을 Target안에 배포(deploy)될 때 시간이 걸림. 그래서 jpg가 사진이 등록되기도 전에 화면이 먼저 실행이 될 수도 있음. 그렇게 되면 액박이 뜸

포토그램 외부에 upload파일이 있으면 jpg등의 파일이 움직일 필요가 없기에 배포 시간이 필요 없음. 하여 액박이 안뜸

Image DB에 업로드하기

이미지 dto에 entity만들고 service에서 entity받는다.

Image 유효성 검사하기

예외 핸들러에 예외처리
컨트롤러에서 날려줄 문장

양방향 매핑 이해하기

controller에서 엔티티로 보내고
service에서 예외처리해주고
exception 따로 만들고
exceptionhandler에서 메세지 보내고
유저dao엔 OneToMany 이미지dao엔 ManyToOne

유저 프로필에 이미지를 보내줄건데 이미지만 보내면 유저정보하고 구독자등의 정보들을 보내지 못함 그러므로 양방향 매핑을 해야함

private List< Image > images : 양방향 매핑을 위해 User안에 넣어줌

@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
mappedBy = "user" : 나는 연관관계의 주인이 아니다. 그러므로 테이블에 칼럼을 만들지마. User를 Select할 때 해당 User에 id로 등록된 image들을 다 가져와
fetch = FetchType.LAZY : User를 Select할 떄 해당 User에 id로 등록된 image들을 가져오지마 - 대신 getImages() 함수의 Image들이 호출될 때 가져와 !!
++ Eager = User를 Select할 때 해당 User id로 등록된 image들을 전부 Join해서 가져와 !!

Image 뷰 랜더링하기

yml파일에 파일 경로가 적혀있는데 WebMvcConfigurer를 이용해 web을 설정하여 addResourceHandlers로 낚아챈다.

  @Value("${file.path}")
  private String uploadFolder;
  @Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
			WebMvcConfigurer.super.addResourceHandlers(registry);
			
			// file:///C:/workspace/photogram_springboot/upload/
			// /upload/ 이런 형태를 낚아채서 값을 C:/workspace/photogram_springboot/upload/ 로 바꿔버림
			registry
				.addResourceHandler("/upload/**")		// jsp페이지에서 /upload/** 이런 주소 패턴이 나오면 발동 
				.addResourceLocations("file:///"+uploadFolder)
				.setCachePeriod(60*10*6)	// 60* 10* 6
				.resourceChain(true)
				.addResolver(new PathResourceResolver());
		}

/upload/ 이런 형태를 낚아채서 값을 C:/workspace/photogram_springboot/upload/ 로 바꿔버림

Open in View 개념잡기

  1. 무한 참조 조심 user -> Image -> user -> ...
    System.out.print(imageEntity) --> 무한루프로 출력하게 됨. 하여 쓰고 주석처리 하기. toString()도 마찬가지

  2. service에서 controller 로 돌아올때 세션이 종료되어 lazy 로딩 불가능 해지면서 controller에서 image를 불러오지 못하게 됨.

    yml파일에 open-in-view: 를 true로 하면 뷰단까지 세션을 오픈 하는 기능. 세션종료가 컨트롤에서 일어나게 하겠다.

  3. service에 @Transactional을 걸어줘야 한다.
    service에서 일이 실패 했을 때 롤백 시켜버리기 위해 @Transactional을 걸어둔다. 예를 들어 송금서비스 구현할때 송금한 사람은 완료했는데 받은 사람이 실패했을 경우 송금한 사람한테 돌려주어야(롤백) 하기 때문에 하나의 트랜잭션(일의 최소단위)으로 관리 해야한다.

  4. 영속성 컨텍스트는 controller과 service 사이에서 변경감지 해줘야 한다. @Transactional(readOnly = true)로 해주면 영속성 컨텍스트가 변경감지(더티체킹)를 하지 않아 일을 적게 한다.

회원정보 수정 오류 해결하기

Images를 호출할 때(JPA 무한참조)가 문제
@JsonIgnoreProperties({"user"}) : User에서 응답할 때 Image 내부에서 파싱할 때 user는 json으로 파싱하지 하지 않겠다.

게시물 갯수 뷰 랜더링하기

${user.images.size()}

DTO로 페이지 완성하기

UserProfileDto를 만들어서 주인 페이지인지 확인한다. 주인 페이지일때 사진등록 버튼, 아니면 구독하기 버튼창을 띄운다.

  • 페이지에선 연산코드(${dto.user.images.size()})가 있으면 좋지않다. service단에 계산식 만들어 놓고 프론트단에서는 호출만 한다.
  • 가져온 값을 확인하여 사진등록 or 구독하기 버튼을 선택하는 것은 service단에 만들어 준다.
  • View 페이지에서는 최대한 연산하지 말고 service에서 만들어 줘야한다.
dto.setImageCount(userEntity.getImages().size());
profile
용용

0개의 댓글