인프런 커뮤니티 질문&답변

정성주님의 프로필 이미지
정성주

작성한 질문수

생산성을 향상시키는 스프링부트 기반의 API 템플릿 프로젝트 구현

안드로이드 스튜디오와 협업

작성

·

523

·

수정됨

0

현재 학부생 3학년으로 안드로이드 앱 개발 팀프로젝트를 진행중입니다.

클라이언트 친구가 하는말이

"회원고유번호를 카카오에서 프론트에게 주고, 프론트에서 그걸 백으로 전달해준다.

백은 그냥 내가 준 고유번호만 가지고 jwt토큰으로 만들어서 반환해달라"

라고 말하는데, 그러면 강의대로 섹션9를 다 수행하고나서, 섹션9의 카카오 토큰 발급 구현(1),(2)빼고

카카오에서 플랫폼만 웹에서 안드로이드로 변경하면 되는건가요?

제가 이해한게 맞다면 프론트(android studio)에서 인증, 인가를 받아 사용자 정보를 받아오고,

백엔드(Spring boot)에서는 단순히 /join 을 통해 프론트에서 넘겨준 User 데이터를 password와 함께 저장하는것 같습니다.

이 때, JWT 토큰을 발행해서 프론트에 넘겨주는것 같구요.

그리고 소셜로그인(6)까지 진행중인데,

ERROR 15266 --- [nio-8080-exec-1] c.a.global.error.GlobalExceptionHandler : Exception

포스트로 value값을 보내면 위와같은 에러가 뜹니다...

그래서 첨부터 다시 쭉 보는데, (5)부분에서 했던 것도 똑같은 에러가 뜨더라고요... 뭐가 문제인지...ㅜ

스프링 첨배워가면서 하고있는데, 미치겠습니다..ㅠ

답변 2

0

구파고님의 프로필 이미지
구파고
지식공유자

프론트에서 소셜 로그인 시 email을 전달하면 직접 그 이메일을 조회하여 회원이 있으면 회원 가입을 추가로 수행하고, JWT를 생성해서 반환합니다. 지금 상황은 사실 email을 누군가가 직접 입력해서 서버로 보내면 로그인을 할 수 있기 때문에 제대로 된 인증과정이라고는 할 수 없습니다 ㅠ

 

하지만 일단 내용이 어려우시다고 하시니 올려주신 코드처럼 안드로이드에서 보낸 이메일을 기준으로 회원 가입을 진행하셔도 될꺼 같습니다.

    @Transactional
    public JwtTokenDto registerOrLoginSocialMember(SocialLoginRequest socialLoginRequest) {
        // 이메일로 회원 조회
        Member existingMember = memberRepository.findByEmail(socialLoginRequest.getEmail())
                .orElse(null);

        if (existingMember == null) {
            // 회원이 존재하지 않으면 회원 가입
            Member newMember = Member.builder()
                    .name(socialLoginRequest.getName())
                    .email(socialLoginRequest.getEmail())
                    .memberType(MemberType.KAKAO) // 혹은 다른 소셜 로그인 유형에 따라서 설정
                    .role(Role.USER)
                    .tokenExpirationTime(LocalDateTime.now().plusDays(7)) // 예시로 토큰 유효 기간을 7일로 설정
                    .build();

            // 회원 저장
            memberRepository.save(newMember);

            // 새로 생성된 회원에 대한 토큰 발급
            JwtTokenDto jwtTokenDto = tokenManager.createJwtTokenDto(newMember.getMemberid(), Role.USER);

            return jwtTokenDto;
        } else {
            // 회원이 이미 존재하면 해당 회원에 대한 토큰 발급
            JwtTokenDto jwtTokenDto = tokenManager.createJwtTokenDto(existingMember.getMemberid(), Role.USER);

            return jwtTokenDto;
        }
    }

 

소셜로그인 4,5를 듣지않아서 문제가 생기셨다면 일단 (4), (5)를 듣고 코드를 마저 작성 후 남은 강의를 진행하시는게 좋을꺼 같습니다. 현재 올려주신 소스만으로는 어디서 문제가있는지 알 수 없어서 (4), (5)를 듣고나서 코드 수정 후 어느 코드에서 오류가 발생하는지 알려주시면 조금 더 도움을 드릴 수 있을꺼 같습니다.

 

