본 시리즈는 작성자의 이해와 경험을 바탕으로 실습 위주의 설명을 기반으로 작성되었습니다.
실습 위주의 이해를 목표로 하기 때문에 다소 과장이 많고 생략된 부분이 많을 수 있습니다.
따라서, 이론적으로 미흡한 부분이 있을 수 있는 점에 대해 유의하시기 바랍니다.
또한, 본 시리즈는 ChatGPT의 도움을 받아 작성되었습니다.
수 차례의 질문을 통해 도출된 여러가지 다양한 방식의 코드를 종합하여
작성자의 이해와 경험을 바탕으로 가장 정석으로 생각되는 코드를 재정립하였습니다.
User Entity
와Auth Entity
를 생성합니다.
User.java
는 말 그대로 유저 정보를 저장하는 용도로 사용하고,
Auth.java
는 JWT 인증을 위한 정보를 저장하는 용도로 사용합니다.
Role.java
public enum Role {
ROLE_USER("USER"),
ROLE_ADMIN("ADMIN");
// "USER", "ADMIN"
private String value;
// Constructor
Role(String value) {
this.value = value;
}
// GetValue
public String getValue() {
return this.value;
}
}
User.java
@NoArgsConstructor
@Getter
@Entity
public class User extends BaseTime {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 50, nullable = false, unique = true)
private String email;
@Column(length = 50, nullable = false, unique = true)
private String contact;
@Column(length = 50, nullable = false, unique = true)
private String username;
@Column(length = 100, nullable = false)
private String password;
@Enumerated(EnumType.STRING)
private Role role;
@OneToOne(mappedBy = "user", cascade = CascadeType.REMOVE)
private Auth auth;
@Builder
public User(String email, String contact, String username, String password, Role role) {
this.role = role;
this.email = email;
this.contact = contact;
this.username = username;
this.password = password;
}
}
Auth.java
@NoArgsConstructor
@Getter
@Entity
public class Auth extends BaseTime {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String tokenType;
@Column(nullable = false)
private String accessToken;
@Column(nullable = false)
private String refreshToken;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Builder
public Auth(User user, String tokenType, String accessToken, String refreshToken) {
this.user = user;
this.tokenType = tokenType;
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
}
각각의 필드는 다음과 같은 역할을 합니다.
tokenType
:JWT
사용시 추후Bearer
타입을 가지게 됩니다.accessToken
: 액세스 요청을 위한 수명이 짧은Token
refreshToken
: 새accessToken
을 발급받기 위한 수명이 긴Token
expirationDate
:accessToken
,refreshToken
만료 일자
Access Token
vsRefresh Token
차이
Access Token
은 인증에 성공한 후 사용자에게 발급되는 단기 토큰입니다. 일반적으로 보호된 리소스 또는 서비스에 대한 요청을 인증하는 데 사용됩니다. 액세스 토큰은 도난당하고 악의적으로 사용될 위험을 최소화하기 위해 수명이 짧습니다. 액세스 토큰이 만료되면 사용자는 새 토큰을 얻기 위해 다시 인증해야 합니다.반면,
Refresh Token
은 새 액세스 토큰을 얻는 데 사용되는 수명이 긴 토큰입니다. 액세스 토큰이 만료되면 사용자는 새로 고침 토큰을 사용하여 재인증 없이 새 액세스 토큰을 얻을 수 있습니다. 이것은 인증 요청의 빈도를 줄이고 시스템을 보다 사용자 친화적으로 만듭니다.[Reference] ChatGPT
Q. What's the difference between accessToken and refreshToken?
User
와 관련된Request
,Response
에 관여하는 데이터 객체입니다.
Database와 직접적으로 연결되어 있지 않기 때문에 안전성 측면에서 용이합니다.
UserRequestDTO.java
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class UserRequestDTO {
private Role role;
private String email;
private String contact;
private String username;
private String password;
public User toEntity() {
return User.builder()
.role(this.role)
.email(this.email)
.contact(this.contact)
.username(this.username)
.password(this.password)
.build();
}
}
회원가입 및 로그인에 사용되는 데이터 객체입니다.
회원가입 등의 DB 생성 요청이 발생할 경우,DTO
객체에서Entity
객체로 변환할
toEntity()
메소드를 미리 하나 구현합니다.
UserResponseDTO.java
@Getter
@Setter
public class UserResponseDTO {
private Long id;
private String role;
private String email;
private String contact;
private String username;
public UserResponseDTO(User entity) {
this.id = entity.getId();
this.email = entity.getEmail();
this.contact = entity.getContact();
this.username = entity.getUsername();
// Enum -> String
this.role = entity.getRole().name();
}
}
로그인 후 응답에 사용되는 데이터 객체입니다.
추후
Service
에서 요청에 따라Database
로부터Entity
정보를 추출한 후,
응답 객체ResponseDTO
를 생성할 때, 생성자의 매개변수로 각각의 필드에 해당하는 값이 아닌, 추출한Entity
객체를 사용함으로써 매개변수 개수에 따른 긴 길이의 생성 코드를 단축합니다.
Enum Type Role
을String Type
으로 변환하여 반환합니다.
Auth
와 관련된Request
,Response
에 관여하는 데이터 객체입니다.
Database와 직접적으로 연결되어 있지 않기 때문에 안전성 측면에서 용이합니다.
AuthRequestDTO.java
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class AuthRequestDTO {
private String username;
private String password;
}
클라이언트측에서 서버측으로 API 요청을 보낼 때 사용될
DTO
입니다.
서버측 API는 사용자를 인증하고accessToken
을 생성하기 위해username
,password
를 사용할 것이기 때문에AuthRequestDTO
에username
,password
필드가 존재해야 합니다.일반적으로 최초 로그인시 API 요청과 함꼐 전달되는
username
,password
를 로그인 요청과 인증 요청을 동시에 Request하며 함께 보냅니다.
AuthResponseDTO.java
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class AuthResponseDTO {
private String tokenType;
private String accessToken;
private String refreshToken;
@Builder
public AuthResponseDTO(Auth entity) {
this.tokenType = entity.getTokenType();
this.accessToken = entity.getAccessToken();
this.refreshToken = entity.getRefreshToken();
}
}
인증 요청에 대해
User
정보와 함께Token
정보를 응답으로 반환합니다.