본문 바로가기

개발 일지/TIL

[ #25 ] TIL

✏️ 0521      


숙련 과제 발제

Spring 숙련 3주차 강의


Spring 숙련 목표

 

  • Spring Security 를 통해 비밀번호를 암호화 할 수 있다
  • 인증/인가의 차이점을 설명할 수 있다
  • JWT 를 통해 어떻게 인증을 관리하는지 설명할 수 있다
  • SQL 을 통해 페이징 하며 조회하는 쿼리문을 작성할 수 있다
  • JPA 를 통해 페이징 하며 조회하는 코드를 작성할 수 있다
  • 외부 API 를 호출하여 데이터 조회 후 DB 에 저장할 수 있다

 

Spring 숙련 강의

 

Bean을 수동으로 등록하는 방법 

 

일반적으로 @Component를 사용하여 Bean을 자동으로 등록하는 것이 좋다

비즈니스 로직과 관련된 클래스들은 그 수가 많기 때문에 @Controller, @Service 와 같은 애너테이션들을 사용해서

Bean 으로 등록하고 관리하면 개발 생산성에 유리

 

 

// Spring IoC Container에 Bean으로 저장
@Configuration
public class PasswordConfig { // passwordConfig
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
        // BCrypt : 비밀번호를 암호화 해주는 Hash 함수
        // 현재까지 사용하고 있는 것들 중에서 아주 강력한 Hash 메커니즘을 가지고 있는 것 중 하나
        // Hash 함수를 통해서 Password 를 Encoder 해주는 것
    }
}


Bean 수동 등록
@Componet를 사용하면 @ComponentScan에 의해 자동으로 스캔되어 해당 클래스를 Bean 등록
=> 기술적인 문제나 공통적인 관심사를 처리할 때 사용하는 객체들을 수동으로 등록하는 것이 좋다


공통 로그처리와 같은 비즈니스 로직을 지원하기 위한

부가 적이고 공통적인 기능들을 기술 지원 Bean 이라 부르고 수동 등록한다
수동 등록된 Bean에서 문제가 발생했을 때 해당 위치를 파악하기 쉽다는 장점이 있다

수동 등록방법
Bean 으로 등록하고자하는 객체를 반환하는 메서드를 선언하고 @Bean을 설정
Bean 을 등록하는 메서드가 속한 해당 클래스에 @Configuration 을 설정
Spring 서버가 뜰 때 Spring IoC 컨테이너에 'Bean' 으로 저장

 

@SpringBootTest
public class PasswordEncoderTest {

    @Autowired
    PasswordEncoder passwordEncoder;

    @Test
    @DisplayName("수동 등록한 passwordEncoder를 주입 받아와 문자열 암호화")
    void test1() {
        String password = "Robbie's password";

        // 암호화
        String encodePassword = passwordEncoder.encode(password);
        System.out.println("encodePassword = " + encodePassword);

        // 평문 => 암호화 되지 않은 것
        String inputPassword = "Robbie";

        // 복호화를 통해 암호화된 비밀번호와 비교
        // matches(입력받은 문자열, 암호화한 비밀번호)
        // 반환 타입 : boolean (ture & false)
        boolean matches = passwordEncoder.matches(inputPassword, encodePassword);
        
        // 암호화할 때 사용된 값과 다른 문자열과 비교했기 때문에 false
        System.out.println("matches = " + matches);
    }
}

 

 

 

같은 타입의 Bean이 2개라면

 


커피콩 눌러서 Select in Spring View를 누르면
등록 되어있는 bean을 확인할 수 있다

 

 

// 오류 발생
// 같은 Bean 타입이 2개이기 때문
@Autowired
Food food;


@Autowired를 사용하여 Bean 객체를 주입려고 시도
=> 주입을 할 수 없다는 오류가 발생
같은 타입의 Bean 객체가 하나 이상이기 때문에 어떤 Bean을 등록 해줘야 할지 몰라서 오류가 발생한 것

 

@Autowired
Food pizza;

@Autowired
Food chicken;

 

등록이 된 Bean 을 사용하는 방법
기본적으로는 Autowired 는 Bean 타입으로 DI 를 지원하는데
연결이 되지 않을 경우 Bean의 이름으로 찾는다

 

 

Primary 와 Qualifier 우선순위

 

@Primary  // 같은 타입의 Bean 이 여러개 있더라도 Primary 가 있는 Bean 을 불러온다
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("치킨을 먹습니다.");
    }
}
@Autowired
@Qualifier("pizza") // 해당 명칭을 가진 Bean 을 주입
Food food;