그리고 해당 사이트에서 Invalid Signature라고 나오는 이유는 token secret값을 입력하지 않아서입니다.

access token을 만들 때 사용한 tokenSecret값을 넣어주면 정상적으로 보일 것 입니다. (현재 토큰자체가 이상한 상태는 아님)

image

0

구파고님의 프로필 이미지
구파고
지식공유자

안녕하세요. 클라이언트에서 백엔드로 회원고유번호를 준다고 하였는데, 안드로이드에서 소셜로그인 후 회원정보 조회까지하고 백엔드로 회원고유번호만 보낸다는게 아닐까 싶네요.

 

안드로이드에서 소셜 로그인 후 조회한 회원정보(이메일, 회원이름, 프로필등)을 서버로 전달해주면 회원가입이 되어있는지 검사를하고 회원가입이 안되어있다면 회원 가입 후 jwt를 만들어서 반환해주시면 될꺼 같습니다.


강의 내용에서 소셜 회원사의 토큰을 받아오고 회원정보를 가져오는 부분을 안드로이드에서 하고있으므로, 서버에서는 안드로이드에서 넘겨준 회원정보로 회원가입 및 jwt반환만 해주면될꺼 같습니다.

 

그리고 아래 오류만으로는 어떤 예외인지 알 수 없는데 에러를 조금 더 자세히 첨부해주시면 확인이 가능할꺼 같습니다. 에러메세지 전체를 콘솔창을 캡처해서 보여주셔도 되구요

ERROR 15266 --- [nio-8080-exec-1] c.a.global.error.GlobalExceptionHandler : Exception

 

정성주님의 프로필 이미지
정성주
질문자

그럼 강의 어느부분부터 보는게 맞는걸까요...소셜로그인(1)부터 맞는것 같긴한데,

지금 제가 카카오랑 연결하는건 아니지 않나요? 전 그냥 프론트에서 준 걸로 jwt만들면 되는거 아닌가요...

구파고님의 프로필 이미지
구파고
지식공유자

각 강의가 유기적으로 연결되어있긴해서 가능하시면 모두 다 들으시는걸 추천드립니다.

 

선택해서 들으시고 싶으시다면

1.프론트에서 회원정보를 카카오로부터 조회해서 서버로 전달해준다면 소셜로그인(1)부터들으시면 되는데, 소셜 로그인(4), 소셜 로그인(5)는 카카오로부터 회원정보를 조회하는 코드이므로 생략하셔도 됩니다. 대신에 회원 가입 때 카카오로부터 회원 정보를 조회하는 로직 대신에 프론트에서 전달한 회원 정보로 회원 가입을 하도록 로직을 구현해주시면됩니다.

 

2.프론트에서 카카오 ACCESS TOKEN을 전달해주는 상황이라면 서버에서 카카오로부터 회원 정보를 조회해야하므로 소셜 로그인 (1)부터 들으시면 됩니다.

정성주님의 프로필 이미지
정성주
질문자

현재 소셜 로그인(1,2,3)은 이해하고 성공했습니다. 이제 프론트에서 전달한 회원 정보로 회원 가입을 하도록 로직을 하려는데, api로 받아와야하는건가요? 프론트랑 연결을 해본적이 없어서, 뭘 보고 따라해야할지 모르겠습니다....

정성주님의 프로필 이미지
정성주
질문자

프론트랑 연결을 도저히 모르겟어서 gpt에 물어보니, 다른 코드는 그대로 두고, MemberService부분만 고치라고 해서 아래처럼 했습니다.

  private final TokenManager tokenManager;

이부분하고,

    @Transactional
    public JwtTokenDto registerOrLoginSocialMember(SocialLoginRequest socialLoginRequest) {
        // 이메일로 회원 조회
        Member existingMember = memberRepository.findByEmail(socialLoginRequest.getEmail())
                .orElse(null);

        if (existingMember == null) {
            // 회원이 존재하지 않으면 회원 가입
            Member newMember = Member.builder()
                    .name(socialLoginRequest.getName())
                    .email(socialLoginRequest.getEmail())
                    .memberType(MemberType.KAKAO) // 혹은 다른 소셜 로그인 유형에 따라서 설정
                    .role(Role.USER)
                    .tokenExpirationTime(LocalDateTime.now().plusDays(7)) // 예시로 토큰 유효 기간을 7일로 설정
                    .build();

            // 회원 저장
            memberRepository.save(newMember);

            // 새로 생성된 회원에 대한 토큰 발급
            JwtTokenDto jwtTokenDto = tokenManager.createJwtTokenDto(newMember.getMemberid(), Role.USER);

            return jwtTokenDto;
        } else {
            // 회원이 이미 존재하면 해당 회원에 대한 토큰 발급
            JwtTokenDto jwtTokenDto = tokenManager.createJwtTokenDto(existingMember.getMemberid(), Role.USER);

            return jwtTokenDto;
        }
    }

