QueryDSL
DSL (Domain-Specific Language)은 특정 분야의 문제 해결에 특화된 프로그래밍 언어라고 볼 수가 있다. 그리고 DSL의 종류 중에 External DSL과 Internal DSL이 있는데 QueryDSL은 이 중 기존 프로그래밍 언어 안에서 만들어지는 Internal DSL이고 Java코드로 SQL쿼리를 작성하기 위한 DSL이다.
QueryDSL을 통해 동적으로 JPQL을 작성 할 수 있게 한다.
의존성 3가지(QueryDSL-core, APA, JPT Support)를 추가하여 사용해주자
// 핵심 라이브러리 (실행 시 사용)
// Source: https://mvnrepository.com/artifact/io.github.openfeign.querydsl/querydsl-jpa
implementation 'io.github.openfeign.querydsl:querydsl-jpa:7.1'
// Source: https://mvnrepository.com/artifact/io.github.openfeign.querydsl/querydsl-core
implementation 'io.github.openfeign.querydsl:querydsl-core:7.1'
// QClass 생성을 위한 도구 (빌드 시 사용)
// Source: https://mvnrepository.com/artifact/io.github.openfeign.querydsl/querydsl-apt
annotationProcessor 'io.github.openfeign.querydsl:querydsl-apt:7.1:jakarta'
// 어노테이션 해석을 위한 API
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
// QueryDsl 설정
@Configuration
public class QueryDslConfig {
@Bean
public JPAQueryFactory queryFactory(EntityManager entityManager){
return new JPAQueryFactory(entityManager);
}
}
QueryDSL을 사용하기 위해 JPAQueryFactory를 스프링 빈으로 등록한다.
private final JPAQueryFactory queryFactory;
@Transactional(readOnly = true)
public Optional<Item> findByCode(String code){
return Optional.ofNullable(queryFactory.selectFrom(item)
.where(item.code.eq(code))
.fetchFirst());
}
queryFactory를 통해 손쉽게 빌더 패턴을 사용하여 jpql을 구현하여 데이터를 넘겨줄 수 있게 된다.
CQRS 패턴 (명령 쿼리 책임 분리)
읽기랑 쓰기 모델 DB를 분리하는 것
데이터의 변경과 조회를 다른 모델로 처리하는 패턴을 의미한다.
장점 : 독립적인 크기 조정 가능, 각 목적에 맞는 최적화된 데이터 스키마, 관심사의 분리 , 더 간단한 쿼리
단점 : 애플리케이션 디자인 복합성 증가, 최종 일관성 문제
Spring DB Migration
DB의 변경사항을 다 기록하여 관리해주는 것
- Flyway : sql로 작성하여 관리가 쉬움, DB간 호환 힘듦
- Liquibase : yaml로 작성하여, 복잡함. DB간 호환이 좋다.
데이터베이스를 만들어주면 안에 건드리지 않은 테이블이 나오게 되는데 이는 flyway_schema_history이다. 이것으로 마이그레이션 툴을 시험해본다.
flyway_schema_history는 어떤 SQL마이그레이션이 이미 실행되었는지 기록하는 일을 수행한다. 문제를 보고 다시 실행시켜준다. 이때 이미 실행된 v1,v2와 같은 migration은 다시 실행하지 않는다. spring batch도 위와 유사한 기능을 갖고있다.
spring batch를 붙이면 위와 같은 스키마가 만들어지게 된다.
applcation.yml 파일에 필요한 설정을 한다.
Migration 파일 명명 규칙
파일 이름을 읽어서 실행 순서를 정하기 때문에 이름이 매우 중요하다
형태 :
__ .sql
[Prefix]
- V : Versioned Migration
- 한 번만 실행 됨.
- 버전 순서대로
- R : Repeatable Migration
- checksum 변경되면 재실행
- version 기재 X
- U : Undo 잘 안쓰임
[Version]
숫자 . _ 사용 가능
V1_1 V1_2 V2 V3 등.
더 작은 것부터 실행
보통 _를 많이 씀
[Description]
Github message 같은 느낌. 설명
공백 대신 _ 사용
마이그레이션을 통한 버전관리를 V3__add_post_status.sql처럼 기능을 추가시키는 것이 가능하다.
spring 생태계

