인증과 인가, 그리고 JWT
인증과 인가인증 (Authentication) : 유저가 누구인지 확인하는 절차인가 (Authorization) : 인증이 끝난 사용자에게 무엇을 할 수 있는지를 판단해 허용하는 절차인증 방식세션 기반 인증(Session-based Authentication)서버가 로그인한 사용자의 정보를 세션에 저장클라이언트는 세션 ID가 담긴 쿠키를 이용해 서버에 요청서버는 해당 세션 ID로 인증된 사용자인지 확인장점단점중앙에서 세션을 관리 → 세션 만료 / 로그아웃 처리 용이서버 확장에 불리 (세션 공유 문제 발생)상태 유지 필요 → 무상태성 X 토큰 기반 인증(Token-based Authentication) → JWT사용자 로그인 후 서버가 인증을 확인클라이언트에게 암호화된 토큰을 발급무상태성 (Stateles..
2025.08.05
@IdClass vs @EmbeddedId : JPA 복합 키 매핑 정리
복합 키(Composite Key)란?하나의 테이블이 2개 이상의 컬럼을 조합해 PK(기본 키)를 구성하는 경우흔히 다대다(N:M) 관계를 풀어내는 조인 테이블에서 자주 사용 예시 테이블 구조CREATE TABLE order_items ( order_id BIGINT, product_id BIGINT, quantity INT, PRIMARY KEY (order_id, product_id) # order_id + product_id 가 복합 PK);하나의 주문(Order)에는 여러 상품(Product)이 포함될 수 있음하나의 상품은 여러 주문에 포함될 수 있음이 경우 OrderItem 테이블은 order_id 와 product_id 를 묶어서 복합 키로 사용 JPA에서 복합 키를 정의..
2025.08.05

인증과 인가

  • 인증 (Authentication) : 유저가 누구인지 확인하는 절차
  • 인가 (Authorization) : 인증이 끝난 사용자에게 무엇을 할 수 있는지를 판단해 허용하는 절차

인증 방식

세션 기반 인증(Session-based Authentication)

  • 서버가 로그인한 사용자의 정보를 세션에 저장
  • 클라이언트는 세션 ID가 담긴 쿠키를 이용해 서버에 요청
  • 서버는 해당 세션 ID로 인증된 사용자인지 확인
장점 단점
  • 중앙에서 세션을 관리 → 세션 만료 / 로그아웃 처리 용이
  • 서버 확장에 불리 (세션 공유 문제 발생)
  • 상태 유지 필요 → 무상태성 X

 

토큰 기반 인증(Token-based Authentication) → JWT

  • 사용자 로그인 후 서버가 인증을 확인
  • 클라이언트에게 암호화된 토큰을 발급
무상태성
(Stateless)
확장성
(Scalability)
무결성
(Integrity)
  • 인증 정보를 서버에 저장 X
  • 서버는 클라이언트의 인증 정보를 저장, 유지하지 않아도 되는 상태
  • 서버 확장 시 상태 관리를 신경 쓸 필요 없음 → 서버 확장 용이
  • 토큰 기반 인증 사용 타 시스템에 로그인 확장 가능
  • 토큰은 서명되어 위변조 불가능
  • 토큰이 변경되면 서버에서는 유효하지 않은 토큰으로 판단

 

JWT 구조

Header.Payload.Signature
Header    타입과 알고리즘 명시 (ex. HS256)
Payload    실제 정보 (ex. email, userId 등) → 최소한의 정보만 담는 것을 권장
Signature    서버 비밀키로 서명된 값, 위변조 여부 검증용
Payload는 Base64 인코딩 되어 있어 누구나 읽을 수 있음. 따라서 민감한 정보는 절대 넣으면 안 됨 !

 

JWT 인증 절차

  1. 사용자 로그인 요청
  2. 서버에서 사용자 정보 인증 후 JWT 생성
  3. 클라이언트가 JWT 저장 (ex. 쿠키, 로컬 스토리지)
  4. 이후 요청 시 JWT 첨부
  5. 서버는 JWT 검증 후, 사용자 권한 확인 및 리소스 제공

JWT 적용 시 고려사항

  1. Access Token과 Refresh Token 분리
    • Access Token : 짧은 유효기간 (ex. 15분)
    • Refresh Token : 긴 유효기간 (ex. 2주) → 재발급 전용
    • Refresh Token 탈취 방지를 위해 Redis에 저장하고, 로그아웃 시 폐기
  2. Refresh Token 보안 강화 전략
    • 1회 사용 후 무효화 (Rotate 방식)
    • IP / 디바이스 정보 기록 후 요청과 비교
    • 비정상 패턴 감지 : 짧은 시간에 여러 요청이 발생하는 경우 블랙리스트 처리

OAuth (Open Authorization)

  • 사용자가 다른 웹 사이트 또는 애플리케이션에 대한 접근 권한을 부여하는 개방형 표준 프로토콜
  • 제3자 서비스에 대한 인가를 제공
  • 로그인 없이 서비스 기능을 사용
  • 액세스 토큰 발급에 사용하여 권한 부여를 관리

'📚 Study' 카테고리의 다른 글

@IdClass vs @EmbeddedId : JPA 복합 키 매핑 정리  (2) 2025.08.05

복합 키(Composite Key)란?

  • 하나의 테이블이 2개 이상의 컬럼을 조합해 PK(기본 키)를 구성하는 경우
  • 흔히 다대다(N:M) 관계를 풀어내는 조인 테이블에서 자주 사용

 

예시 테이블 구조

CREATE TABLE order_items (
    order_id BIGINT,
    product_id BIGINT,
    quantity INT,
    PRIMARY KEY (order_id, product_id) # order_id + product_id 가 복합 PK
);
  • 하나의 주문(Order)에는 여러 상품(Product)이 포함될 수 있음
  • 하나의 상품은 여러 주문에 포함될 수 있음
  • 이 경우 OrderItem 테이블은 order_id 와 product_id 를 묶어서 복합 키로 사용

 

JPA에서 복합 키를 정의하는 방법

대표적으로 @IdClass 방식과 @EmbeddedId 방식이 있다.

 

@IdClass 방식

  • 복합 키를 외부 식별자 클래스로 정의하고, 엔티티 내부에서 각 키 필드를 개별적으로 선언하는 방식
  • 이 방식은 구조가 단순한 조인 테이블에 특히 유용함. 예를 들어 학생(Student)과 수업(Course)의 다대다 관계를 풀어내는 중간 테이블(StudentCourse)처럼, 복합 키만 정의하면 되는 테이블에서는 빠르고 간단하게 구현할 수 있음
  • 식별자 클래스와 엔티티 클래스 양쪽에 동일한 필드를 선언해야 함 → 코드 중복
  • 레거시 시스템을 다루거나 기존 데이터베이스 모델이 POJO 스타일로 구성된 경우
  • 필드의 개별 접근이 자주 필요하거나, 별도의 연관관계 없이 식별자만으로 조회하는 경우

 

식별자 클래스 생성
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

import jakarta.persistence.Embeddable;
import java.io.Serializable;

@Getter 
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
// @Embeddable 안 씀 !
public class OrderItemId implements Serializable {

    private Long orderId;
    private Long productId;
}

 

Entity 클래스
import jakarta.persistence.*;

@Entity
@IdClass(OrderItemId.class)
public class OrderItem {

    @Id
    private Long orderId;

    @Id
    private Long productId;

    private int quantity;
	
     /*
        연관관계 매핑(예: Order, Product) 추가 시
        @ManyToOne
    	@JoinColumn(name = "order_id", insertable = false, updatable = false)
    	private Order order;

    	@ManyToOne
    	@JoinColumn(name = "product_id", insertable = false, updatable = false)
    	private Product product;
    */
    
    // 기본 생성자, getter/setter 생략
}

@EmbeddedId 방식

  • 복합 키를 하나의 값 객체로 만들어, 해당 객체를 엔티티의 식별자로 사용하는 방식
  • 코드 중복이 없고 구조적으로 더 깔끔함
  • 객체지향적인 설계를 선호하는 경우
  • 엔티티와 연관관계 매핑이 필요한 경우 (@EmbeddedId + @MapsId) 
  • 복합 키 자체가 하나의 도메인 객체로 의미가 있을 경우 적합

 

복합 키 클래스 정의
import jakarta.persistence.Embeddable;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Embeddable  // @EmbeddedId 방식일 때는 꼭 필요!
public class OrderItemId implements Serializable {

    private Long orderId;
    private Long productId;
}

 

Entity 클래스
import jakarta.persistence.*;

@Entity
public class OrderItem {

    @EmbeddedId
    private OrderItemId id;

    private int quantity;
	
    /*
        연관관계 매핑(예: Order, Product) 추가 시
        @ManyToOne
        @MapsId("orderId")
        @JoinColumn(name = "order_id")
        private Order order;

        @ManyToOne
        @MapsId("productId")
        @JoinColumn(name = "product_id")
        private Product product;
    */
   
    // 기본 생성자, getter/setter 생략
}

'📚 Study' 카테고리의 다른 글

인증과 인가, 그리고 JWT  (1) 2025.08.05