- [ backend ][etc] Spring REST Docs와 Swagger UI를 사용한 API 문서화2025-01-17 15:20:49프론트엔드(클라이언트)와 백엔드 사이 원활한 협업을 위해서는 API가 필수적으로 작성되어야 한다. 이때 중요한 역할을 하는 것이 바로 OpenAPI, Swagger, Spring REST Docs다.OpenAPI : API를 정의하기 위한 표준 형식 (주로 JSON과 YAML 형식으로 작성)Swagger : OpenAPI 스펙을 기반으로 API 문서를 시각화하는 도구Spring REST Docs : 스프링에서 제공하는 API 문서화 도구Swagger vs. Spring REST Docs스웨거는 컨트롤러에 몇 가지 어노테이션만 달아주면 API 문서를 자동으로 만들어준다. 문서화가 간편하다는 장점도 있지만 단점도 가진다.스웨거 어노테이션과 비즈니스 로직이 섞인다 (침투적)테스트가 없어 문서의 신뢰성이 낮다 ..
- [ backend/프레임워크 ][spring] 웹 어플리케이션 기능 확장하기 (WebMvcConfigurer)2025-01-05 18:00:29스프링 부트 프레임워크는 프로젝트 설정 과정을 간소화하여 어플리케이션을 빠르게 개발하도록 돕는다. 하지만 프로젝트 목적에 따라 스프링 부트 기본 설정을 변경해야 하는 경우가 있다. 다행히 스프링 웹 MVC 프레임워크는 기존 기능을 확장하거나 교체하는 다양한 방법을 제공한다. 웹 어플리케이션을 설정하는 방법은 크게 세 가지가 있다.`WebMvcConfigurer` 인터페이스를 사용하여 필요한 기능들을 추가하거나(add) 교체한다(configure)`@Primary` 어노테이션을 사용하여 기본으로 만들어지는 빈을 재설정한다웹 MVC 프레임워크에서 정의한 스프링 빈 이름과 타입으로 빈을 직접 생성한다 (스프링은 이미 이름과 타입이 일치한 스프링 빈이 있다면 새롭게 만들지 않기 때문이다!)여기서는 `WebMvc..
- [ backend/프레임워크 ][spring] 스프링 부트 시작하기 (스프링/스프링 부트/@SpringBootApplication/ApplicationContext)2024-12-19 20:00:54프레임워크는 목적에 맞는 일반적인 기능을 제공한다. 예를 들어 웹 어플리케이션 프레임워크는 HTTP 기반의 요청과 응답을 처리할 수 있도록 객체나 클래스를 제공한다. 이처럼 프레임워크에서 일반적인 기능과 비기능적인 로직을 제공함으로써 개발자는 비즈니스 로직에 집중할 수 있다. EJB vs. 스프링스프링 프레임워크 이전에는 EJB(Enterprise JavaBeans)를 사용했다. EJB를 사용하기 위해서는 인터페이스를 구현하고 클래스를 상속 받아 부모 클래스를 오버라이드 해야 했다. 즉, EJB 프레임워크의 메서드가 비즈니스 로직에 침투되고, (invasive) 프레임워크와 개발자의 코드가 강하게 결합된다. 스프링은 개발하기 복잡하고 어려운 EJB를 대체하기 위해 등장했다. 스프링을 사용하면 더 이상 특..
- [ backend/프레임워크 ][spring] JPA/Hibernate, Spring Data JPA, 영속성 컨텍스트2024-12-16 15:00:51JPA/HibernateJPA는 Java Persistence API로, 자바 어플리케이션이 데이터를 영속할 수 있도록 API를 제공한다. JPA는 ORM 표준 스펙이므로 실제로 동작하기 위해서는 구현체가 필요한데 Hibernate가 대표적인 JPA 구현 프레임워크다. 모든 자바 어플리케이션은 데이터베이스에 데이터를 저장하기 위해 JDBC API를 사용한다. JDBC는 Java Database Connectivity의 약어로, 자바의 데이터 접근 표준이다. Hibernate 같은 프레임워크를 이용하면 내부에서 JDBC를 사용하여 데이터를 처리한다.# JPA/Hibernate 관련 설정spring: jpa: show-sql: false # (default=false) JPA/Hibernate가 생성..
- [ backend/삽질일기 ][spring] 분산락을 걸어도 동시성 문제가 발생한다?! (feat. 트랜잭션 AOP)2024-12-12 21:50:19🔗 [redis] redisson으로 분산락 걸어서 동시성 문제 해결하기 (근데 해결 안됨)때는 분당으로 교육 가던 길.. 갈 길도 멀고 가방이 무거워 노트북을 가져가지 않았다. 근데 아침 7시부터 슬랙 알림이 100개 넘게 왔다. (😈 : 어? 노트북 두고 간다 장애각이다) 앱 진입 시점에 사용하는 API + 사용자의 포기하지 않는 인내심이 합쳐져 팀원들한테 슬랙 알림 테러를 시작했다.해당 포스팅에서 처리한 줄로만 알았던 데이터베이스 동시성이 원인이었다. 우리 서비스는 하루에 한 번만 미션 인증을 할 수 있는데 Repeatable Read 격리 수준이 INSERT 작업을 예방할 수 없어 API를 빠르게 연달아 호출하면 여러 번 인증하는 것이 가능했다.이러한 동시성 문제를 막고자 분산락을 적용했고 잘..
- [ backend/데이터베이스 ][redis] redisson으로 분산락 걸어서 동시성 문제 해결하기2024-11-19 12:00:41Repeatable Read 격리 수준으로 인한 동시성 문제 발생내가 진행중인 프로젝트에서 동시성 문제가 발생했다. 요구사항에 의해 하루에 한 번만 미션을 수행할 수 있다. 이를 위해 미션 인증 레코드를 생성하기 전에 오늘 인증 내역이 있는지 확인하고 INSERT 쿼리를 수행한다.@Transactionalpublic void createVerification(final CreateMissionVerificationCommand command) { MissionMember missionMember = missionMemberRepository.getMissionMember(command.memberId(), command.missionId()); // 유효성 검사 진행 (이미 레코드가 있는 경우..
- [ backend/프레임워크 ][spring] 스프링 이벤트 (ApplicationEvent와 ApplicationListener/@EventListener와 @TransactionalEventListener/비동기 이벤트)2024-11-15 12:00:58스프링 이벤트public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver { ... }스프링의 핵심인 `ApplicationContext`는 `ApplicationEventPublisher`를 상속 받아 이벤트를 게시(publish)하고 구독(listen)할 수 있도록 지원한다. 스프링 이벤트는 RabbitMQ 같은 외부 메시지 브로커와 달리 어플리케이션 내부에서 게시/구독할 목적으로 사용한다. 스프링 이벤트는 다음 장점을 가진다.이벤트를 게시하는 클래..
- [ backend/프레임워크 ][spring] REST 구현 (@RestController를 사용하는 이유/ResponseEntity를 사용하는 이유/글로벌 예외 핸들러 정의하기)2024-11-12 09:50:01@Controller 대신 @RestController를 사용하는 이유웹 앱을 만드는 방식에는 크게 두 가지가 있다.백엔드가 완성된 뷰를 제공하는 앱프론트엔드-백엔드 분리 방식의 앱프론트엔드-백엔드 분리 방식의 경우, 백엔드는 원시 데이터만 제공한다. 따라서 스프링 MVC 다이어그램에서 뷰 리졸버가 더 이상 필요하지 않다. 스프링은 컨트롤러 클래스를 컨텍스트에 빈으로 등록하기 위해 `@Controller` 어노테이션을 사용한다. 하지만 HTTP 응답을 전달하기 위해서는 `@ResponseBody` 어노테이션이 필요하다. 이를 통해 컨트롤러가 뷰 이름이 아닌 HTTP 응답 데이터를 반환한다는 것을 디스패처 서블릿에게 알릴 수 있다.@RequestMapping("/member")@Controller // 컨..