[미션 Day 4] 코드 리팩토링 및 나만의 언어로 작성한 SOLID 원칙
·
인프런 워밍업 스터디
📌 1. 코드 리팩토링✔️ 사용자가 생성한 '주문'이 유효한지를 검증하는 메서드.✔️ Order는 주문 객체이고, 필요하다면 Order에 추가적인 메서드를 만들어도 된다. (Order 내부의 구현을 구체적으로 할 필요는 없다.)✔️ 필요하다면 메서드를 추출할 수 있다.public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { ..
AI 시대의 개발자의 가치
·
인프런 워밍업 스터디
인프런 지식공유자 박우빈님의 강의내용을 기반으로 작성된 글 입니다!최근 몇 년 사이에 AI 라는 단어가 더 가까이 다가온 듯 합니다. 과거 알파고를 통해 AI를 간접적으로 경험하였지만, 제 생활과는 거리가 먼 이야기 같았습니다. 하지만 이제는 모두가 ChatGPT를 알고, IT 업계가 아니더라도 잘 활용되고 있습니다. 또한 최근에는 딥시크가 화제에 오르기도 하였습니다.AI!AI…AI는 세상을 급변화시키고 있고, 현재 엄청난 생산성을 가져다주는 도구입니다. 하지만 반대로 이로 인해 대체되는 일도 생기게 됩니다.개발자! 개발자의 미래는 어떻게 될까요?AI는 PMF(제품 시장 적합성, Product Market Fit) 임계값을 급변시켜 붕괴를 일으킬 수 있다!PMF 임계값을 급변시킨다는게 뭐지..?우빈님께서..
[Real MySQL 8.0] 트랜잭션과 잠금
·
개발서적
트랜잭션 : 작업의 완전성 보장논리적인 작업 셋을 모두 완벽하게 처리처리하지 못할 경우, 원 상태로 복구작업의 일부만 적용되는 현상(Partial update) X데이터의 정합성을 보장하기 위한 기능잠금 : 동시성을 제어하기 위한 기능한 시점에서 하나의 커넥션만 자원 변경 가능📌  트랜잭션논리적인 작업 셋 자체가 100% 적용되거나 아무것도 적용되지 않아야 함을 보장쿼리 중 일부라도 오류가 발생하면 전체를 원 상태로 만든다.1) 처리 시작 - 데이터베이스 커넥션 생성 - 트랜잭션 시작2) 로그인 여부 확인3) 글쓰기 내용 오류 확인4) 입력 내용 DBMS에 저장5) 첨부 파일 정보 DBMS에 저장6) 저장된 내용 또는 기타 정보 DBMS에서 조회7) 게시글 등록에 대한 알림 메일 발송8) 알림 메일 발..
알림을 비동기 방식으로 보내기
·
스프링
보틀러에서 알림이 필요한 경우, 알림이 저장되고 푸시 알림이 전송됩니다. 이때 푸시 알림이 전송되기를 기다리기보다는 비동기적으로 푸시 알림을 전송하는 것이 효율적이라 판단하였습니다.📌 비동기 처리란?비동기 처리는 작업의 결과를 기다리지 않고 다른 작업을 진행하는 방식입니다.푸시 알림 전송의 경우, 전송 결과를 통한 추가 작업이 존재하지 않고 FCM을 이용하기 때문에 비동기 작업으로 진행해도 괜찮다 판단하였습니다.그렇다면 스프링에서 비동기 처리는 어떻게 할 수 있을까요?📌 스프링에서의 비동기 처리스레드 생성 이용하기직접 스레드를 생성하여 실행시키는 방법이 있습니다. private void pushMessage(NotificationType type, Subscriptions subscription..
Kafka를 이용한 이벤트 기반 아키텍처 맛보기
·
아키텍처
이전 프로젝트에서 개발을 하다가 서비스가 가지는 필드가 상당히 많아지는 상황이 존재했습니다.프로젝트 내에서 편지에 대해 신고가 접수될 경우 다음의 로직을 거치게 됩니다.신고 생성해당 편지에 신고가 3회 쌓였다면,해당 편지 블락 처리편지 작성자에게 경고 알림 전송편지 작성자 경고 횟수 증가신고 서비스에서 a, b, c에 해당하는 내용은 다른 서비스를 통해 처리해야 하는 로직입니다. 그러다 보니 신고 서비스의 필드는 늘어나 다른 서비스와 강결합되어 있는 상태입니다.public class ComplaintService { private final KeywordComplaintRepository keywordComplaintRepository; private final MapComplaintRepos..
알림 기능의 필수 여부 확인하기
·
데브코스
보틀러 프로젝트에서 알림이 보내지는 경우는 총 6가지입니다.계정 일시정지계정 경고키워드 편지 도착타겟 편지 도착답장 편지 도착키워드지도이 6가지의 기능에서 알림 보내기를 실패했을 때, 해당 기능도 실패해야 하는지에 대해 의문이 들었습니다.알림 전송은 2가지 단계가 존재합니다.알림 저장알림 푸시이때, 알림의 주요사항은 다음과 같습니다.알림 전송에 실패해도, 알림을 호출한 기능에 영향을 주면 안 된다.알림 저장에 실패해도, 알림을 호출한 기능에 영향을 주면 안 된다.알림 푸시에 실패해도, 알림 저장에 영향을 주면 안 된다.알림 푸시 실패포스트맨에서 생각한 비즈니스 로직 상 알림 푸시에 실패하더라도, 알림을 저장하는 데에 영향을 주지 않도록 결정하였습니다.사용자 정지 시, 알림을 요청하는 기능은 다음과 같습니..
모니터링 서버 구축하기
·
데브코스
이전에 서버가 알 수 없는 이유가 내려가는 상황이 발생해서 이에 대한 방안으로 swapfile을 추가하고 모니터링 서버를 구축하기로 하였습니다. 모니터링을 하기 위해서 Spring Actuator + Prometheus + Grafana를 사용하였습니다.📌 Actuator + Prometheus + Grafana?Actuator서버를 운영하면 서버의 CPU, 메모리, 쓰레드 수 등 다양한 지표가 존재합니다. 그런데 모니터링 툴 마다 측정 방식이 다르다면 교체 시 측정 코드 또한 변경할 수 밖에 없습니다. 이를 위해 마이크로미터가 존재합니다.마이크로미터는 모니터링 툴에서 사용되는 기능들을 추상화하고 각각의 모니터링 툴에 맞는 구현체들을 가지고 있습니다. 스프링에서 이를 손쉽게 사용하는 방법은 Spring..
@Modifying의 동작 알아보기
·
스프링
📌 @Modifying?Spring Data JPA를 사용하는 경우, @Query를 통해 JPQL을 작성하는 상황이 있습니다. 예시로, 상품의 모든 가격을 인상해야 하는 상황이라고 가정해 보겠습니다. 이때 변경 감지를 통해서 정보를 업데이트한다면 상품 개수별로 쿼리가 각각 실행됩니다. 주로 이러한 상황에 우리는 @Query를 통해 벌크 연산을 수행하게 됩니다.@Query("update Item i set i.price = i.price + 1000")@Modifyingvoid increasePrice();@Query는 네임드 쿼리(Named Query)를 인터페이스에서 바로 사용할 수 있게 하는 어노테이션입니다.이때 @Query로 작성된 JPQL이 DML(INSERT, DELETE, UPDATE 쿼리)..
JPA의 Fetch Join을 사용하는 이유 (vs Join)
·
카테고리 없음
📌 Fetch Join이란?JPA에서는 fetch join이 존재합니다. 기존 SQL에서는 존재하지 않아서 생소할 수 있습니다.fetch join은 JPQL에서 성능 최적화를 위해 제공하는 기능이며 연관된 엔티티나 컬렉션을 SQL 한 번에 함께 조회하는 기능입니다. 이해를 위해 Member와 Team을 예시로 들어보겠습니다.📌 Member와 Team 연관관계우선 join을 아예 사용하지 않고, Member를 조회를 해보겠습니다.Join X 예시String query = "select m from Member m";List result = em.createQuery(query, Member.class) .getResultList();// Member의 Team은 지연로딩for (Member..
[JPA] 연관관계의 주인이란?
·
스프링
JPA에서 연관관계 매핑은 총 4가지가 존재합니다.@OneToOne@ManyToOne@OneToMany@ManyToMany이때 방향이 단방향인지, 양방향인지에 따라 또 나뉘게 됩니다. 예를 들어 팀과 멤버가 있다고 가정해 봅시다.간단하게 생각해 보면 멤버만 팀을 알고 있다면 단방향, 팀 또한 멤버에 대해 알고있다면 양방향이 됩니다. 양방향 연관관계를 코드로 한번 확인해 보겠습니다.@Entitypublic class Member { @Id @GeneratedValue @Column(name = "MEMBER_ID") private Long id; @Column(name = "USERNAME") private String username; @ManyToOne(fe..