인덱스를 붙이면 균형 트리(balanced tree) 노드가 생성되어 빠른 탐색이 가능해진다. 열번 데이터를 읽어서 찾던 것을 2, 3번만에 찾는다.
인덱스가 없다면 순차적으로 읽어서 조건에 맞는 데이터를 가져오므로 뒷쪽에 위치한 데이터를 찾게 될 때 시간이 많이 걸리게 된다.
✅ 인덱스의 장점⭕과 단점✖️
⭕ SELECT 문으로 검색하는 속도가 매우 빨라집니다.
✖️ 인덱스도 공간을 차지해서 데이터베이스 안에 추가적인 공간이 필요합니다.
✖️ 데이터 변경 작업(INSERT, UPDATE, DELETE) 가 자주 일어나면 오히려 성능이 나빠질 수 있습니다.
✅인덱스의 종류(💟자동 & 💫수동)
💟 자동으로 생성되는 인덱스
클러스터형 인덱스: 어떤 열을 기본 키(Primary key)로 설정하면 자동으로 클러스터형 인덱스가 생성된다. 데이터가 정렬 되어 있음. 영어사전
보조 인덱스: 어떤 열을 고유키(Unique)로 설정하면 자동으로 보조 인덱스가 생성다. 데이터 정렬은 하지 않음. 책 뒷부분의 색인
❣️ 실습
create database index_test_db; use index_test_db;
create table table1( col1 int primary key, col2 int unique, col3 int );
-- 인덱스 확인 show index from table1;
drop table if exists member; create table member( mem_id char(8), mem_name varchar(10), mem_number int, addr char(2) );
show index from member;
insert into member values('TWC', ' 트와이스', 9, '서울'); insert into member values('BLK', ' 블랙핑크', 5, '경남'); insert into member values('WMN', ' 여자친구', 6, '경기'); insert into member values('OMG', ' 오마이걸', 7, '서울');
-- 데이터 순서 확인 select * from member;
-- 클러스터 alter table member add constraint primary key (mem_id);
Key에 PRI로 지정되어 있음을 확인 할 수 있다.
인덱스 확인 완료!분명 우리는 12~15 순으로 인서트해서 보였었는데 index를 지정해주고 나니까 mem_id가 알파벳순으로 바뀌었음을 확인 할 수 있다.
alter table member add constraint unique (mem_id);
👉 alter는 테이블의 속성을 바꾸고, 제약사항도 , 값의 속성도 전부 바꿀 수 있다.
💫 사용자가 직접 생성하는 인덱스
사용자가 생성하는 인덱스도 보조 인덱스이다.
인덱스 생성
CREATE [UNIQUE] INDEX 인덱스_이름
ON 테이블_이름 (열_이름) [ASC | DESC];
인덱스 확인
SHOW INDEX 테이블_이름;
인덱스의 적용
ANALYZE TABLE 테이블_이름;
인덱스 제거
DROP INDEX 인덱스_이름 ON 테이블_이름;
❣️ 실습
use market_db;
select * from member;
show index from member;
5번 실행
-- 인덱스 직접 생성 create index idx_member_addr on member(addr); create unique index idx_member_mem_name on member (mem_name);
analyze table member;
8~11 실행정상적으로 인덱스가 들어가있음을 확인할 수 있다.
-- excution plan 확인 select * from member;
이 부분을 확인해 보면 이렇게 나오는데 우리가 인덱스를 쓰질 않았기 때문에 그냥 출력이 된 것이다.
select mem_id, mem_name, addr from member;
.여전히 풀테이블 스캔이 나온다. 인덱스가 있는 열을 선택하는 게 인덱스를 쓰는게 아님을 알 수 있다.
select mem_id, mem_name, addr from member where mem_name = '에이핑크';
인덱스 적용이 잘 되었음을 알 수 있다.
✅ 인덱스는 where로 데이터를 찾아낼 때 쓰이는 것을 알 수 있다.
show index from member;
-- 인덱스 삭제 drop index idx_member_addr on member; drop index idx_member_mem_name on member;
1번 실행2,3번 실행
자동생성된 클러스터형 인덱스를 제외하고 전부 인덱스가 제거 되었다.
💡 자동으로 생성된 인덱스는 위 명령으로 제거할 수 없다. 테이블 구조를 변경하는 ALTER TABLE 문으로 기본키나 고유키를 제거하면 자동으로 인덱스도 제거할 수 있다.
package com.sparta.myselectshop.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// CSRF 설정
http.csrf().disable();
http.authorizeRequests().anyRequest().authenticated();
// 로그인 사용
http.formLogin();
return http.build();
}
}
[Sprng Boot 3.0 이상] 나는 여기에 해당!
2.7이랑 다른 점 : authorizeRequests() → authorizeHttpRequests()
package com.sparta.springsecurity.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// CSRF 설정
http.csrf().disable();
http.authorizeHttpRequests().anyRequest().authenticated();
// 로그인 사용
http.formLogin();
return http.build();
}
}
👉 Spring Security 와 Filter
내가 이해하기로는 클라이언트가 요청을 넣게 되고 그 것들이 시큐리티 쪽을 거치게게 되면 필터 체인에 적용된 올바른 url이 아니면 걸러준다는 거 같다.
Spring Security는 요청이 들어오면 Servlet FilterChain을 자동으로 구성한 후 거치게 한다. FilterChain은 여러 Filter를 chain형태로 묶어놓은 것을 의미합니다.
여기서 Filter 란❓ 톰캣과 같은 웹 컨테이너에서 관리되는 서블릿의 기술이다. Filter는 Client 요청이 전달되기 전후의 URL 패턴에 맞는 모든 요청에 필터링을 해준다. CSRF, XSS 등의 보안 검사를 통해 올바른 요청이 아닐 경우 이를 차단해 준다. 따라서 Spring Security는 이런한 기능을 활용하기위해 Filter를 사용하여 인증/인가를 구현하고 있다.
👉 SecurityFilterChain
말 그대로 보안 방식을 사용하는데 필요한 설정을 분리한 것
Spring 의 보안 Filter를 결정하는데 사용되는 Filter session, jwt 등의 인증 방식들을 사용하는데에 필요한 설정을 완전히 분리할 수 있는 환경을 제공한다.
👉 여러가지 필터들 중에서 내가 사용할 것은 AbstractAuthenticationProcessingFilter
: 사용자의 credential을 인증하기 위한 베이스 Filter
👉 위의 Abstract어쩌고를 상속한 UsernamePasswordAuthenticationFilter
: 기본적으로 아래와 같은 Form Login 기반을 사용할 때 username 과 password 확인하여 인증.
Form Login 기반 ❓
인증이 필요한 URL 요청이 들어왔을 때 인증이 되지 않았다면 로그인페이지를 반환하는 형태.
👉 SecurityContextHolder
: 스프링 시큐리티로 인증을 한 사용자의 상세 정보를 저장.
SecurityContext 란? SecurityContextHolder 로 접근할 수 있으며 Authentication 객체를 가지고 있다.
principal : 사용자를 식별한다. Username/Password 방식으로 인증할 때 보통 UserDetails 인스턴스다.
credentials : 주로 비밀번호, 대부분 사용자 인증에 사용하고 다음 비운다.
authorities : 사용자에게 부여한 권한을 GrantedAuthority 로 추상화하여 사용한다
<UserDetails>
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
UserRoleEnum role = user.getRole();
String authority = role.getAuthority();
System.out.println("authority = " + authority);
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(authority);
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(simpleGrantedAuthority);
return authorities;
}
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
// UsernamePasswordAuthenticationToken는 Authentication을 implements한 AbstractAuthenticationToken의 하위 클래스로, 인증객체를 만드는데 사용된다.
👉 UserDetailsService username/password 인증방식을 사용할 때 사용자를 조회하고 검증한 후 UserDetails를 반환 Custom하여 Bean으로 등록 후 사용 가능하다.
👉 UserDetails 검증된 UserDetails는 UsernamePasswordAuthenticationToken 타입의 Authentication를 만들 때 사용되며 해당 인증 객체는 SecurityContextHolder에 세팅된다. Custom하여 사용가능하다.
👉 WebSecurityConfig h2-console 사용 및 resources 접근 허용 설정하기spring secuity 지원CSRF 설정security 내의 로그인 사용 (기본적으로 session 방법으로 로그인 됨)
👉 UserDetailsImpl UserDetailsServiceImpl을 통해 갖고온 user의 정보를 활용해서 만든 객체
👉 UserDetailsServiceImpl 사용자를 DB에서 조회하고 인증해서 검증하는 부분user 객체와, DB에서 가져온 이름, 비번을 담아서 UserDetailsImpl로 반환시켜서 인증 객체 만든다
🚨 비밀번호 암호화 이해하고 적용하기
: 회원 등록 시 '비밀번호' 는 사용자가 입력한 문자 그대로 DB 에 등록하면 안 된다. '정보통신망법, 개인정보보호법' 에 의해 비밀번호 암호화(Encryption)가 의무이다.