개요 작년에 스프링 시큐리티를 처음 공부했을 때(https://eckrin.tistory.com/103) 시큐리티 구조와 초기 설계에 대해서 글을 썼던 적이 있는데, 실제로 사용하면서 궁금했던 점들을 정리해보고자 한다. SecurityFilterChain과 WebSecurityCustomizer 먼저 시큐리티 설정을 위해서 Configuration 파일을 만들 때 httpbasic, csrf, cors 등 다양한 설정을 했는데, 그 중 antMatchers(스프링 3.x버전에서는 requestMatchers로 대체)를 사용하는 SecurityFilterChain과 WebSecurityCustomizer에 대한 설명을 해보고자 한다. SecurityFilterChain에서는 특정 경로로 들어오는 요청 패턴..
개요 Spring Data JPA가 제공하는 JPARepository 인터페이스는 PagingAndSortingRepository와 CrudRepository, Repository 인터페이스를 차례로 상속받는데, 그 중에서 페이지네이션을 지원하기 위한 repository가 PagingAndSortingRepository이다. PagingAndSortingRepository를 보면 Pageable 타입을 인자로 받고, Page타입을 반환하는 findAll() 추상메소드가 존재하는 것을 볼 수 있다. 여기서 인자로 넘어오는 Pageable 인터페이스는 페이지 번호, 페이지 크기, 정렬순서와 같은 정보들을 갖고 있으며, PageRequest의 of()라는 정적 팩토리 메소드를 통해서 Pageable 인터..
개요 스프링 프로젝트에서 데이터베이스 연결정보, 서버 포트, 로깅수준 같은 어플리케이션에 관련된 다양한 설정값들을 저장하기 위해서 application.yml을 사용한다. 그런데 이러한 정보들 중에는 외부로 노출되어서는 안되는 값들이 많이 존재하기 때문에, 아무 생각없이 Github과 같은 public 저장소에 올렸다가는 정보가 다 털릴 수 있다. (백엔드에서 잘 처리해놨다고 생각해도 어떤식으로든(노션, 발표자료, organization 등등..) 노출될 수 있으니 항상 조심하자) 어쨌든 모든 git repository를 private로 닫아둘수는 없으므로, public으로 열어두려면 아예 configuration파일 자체의 노출을 막거나, 암호화하는 등의 처리를 해주어야 하는데, 그 방법들에 대해서 다..
swagger에는 크게 springfox, springdoc 2가지 라이브러리가 있다. springfox가 먼저 나왔고 springdoc이 나중에 나왔다고 하는데, 현재 Springboot 3.x버전의 경우 현재는 springfox를 이용할 수 없다. (정확히 말하면 springboot 3.x버전이 java17을 이용하기 때문에 그런 것 같다. 더 이상 업데이트가 되지 않는 것 같음) springfox를 이용하기 위해서는 springboot 2.x버전으로 다운그레이드하거나 업데이트를 기다려야 하는데, 본인이 스프링 3.x버전(java 17)을 사용한다면 springdoc을 이용하자. springdoc에서 configuration파일은 아래와 같이 구성하면 되고, @EnableSwagger2 어노테이션도 ..
쿠버네티스란?역사 오늘날의 어플리케이션은 하나의 통일체의 형태로 동작하는 것이 아니라, 하나의 어플리케이션의 동작을 위해서 필요한 수많은 컨테이너들이 느슨하게 결합되어 함께 작동하는 형태로 구성되어 있다. MSA환경을 기반으로 만들어진 어플리케이션이 여러 개의 서버로 구성되어 있고, 각 서비스가 독립적으로 개발되고 배포되는 구조로 이루어져 있다는 것을 생각해보면 이해가 쉽다. 위의 그림은 전통적인 배포 환경과, 가상 환경을 이용한 배포, 그리고 컨테이너를 사용한 배포의 차이를 보여준다. 전동적인 배포는 물리적인 컴퓨터 하나와 하나의 운영체제 위에 여러개의 프로그램을 설치하는 방식이었다. 한대의 컴퓨터에서 여러 프로그램을 실행하다 보니 애플리케이션의 개수가 늘어날수록 퍼포먼스 저하와 프로그램 충돌이 일어나..
도커 컨테이너를 실행하면 NAT와 비슷한 환경에서 사용하게 된다. 컨테이너가 실행되는 호스트 시스템에는 이러한 기능이 사용되기 때문에, 외부에서 컨테이너 안에서 실행하는 프로그램에 대한 접근을 위해 포트포워딩이 필요할 수 있다. 한마디로 호스트의 해당 포트를 컨테이너의 대상 포트로 연결해서 컨테이너 외부에서도 접근할 수 있게 된다. docker run -p 8080:80 --name redis_container redis_image 따라서 도커에서는 위와 같이 -p옵션을 통해서 포트포워딩을 설정할 수 있는데, 위와 같이 컨테이너를 실행하면 이 redis 컨테이너의 8080번 포트로 들어오는 모든 호스트 요청은 도커 컨테이너의 80번 포트로 전달된다. 만약 호스트의 8080포트가 이미 사용중인 경우, 80..
간단한 역사 1. Tradition Deployment: 물리적인 컴퓨터 한 대(Hardware)에 하나의 OS를 깔고 그 위에 여러가지 프로그램을 설치하는 방식이다. 한 대의 컴퓨터에서 여러 프로그램을 수행하다 보니 퍼포먼스 저하, 또는 프로그램 충돌이 일어날 수 있다. 2. Virtualized Deployment: VMware, VirtualBox 등.. 리눅스쓸때 지겹게 썼던 그것이다. 1번 방법으로 문제를 해결하기 위해 여러개의 물리적 컴퓨터를 이용하는 방법 대신, Hypervisor를 사용하여 하나의 시스템위에 여러개의 가상 컴퓨터를 올려 구동한다. 각각의 가상머신은 논리적 컴퓨터이므로, CPU, 메모리, 저장장치를 각각 할당할 수 있다 (물론 Hardware의 리소스를 잡아먹는다). 이 방법..
N+1 Problem N+1 문제란, 연관관계가 설정된 엔티티를 조회할 때 연관된 엔티티의 개수(N)만큼 추가적인 쿼리가 발생하는 문제를 말한다. Member와 Order, Delivery엔티티가 있다고 하자. Order는 주문정보를 담은 엔티티로, Member(회원)와 다대일 연관관계를 가지며, 배송정보를 담은 엔티티인 Delivery와는 일대일 연관관계를 갖는다. @Entity@Table(name="orders")@Getter @Setter@NoArgsConstructor(access = AccessLevel.PROTECTED)public class Order { @Id @GeneratedValue @Column(name="order_id") private Long id; ..
스프링의 트랜잭션 스프링을 사용하면 @Transactional 어노테이션을 사용하여 선언적 트랜잭션 관리를 하게 된다. 이렇게 선언적 트랜잭션 관리 방식을 사용하게 되면 프록시 방식의 AOP가 동작한다. 그 전에 앞서 공부했던 스프링의 db 연동과정부터 차례로 살펴보면 다음과 같은 흐름을 가진다. 0. 트랜잭션을 시작하기 위해서는 db 커넥션이 필요하다.1. 스프링 컨테이너에 등록된 트랜잭션 매니저는 datasource라는 객체를 통해서 스프링이 관리하는 커넥션 풀에서 커넥션을 획득한다.2. 트랜잭션 매니저는 트랜잭션 컨텍스트를 통해 생성된 커넥션을 트랜잭션 동기화 매니저에 보관한다. 트랜잭션 컨텍스트는 트랜잭션 매니저와 트랜잭션 동기화 매니저 사이에서 트랜잭션의 작업을 관리한다.3. 트랜잭션 동기화 ..
구체적인 상황은 다음과 같다. Admin 페이지에서 POST api 요청이 올때마다 db에서 기존 데이터들을 모두 제거한 후에 request body로 들어온 데이터들을 저장해주는 로직을 기대하고 다음과 같은 코드를 작성하였다. featureRepository.deleteAll()sectionRepository.deleteAll()//req로 들어온 데이터 저장... 하지만 클라이언트 qa중 500 server error가 발생한다는 말을 듣고 찾아보니 다음과 같은 로그가 남겨져 있는 것을 볼 수 있었다. 엔티티에서 unique값으로 설정해놓은 필드가 중복된다는 뜻이었다. 그런데 삽입된 데이터는 중복이 아예 없는데, 이상하다고 생각하면서 코드를 다시 보던 중 JPA 쓰기 지연과 관련된 문제일 수 있겠..
1. 일대일 매핑에서 어느쪽을 연관관계의 주인으로 하는것이 맞는가? 반드시 다(N)쪽이 fk를 가져 연관관계의 주인이 되는 다대일 관계와 다르게, 일대일 매핑의 경우 어느쪽이 fk를 갖게 하여 주인으로 설정하든 기능적으로 문제가 없다. 어느쪽을 연관관계의 주인으로 설정하는 것이 좋을까?일대일 매핑에서도 주 테이블(자주 접근하는 테이블)과 대상 테이블이 존재하는데, 일반적으로 주 테이블에 외래키가 있는 것이 좋다고 느꼈다. 내가 진행했던 프로젝트 중에, feature별로 고유 이름을 가지게 하고, 사용자들이 그 고유 이름을 기준으로 즐겨찾기를 등록하여 feature가 변경되거나 삭제되더라도 고유 이름에 대한 즐겨찾기는 유지되게 하는 요구사항이 있었다. @Entity@Table(name = "featu..
개요 스프링 프레임워크가 처음 출시되었을 때는 의존성 버전을 직접 관리하거나, 서버를 직접 설치해주어야 하는 등의 초기 설정을 직접 해주어야 했다. 이를 보완하기 위해서 스프링 부트가 출시되었는데, 이것은 최소한의 설정으로 스프링 기반의 애플리케이션을 독립 실행할 수 있게 돕는 프레임워크라고 할 수 있다. 우리는 스프링 부트를 통해 1. starter 패키지를 통해 필요한 의존성을 자동으로 가져올 수 있게 되었을 뿐 아니라,2.기존에는 @ComponentScan, @EnableAutoConfiguration, @Configuration을 통해서 명시적으로 설정해주어야 했던 반면, @SpringBootApplication을 통해서 이 셋 대신 자동으로 필요한 빈을 설정해줄 수 있게 되었다.3. 또한, 내..