이부분만 추가를 햇는데, 이게 맞는 과정인가요? 블로그들 뒤져봐도 딱 저같은 상황이 없어서 도저히 모르겠어서gpt에게....

맞다면,뒤에 회원가입 (6)의 경우 (4),(5)콛를 구현하지 않아 영상대로 진행할수 없는데,

어느부분을 수정하면서 해야할까요... 부탁드립니다 선생님ㅜㅜ

@Transactional
//@RequiredArgsConstructor
@Service
public class MemberService {
    private final MemberRepository memberRepository;
    private final TokenManager tokenManager;
    public MemberService(MemberRepository memberRepository, TokenManager tokenManager) {
        this.memberRepository = memberRepository;
        this.tokenManager = tokenManager;
    }


    public Member registerMember(Member member){
        return memberRepository.save(member);
    }
    private void validateDuplicateMember(Member member){
        Optional<Member> optionalMember = memberRepository.findByEmail(member.getEmail());
        if(optionalMember.isPresent()){
            throw new BusinessException(ErrorCode.ALREADY_REGISTERED_MEMBER);
        }
    }

    @Transactional(readOnly = true)
    public Optional<Member> findMemberByEmail(String email) {
        return memberRepository.findByEmail(email);
    }

    @Transactional(readOnly = true)
    public Member findMemberByRefreshToken(String refreshToken) {
        Member member = memberRepository.findByRefreshToken(refreshToken)
                .orElseThrow(() -> new AuthenticationException(ErrorCode.REFRESH_TOKEN_NOT_FOUND));
        LocalDateTime tokenExpirationTime = member.getTokenExpirationTime();
        if(tokenExpirationTime.isBefore(LocalDateTime.now())) {
            throw new AuthenticationException(ErrorCode.REFRESH_TOKEN_EXPIRED);
        }
        return member;
    }

    public Member findMemberByMemberId(Long memberId) {
        return memberRepository.findById(memberId)
                .orElseThrow(() -> new EntityNotFoundException(ErrorCode.MEMBER_NOT_EXISTS));
    }
    @Transactional
    public JwtTokenDto registerOrLoginSocialMember(SocialLoginRequest socialLoginRequest) {
        // 이메일로 회원 조회
        Member existingMember = memberRepository.findByEmail(socialLoginRequest.getEmail())
                .orElse(null);

        if (existingMember == null) {
            // 회원이 존재하지 않으면 회원 가입
            Member newMember = Member.builder()
                    .name(socialLoginRequest.getName())
                    .email(socialLoginRequest.getEmail())
                    .memberType(MemberType.KAKAO) // 혹은 다른 소셜 로그인 유형에 따라서 설정
                    .role(Role.USER)
                    .tokenExpirationTime(LocalDateTime.now().plusDays(7)) // 예시로 토큰 유효 기간을 7일로 설정
                    .build();

            // 회원 저장
            memberRepository.save(newMember);

            // 새로 생성된 회원에 대한 토큰 발급
            JwtTokenDto jwtTokenDto = tokenManager.createJwtTokenDto(newMember.getMemberid(), Role.USER);

            return jwtTokenDto;
        } else {
            // 회원이 이미 존재하면 해당 회원에 대한 토큰 발급
            JwtTokenDto jwtTokenDto = tokenManager.createJwtTokenDto(existingMember.getMemberid(), Role.USER);

            return jwtTokenDto;
        }
    }
}
정성주님의 프로필 이미지
정성주
질문자

그리고 나온 토큰을 jwt사이트에서 보면 정보는 맞게 뜨는데, invalid 나오는데 이건 자체로컬에서 만든거니까 invalid 떠도 상관없는게 맞나요? 정보만 잘 나오면?image

정성주님의 프로필 이미지
정성주

작성한 질문수

질문하기