2024.08.08.목.TIL 내일배움캠프 80일차 <최종프로젝트Day16>

김기남·2024년 8월 8일
post-thumbnail

안녕하세요, 오늘은 기술면접 준비내용과 최종프로젝트 진행상황을 정리해보았습니다.

사용자가 API 요청에 대한 응답을 할 때 Spring 내부 동작에 대해 설명할 수 있는가?

Spring 프레임워크에서 사용자가 API 요청을 보낼 때 내부적으로 어떤 동작이 일어나는지 설명하겠습니다. Spring MVC(Model-View-Controller) 아키텍처를 기준으로 설명드리겠습니다.

클라이언트 요청:

  • 사용자가 클라이언트(예: 웹 브라우저 또는 모바일 앱)에서 API 요청을 보냅니다. 이 요청은 HTTP 프로토콜을 사용하여 서버로 전송됩니다.

디스패처 서블릿(DispatcherServlet):

  • Spring MVC 애플리케이션의 진입점은 DispatcherServlet입니다. 모든 HTTP 요청은 먼저 DispatcherServlet으로 전달됩니다.
  • DispatcherServlet은 요청을 처리하기 위한 적절한 핸들러를 찾는 역할을 합니다.

핸들러 매핑(Handler Mapping):

  • DispatcherServlet은 요청 URL을 기반으로 어떤 컨트롤러(controller)가 이 요청을 처리할지 결정하기 위해 여러 HandlerMapping을 조회합니다.
  • HandlerMapping은 요청 URL과 컨트롤러 메서드를 매핑하는 역할을 합니다.

핸들러 어댑터(Handler Adapter):

  • 매핑된 핸들러가 찾아지면, 해당 핸들러를 실행하기 위해 HandlerAdapter가 사용됩니다.
  • HandlerAdapter는 핸들러(보통은 컨트롤러 메서드)가 호출될 수 있도록 필요한 작업을 수행합니다.

컨트롤러 실행:

  • HandlerAdapter에 의해 컨트롤러의 특정 메서드가 호출됩니다. 이 메서드는 클라이언트 요청을 처리하고, 비즈니스 로직을 수행하며, 필요한 경우 서비스를 호출합니다.
  • 컨트롤러 메서드는 처리 결과를 ModelAndView 객체로 반환하거나, REST API의 경우 직접 데이터를 반환할 수 있습니다.

뷰 리졸버(View Resolver):

  • ModelAndView 객체가 반환되면, DispatcherServlet은 이를 처리하기 위해 적절한 뷰를 찾습니다.
  • 여러 ViewResolver를 사용하여 논리적 뷰 이름을 실제 뷰로 변환합니다. 예를 들어, JSP, Thymeleaf 템플릿 등이 될 수 있습니다.

뷰 렌더링(View Rendering):

  • 최종 뷰가 결정되면, 뷰는 모델 데이터를 사용하여 HTML을 생성하고 클라이언트에게 반환합니다.
  • REST API의 경우, HttpMessageConverter가 사용되어 자바 객체를 JSON 또는 XML 등으로 변환하여 응답 본문으로 클라이언트에게 반환됩니다.

응답 전송:

  • 최종적으로 HTTP 응답이 클라이언트에게 전송됩니다. 이 응답은 클라이언트의 브라우저에 표시되거나, 클라이언트 애플리케이션에 의해 처리됩니다.

이 모든 과정은 Spring의 다양한 컴포넌트와 설정에 의해 자동으로 관리되며, 개발자는 주로 컨트롤러와 서비스 로직에 집중하여 비즈니스 요구사항을 구현할 수 있습니다. Spring의 DI(의존성 주입)와 AOP(관점 지향 프로그래밍) 등 다양한 기능이 이 과정에서 사용되어 모듈화되고 효율적인 애플리케이션을 개발할 수 있도록 돕습니다.

Spring AOP는 무엇인가?

Spring AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍)는 코드의 관심사를 분리하여 모듈화하는 프로그래밍 패러다임입니다. Spring AOP는 주로 횡단 관심사(cross-cutting concerns)를 모듈화하는 데 사용됩니다. 이러한 관심사는 로깅, 트랜잭션 관리, 보안 등과 같이 여러 모듈에 걸쳐 나타나는 기능입니다.

