have a good time 2021. 12. 18. 22:03

사용자 2명을 만든다. hi, hello

현재 사용자를 hi 라고 한다.

그래서 만약 본인 프로필 화면이라면, 아래와 같이 사진등록 버튼이 뜨고, 구독하기 버튼은 안나오도록,

다른 사람(hello) 의 프로필 화면으로 이동했다면, 사진등록 버튼이 뜨지 않지만, 구독하기 버튼은 나오도록 할 것이다.

본인이 아니기 때문.

 

 

그러려면, 로그인한 사용자가 프로필 페이지의 주인인지 판단해야 한다.

 즉, 한 명의 사용자는 다른 사람의 프로필 화면으로 이동 가능한데, 

이 수 많은 프로필 화면 중 본인의 프로필 화면으로 이동한 것인지 알아야 한다.

그때만 사진등록 버튼이 나오도록.

 

그럴 때 다음과 같은 방법이 있다. 

프로필 화면으로 이동 시

/user/id번호

로 주소 요청한다.

 

1번 사용자의 프로필 화면 이동 : /user/1 요청

 

그래서 만약 로그인 한 1번 사용자가  /user/2로 이동했다면

자신의 프로필 화면이 아니다.

 

 

방법 1 - jsp 파일에서 설정

 

그러면 profile.jsp 파일에서 간단하게 처리해볼 수 있다.

 

우리가, jsp 파일에서 로그인한 사용자의 정보를 사용하기 위해

principal 을 사용한 적이 있다.

 

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>

<sec:authorize access="isAuthenticated()">
	<sec:authentication property="principal" var="principal"/>
</sec:authorize>

이와 같이 등록해서 사용했었다.

 

때문에, 여기서도 principal(로그인한 사용자) 를 사용하여 코드를 완성하면 된다.

여기서(jsp) 사용된 principal은, 자바 파일에서 PrincipalDetails 를 의미함

 

<profile.jsp > 파일

		<c:choose>
			<c:when test = "${principal.user.id == user.id }">
				<button class="cta" onclick="location.href='/image/upload'">사진등록</button>
			</c:when>
			<c:otherwise>
				<button class="cta" onclick="toggleSubscribe(this)">구독하기</button>
			</c:otherwise>
		</c:choose>

 

 

principal.user.id : 로그인한 사용자 id

user.id : 현재 프로필 화면의 주인 id

 

이렇게 한 다음,

만약 1번 사용자(hi) 가 로그인 해서 자신의 프로필 화면으로 이동하면 (/user/1)

아래와 같이 사진등록 버튼만 나온다.

하지만 만약 /user/2 를 주소요청하여 hello 사용자의 프로필 화면으로 이동한다면

 

이와 같이 사진등록이 아니라 구독하기 버튼만 나오게 할 수 있다.

 

그런데, 강사님은 view 페이지(jsp)에 자바 코드 로직을 사용하는 것을 추천하지 않는다고 하심

아래와 같은 코드 

"${principal.user.id == user.id }"

 

 

방법 2 - UserProfileDto.java 파일 사용하기

 

jsp 파일에서 연산을 하지않고,

자바 파일에서 연산한 뒤 jsp 파일에 데이터를 보내주는 방식을 사용하자.

 

<UserProfileDto.java> 파일

 

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class UserProfileDto {

	
	private boolean pageOwnerState;
	private int imageCount;
	private User user;
}

<UserController.java> 파일

 

	@GetMapping("/user/{pageUserId}")
	public String profile(@PathVariable int pageUserId, Model model, @AuthenticationPrincipal PrincipalDetails principalDetails) {
		UserProfileDto dto = userService.회원프로필(pageUserId, principalDetails.getUser().getId());
		model.addAttribute("dto", dto);
		return "user/profile";
	}

 

UserController.java 에서 UserService.java 의 회원프로필 메서드에

매개변수 id를 넘겨줄 때 그 의미가 잘 드러나도록

pageUserId 즉, 로그인한 사용자(id)가 아니라 그 페이지의 주인 (id)

(물론 로그인한 사용자가 페이지 주인일 수도 있음) 

 

 

<UserService.java> 파일

 

	
	@Transactional(readOnly = true)
	public UserProfileDto 회원프로필(int pageUserId, int principalId) {
		UserProfileDto dto = new UserProfileDto(); 
	
		User userEntity = userRepository.findById(pageUserId).orElseThrow(()-> {
			throw new CustomException("해당 프로필 페이지는 없는 페이지입니다.");
		});
		
	
		dto.setUser(userEntity);
		dto.setPageOwnerState(pageUserId == principalId);
		dto.setImageCount(userEntity.getImages().size());
		
		return dto;
	}

 

UserService.java 의 회원프로필 메서드 매개변수

pageUserId : 현재 페이지 주인(id)

principalUserId : 현재 로그인한 사용자(id)

 

 

이렇게 service에서 값들을 리턴해주면, controller에서 받고, 또 profile.jsp 파일까지 그 데이터들이 리턴된다.

이때, profile.jsp 파일에서는 아래와 같이, dto라는 변수명으로 사용하면 된다.

UserController.java 파일에서 model 객체에 dto라는 변수명으로 profile.jsp 파일에 데이터를 넘겨주므로.

		<h2>${dto.user.name}</h2>

 

 

그 결과 아래와 같이, 본인(user 1 : hi) 의 프로필 페이지일땐 (/user/1)

사진 등록 버튼이 잘 나오고

게시물 개수도 잘 표시된다.

 

 

위 화면의 profile.jsp 파일을 살펴보겠다.

 

1) 일단, hi라고 표시된 부분은 사용자의 name이다.

그래서 아래와 같이 사용했다.

 

			<h2>${dto.user.name}</h2>

 

2) 그리고 본인 프로필 화면일 때는 사진등록 버튼이, 다른 사용자의 프로필 화면일 때는 구독하기 버튼이 나타나도록

아래와 같이 변경했다.

 

 

		<c:choose>
				<c:when test = "${dto.pageOwnerState}">
				<button class="cta" onclick="location.href='/image/upload'">사진등록</button>
			</c:when>
			<c:otherwise>
				<button class="cta" onclick="toggleSubscribe(this)">구독하기</button>
			</c:otherwise>
		</c:choose>

 

3) 게시물 개수도 원래는 jsp 화면에서 연산되도록 했다.

(view 페이지에서 연산되도록 하는 것은 좋지 않음)

프로필 페이지 8 글에 보면 아래와 같았음.

 

${user.images.size()}

하지만 UserProfileDto.java 파일에 

imageCount 변수를 추가해서 이를 자바 파일에서 연산되도록 수정했다.

그래서 profile.jsp 파일에서는 아래와 같이 사용

 

	<li><a href=""> 게시물<span>${dto.imageCount}</span>

 

4) 업로드된 이미지가 화면에 표시되도록 하는 부분

 

			<c:forEach var="image" items="${dto.user.images}">
				<div class="img-box">
					<a href=""> <img src="/upload/${image.postImageUrl}"/>
					</a>
					<div class="comment">
						<a href="#" class=""> <i class="fas fa-heart"></i><span>0</span>
						</a>
					</div>
				</div>
			</c:forEach>

 

 

 

 

 

 

 

이제는 다른 사용자, 즉 hello 의 프로필 화면으로 이동해보자.

(/user/2)

아래와 같이 구독하기 버튼만 잘 나온다.

 

 

 

참고 자료 :  이지업 강의 사이트 "스프링부트 SNS프로젝트 - 포토그램 만들기"