[내일배움캠프] (ver. 2) CH3 점심 추천&투표

변채주·2025년 10월 29일

Spring

목록 보기
6/13

1. 요구사항 분석하기

...는 과제할 시간이 부족해서 Skip하도록 하겠다.

2. 구현하기

0) 3 Layer Architecture 구조 만들기

  • 기본 Entity 설정 작성 및 연관관계 설정

    맞든 틀렸든 일단 연관관계를 아래와 같이 설정해봤다.

    [해당 이미지는 IntelliJ에서 내가 쓴 객체의 연관관계를 알아서 읽어서 만들어준 다이어그램이다.]
    왼쪽 다이어그램은 내가 의도한 바가 맞지만 오른쪽은 뭔지 모르겠다.
    (+1 질문소재)

1) 회원가입 API

  • Users 테이블에 Email, Password, Name 컬럼 생성하기
  • 검증 규칙 설정하기
    • 이메일 중복 여부 check, 형식 검증
    • 비밀번호 8자 이상 조건 check
      → 위 두 항목은 Entity 설정에서 작성 완료
    • BCrypt 암호화하기
  • POST 경로 ("/api/auth/signup")로 설정하기

Spring Security를 추가하고 차근차근 Service와 Controller를 작성해나갔다.

API Test 결과

성공!

2) 로그인 API + JWT

  • 로그인 성공 시 Access Token + Refresh Token을 발급하기
  • 이후 모든 API 요청에 활용하기?

일단 아래와 같이 Access Token과 Refresh Token을 생성하고 Access Token만 response에 저장하도록 했다.

//user 로그인
    @Transactional
    public LoginResponse login(LoginRequest request, HttpServletResponse response) {
        String userEmail = request.getEmail();
        String password = request.getPassword();

        //사용자가 존재하는지 확인
        User user = userRepository.findByEmail(userEmail).orElseThrow(
                () -> new IllegalArgumentException("등록된 이메일이 없습니다."));

        // 비밀번호 맞는지 확인
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
        }

        // JWT 생성 및 쿠키에 저장 후 Response 객체에 추가
        String accessToken = jwtUtil.createToken(user.getEmail(), ACCESS_TOKEN_TIME);
        String refreshToken = jwtUtil.createToken(user.getEmail(), REFRESH_TOKEN_TIME);
        jwtUtil.addJwtToCookie(accessToken, response);

        return new LoginResponse(accessToken, refreshToken);
    }

거의 강의 내용을 따라한거나 마찬가지라 아직 미숙해보인다...

API Test 결과

(트러블슈팅이 있었으나)결국 성공!

3. JWT 재발급 API

API Test 결과

성공!

4. JWT 인증 필터 작성 / 기본 검증

트러블슈팅

❗ 로그인 시도 시 이메일 검증이 항상 예외 처리되는 이슈

(발생 이슈)

로그인 API 구현 후 테스트를 진행했는데 아무리 봐도 같은 이메일 문자열인데 내가 입력한 문자열이 등록된 문자열이랑 다르다면서 콘솔 창에 IllegalArgumentException '등록되지 않은 이메일입니다.' 예외처리 메시지가 떴다.

(원인 분석)

가설 1. ddl-auto 설정을 create로 해서?
서버를 시작할 때마다 테이블이 재생성되어서 못 찾는 건가 의심했다.
그래서 application.properties에서 MySQL url도 다시 점검해보고 ddl-auto 설정도 update로 변경해줬다.

→ 아~무 변화도 없었다. 문제는 여전했고...머리 세가닥은 빠졌다.

원인을 찾기 위해 일부러 다시 요청을 보내고, 콘솔창에 뜨는 SQL(Hibernate) 내용을 확인했다.

Hibernate:
    select:
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.modified_at,
        u1_0.name, 
        u1_0.password
    from
        users u1_0
    where
        u1_0.email is null

보이는가...? 마지막 줄
이거 왜 Null인 컬럼을 조회하고 있어???

가설 2. 잘못된 비교 대상을 가져왔다

Request DTO

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class LoginRequest {
    private String userEmail;
    private String password;
}

Response DTO

@Getter
@AllArgsConstructor
public class LoginResponse {
    private final String accessToken;
    private final String refreshToken;
}

DB에 등록된 이메일의 컬럼명은 'email'
로그인할 때 제출받은 JSON 키 이름도 'email'

근데 JPA가 매핑해야 하는 DTO 필드명은 'userEmail' ... . . . .
같은 이름이 아니니 당연히 정확한 email 값을 못 가져왔던 것이다. (원인)

(해결 방법) DTO의 필드명 변경('userEmail' → 'email')

(참고용 ⬇️)

Service 로직

//user 로그인
    @Transactional
    public LoginResponse login(LoginRequest request, HttpServletResponse response) {
        String userEmail = request.getEmail();
        String password = request.getPassword();

        //사용자가 존재하는지 확인
        User user = userRepository.findByEmail(userEmail).orElseThrow(
                () -> new IllegalArgumentException("등록된 이메일이 없습니다."));

        // 비밀번호 맞는지 확인
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
        }

        // JWT 생성 및 쿠키에 저장 후 Response 객체에 추가
        String accessToken = jwtUtil.createToken(user.getEmail(), ACCESS_TOKEN_TIME);
        String refreshToken = jwtUtil.createToken(user.getEmail(), REFRESH_TOKEN_TIME);
        jwtUtil.addJwtToCookie(accessToken, response);

        return new LoginResponse(accessToken, refreshToken);
    }

‼️ 모든 Postman 테스트가 갑자기 무한 로딩되다

굉장히 어이없는 해결 방법...Postman을 껐다 켜자!
이전 요청이 너무 쌓였던건지 수정수정을 반복하다가 아무리 해도 동작 로딩이 계속 걸리더라. 열받아서 끄고 잠시 쉬다가 와서 다시 해봤는데? 멀쩡히 잘 돌아가더라😬

profile
우당탕탕얼레벌레 개발 일지

0개의 댓글