전체 글 67

Redis Pub/Sub + FastAPI SSE: 동기 vs 비동기 비교 경험기

SSE 기반 LLM 챗봇을 만들면서, 동기와 비동기 방식에서 발생하는 이슈를 직접 확인하게 되었습니다.이번 글에서는 개발 과정에서 발견한 문제와 개선점을 중심으로 작성해봤습니다. 상황- Python,FastAPI를 통해 LLM기반의 챗봇 개발- 채팅 방식은 SSE(Server-Sent Events)를 사용했으며, 사용자 간 채팅이 아니라 사용자의 메시지에 대해 서버 LLM이 응답을 제공하는 구조입니다. 따라서 서버 측에서 지속적으로 응답을 내려주는 형식입니다. 로직클라이언트가 SSE 연결 요청을 보내면 서버는 고유한 id를 생성하여 큐와 매핑하고, "채팅 준비 완료" 메시지를 즉시 응답합니다.SSE 엔드포인트는 해당 id에 연결된 큐를 지속적으로 모니터링하며, 새로운 메시지가 들어오면 StreamingR..

BackEnd 2025.09.19

[Spring/JPA] - N+1 이슈 (paging을 곁들인)

crud기반의 개인 프로젝트를 만들고 있는데 게시글 리스트 목록 로드API 에서 N+1현상이 발생하였다. 양방형 맵핑관계의 게시글(Board)과 댓글(Comment)의 갯수를 불러오고자 했다. 이 두테이블은 양방향맵핑관계이며Board->Comment (OneToMany)Comment->Board (ManyToOne)관계이다. 겉으로 보기에는 정상적으로 로드 되는것 같았지만, 로그를 통해 N+1현상을 확인하게 되었다.       N+1현상은 무엇이며 왜 일어나는 것일까?? N+1 이슈란?JPA같은 ORM에서 연관된 엔티티를 조회할 때 발생하는 성능이슈.한번의 쿼리로 원하는 데이터를 가져오는것처럼 보이지만, 실제로 추가적인 N개의 쿼리가 실행되는 문제  N+1 발생 원인??JPA에서 @OneToMany, @..

BackEnd/Spring 2025.02.18

[Java] - 인터페이스