위는 Monolitic 구조로 spring 생태계를 표현한 것이다. 단순히 spring Data JPA, spring WebMVC 말고도 알아야 하는 것이 매우 많음을 알 수가 있다.
하지만 이렇게 Monolitic 구조로 서비스를 운영하게 되면 단 하나의 장애로 인해 다른 모든 기능을 이용할 수 없게 된다. 이와 같은 문제를 보완하기 위해 나온 구조가 MSA(Micro Service Architecture)이다. 이는 여러 작은 구조를 합쳐서 하나의 서비스로 만드는 것이다. 여기에는 입력을 한 통로로 받아야 하는 것이 있는데 이를 spring gateway이고 클라우드로 구현한 것이 spring cloud이다. 또한 spring이 쿠버네티스와 호환이 좋아져서 spring k8s를 사용할 줄 알아야 한다. 이처럼 단순 mvc구조와, jpa를 사용할 줄 아는 것만으로는 규모의 서비스를 제공하는 것은 힘들다.
Spring Security 첫걸음
웹에서 규모있는 서비스를 제공하기 위해서는 필요한 보안조치를 할 필요가 있다.
스프링에서 어떠한 방식으로 sequrity를 제공하고 있을까?
모든 해킹을 완전히 막는 것은 불가능하다. 아무리 견고한 방어를 만들더라도 미세한 틈을 뚫고 들어온다. 완벽했다고 생각하는 방어벽도 뚫리고 다시 막는 것의 반복이다. 그렇지만 우리는 적절한 보안 조치로 해킹의 성공 확률을 많이 낮출 수가 있다.
또한 백엔드에서도 어느정도 보안에 관한 조치를 취할 필요가 있다. csrf, xss 와 같은 잘알려진 공격은 우리가 막아주는 것이 좋다. 우리가 취할 수 있는 최대한의 조치는 해줘야 한다.
스프링 시큐리티는 집단지성이라고 봐도 된다. 백엔드에서 마주친 여러가지 보안 대책이 모아진 spring 하위 프레임워크 중 하나이다. 인증, 인가 등을 활용한 애플리케이션의 리소스 접근 제한등 가장 기본적이고 필요한 보안 기능을 제공해준다.
추가적으로 이 spring security는 보안에 관한 내용을 커스터마이징 해준다. jwt를 사용한 통신방식, OAuth 2.0 사용등을 사용하게 된다.
Interceptor은 controller에 요청이 들어가기전에 부가적인 작업을 수행할 수 있도록 도와주는 객체이다.
WAS에서 Dispatcher Servlet 내부로 들어오지 않은 것은
논리적으로 위임하기 전에 catch를 한것은 위임하지 않았다고 봐도 된다. dispatcher servlet에 들어가기 전에 이시점에서 interceptor해서 무언가를 판별하고 수행하는 것을 Filter라고 한다

필터라는 친구는 Dispatcher servlet에 들어가기 전에 수행하는 것을 의미한다.
정수기 내부에는 여러가지 정수를 거치기 위해 필터가 존재한다. 각각의 필터는 내가 거를 수 있는 불순물만 거스른다. 내가 못거르는 것은 다음 필터를 통해 거르도록 한다.
Spring Security에서 사용하는 filter도 이와 동일하다. filter chain이라는 것을 사용하여 자신이 여과할 수 있는 것만 거쳐서 여과되도록 한다. 다음 필터로 이동해서 깨끗한 물이 나오도록 하는 방식이다.
dispatcher servlet을 거쳐서 나오게 한다.
이러한 필터를 통해 스프링 어플리케이션에 대해 보안과 접근이 가능하다. 이게 스프링 시큐리티에 관한 전반적인 내용이다.
다음은 무엇을 봐야 할까? 인증과 인가를 봐야 한다.
회사에는 여러가지 기밀이 존재한다. 회사는 여러가지 이유로 회사의 관계자가 아닌 이상 회사의 구역에 접근하는데 제한을 두게 된다. 내가 회사의 관계자라는 것을 증명해서 회사에 입장을 할 수 있게 된다.
인증 Authentication
본인이 누구인지 인증하는 것이 인증, Authentication이다.
인증이 되어야지 스스로에 대한 정보를 밝혀서 들어갈 수 있게 된다.
계정과 비밀번호를 통해 밝히는 나라는 정보를 밝히는 것이다.
이러한 서비스에 접근하기 위해서는 인증이 필요하다.
요즘 많이 사용하는 인증으로는 소위 sns로그인이라고 불리는 방식이 OAuth 2.0 방식이 있다.
이것은 추후에 다루도록 하겠다.
인가 Authorization
인증은 되었으나 우리가 들어갈 수 있는 건물이 다를 수가 있다. 이처럼 인증된 회원을 구분할 수 있게 하는 것이 인가이다. 인가는 전제가 뭐냐면 인증이 완료된 사람한테 어떠한 권한이 있는 지 확인하는 것을 의미한다.
로그인은 인증이라면 회원 등급이 인가라고 볼 수가 있다. 인증이라는 것은 인가의 대전제라고 봐도 무방하다.
Spring Security 에서 인증을 어떻게 수행하고 있을까?
Filter을 수단으로 사용한다. 우리가 따로 여러가지를 정의하지 않더라도 이 Spring Security를 통해 적용된다. 인증정보를 보게된다. 우리 관계자라면 요청을 처리할 수 있도록 다음 곳으로 넘겨주고 필터를 통해 막고 다음으로 되돌려 보낸다.
이게 스프링 시큐리티에서 인증을 위한 사용방식이다.
그 중 하나로 계정과 비밀 번호를 통해 보안을 수행하는 방식이 존재한다.

이 스프링 시큐리티를 주입받으면 어떠한 url을 적용해도 보이게 된다. 사용자 이름과 비밀번호를 찍어준다. 이 계정을 유저네임과 패스워드에 입력을 해주고 사용자 인증을 할 수 있게 된 것이고 다른 페이지에 접근을 할 수 있게 된다.
당연히 html 페이지가 어떻게 구성되어 있는가를 보면 이 페이지는 html form 태그로 이루어져 있다. 여기에는 두가지 input 태그가 있다. 유저네임, 패스워드가 포함된다. sign in 을 눌러 들어가게 되면 username은 뭐고 패스워드가 뭔지 나오게 된다.
이 방식에서 인증을 위한 방식으로 username, password를 통한 폼태그를 사용한다. 이게 기본적인 흐름이다. 이러한 방식을 form based authentication이다. 별도의 설정을 하지 않는 이상 폼기반 동작방식으로 진행이 이뤄진다.