@Qualifier("pizza")
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}

 

Qualifier 의 우선순위가 더 높다
하지만 Qualifier 는 적용하기 위해서 주입 받고자하는 곳에 해당 Qualifier 를 반드시 추가해야 한다

같은 타입의 Bean 이 여러 개 있을 때는
범용적으로 사용되는 Bean 객체에는 Primary
지엽적으로(자주 사용하지 않는 Bean) 사용되는 Bean 객체에는 Qualifier

 


Spring 설정의 우선순위
큰 범위가 우선순위가 더 낮다  == 좁은 범위의 설정이 우선순위가 더 높다

 

큰 범위 => Primary

좁은 범위 => Qualifier

 

 

인증과 인가

 

 

 

 

인증(Authentication)
인증은 해당 유저가 실제 유저인지 인증하는 개념

스마트폰에 지문인식, 이용하는 사이트에 로그인 등과 같이, 실제 그 유저가 맞는지를 확인하는 절차

 

 

인가(Authorization)
인가는 해당 유저가 특정 리소스에 접근이 가능한지 허가를 확인하는 개념
관리자 페이지-관리자 권한 같은 것

 

 

 

일반적으로 서버-클라이언트 구조로 되어있다
Http 라는 프로토콜을 이용하여 통신

 

비연결성(Connectionless) 은 서버와 클라이언트가 연결되어 있지 않다는 것
채팅이나 게임 같은 것들을 하지 않는 이상 서버와 클라이언트는 실제로 연결되어 있지 않다
리소스를 절약하기 위해서
만약 서버와 클라이언트가 실제로 계속 연결되어있다면 서버의 비용이 기하급수적으로 늘어나기 때문
서버는 실제로 하나의 요청에 하나의 응답을 내버리고 연결을 끊어버리고있다 라고 생각하면 좋다

무상태(Stateless) 는 서버가 클라이언트의 상태를 저장하지 않는다는 것
기존의 상태를 저장하는 것들도 마찬가지로 서버의 비용과 부담을 증가시키는 것 이기 때문에 기존의 상태가 없다고 가정하는 프로토콜을 이용해 구현되어 있다
실제로 서버는 클라이언트가 직전에, 혹은 그 전에 어떠한 요청을 보냈는지 관심도 없고 전혀 모른다

 

인증의 방식

 

  • 쿠키-세션 방식

서버가 ‘특정 유저가 로그인 되었다’는 상태를 저장하는 방식
인증과 관련된 아주 약간의 정보만 서버가 가지고 있게 되고
유저의 이전 상태의 전부는 아니더라도
인증과 관련된 최소한의 정보는 저장해서 로그인을 유지시킨다는 개념

  • JWP 방식

JWT(JSON Web Token)란 인증에 필요한 정보들을 암호화시킨 토큰을 의미
JWT 기반 인증은 쿠키/세션 방식과 유사하게 JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별

 


둘의 차이점은
세션을 저장해야 하는 저장소가 필요하거나(쿠키-세션) 필요없다(JWP)

 

 

 

쿠키와 세션

 

쿠키와 세션 모두 HTTP 에 상태 정보를 유지(Stateful) 하기 위해 사용
쿠키와 세션을 통해 서버에서는 클라이언트 별로 인증 및 인가를 할 수 있다

 


쿠키 = 토큰 저장소 (저장공간)
클라이언트에 저장될 목적으로 생성한 작은 정보를 담은 파일

 

  • 구성요소
    •  Name(이름): 쿠키를 구별하는 데 사용되는 키 (중복X)
    • Value (값): 쿠키의 값
    • Domain (도메인): 쿠키가 저장된 도메인
    • Path (경로): 쿠키가 사용되는 경로
    • Expires (만료기한): 쿠키의 만료기한 (만료기한 이후 삭제)

 

 


세션 = 인증 정보
서버에서 일정시간 동안 클라이언트 상태를 유지하기 위해 사용
서버에서 클라이언트 별로 유일무이한 '세션 ID' 를 부여한 후 클라이언트 별 필요한 정보를 서버에 저장
서버에서 생성한 '세션 ID' 는 클라이언트의 쿠키값('세션 쿠키' 라고 부름)으로 저장되어 클라이언트 식별에 사용

'개발 일지 > TIL' 카테고리의 다른 글

[ #27 ] TIL  (2) 2024.05.23
[ #26 ] TIL  (0) 2024.05.22
[ #24 ] TIL  (2) 2024.05.20
[ #23 ] TIL  (3) 2024.05.19
[ #22 ] TIL  (1) 2024.05.17