Interface(인터페이스)인터페이스는 객체의 사용 방법을 정의한 타입입니다.또한 인터페이스를 통해 다양한 객체를 동일한 사용 방법으로 이용할 수 있습니다. - 자바의 특징중인 하나인 '다형성'과 연관이 있습니다. 다형성은 하나의 객체가 여러 형태를 가질 수 있는 성질을 의미합니다. - 메소드의 선언만 가능합니다. (body 구현불가)public interface UserRepository extends CrudRepository { //가능 public User findById(); //메소드 바디가 있으므로 불가 public User findById(){ }}

BackEnd/Java 2025.01.27

[Java] - Thread, ThreadPool

최근에 재직했던 기업에서 ThreadPool을 이용해 외부 API 호출 개발경험이 있습니다.기간이 조금 지나기도 했고 다시 공부하여 개념을 정리하기 위하여 포스팅을 작성해봅니다. Thread(스레드)란?컴퓨터 프로그래밍와 OS에서 프로스세스 내에서 실행되는 하나의 작업단위를 의미합니다. 실행중인 하나의 애플리케이션을 프로세스라고 칭합니다.사용자가 애플리케이션을 실행하면 운영체제로부터 실행에 필요한 메모리를 할당받아 애플리케이션의 코드를 실행하는데 이것이 프로세스입니다. (출처: 혼자공부하는 JAVA, 520P 스레드 파트) Thread의 핵심 개념스레드는 프로세스 안에서 실행되는 단위로써 여러 스레드가 한 프로세스 안에서 코드, 데이터, 파일 같은 자원을 공유하며 동작할 수 있습니다.싱글 스레드 : 하나..

BackEnd/Java 2025.01.13

[Java] - Page객체 형 변환 / map()메소드 / Stream 사용

CRUD 사이드 프로젝트를 만들고있는데 '게시글리스트 조회'기능에서 게시글 테이블과 양방향관계에 있는 댓글 테이블에서 순환참조 이슈가 발생했다. 이전 포스팅처럼 Entity->DTO 방법으로 사용하고자 했는데 단순 Entity가 아니라 페이징객체의 Entity여서 DTO변환이 고민되었다..  Page객체는 유지하고 내부 타입을 Entity->DTO로 변환 할 수있는 방법을 생각해보았다. 다행히도 Page객체의 메소드중에 map이라는 메소드가 있었고 해당 메소드를 통해 람다식을 통해 DTO타입으로 내부 형변환이 가능했다.  그런데 한가지 문제가 더 있었다..!게시글과 연관관계 엔티티인 댓글(Comment)객체의 값을 가져오기 위해선 또 다른 형변환이 필요했다.형변환없이 그대로 가져오면 순환참조를 다시 일으..

BackEnd/Java 2025.01.10

[Spring/JPA] JPA 양방향 맵핑 과정(순환참조,DTO)

현재 만들고 있는 프로젝트의 게시글(board)와 댓글(comment)테이블이 있고 이 엔티티들을 양방향으로 맵핑하고자 한다. 그리고 그 과정에서 발생한 이슈들을 정리해보려 한다. 현황게시판의 글을 저장하는 Board테이블과 해당 게시글의 댓글을 저장하는 Comment테이블을 설계하였고 이 두테이블은 Board의  id컬럼 그리고 Comment의 board_id컬럼을 기반으로 Join할것이다.  그리고 두 데이터들을 Spring Data JPA 기반 양방향으로 연결하고자 한다. Board(게시판)과 Comment(댓글) 테이블이 부모-자식으로 연결되어 있고 comment의 board_id는 Foreign Key로, Board의 id(Primary Key)를 참조하고 있다.     위와 같은 코드로 두 E..

BackEnd/Spring 2025.01.06

[Java] Builder 패턴

이전까지 해오던 프로젝트들에서는 DTO를 lombok의 Getter,Setter를 통해 값을 세팅하곤 했었다. Builder패턴에 대해선 대략적으로 알고있었지만 그 당시에는 왜써야하는지를 이해하지 못하여 넘어갔었는데 최근에 이펙티브 자바를 읽으면서 Builder패턴에 대한 내용이 초반에 나와 학습하게 되었다. Builder패턴을 왜 쓰게 되었고 왜 써야하는지 일련의 순서로 내용을 정리했다.   아래코드는 일련의 여러 색깔들을 조합으로 새로운 색깔을 만드는 객체가 있다고 가정하여 짠 코드이다. 점층적 생성자를 이용하여 객체를 만드는 방법이고 보다시피 파라미터의 종류/갯수에 따라서 객체를 생성 할 수있다.//점층적생성자 패턴public class ColorColection { private final ..

BackEnd/Spring 2024.12.30

[스프링 핵심 원리] - 생성자 주입을 선택해라

최근에는 스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장한다.  이유 불변- 대부분 의존관계 주입은 한번 일어나면 앱 종료시점까지 의존관계를 변경할 일이 없다.- 수정자 주입을 사용하면 , set메서드를  public으로 사용해야 한다.(수정이 생길수도 있음.)  => 누군가 실수로 변경할 수 있고, 변경하면 안되는 메서드를 열어두는건 좋지 않다.- 생성자 주입은 객체 생성할때 1번만 호출되므로 이후에 호출되는 일이 없어, 불변하게 설계 가능   누락- 의존관계의 누락을 쉽게 파악할 수 있다. - 수정자 주입(set메소드) 사용시 의존성이주입되어있는 객체를 new로 생성시 누락된 객체들을 알수가 없음.  =>또한 객체가 생성되는 시점에 라이프사이클에 의존성 주입이 일어나는것이 불변의 법칙에 ..

[스프링 핵심 원리] - 의존관계 자동주입

의존관계 주입 방법1. 생성자 주입2. 수정자 주입(Setter 주입)3. 필드 주입4. 일반 메서드 주입 1. 생성자 주입생성자를 통해서 의존관계를 주입방법 특징- 생성자 호출시점에 1번만 호출되는것이 보장- 불변, 필수 의존관계에서 사용 ->생성자는 객체생성시에 무조건 실행 됨- 당연히 주입된 객체는 변경, 수정이 불가- 생성자 주입은 OrderServiceImpl 객체가 생성되는단계에서 생성자에 있는 객체들을 자동적으로 의존관계설정해준다. @Componentpublic class OrderServiceImpl implements OrderService{ private final MemberRepository memberRepository; private final DiscountPoli..

[스프링 핵심 원리] - 컴포넌트스캔 - 중복등록과 충돌

컴포넌트스캔에서 같은 빈 이름을 등록하게 되면???  자동 빈 등록 vs 자동 빈 등록컴포넌트 스캔에 의해 자동으로 스프링 빈이 등록되는데, 그 이름이 같은 경우 스프링은 오류 발생시킨다.,ConflictingBeanDefinitonException 예외 발생 수동 빈 등록 vs 자동 빈 등록이 경우 수동 빈 등록이 우선권을 가짐. 수동 빈이 자동 빈을 오버라이딩해버린다!  다만 최근에는 이 상황의 경우에 스프링에서 오류가 발생하도록 기본 값을 바꾸었다  해당 에러를 띄워주며 빨간줄부분을 application.properties에 추가하고 true로 등록시 오버라이딩이 진행된다.

반응형