[클론 코딩] 네이버 카페 - 네이버 회원 정보 조회(읽기)

2024. 5. 3. 16:36Project/Naver Cafe

  저장된 회원의 정보를 찾아 사용자가 확인할 수 있도록 조회(읽기)기능을 추가하고자 한다. 회원 조회시 엔티티의 식별키(id)를 사용했다. 해당 기능이 필요한 이유는, 예를 들어 사용자가 정보를 수정할 때 본인의 현재 정보를 확인할 수 있어야 하기 때문이다.


ResponseMemberInfo

package CloneCoding.NaverCafe.domain.member.dto;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ResponseMemberInfo {

    private String accountId;
    private String email;
    private String username;
    private LocalDate birthday;
    private String phoneNumber;
    private String nickname;

}

 

  사용자에게 제공할 회원 정보를 전달하는 DTO이다. 서버는 사용자에게 회원 계정 아이디, 이메일, 사용자명, 생년월일, 휴대전화번호, 별명에 대한 정보를 제공할 것이다. 


MemberController

package CloneCoding.NaverCafe.domain.member.controller;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/member")
public class MemberController {

    private final MemberService memberService;

    @GetMapping("/{id}")
    public ResponseMemberInfo readMemberInfo(@PathVariable("id") Long id) {
        log.info("회원 정보 요청");
        return memberService.findMemberInfoById(id);
    }

}

 

  MemberController에는 URL에 포함되어 있는 id 값을 파라미터로 하는 readMemberInfo 메서드를 추가하였다. 해당 메서드는 찾고자 하는 회원의 id 값(식별키)을 통해 찾은 회원 정보를 ResponseMemberInfo 객체로 반환한다.


MemberService, MemberServiceImpl

// MemberService
package CloneCoding.NaverCafe.domain.member.service;

public interface MemberService {

    ResponseMemberInfo findMemberInfoById(Long id);

}

// MemberServiceImpl
package CloneCoding.NaverCafe.domain.member.service;

@Service
@Transactional
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;

    @Override
    public ResponseMemberInfo findMemberInfoById(Long id) {

        Member findMember = memberRepository.findById(id)
                .orElseThrow(() -> new NoSuchElementException("id가 일치하는 회원을 찾을 수 없습니다."));

        return memberRepository.makeResponseMemberInfo(findMember);

    }

}

 

  MemberService 인터페이스에 findMemberInfoById(Long id) 추상 메서드를 추가하고 MemberServiceImpl에서 이를 구현하였다. 해당 메서드는 Member의 id 값을 통해 회원을 조회하고 조회한 회원의 정보를 통해 응답 DTO를 생성하고 반환하는 메서드이다. 조회의 경우 Spring Data JPA가 제공하는 findById(Long id) 메서드를 사용하였으며, 응답 DTO 생성의 경우 memberRepository의 makeResponseMemberInfo(Member member) 메서드를 사용하였다.


QueryMemberRespository, QueryMemberRespositoryImpl

// QueryMemberRepository
package CloneCoding.NaverCafe.domain.member.repository;

public interface QueryMemberRepository {

    ResponseMemberInfo makeResponseMemberInfo(Member member);

}

// QueryMemberRespositoryImpl
package CloneCoding.NaverCafe.domain.member.repository;

@Repository
@RequiredArgsConstructor
public class QueryMemberRepositoryImpl implements QueryMemberRepository {

    private final JPAQueryFactory query;

    @Override
    public ResponseMemberInfo makeResponseMemberInfo(Member member) {
        return ResponseMemberInfo.builder()
                .accountId(member.getAccountId())
                .email(member.getEmail())
                .username(member.getUsername())
                .birthday(member.getBirthday())
                .phoneNumber(member.getPhoneNumber())
                .nickname(member.getNickname())
                .build();
    }

}

 

  QueryMemberRespository 인터페이스에 makeResponseMemberInfo(Member member) 추상 메서드를 추가하고, 이를 QueryMemberRespositoryImpl 에서 구현하였다. 해당 메서드는 Member 객체의 정보를 통해 응답 DTO 객체를 생성하고 반환한다. 반환 객체에 포함된 회원 정보들은 회원 계정 ID, 이메일, 사용자명, 생년월일, 휴대전화번호, 별명이 있다.


GlobalExceptionhandler

package CloneCoding.NaverCafe.exception.handler;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NoSuchElementException.class)
    public ResponseEntity<Object> handleNoSuchElementException(NoSuchElementException e) {
        ErrorCode errorCode = CommonErrorCode.RESOURCE_NOT_FOUND;
        return handleExceptionInternal(errorCode, e.getMessage());
    }

    private ResponseEntity<Object> handleExceptionInternal(ErrorCode errorCode, String message) {
        return ResponseEntity.status(errorCode.getHttpStatus())
                .body(makeResponseError(errorCode, message));
    }

    private ResponseError makeResponseError(ErrorCode errorCode, String message) {
        return ResponseError.builder()
                .code(errorCode.name())
                .message(message)
                .build();
    }

}

 

  전역적으로 예외를 처리하는 GlobalException에는 존재하지 않는 회원 정보를 찾을 때 발생 가능한 NoSuchElementException을 처리하는 예외 핸들러를 추가하였다.


API TEST

API TEST - 회원 정보 조회

 

  회원 등록을 한 상태에서 등록된 회원의 id(=1)를 통해 회원의 정보를 조회하였다. 원하는대로 id, 계정 비밀번호 정보를 제외한 나머지 정보가 정상적으로 출력된 것을 볼 수 있다.


API TEST - id와 일치하는 회원이 없는 경우

 

  회원을 등록하지 않은 상태로 id를 통해 회원을 조회한 테스트이다. 없는 회원을 조회하였기에 에러가 발생하며, 에러코드와 메시지가 출력되며 사용자에게 id와 일치하는 회원을 찾지 못했다는 정보를 제공, 사용자에게 좀 더 질 좋은 서비스를 제공할 수 있게 된 것이다!