토이 프로젝트 배우게 된 것들 & 오류 해결🐰 18

Session vs Cookie vs JWT

http 프로토콜 환경은 Connectionless, stateless 한 특성을 가지기 때문에 서버는 클라이언트가 누구인지 매번 확인해야 합니다. 이러한 특성을 보완하기 위해서 쿠키와 세션을 사용하게 됩니다. 1. Connectionless - 클라이언트가 요청을 보내고 응답을 받으면 그 연결을 끊어 버리는 특징 - 즉, http는 클라이언트가 request를 서버에 보내면, 서버는 클라이언트에게 요청에 맞는 response를 보내고 접속을 끊는다. 2. Stateless - 통신이 끝나면 상태를 유지하지 않는 특징 - 연결을 끊는 순간 클라이언트와 서버의 통신이 끝나며 상태 정보는 유지하지 않는 특성이 있다. 쿠키와 세션은 위의 두 가지 특징을 해결하기 위해 사용한다. 예를들어, 쿠키과 세션을 사용하..

ObjectMapper & ModelMapper

토이프로젝트를 진행하면서, entity 객체에 대하여 dto로 변환하는 로직이 코드량의 많은 부분을 차지하고 있었다. 특히 계층 구조가 깊은 객체일수록 dto로 변환하는 로직은 더 복잡해지고 방대해졌다. 해당 문제를 해결하기 위해 라이브러리를 사용하기로 하였고, 라이브러리를 찾아보던 중, 두가지 mapper가 존재하였다. ✅ ObjectMapper ObjectMapper에 대해 알아보기 전, 직렬화 및 역직렬화에 대한 개념을 알고 있어야 한다. ✔️ 직렬화 객체 형식의 Object를 Json 형태로 변환해주는 것을 의미 직렬화를 위해서는 각 인스턴스 변수에 Getter 메소드가 포함되어 있어야 한다 OR @JsonProperty가 명시되어 있어야 한다. ✔️ 역직렬화 Json 형식의 포맷을 Object ..

Unit Test 작성의 필요성

단위 테스트 vs 통합 테스트 🏷 단위 테스트 (Unit Test) Unit Test는 하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트이다. 여기서 모듈은 애플리케이션에서 작동하는 하나의 기능 또는 메소드로 이해할 수 있다. 예를 들어, 웹 애플리케이션에서 로그인 메소드에 대한 독립적인 테스트가 1개의 단위테스트가 될 수 있다. 즉, 단위 테스트는 애플리케이션을 구성하는 하나의 기능이 올바르게 동작하는지를 독립적으로 테스트 하는 것으로, '어떤 기능이 실행되면 어떤 결과가 나온다' 정도로 테스트를 진행한다. 🏷 통합 테스트 (Integration Test) Integration Test는 모듈을 통합하는 과정에서 모듈 간의 호환성을 확인하기 위해 수행되는 테스트이다. 일반적으로 애플리..

JPA | @Transactional 과 변경감지

DB 테이블에 저장되어 있는 데이터의 정보를 수정하기 위해 update 하는 로직을 개발하고자 한다면 다음과 같은 논리적 절차를 거치게 될 것이다. 트랜잭션 시작 변경하고자 하는 데이터의 id를 통한 조회 조회한 데이터에 수정할 내용들로 교체 update 처리 트랜잭션 커밋 JPA에서는 위의 데이터 변경 로직을 어떻게 처리해주는지 확인해보자 트랜잭션의 시작 영속성 Entity 조회 - 없으면 DB 조회 후 영속화 조회한 영속성 Entity의 데이터 수정 트랜잭션 커밋 위의 과정에서 볼 수 있듯이 JPA에서는 따로 update 쿼리를 요청하는 부분이 없습니다. 여기서 JPA의 장점 중 하나가 나오는데 바로 변경감지(Dirty Checking) 입니다. ✅ 변경감지 변경감지는 트랜잭션 커밋 시, 영속화된 E..

JPA | 일대일 양방향 관계에서 CasCade 옵션 적용 일화 ..?🤔

만약에 Parent - Child 는 양방향 연관관계로 되어 있고,. Child 테이블이 외래키를 관리하는 주 테이블이라고 하자. 여기서 이 두개의 인스턴스를 모두 영속화 하기 위해서는 em.persist()를 최소 2번은 호출하여야 각각 모두 영속화가 된다. 여기서 드는 의문점은 다음과 같다. Parent가 관리하는 Child 인스턴스의 경우 Parent를 em.persist() 할 때 같이 진행하면 편하지 않을까? 이러한 질문을 해결할 수 있는 옵션이 바로 cascade 영속성 전이 이다. ✅ cascade의 종류 All Persist Remove Merge Refresh Detach 주로 사용하게 되는 것은 All 또는 Persist 이다. 위의 종류에 대한 자세한 설명은 후속편으로 깊이 있기 공부..

