이번 주는 스프링 주특기 주차로 정말 많은 걸 배웠다. 처음엔 그냥 생각나는 대로 막 구현했지만, 멘토링을 통해 점점 더 많은 걸 배우고 개선할 수 있었다.
Restful한 API
처음엔 View와 API를 구분하지 않고 하나의 컨트롤러에서 모든 작업을 했었다. 이번엔 View 전용 컨트롤러와 API 전용 컨트롤러로 나눠서 작업했다. 덕분에 API를 재사용할 수 있게 되었고, 유지보수도 쉬워졌다.
- API 분리 전: View와 API를 하나의 컨트롤러에서 처리하여 코드가 복잡하고 유지보수가 어려웠다.
- API 분리 후: View 전용 컨트롤러는 사용자 인터페이스 관련 작업을 처리하고, API 전용 컨트롤러는 데이터 처리를 담당하여 코드가 간결해지고 재사용성이 높아졌다.
서비스 단계 로직
이전에는 컨트롤러에서 오류 처리 로직을 복잡하게 구현했었다. 이제는 컨트롤러는 최대한 간단히 만들고, 오류 처리는 서비스에서 처리하도록 했다. 이렇게 하니 코드가 훨씬 깔끔해졌다.
- 오류 처리 전: 컨트롤러에서 모든 오류를 처리하여 코드가 복잡하고 가독성이 떨어졌다.
- 오류 처리 후: 컨트롤러는 요청을 받아 서비스에 전달하는 역할만 하고, 실제 오류 처리는 서비스에서 담당하여 코드의 책임 분리가 명확해졌다.
JWT를 사용한 인증/인가
이전에는 로그인 기능을 구현할 때 세션을 사용했었는데, 이 방법은 기능이 많아지면 관리가 어려웠다. JWT를 사용하니 서버 측에 세션을 저장할 필요가 없고, 인증이 간편해졌다. 하지만 JWT는 토큰 크기로 인한 네트워크 부하 증가와 보안 위험 같은 한계점이 있다.
- JWT의 장점:
- 서버에 세션을 저장하지 않아 서버 부하가 줄어든다.
- JWT는 클라이언트에 저장되므로, 인증 정보가 간편하게 확인 가능하다.
- Json 형식이어서 자바스크립트에서 쉽게 파싱할 수 있다.
- JWT의 한계점:
- 토큰 크기가 커지면 네트워크 부하가 증가할 수 있다.
- 토큰이 탈취되면 보안 문제가 발생할 수 있다.
- 만료된 토큰을 처리하는 데 어려움이 있을 수 있다.
단방향 연관관계와 양방향 연관관계
이번 주엔 강사가 강의 목록을 참조하고, 강의는 강사 ID를 참조하도록 했다. 덕분에 강사 정보를 불러오는 과정이 간단해졌다. 양방향 연관관계를 사용할 때는 무한 루프 문제가 발생할 수 있어 ResponseDTO에 필요한 요소만 반환하도록 작업했다.
- 단방향 연관관계: 한쪽에서만 다른 엔티티를 참조하는 구조. 예를 들어, 강의가 강사를 참조하면 강사는 강의를 참조하지 않는다.
- 양방향 연관관계: 양쪽에서 서로를 참조하는 구조. 강사가 강의를 참조하고, 강의도 강사를 참조한다. 이 경우 무한 루프를 방지하기 위해 DTO를 사용하여 필요한 데이터만 반환했다.
@OneToMany(mappedBy = "teacher", orphanRemoval = true, cascade = CascadeType.REMOVE)
@Builder.Default
private List<Lecture> lectures = new ArrayList<>();
DB와 JPA의 Cascade
Cascade 설정을 통해 부모 엔티티와 자식 엔티티 간의 연관된 작업을 자동으로 처리할 수 있다. 예를 들어, 강사 데이터를 삭제하면 강사의 강의 데이터를 모두 삭제하는 CascadeType.REMOVE를 사용하였다. 이 설정 덕분에 연관된 데이터에 대한 작업을 간편하게 관리할 수 있었다.
- CascadeType.PERSIST: 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장된다.
- CascadeType.REMOVE: 부모 엔티티를 삭제할 때 자식 엔티티도 함께 삭제된다.
- CascadeType.MERGE: 부모 엔티티를 병합할 때 자식 엔티티도 함께 병합된다.
- CascadeType.ALL: 모든 작업에 대해 연쇄적으로 적용된다.
예를 들어, 강사 엔티티에서 CascadeType.REMOVE를 사용하면, 강사를 삭제할 때 강사의 강의도 자동으로 삭제된다.
@OneToMany(mappedBy = "teacher", orphanRemoval = true, cascade = CascadeType.REMOVE)
@Builder.Default
private List<Lecture> lectures = new ArrayList<>();
JPA의 영속성 컨텍스트
영속성 컨텍스트는 JPA에서 엔티티를 영구적으로 저장하고 관리하는 환경이다. 이는 스프링과 데이터베이스 사이에서 객체를 보관하여 데이터의 일관성을 유지하고, 데이터베이스 접근 횟수를 줄여 성능을 최적화하는 역할을 한다.
-
장점:
- 데이터 일관성 유지: 엔티티 객체의 상태를 일관되게 관리하여 데이터의 일관성을 보장한다.
- 데이터베이스 접근 최적화: 데이터베이스 접근 횟수를 줄여 성능을 개선할 수 있다. 이는 영속성 컨텍스트가 데이터베이스와의 상호작용을 효율적으로 관리하기 때문이다.
- 엔티티 객체의 동일성 보장: 같은 트랜잭션 내에서 동일한 엔티티 객체를 사용하여 데이터의 중복을 방지하고 일관성을 유지한다.
-
영속성 컨텍스트의 작동 방식:
- 엔티티 캐싱: 영속성 컨텍스트는 엔티티를 캐시하여 같은 트랜잭션 내에서 동일한 엔티티 객체를 재사용한다.
- 변경 감지: 엔티티의 상태가 변경되면 영속성 컨텍스트가 이를 감지하고, 트랜잭션이 끝날 때 데이터베이스에 변경 사항을 자동으로 반영한다.
- 플러시: 영속성 컨텍스트의 변경 사항을 데이터베이스에 반영하기 위해
flush 메서드를 호출할 수 있다. 이는 트랜잭션 커밋 시 자동으로 호출된다.
Servlet
서블릿은 웹 요청을 처리하는 기본적인 구성 요소로, 클라이언트의 요청을 받아서 동적으로 페이지를 생성하고, 결과를 반환한다. 서블릿을 사용하면 웹 통신을 보다 쉽게 처리할 수 있다.
- Servlet 작동 방식:
- 사용자가 URL로 요청을 보내면, 서블릿 컨테이너가 요청을 받아 처리한다.
- 컨테이너는 HTTP Request와 Response 객체를 생성하고, 서블릿에 전달한다.
- 서블릿은 요청을 처리하고, 결과를 Response 객체에 담아 클라이언트에 반환한다.
Web Server와 Web Application Server
웹 서버와 웹 애플리케이션 서버는 서버와 클라이언트 간의 통신을 처리하지만, 처리 방식에는 차이가 있다.
- Web Server: HTML, CSS, JavaScript와 같은 정적인 파일을 제공한다. 클라이언트의 요청에 대해 정적 콘텐츠를 처리한다.
- Web Application Server: 데이터베이스와 연동하여 동적인 데이터를 생성하고 처리한다. 클라이언트의 요청에 대해 동적 콘텐츠를 처리한다.
Spring AOP
Spring AOP는 애플리케이션의 비즈니스 로직과 부가적인 관심사를 분리하여 코드의 모듈성을 개선하는 기법이다. @Aspect 어노테이션을 활용해 AOP를 구현할 수 있다.
- 주요 개념:
- Aspect: 로깅, 트랜잭션 관리 등 공통 관심사를 모듈화한 것.
- Target: Aspect가 적용되는 대상.
- Join Point: Aspect가 적용될 수 있는 지점. 주로 메서드 호출.
- Advice: Join Point에서 수행될 작업. Before, After, Around 등의 유형이 있다.
- Pointcut: Advice가 적용될 Join Point를 정의하는 표현식.
Spring PSA
Spring PSA는 애플리케이션이 특정 기술에 종속되지 않도록 추상화 계층을 제공하여 다양한 기술 스택 간에 쉽게 교체하거나 확장할 수 있도록 한다.
- 데이터 접근 기술: JDBC, JPA, Hibernate 등.
- 트랜잭션 관리: 프로그래매틱 트랜잭션, 선언적 트랜잭션 관리.
- 메시징: JMS(Java Message Service) 추상화.
- 메일 서비스: JavaMail 추상화.
Spring Context
Spring Context는 애플리케이션의 구성과 설정을 중앙에서 관리하며, IoC (Inversion of Control)를 통해 애플리케이션 컴포넌트의 생성과 의존성 주입을 관리한다.
- 주요 기능:
- ApplicationContext: 애플리케이션 컴포넌트의 설정을 관리하고, 런타임 시점에 접근할 수 있도록 한다.
- 빈 라이프사이클 관리: 빈의 생성, 초기화, 소멸 등의 라이프사이클을 관리한다.
- 국제화(I18n): 메시지 소스를 통해 국제화 지원을 제공한다.
- 이벤트 발행 및 구독: 애플리케이션 이벤트를 발행하고 구독할 수 있는 기능을 제공한다.
- 리소스 로딩: 파일 시스템, 클래스패스 등 다양한 위치에서 리소스를 로드할 수 있다.
이번 주에는 스프링 프레임워크의 다양한 기능과 개념에 대해 깊이 있게 배울 수 있었고, 이를 통해 실무에 적용할 수 있는 능력을 더욱 키울 수 있었다.