Spring AOP의 주요 개념과 동작 원리를 설명드리겠습니다.

주요 개념

Aspect(애스펙트):

  • 애스펙트는 횡단 관심사를 모듈화한 것입니다. 예를 들어, 로깅이나 트랜잭션 관리 등이 애스펙트가 될 수 있습니다.
  • 애스펙트는 일반적으로 하나 이상의 어드바이스와 포인트컷으로 구성됩니다.

Advice(어드바이스):

  • 어드바이스는 애스펙트의 구체적인 작업을 정의한 것입니다. 어드바이스는 메서드가 호출되거나 객체가 초기화되는 등의 특정 시점에 실행됩니다.
  • 어드바이스의 종류:
    - Before: 대상 메서드가 실행되기 전에 실행됩니다.
    - After: 대상 메서드가 실행된 후에 실행됩니다.
    - AfterReturning: 대상 메서드가 정상적으로 반환된 후에 실행됩니다.
    - AfterThrowing: 대상 메서드가 예외를 던진 후에 실행됩니다.
    - Around: 대상 메서드 호출을 가로채서, 호출 전후 또는 대신 실행됩니다.

Pointcut(포인트컷):

  • 포인트컷은 어드바이스가 적용될 타겟을 정의한 것입니다. 포인트컷은 메서드 실행, 객체 생성, 필드 접근 등과 같은 조인 포인트를 필터링합니다.
  • Spring AOP는 주로 메서드 실행을 조인 포인트로 사용합니다.

Join Point(조인 포인트):

  • 조인 포인트는 애스펙트가 적용될 수 있는 실행 지점입니다. 예를 들어, 메서드 호출, 객체 생성, 예외 발생 등이 조인 포인트가 될 수 있습니다.

Weaving(위빙):

  • 위빙은 애스펙트를 실제 타겟 객체에 적용하는 과정입니다. Spring AOP는 런타임 위빙을 사용하여 프록시 객체를 통해 이 작업을 수행합니다.

Spring AOP를 사용하면 반복되는 횡단 관심사를 애스펙트로 모듈화하여 코드의 가독성과 유지보수성을 높일 수 있습니다. 이와 같은 구조는 주요 비즈니스 로직을 깨끗하게 유지하면서도 다양한 부가 기능을 효율적으로 적용할 수 있게 해줍니다.

Transaction 전파 전략을 설명하고 각각 어떤 상황에서 사용되는가?

