중복 추가 이슈를 해결하기 위한 고민
·
대외 활동/SOPT
메뉴 추가 동시성 이슈요즘, 동시성에 대해 공부하면서, 이전에 만들었던 프로젝트에서 발생할 수 있는 동시성 문제들에 대해 찾아보고 해결방법을 고민하고 있다. '한끼족보' 프로젝트에서는, 여러 명의 사람이 동시에 같은 메뉴를 추가할 경우, 같은 메뉴가 하나의 테이블에 여러 개 저장되는 현상이 발생한다.테이블 구조고민한 해결방법위의 문제를 해결하기 위해 고민한 방법은 2가지이다. 1. 유니크 키 제약조건(store_id, name) 컬럼 조합에 대해 복합 유니크 제약 조건을 걸어, 동시성 문제 해결하는 것이다.가장 간단한 해결 방법으로 DB 차원에서 중복 삽입을 자동으로 방지할 수 있다. 하지만 이 경우, DB단에서 발생하는 예외(유니크 키 제약 위반)를 service의 비즈니스 로직 상에서 try-catc..
비관적 락과 낙관적 락
·
대외 활동/SOPT
한끼족보에서 발생하는 동시성 문제'한끼족보'에도 동시성 문제(=Race Condition)가 존재한다.(테스트코드에 아직 미숙하여 curl 명령어를 이용하여 동시 요청을 해보았다.) 위 사진에서 볼 수 있듯, 2명의 유저가 동시에 하나의 가게에 좋아요를 누른다면, 해당 가게의 전체 좋아요 수가 2가 아니라 1로 집계되는 문제가 발생했다. 왜 이런 문제가 발생하는 것일까?문제 발생 원인위는 현재 '한끼족보'의 테이블 구조이다. '좋아요 수'를 비정규화 하여 가게 테이블에 위치해 있는 상태이다.@Transactionalpublic HeartCreateResponse createHeart(final HeartPostCommand heartPostCommand) { User user = userFi..
스프링 DB 1편 - 섹션 3~4
·
Spring
트랜잭션트랜잭션은 작업의 완전성을 보장해 준다. 즉, 논리적인 작업 셋을 모두 완벽하게 처리하거나, 처리하지 못할 경우에는 원 상태로 복구하여 작업의 일부만 적용되는 현상(Partial update)이 발생하지 않도록 해준다.ACID원자성(Atomicity)트랜잭션 내에서 실행한 작업들은 모두 성공하거나 모두 실패해야 한다.일관성(Consistency)모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야 한다. 예를 들어 데이터베이스에서 정한 무결성 제약 조건을 항상 만족해야 한다.격리성(Isolation)동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않도록 격리한다. 예를 들어 동시에 같은 데이터를 수정하지 못하도록 해야 한다. → 격리성은 동시성과 관련된 성능 이슈로 인해, 트랜잭션 격리 수..
스프링 DB 1편 - 섹션 1~2
·
Spring
JDBC 이해애플리케이션 서버는 DB를 사용하기 위해 커넥션을 연결해야 한다. 문제는 각각의 데이터베이스마다 커넥션을 연결하는 방법, SQL을 전달하는 방법 그리고 그 결과를 응답받는 방법이 모두 다르다는 점이다. 즉, 데이터베이스를 다른 종류의 데이터베이스로 변경하면 애플리케이션 서버에 개발된 데이터베이스 사용 코드도 함께 변경해야 한다는 문제가 발생한다.JDBC 표준 인터페이스JDBC는 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API이다. 이 JDBC 인터페이스를 각각의 DB 벤더에서 자신의 DB에 맞도록 구현해서 라이브러리로 제공하는데, 이것을 JDBC 드라이버라 한다. 이렇게 JDBC 표준 인터페이스를 정의함으로써 데이터베이스를 변경했을 때 사용 코드도 함께 변경해야 하는 문제를 해결할..
애플 로그인
·
대외 활동/SOPT
애플 로그인.. 정말 악명이 높다. 이번 프로젝트에서 소셜 로그인 구현을 담당하게 되었는데, 그 과정에서 학습한 애플 로그인부터 탈퇴까지 그 흐름에 대해서 정리해 보았다.Apple OAuth의 흐름사용자가 애플 계정으로 로그인을 하면 Apple 서버로부터 다양한 정보를 얻게 된다. 이 중 사용자 인증의 핵심 열쇠인 Identity Token과 Authorization Code 을 잘 기억해두자.Authenticating users with Sign in with Apple | Apple Developer Documentation위 링크는 애플 공식 문서에서 로그인에 대해 설명한 문서이다. 전체적인 흐름, 받아올 수 있는 정보 또는 받아오지 못하는 정보 등 굉장히 자세하게 적혀있으므로 꼭 위 문서를 꼼꼼히..
스프링 핵심 원리 고급편 섹션2
·
Spring
쓰레드 로컬동시성 문제여러개의 쓰레드나 프로세스가 동일한 데이터(공유 자원)에 접근할 때, 데이터 일관성을 해치는 문제(Inconsistency)를 동시성 문제라고 한다. 스프링은 기본적으로 모든 빈들을 싱글톤 스코프로 관리한다. 즉, 한 번 생성된 객체를 스프링 컨테이너가 재사용하도록 설계되는데, 이는 곧 해당 객체의 인스턴스가 애플리케이션에 단 1개 존재한다는 뜻이다. 때문에 인스턴스의 필드를 여러 쓰레드가 동시에 접근하게 될 경우, 동시성 문제가 발생하게 된다. 스프링 빈처럼 싱글톤 객체의 필드를 변경하며 사용할 때는 특히, 이러한 동시성 문제를 조심해야 한다.→ 이러한 문제를 해결하기 위해 사용하는 것이 쓰레드 로컬이다.+ 더 알아보기이런 동시성 문제는 지역 변수에서는 발생하지 않는다. 지역 변수..
빈으로 등록된 필터가 WebSecurity의 ignoring에 의해 무시되지 않는 이유
·
Spring
커스텀 필터를 만들었을 때, @Componenet 어노테이션을 통해 해당 필터를 bean으로 등록했는지의 여부에 따라 filter가 web ignoring에 의해 무시되지 않는 상황이 발생했다.첫번째는 @component로 빈을 등록했을 때이고, 두번째는 빈으로 등록하지 않았을 때이다.왜 이런 상황이 발생했는지 차근차근 알아보자.Spring Security🌱 Spring SecuritySpring 기반의 애플리케이션의 보안(인증과 권한, 인가 등)을 담당하는 스프링 하위 프레임워크Spring Security 구조먼저 Spring Security의 구조를 먼저 이해할 필요가 있다.Security 의존성이 없는 경우클라이언트 요청은 서버 컴퓨터의 WAS(톰캣)의 필터들을 통과한 뒤 스프링 컨테이너의 컨트롤..
실전! 스프링 데이터 JPA - 섹션 6~8
·
JPA
사용자 정의 레포지토리필요한 이유개발을 하다보면 기본적인 네이밍 메서드, @Query 어노테이션 안에 간단한 쿼리문으로 구현할 수 없는 복잡한 동적 쿼리(Querydsl 사용) 등이 필요한 상황이 존재한다. 하지만 Spring data JPA가 제공하는 인터페이스에서는 동적쿼리를 구현할 수 없다. 이때, 사용하는 것이 사용자 정의 레포지토리이다.구현 방법// 사용자 정의 인터페이스public interface MemberRepositoryCustom { List findMemberCustom();}// 사용자 정의 인터페이스의 구현체@RequiredArgsConstructorpublic class MemberRepositoryImpl implements MemberRepositoryCustom {..
실전! 스프링 데이터 JPA - 섹션 1~5
·
JPA
공통 인터페이스 구성엔티티의 기본생성자기본생성자가 필요한 이유JPA 구현체마다 스펙이 조금 달라서 기본 생성자를 만들지 않아도 정상적으로 작동하는 경우가 있지만, ’엔티티에는 기본 생성자가 있어야 한다’가 공식 스펙이기 때문에 반드시 기본 생성자를 만들어주는 것이 좋다. 그렇다면 JPA는 왜 엔티티에 기본 생성자를 만들도록 강제하고 있을까?JPA는 데이터를 DB에서 조회해 온 뒤 객체를 생성할 때 **Reflection(리플렉션)**을 사용하기 때문이다. 리플렉션은 클래스 이름만 알면 생성자, 필드, 메서드 등 클래스의 모든 정보에 접근이 가능하다. 하지만 리플렉션이 가져올 수 없는 정보가 있는데 바로 ’생성자의 매개변수 정보’다. 때문에 리플렉션으로 생성할 객체에 모든 필드를 받는 생성자가 있더라도 리..
스프링 MVC 2편 - 섹션 10~11
·
Spring
Converter스프링 타입 컨버터(converter)란, 서로 다른 타입 간의 변환을 쉽게 처리할 수 있도록 돕는 도구이다. HTTP 요청 파라미터는 모두 문자로 처리된다. 때문에 요청 파리미터를 자바에서 다른 타입으로 변환해서 사용하고 싶으면 원하는 타입으로 변환하는 과정을 거쳐야한다. 실제로, 스프링 MVC가 제공하는 @RequestParam을 사용해보면, 스프링이 자동으로 타입을 변환해주는데 어떻게 이것이 가능한걸까? 이때, 사용하는 것이 바로 스프링 타입 컨버터이다.컨버터 인터페이스package org.springframework.core.convert.converter;public interface Converter { T convert(S source);}스프링은 확장 가능한 컨버터 인터페..