JPA | QueryDsl orderBy(정렬) 동적으로 사용하는 방법

리뷰 리스트를 조회하는 API 내에서, - 최근 등록 순 - 별점 높은 순 - 별점 낮은 순 으로 데이터를 정렬했어야 했다. 정적으로 고정된 정렬이 아닌, 파라미터 값에 따라 동적으로 정렬이 되어야 했다. queryDsl 에서 동적 정렬을 위한 OrderSpecifier 클래스를 사용해보려고 한다! 일단 해당 클래스의 필드들을 살펴보면 아래와 같다. 클래스의 멤버들을 살펴 보면 해당 클래스의 생성자를 사용하여 생성할 수 있는데, 파라미터 변수들로는 Order enum, target 객체, NullHandling enum이 존재한다. - order Enum은 아래와 같이 구성되며, 상황에 맞게 내림차순, 오름차순을 적용해주면 될 것 같다. public enum Order { /** * Ascending o..

Querydsl | Pageable과 page를 사용하는 방법

SpringData에서 Pageable은 페이지 요청에 대한 데이터를 담을때 사용하는 인터페이스이다. 본론으로 들어가기 전에 위의 인터페이스에 대해 잠시 살펴보자!! 위의 사진과 같이 페이징 처리에 필요한 (limit, offset) 등을 구현하기 위한 메소드들이 정의되어 있으며, pageable의 구현체인 AbstractPageRequest 클래스에 구현되어 있다. pageable을 사용하기 위해서는 Controller 단에서 pageable 파라미터를 받으면 Spring MVC에서 pageable 사용을 지원하기 때문에 자체적으로 PageableHandlerMethodArgumentResolver 클래스를 사용하여 pageable 인스턴스를 구현체인 PageRequest로 변환한다. 그래서 reque..

JPA | QueryDsl 집계함수[SUM, COUNT ..] 사용 시, Dto로 반환

✅ 고민되었던 부분 querydsl 에서 집계함수를 사용하게 되면 반환값이 Tuple 형식으로 반환되게 된다. Tuple 형식을 사용해보려고 했지만 반환되는 값에서 필드 하나하나를 가져와 다시 dto에 맵핑해야 하는 상황이 발생되었고, Tuple 자체가 querydsl 객체이기 때문에 Repository 계층이 아닌, Service 계층까지 가져오는 것을 막고 싶었다. 위의 방법을 찾아보다가 집계함수 사용 시, groupby와 projection을 사용하여 dto로 받아올 수 있다는 사실을 알게 되었고, projection에 대하여 공부해보고, 사용 방법에 대해서도 적어보려고 한다! ✅ Projection 연산자란 ..? 한 Relation의 Attribute들의 부분 집합을 구성하는 연산자이다. 결과로..

feign client ErrorDecoder 인터페이스 사용시 마주한 문제 해결기 🙂

위의 해결기를 작성하기 전에 저는 Feign Client를 사용하면서 예외 처리시, ErrorDecoder 인터페이스를 통해서 예외를 처리하고 있다. 정도의 간단한 개념만 잡혀 있는 상태였다. 👉🏻 내가 마주한 문제 프로젝트에서 특정 주소에 대한 위, 경도 값을 알기 위해서 카카오 개발자 센터에서 제공하는 지도 Rest-Api 통신을 개발하였고, 통신을 위한 클라이언트는 Feign Client 를 사용하게 되었다. 정상 응답값에 대한 처리는 완료하였고, 예외에 대한 처리를 진행하고자 하였다. 예를들어, 카카오 API에서는 클라이언트 Error로 HttpSatus를 400, 401로 내려주고 있었으며, 클라이언트 에러의 예시는 파라미터 정보를 보내지 않았거나, API Key 등을 잘못 보냈을 경우로 보고 ..

[ feign client ] 사용 시, 응답값 형식 오류

지도를 그리기 위해서는 위, 경도 값이 필요하여 카카오 지도 API를 사용하게 되었다. 앞선 포스팅에서 어떠한 클라이언트 툴을 사용할지 고민하던 중에 feign 의 장점이 크다고 생각하여 feign-client를 적용하였다. 내가 사용한 카카오 지도 API의 응답 값은 아래와 같았다. ex) { "meta": { "total_count": 4, "pageable_count": 4, "is_end": true }, "documents": [ { "address_name": "전북 익산시 부송동 100", "y": "35.97664845766847", "x": "126.99597295767953", "address_type": "REGION_ADDR", "address": { "address_name": "..