Spring의 트랜잭션 전파 전략(propagation strategies)은 트랜잭션이 시작되거나 다른 트랜잭션에 참여하는 방식을 결정합니다. Spring에서는 여러 가지 전파 전략을 제공하며, 각 전략은 특정 상황에서 유용하게 사용됩니다. 주요 전파 전략과 그 사용 사례를 설명하겠습니다.

  1. PROPAGATION_REQUIRED
  • 설명: 현재 트랜잭션이 존재하면 해당 트랜잭션에 참여하고, 그렇지 않으면 새 트랜잭션을 시작합니다.
  • 사용 사례: 대부분의 비즈니스 로직에서 기본값으로 사용됩니다. 새 트랜잭션이 필요하거나 기존 트랜잭션에 참여해야 할 때 유용합니다.
  • 예시: 여러 서비스 메서드를 호출하여 하나의 작업 단위를 구성할 때 사용됩니다.
  1. PROPAGATION_REQUIRES_NEW
  • 설명: 항상 새 트랜잭션을 시작하며, 기존 트랜잭션이 존재하면 일시 정지시킵니다.
  • 사용 사례: 현재 트랜잭션과 독립적인 트랜잭션이 필요할 때 유용합니다.
  • 예시: 감사 로그를 기록하는 메서드나, 현재 트랜잭션의 상태와 관계없이 실행되어야 하는 작업에 사용됩니다.
  1. PROPAGATION_SUPPORTS
  • 설명: 현재 트랜잭션이 존재하면 해당 트랜잭션에 참여하고, 존재하지 않으면 트랜잭션 없이 실행됩니다.
  • 사용 사례: 트랜잭션이 필요하지 않지만, 트랜잭션 내에서 호출될 때는 트랜잭션에 참여하는 메서드에 사용됩니다.
  • 예시: 읽기 전용 메서드나 캐시 조회 메서드에 사용됩니다.
  1. PROPAGATION_NOT_SUPPORTED
  • 설명: 항상 트랜잭션 없이 실행하며, 기존 트랜잭션이 존재하면 일시 정지시킵니다.
  • 사용 사례: 트랜잭션 컨텍스트 밖에서 실행되어야 하는 메서드에 사용됩니다.
  • 예시: 트랜잭션이 필요 없는 단순한 조회 작업이나 외부 API 호출에 사용됩니다.
  1. PROPAGATION_NEVER
  • 설명: 트랜잭션 없이 실행되며, 현재 트랜잭션이 존재하면 예외를 발생시킵니다.
  • 사용 사례: 트랜잭션 내에서 실행되면 안 되는 메서드에 사용됩니다.
  • 예시: 트랜잭션이 금지된 작업에 사용됩니다.
  1. PROPAGATION_MANDATORY
  • 설명: 반드시 기존 트랜잭션 내에서 실행되어야 하며, 현재 트랜잭션이 존재하지 않으면 예외를 발생시킵니다.
  • 사용 사례: 트랜잭션 내에서만 호출되어야 하는 메서드에 사용됩니다.
  • 예시: 기존 트랜잭션의 일부로 실행되어야 하는 필수 작업에 사용됩니다.
  1. PROPAGATION_NESTED
  • 설명: 현재 트랜잭션이 존재하면 중첩 트랜잭션을 시작하고, 존재하지 않으면 PROPAGATION_REQUIRED와 동일하게 동작합니다.
  • 사용 사례: 주 트랜잭션 내에서 독립적인 커밋/롤백이 가능한 중첩 트랜잭션이 필요할 때 사용됩니다.
  • 예시: 주 트랜잭션의 영향을 받지 않으면서도 독립적인 롤백 지점이 필요한 경우에 사용됩니다.

결론
각 전파 전략은 특정 상황에서 유용하게 사용될 수 있으며, 올바른 전파 전략을 선택하는 것은 트랜잭션 관리의 중요한 부분입니다. 비즈니스 로직의 요구사항에 맞춰 적절한 전파 전략을 선택하여 트랜잭션을 효율적으로 관리할 수 있습니다.

최종프로젝트

기존 PaginationResponse 디렉토리 위치를 challenge -> global 로 리팩토링
AdminPaginationResponseDto 파일 삭제 및 연결 리팩토링 AdminPaginationResponseDto -> PaginationResponse

챌린지 참가 인원 제한

  • 챌린지마다 참가 가능 인원에 제한을 설정
  • 인원이 다 찰 경우, 추가 인원 참가 불가
  • 필요한 api : (기존 api에 limitedUsers, joinedUsers request response 추가 및 로직 추가)

    챌린지 등록 api에 req, res 추가
    챌린지 수정 api에 req, res 추가
    챌린지 전체조회 api에 res 추가
    챌린지 단건조회 api에 res 추가

    챌린지 entity에 limitedUsers 추가
    챌린지 entity에 joinedUsers 추가
    챌린지 전체조회 api에 res 추가
    챌린지 단건조회 api에 res 추가
    챌린지 카테고리별조회 api에 res 추가
    챌린지 참가 api에 로직 추가
    - joinedUsers < limitedUsers 참가처리하고 joinedUsers ++;
    - joinedUsers >= limitedUsers 예외처리
    챌린지 참가취소 api에 로직 추가
    - joinedUsers --;
  • 선착순 개념, 락을 획득한 트랜잭션에서만 참가 신청가능, 획득하지 못한 트랜잭션은 읽기만 허용
  • 동시성제어 비관적 락 ( Shared lock, PESSIMISTIC_READ ) 적용
profile
새로운 시작~!

0개의 댓글