전체 글 148

스프링 핵심 원리이해 - 객체 지향 설계 (2)

새로운 정책 개발 다형성 활용을 잘한 코드라면 새로운 정책을 추가하는데 아무 문제 없음 하지만 새로운 정책 적용에 문제가 있음 클라이언트 코드인 주문 서비스 구현체도 함께 변경필요 클라이언트가 인터페이스뿐만아니라 구현체도 함께 의존 → DIP 위반 관심사의 분리 AppConfig는 구현 객체를 생성하고 연결하는 책임 AppConfig의 등장으로 기존의 클라이언트 코드에서 구현체를 생성할 필요가 없어짐 결과적으로 클라이언트 객체는 자신의 역할을 실행하는 것만 집중, 권한이 줄어듬(책임이 명확해짐) AppConfig 리팩토링 구성 정보에서 역할과 구현을 명확하게 분리 역할이 잘 들어남 중복 제거 기존코드 public class OrderServiceImpl implements OrderService { //..

비관적 락, 낙관적 락 사용시 deadlock 관련 이슈들

개요 스카우터 알람 설정 이후, 간헐적으로 에러가 발생하는 API가 2건 있었다. 급한 이슈는 아니였기에, 우선순위를 뒤로 미뤘었는데, 스카우터 알림방에 빨간색 에러 메시지를 보니까 도저히 그냥 지나칠 수 없었다..(개발자 특) 참고로 아래에 나오는 내용은 낙관적 Lock과 비관적 Lock을 알고 있어야 하는 내용이다. https://code-killer.tistory.com/163 멀티스레딩 환경에서의 동시성 이슈 첫번째 이슈는 select 쿼리 이후, 조건에 따라 insert을 하는 로직이였는데, 동시요청이 들어오면 당연한 결과지만, Duplicate primary Key 에러가 발생했다. Exception - org.springframework.dao.DataIntegrityViolationExce..

JAVA - stream count() 메서드의 반환값은 왜 long 일까 (feat. chatGPT)

개요 회사에서 자바로 신규 게임을 개발 중에 있기도 하고, 의식적으로 계속 stream을 사용하려고 연습중이라, Stream을 무지하게 사용하고 있다. 그런 와중에 stream의 종결함수인 count()를 사용하며 int로 형변환 하던 중 '생각해보니 count()의 return 타입이 왜 long 타입이지?' 라는 궁금증이 들었다. 뇌피셜로는 당연하게도 얼마나count()가 될지 모르니, 가장 큰 타입(long)으로 한 거 같긴한데.. 그렇다면 왜collection의 size()메서드는 retrun 타입이 int인걸까? 요즘 핫한 chatGPT와 구글 서치를 통해 알아보았다. 구글 1996년 초 자바가 나왔을 때는 일반 pc 메모리는 8~16MB 였다. 배열과 collection 모두 메모리 크기와 밀..

성공과 실패를 결정하는 1% 네트워크 - 서버의 수신 동작

1. LAN 어댑터에서 수신 신호를 디지털 데이터로 변환한다. 수신 동작은 패킷의 신호를 LAN 어댑터에서 수신하고 디지털 데이터로 바꾸는 부분에서 시작된다. LAN을 흐르는 패킷의 신호는 1과 0으로 이루어진 디지털 데이터의 신호와 타이밍을 나타내는 클록 신호를 합성한 것이다. 여기에서 클록 신호를 추출하고 클록 신호에서 타이밍을 계산하면서 신호를 읽어오면, 1과 0의 디지털 데이터로 바꿀 수 있다. 신호에서 디지털 데이터로 되돌린 패킷은 아래와 같다. LAN 어댑터 담당 프리앰블/스타트 프레임 딜리미터 FCS IP가 담당 MAC 헤더 IP 헤더 TCP가 담당 TCP 헤더 데이터 이부분을 만드는 것이 애플리케이션의 담당 LAN 어댑터의 MAC 부분이 패킷을 신호로부터 디지털 데이터로 되돌리고 FCS을 ..

성공과 실패를 결정하는 1% 네트워크 - 서버의 개요

1. 클라이언트와 서버의 차이점 접속동작을 할때 클라는 보내는쪽이고, 서버는 기다리는 쪽이라, Socket 라이브러리의 활용법이 달라진다. 또한, 서버는 동시에 다수의 클라이언트 PC와 통신한다는 차이도 있다. 그러므로 서버와 클라이언트는 구조가 다르다. 2. 서버 애플리케이션의 구조 서버는 여러 클라이언트와 통신해야 함으로 대화의 진행이 어디까지인지 알아야한다. 그래서 클라가 새로 접속할 때 마다 새로 서버 프로그램을 작동하여 서버 애플리케이션이 클라와 1대 1로 대화하는 방법을 선택하는 것이 일반적이다. 서버 OS는 멀티태스크, 멀티스레드 라는 기능에 의해 다수의 프로그램을 동시에 함께 작동할 수 있는데 이를 활용하여 접속을 기다리는 부분과 클라이언트가 대화하는 부분을 나눈다. 만약 접속을 접수하면 ..

Spring boot + JPA 환경에서 비관적 vs 낙관적 Lock 선택하기

개요 회사에서 Spring boot + JPA + mysql 조합을 사용하는 프로젝트가 있는데, PK 중복 문제로 update 시 문제가 발생하였다. 추적 결과 기존 코드는 멀티스레딩 환경에서 조건적으로 동시성 이슈로 생기는 문제였다. 비관적 락, 낙관적 락을 사용하여 해당 이슈를 해결해보기로 한다. 비관적 락 이름 그대로 트랜잭션끼리 충돌을 발생한다고 가정(비관적 락)하여 우선 락을 거는 방법이다. DB의 Lock 기능을 이용한다. (쿼리에 Select for update 구문이 들어감) Lock을 획득할 때까지 트랜잭션은 대기하므로, Timeout 설정 가능 낙관적 락 이름 그대로 트랜잭션 끼리 충돌나지 않는다고 가정하고(낙관적 락)하여 커밋 시 충돌을 알 수 있다. DB Lock 기능을 이용하지 않..

Spring Boot + JPA 환경에서 변경 감지(dirty checking)와 병합(merge)

변경감지와 병합(merge) 병합은 대부분이 알고있는 엔티티 매니저의 merge 메서드이다. 여기서 변경감지(dirty checking)은 JPA의 특징 중 하나이며 entity의 값만 바꿔주면 알아서 변경감지(dirty checking)를 하여 update 쿼리문을 날린다. 준영속 엔티티 영속성 컨텍스트가 더는 관리하지 않는 엔티티 문제는 준영속 엔티티인 경우 JPA가 관리하지 않음으로 어떻게 update을 할 지 애매한 경우이다. 그 때는 2가지 방법을 이용할 수 있다. 변경 감지 기능 사용 병합(merge) 사용 변경 감지 기능 사용 @Transactional public void update(Long id, Entity entity) { // entity를 가져온다. Entity entity = ..

백엔드 주니어 개발자의 2022년 회고

백엔드 개발자로서 지낸 첫 해가 지나갔다. 이번년도는 유난히, 부족함을 느낌과 동시에 성장했다고도 느껴졌다. 물론 쉽지 않은 길이였다. 학부 때 부터 내 커리어에 전부는 임베디드와 인공지능이였다. 그러다, SSAFY를 하게 되었고, 운 좋게 초록창 회사 인턴을 하게 되었지만, 부족함을 느끼고, '역시 나는 제조업 SW로 가야겠어' 라는 다짐을 하였다. 이후, 어렵지 않게 제조업 SW로 취업하게 되었지만, 고민은 계속 있었다. 큰 기업의 제조업 SW는 개발보다는 관리직에 가깝고, 무엇보다 개발자로서의 로망을 이루기에 환경이 따라주지 않았다. 자고로 내가 꿈꾸던 개발자는 카페나, 관광지에서 노트북 하나 들고, 업무를 하는 자유로운 직업이였지만, 현실은 보안 때문에 회사 밖으로 노트북하나 들고 나가기도 어렵다..

생각생각생각 2023.01.25

성공과 실패를 결정하는 1% 네트워크 - UDP 프로토콜을 이용한 송 수신 동작

수정 송신이 필요없는 데이터의 송신은 UDP가 효율적이다. TCP가 복잡한 원리를 사용할 이유는 데이터를 확실하면서도 효율적으로 전달하기 위함이다. 데이터를 확실히 전달하려면 도착한 것을 확인하고, 도착하지 않았으면 다시 보내야한다. 위 내용을 가장 간단히 실현할 수 있는 방법은 그냥 데이터를 ‘전부’ 보낸 후에 수신측에서 수신 확인 응답을 받는 것이다. 이는 TCP 처럼 복잡한 과정을 생략하는 것이다. 그러나, 패킷이 한개만 없어져도 전체를 다시 보내야 함으로 비효율적인데, 용도에 맞게 TCP와 UDP를 사용하면 된다. 제어용 짧은 데이터 예를들어 DNS 서버에 대한 조회는 한개의 패킷으로 끝나기 때문에 UDP를 사용한다. UDP 동작방식도 간단하다. 애플리케이션에서 송신 데이터를 받으면 UDP 헤더를..

728x90