본문 바로가기

전체 글143

[마이크로서비스패턴] 1. 모놀리식 지옥에서 벗어나라. 1장은 전체적인 이해를 위해 꼭 읽고 넘어가야 한다. 모놀리식 아키텍쳐의 장점 개발이 간단하다. 애플리케이션을 쉽게 변경할 수 있다. 테스트하기 쉽다. 배포 및 확장이 쉽다. 모놀리식 아키텍쳐의 한계 규모 있는 애플리케이션은 모놀리식 아키텍쳐가 더이상 맞지 않게된다. 스프린트를 추가할때 구현할 스토리가 늘어났고 코드베이스와 관리 오버헤드가 늘어났다. 팀별로 분화된 스프린트도 불가능해졌다. 사이즈가 늘어나 너무나도 복잡해 이해하기 힘들고 변경도 오래 걸린다. IDE 실행 속도도 느리고 빌드 시간 또한 늘어난다. 아마존은 성공적으로 마이크로 서비스 아키텍쳐를 구축했기에 11.6 초마다 변경점을 배포할 수 있다. 확장 큐브와 마이크로 서비스 확장 큐브는 3가지 축으로 모델을 확장할 수 있다. X축 확장: 다중.. 2022. 9. 14.
[자바] 상속보다 합성을 사용해야 하는 이유 상속이란? 상속은 상위 클래스에 로직을 구현하고 하위 클래스에스 코드를 재사용하는 방법이다. IS-A 관계로 불린다. 상속으로 얻는 장점? 외부의 접근으로 인한 다형성을 보장하고 공통된 로직을 사용할 수 있다. 하위 클래스에 따라 구현 로직만 변경해주면 된다는 장점이 있다. 그러나 Java 8의 인터페이스 Default 메소드 기능으로 이러한 상속의 장점도 불필요하게 되었다. 잘못된 상속으로 인한 오류들 1. 불필요한 인터페이스 상속 문제 하위 클래스에 부적합한 부모 클래스의 메소드를 물려받기에 자식 클래스의 캡슐화가 깨지는 문제가 발생한다. 대표적으로 자바의 Stack과 Vector 클래스가 있다. stack 클래스는 vertor를 상속받는 설계로 의도치 않는 동작이 실행되어 캡슐화를 깨뜨린다. 2. .. 2022. 9. 13.
[자바] Long 타입 비교를 equals로 해야만 하는 이유 멘토님께서 Long 타입은 == 비교를 하면 안되고 equals 비교를 해야 한다고 말씀하셨던 적이 있다. 왜 그런지 궁금해서 찾아보았다. @Test public void 숫자비교() { Long num1 = 127L; Long num2 = 127L; Long num3 = 128L; Long num4 = 128L; assertThat(num1 == num2).isTrue(); assertThat(num3 == num4).isFalse(); } Long 타입의 동일성 비교가 왜 128부터는 안되는지 궁금해 Long의 구현부를 들어가봤다. 내부적으로 -128 부터 127의 상수 값을 캐시해 동일성 비교를 하고, 상수 풀이 넘거나 적은 값이 들어왔을땐 새 객체를 만들어낸다. public static Long .. 2022. 9. 13.
마켓컬리 해커톤 우승 회고 목차 참여배경부터 팀빌딩까지 정윤, 수민, 혜원 작성 [팀 디테일리테일 결성] 정윤 예선 [첫 회의-물류센터 공정 이해하기] 정윤 [서비스화할 문제를 정의] 정윤 [해결기능 구상] 정윤 [설문조사 진행] 정윤 [IA, 프로토타입, 간트차트 작성] 수민 [아키텍쳐 설계] 완수 본선 [각자의 위기와 어려움과 극복] 각자 작성 본선 이후 [잘한 점, 뿌듯한 점] [아쉬운 점, 보완할 점] 결선 [발표 연습] 1. 참여배경부터 팀빌딩 까지 [될까요? 에서 됩니다! 로] 정윤님 - 우연히 ‘컬리 핵 페스타 2022’ 공고를 보게 되었다. 주제1번을 보는데, 컬리 물류센터에서 알바 해 본 경험으로 어떻게든 아이디어를 낼 수 있지 않을까 하는 생각이 들었다. 보자마자 내가 생각한 물류센터의 공정과 문제점을 빈 종이에.. 2022. 9. 12.
[개발방법론] DDD란 무엇인가? DDD는 Domain Driven Design의 약자 비즈니스 도메인 별로 나누어 개발하는 방식이다. 핵심 목표 도메인을 서비스별로 분리하자. 모듈 간 의존성은 최소화하고, 응집성은 최대화하기 여러 도메인이 역할에 따라 서로 상호장용하며 설계하는 것이다. Bounded Context에 따라 객체의 역할은 바뀐다. 크게 3가지 레이어로 구분한다. 1. Application Layer - API를 제공하는 계층 2. Domain Layer - Entity, VO를 활용해 도메인 로직이 중점적으로 진행되는 계층 3. Infrastructure Layer - 외부 라이브러리, DB 등을 담당하는 계층이다. DTO는 데이터를 전달하는 역할을 한다. VO는 데이터를 가지고, 자신만의 로직을 가진다. Entity는 .. 2022. 9. 10.
[스프링] 재고 시스템으로 알아보는 동시성 문제 해결 방법 아래 코드를 보면 재고 100개의 요청에서 100개의 재고를 하나씩 감소시켰기 때문에 일반적으로 0이 나오는 것을 예상한다. 그러나 실제로는 race condition이 발생했기 때문에 예상한 결과를 받을 수 없다. @Test public void 동시에_100개_요청() throws InterruptedException { int threadCount = 100; ExecutorService executorService = Executors.newFixedThreadPool(threadCount); CountDownLatch countDownLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { executorSe.. 2022. 9. 2.
[스프링] DATA JPA In절로 파라미터 넣기 JPA를 통해 in clause를 쉽게 사용할 수 있습니다. 아래처럼 in을 통해 한 개의 쿼리만 수행됩니다. List findByIdIn(List ids); select .... from Worker where id in (? ,? ,?) 여기서 문제는 ids가 고정된 크기의 객체가 아니라는 점입니다. 한번에 16개를 할당해 결과를 얻고 싶을때 너무 많은 데이터를 대비해 5개씩 짤라서 조회했다고 가정했을때, 여러 가지의 SQL이 생성되고 호출이 됩니다. JDBC에는 PreparedStatement 객체가 있는데 이 객체는 이미 생성된 SQL문을 활용해 지속해서 재사용을 통해 좋은 성능을 얻을 수 있도록 하는 객체입니다. in절을 통해 생성하다보면 호출마다 다른 SQL이 호출되고 저장되어 위의 장점을 활.. 2022. 8. 25.
[스프링] @Query에 ENUM 타입 쓰는 법 프로젝트 진행 중 ENUM으로 조건을 걸어야 할 일이 있어 찾아보았습니다. ENUM 타입의 모든 경로를 가져와 비교하면 String으로 변환되어 쿼리가 수행됩니다. @Query("SELECT w FROM Worker w WHERE w.region = com.detailretail.kurlyflow.common.vo.Region.UNASSIGNED) 2022. 8. 25.
[스프링] UserDetailsService를 여러 개 구현하고 잘 사용하기 그동안의 프로젝트들은 UserDetails를 하나만 구현했었습니다. 최근 진행한 프로젝트에서 관리자와 작업자 간 도메인이 명확히 달랐고, 그에 따른 인증과 인가 과정이 필요했습니다. 이런 경우 보통 관리자 앱으로 따로 만드는 것으로 알고 있지만 단일 프로젝트였기에 jwt 토큰 발행 시 권한을 다르게 부여하고, UserDetailsService 인터페이스의 loadUserByUsername 구현할때 두 개의 서비스를 두고 구현했습니다. @Override public CustomDetails loadUserByUsername(String adminId) { Admin admin = adminRepository.findById(Long.valueOf(adminId)) .orElseThrow(() -> new .. 2022. 8. 25.
[Error-Log] ORA-01861: literal does not match format string ORA-01861: literal does not match format string 리터럴이 형식 문자열과 일치하지 않음 해커톤 마감을 앞두고 로컬에선 잘만 되던 API가 EC2에선 400에러를 뱉는 상황이 있었습니다. OS의 LANG 설정이 달라 문자열을 날짜로 제대로 변환을 못해서 발생하는 이슈였습니다. 맥 OS와 아마존 리눅스 LANG 설정 차이 OS의 LANG에 대해 전혀 인지를 못해 발생했었습니다. 이런 경우 서로 서버의 LANG을 맞춰주는 것보단 조회 쿼리에서 데이트 포맷을 명시적으로 맞춰주는게 좋아보입니다. EC2 인스턴스가 여러가지 이유들로 교체될 수도 있고 로컬 Lang 또한 상황에 따라 바뀔수도 있기 때문입니다. NLS_LANG이란 것이 등장하는데 OS 계정의 환경 변수를 말합니다. .. 2022. 8. 25.
[스프링부트] 트랜잭션 격리 수준 트랜잭션에서 격리 수준은 일관성 없는 데이터를 허용하도록 하는 수준을 말한다. 격리 수준에는 4가지 종류가 있다. READ_UNCOMMITED READ_COMMITED REPEATABLE_READ SERIALIZABLE\ 숫자가 높아질수록 속도는 느려진다. READ_UNCOMMITED 트랜잭션 처리 중인거나 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용한다. 그러나 Dirty Read라는 문제가 발생한다. Dirty Read는 트랜잭션이 완료되지 않았는데 다른 트랜잭션에서 볼 수 있는 현상을 말한다. READ_COMMITED 트랜잭션이 커밋된 데이터만 읽을 수 있다. 어떤 사용자가 A라는 데이터를 변경할때 다른 사용자는 접근할 수 없다. 그러나 Non-Repeatable Read 문제가 발.. 2022. 7. 13.
[스프링부트] Event 발행과 @EventListener에 대해 알아보자 이벤트란? 이벤트 발생이란 상태가 변경됨을 의미한다. 상태가 변경되고 해당 이벤트에 해당하는 동작을 수행하는 기능을 구현할 수 있다. 이벤트 생성 과정 이벤트 생성주체가 이벤트 생성 퍼블리셔가 이벤트 발행 이벤트 핸들러(구독자) 이벤트의 용도 트리거: 도메인 상태가 바뀔때마다 후처리가 필요할때 사용 다른 도메인 간의 동기화: 주문 도메인에서 배송지 변경 이벤트를 발생 시키고 구독자인 핸들러는 외부 배송 서비스와 이를 동기화하는 로직을 구성할 수 있다. 이벤트의 장점 연관 관계 제거 - 서로 다른 도메인 간의 의존 관계를 제거할 수 있다. 기능 확장 용이 - 구매 취소 시 환불과 함께 이메일 전송이 필요하다면 이메일 발송 이벤트를 구현하면 된다. 프로젝트에 적용하기 에어비앤비같은 숙소 예약 플랫폼을 제작하.. 2022. 7. 6.