전체 글
-
양방향 연관관계와 CASECADE 옵션spring/JPA 2021. 2. 25. 00:56
프로젝트를 진행하던 중 게시글 입력 규칙을 바꾸기로 했다. 기존 게시글은 본인의 이력을 입력하는 필드가 있었는데 이 입력 필드의 개수는 2개로 고정되어 있었다. 요구사항이 변경돼 사용자는 입력 필드를 동적으로 추가하거나 삭제할 수 있게 했다. 변경된 요구사항을 반영하기 위해 JPA와 RDB의 설계를 수정했다. 우선, RDB에서는 간단하게 동적 필드를 테이블로 분리했다. 분리한 테이블은 고유ID를 갖고 게시글의 ID를 FK로 갖는다. 다음으로 JPA 수정에 들어 갔다. 게시글과 이력의 관계는 1:N관계 즉, 한 게시글은 N개의 이력을 갖는다. JPA에서 1:N관계를 설계할 때 고려해야할 2가지 사항이 있다. 첫째는 연관관계를 단방향으로 가질지 양방향으로 가질지를 결정해야 한다. 대부분의 객체는 단방향으로 ..
-
트랜잭션과 트랜잭션 격리수준database 2021. 2. 23. 00:54
트랜잭션 DBMS를 이용하는 WAS 환경에서 트랜잭션 설정은 보통 DAO에서 직접 정하지 않고, 비지니스로직이 들어간 서비스 계층에서 정하기 마련이다. 이 부분을 곱씹어보면 트랜잭션을 좀 더 가슴으로 느낄 수 있다. 트랜잭션은 한 비지니스로직과 DBMS가 소통하는 논리적 단위이다. 같은 트랜잭션 내에서 모든 변경사항은 그 생명주기를 같이 하게 된다. 트랜잭션 격리수준 트랜잭션 격리수준은 여러 트랜잭션의 동시성과 관련된 개념이다. 이를테면 A 트랜잭션에서 변경하고 있는 레코드를 B트랜잭션이 읽어올 수 있을지에 대한 내용이다. READ_UNCOMMITTED READ_UNCOMMITTED 격리수준에서는 아무런 RACE CONDITION을 고려하지 않는다. 즉, 한 트랜잭션이 특정 레코드에서 어떤 작업을 하든 ..
-
spring session 아키텍처spring/session 2021. 2. 22. 12:35
현재 프로젝트는 session을 was의 메모리에서 관리하고 있다. 이 방법은 내가 지정한 방법이 아니라, tomcat이 기본으로 실행하고 있는 방법이다. 요청에 대한 getSession()이 호출되는 시점에 쿠키 설정부터 쿠키와 세션을 저장하기까지 was가 다 해준 것이다. 구현은 편리하지만, 서버 확장 시 큰 문제가 생긴다. 논리적으로 동일한 서버지만 물리적으로 다른 서버라면 세션의 동기화가 필요하다. 또한, was의 메모리를 직접 할당해 세션을 관리하므로 공간적 제약도 고려해야 한다. 결국 세션 저장소를 분리하기로 했고, Filter로 spring session을, 저장소로 redis를 사용하기로 했다. boot를 이용한 프로젝트에서 의존성을 추가하고, application.yml에 필요한 정보를 ..
-
Spring Security 아키텍처spring/security 2021. 2. 21. 01:29
늘 그렇듯 아키텍처를 이해하는 게 모든 커스터마이징의 기본이다. 현재 프로젝트의 세션 관리는 전부 was내에서 처리한다. 나중에 서비스가 커져서 was를 분산하거나, 한 was에 모든 세션을 저장하기 부담스러운 상황이 온다면? redis를 이용해 세션을 was에서 분리하는 목표를 세웠다. 그전에, servlet으로 가기 이전인 filter기반으로 동작하는 스프링 시큐리티 아키텍처를 이해해보자. 스프링 WAS의 큰 그림 클라이언트의 요청이 오면 요청은 FilterChain으로 이루어진 Filter를 하나씩 거치게 된다. 모든 Filter를 거친 후 최종적으로 servlet에 요청을 위임한다. 이때 spring security는 servlet에게 요청을 위임하기 전에 인증, 인가만 따로 처리하는 하나의 Fi..
-
RDBMS 아키텍처(MySQL)database 2021. 2. 19. 23:50
DB와 연결한 서버에서(spring) DB api를 이용해 쿼리를 보낸 경우를 생각해보자. 객체 간 역할 분담이 잘 되어 있다면 프로그래머는 DBMS에서 어떤 일이 벌어지는지 신경 쓸 필요가 없다. 그래도 가끔은 상상해본다. 내가 요청한 쿼리가 어떻게 처리될까? 또, 내가 요청한 쿼리가 DBMS와 협업하기에 최적의 쿼리일지 의심이 될 때도 있다. 아키텍처 큰 그림은 항상 머릿속에 담자두자. - 파서 : 요청받은 쿼리를 토큰 단위로 잘라 문법 체크를 해준다. - 전처리기 : 토큰 단위로 객체를 테이블 또는 내장 메서드로 매핑한다. - 옵티마이저 : 요청받은 쿼리의 최적화를 담당 - 쿼리 실행기 : 핸들러를 이용해 스토리지 엔진에게 결과 요청 및 결과 사용자에게 반환 - 스토리지 엔진 : 쿼리 실행기에게 전..
-
스프링서버 EC2에 배포하기infrastructure 2021. 2. 17. 23:50
아키텍쳐 구성 과정 1. 작성한 코드 깃헙에 올리기 2. 깃헙과 트래비스CI를 연동해서 빌드 및 테스트하기 3. 트래비스CI에서 빌드된 파일 S3에 업로드하기 4. codedeploy가 S3에서 빌드파일을 EC2에 배포 및 자동 실행해주기 1. 작성한 코드 깃헙에 올리기 깃헙 레파지토리를 생성하고 로컬과 연결한 상황에서 시작 - git add -A - git commit -m "any message" - git push 2. 깃헙과 트래비스CI를 연동해서 빌드 및 테스트하기 - 연동하고 싶은 계정으로 트래비스CI에 로그인하자 - 트래비스CI의 settings의 Legacy Service integration에서 연동하고 싶은 레퍼지토리를 선택하자 (너무나도 놀랍게도 이러면 연동이 끝난다.) - 레파지토리..
-
HashMap이란?java 2021. 2. 12. 23:09
HashMap이란? 일단, 이름 자체에서 내부 구현을 추측해보았다. Hash란 인덱스를 통해 데이터의 저장위치를 찾는 알고리즘이고, Map이란 key와 value 쌍으로 데이터를 저장하는 방식이다. 그럼 이 둘을 조합한 HashMap은 key와 value의 쌍으로 이루어진 데이터를 인덱스를 이용해 저장 또는 검색하는 자료구조다. 해시의 종류는 크게 두가지로 나뉜다. 하나는 Open Addressing이고 다른 하나는 Separate Chaining이다. java에서 실제로 사용하는 해싱기법은 Separate Chaining이므로 이 부분만 정리하도록 하겠다. 메모리는 한정적이기 때문에 현실적으로 모든 객체에 대해 고유한 인덱스를 갖게 하는 해시함수를 설계하는 건 비효율적이다. 한 WAS에서도 여러 Has..
-
Spring Security를 적용한 Web Layer 테스트하기spring/test 2021. 2. 11. 12:50
클라이언트로부터 http요청을 받아 서비스계층으로 요청을 위임하는 Controller는 단위테스트가 불가능하다고 생각했다.애초에 복잡한 비지니스로직보다는 http요청을 잘 전달받고 서비스계층에게 역할을 위임한 후 올바른 데이터가 올 것이란 믿음과 함께 request를 잘 리턴하기만 하면 됐기 때문이다. 테스트를 하더라도 @SpringBootTest와 postman을 이용한 테스트를 했었고, 이는 결국 실제 애플리케이션을 띄우는 작업과 다를 바 없는 무의미한 테스트로 생각했다. 결국 테스트코드를 이용한 자동화 테스트보다는 서버를 띄운 수동테스트를 주로 했었다. 그러던 중, @WebMvcTest에 대한 예제를 확인했고, @SpringBootTest보다 훨씬 가벼운 준?통합 테스트를 확인했다.(자동화가 가능한..