분류 전체보기 1341

함수형 엔드포인트

함수형 엔드포인트 스프링 WebFlux는 클라이언트의 요청을 라우팅하고 처리할 수 있는 람다 기반 프로그래밍 모델인 함수형 엔드포인트를 제공한다. 함수형 엔드포인트는 요청을 분석해 핸들러로 라우팅 하는 라우터 함수 과 요 청 객체를 전달받아 응답을 제공하는 핸들러 함수로 이뤄져 있다. 라우터 함수 @Configuration class Router { // 클라이언트로부터 전달받을 요청을 해석하고, 핸들러로 전달 //Configuration 과 Bean 에노테이션을 통해 빈으로 등록해야한다. @Bean fun userRouter(handler: UserHandler): RouterFunction = /* route() .GET("/users/{id}", handler::getUser) //중복되는 경로는 ..

스프링 Webflux

프로젝트 리액터 프로젝트 리액터는 리액티브 스트림의 구현체 중 하나로, 스프링의 에코시스템 범주에 포함된 프레임워크이다. 리액티브 스트림 사양을 구현하고 있으므로 리액티브 스트림에서 사용하는 용어와 규칙을 그대로 사용한다. 리액터를 사용하면, 애플리케이션에 리액티브 프로그래밍을 적용할 수 있고, 비동기-논블로킹을 적용할 수 있다. 함수형 프로그래밍의 접근 방식을 사용해서 비동기-논블로킹 코드의 난해함을 어느 정도 해결한다. 백 프레셔를 사용해 시스템의 부하를 효율적으로 조절할 수 있다. Mono/ Flux 리액터는 리액티브 스트림의 Publisher 인터페이스를 구현하는 Mono와 Flux라는 핵심 타입을 제공한다. Mono는 0..1개의 단일 요소 스트림을 통지하는 발행자이다. Flux는 0..N개로 ..

리액티브 프로그래밍

리액티브 프로그래밍은 데이터, 이벤트의 변경이 발생하면, 이에 반응해 처리하는 프로그래밍 기법이다. 리액티브 프로그래밍은 비동기 프로그래밍을 처리하는 새로운 접근 방식이며, 2010년 에릭 마이어에 의해 MicroSoft .Net 에코 시스템으로 정의되었다. 리액티브 프로그래밍은 데이터의 통지, 완료, 에러에 대한 처리를 Observer 패턴에 영감을 받아 설계되었고, 데이터의 손쉬운 비동기 처리를 위해 함수형 언어의 접근방식을 사용했다. 리액티브와 비동기 프로그래밍 리액티브 프로그래밍이 나오기 전 비동기 프로그래밍은 대부분 콜백 기반의 비동기 처리방식을 사용했다. 간단한 콜백은 이해하기 쉽지만, 콜백이 많아져서 발생하는 콜백 헬로 인해 코드의 복잡도가 늘어났다. 리액티브 프로그래밍을 사용하면서, 콜백 ..

Iterator 패턴

Iterator 패턴은 데이터의 집합에서 데이터를 순차적으로 꺼내기 위해 만들어진 디자인 패턴이다. Iterator 패턴을 사용하면, 컬렉션이 변경되더라도 동일한 인터페이스를 사용해 데이터를 꺼내올 수 있기 때문에 변경사항 없이 사용할 수 있다. 데이터의 집합이 얼마큼의 크기를 가졌는지 알 수 없는 경우 Iterator 패턴을 사용하면, 순차적으로 데이터를 꺼내 올 수 있다. Aggregate는 요소들의 집합체를 나타낸다. Iterator는 집합체 내부에 구현된 Iterator를 이용해 생성한다. Iterator를 사용하는 클라이언트는 생성된 Iterator의 hasNext 함수를 사용해 데이터가 존재하는지 검사하고, next 함수를 사용해 데이터를 꺼낸다. 구현 data class Car(val bra..

Observer 패턴

Observer 패턴 observer 패턴은 GoF의 디자인 패턴 중 하나로 관찰 대상이 되는 객체가 변경되면 대상 객체를 관찰하고 있는 observer에게 변경사항을 통지하는 디자인 패턴을 말한다. observer 패턴을 사용하면 객체 간의 상호작용을 쉽게 하고, 효과적으로 데이터를 전달할 수 있다. 구조 observer 패턴은 관찰 대상인 Subject와 Subject를 관찰하는 Observer로 이루어져 있다. 하나의 Subject에는 1개/여러 개의 observer를 등록할 수 있다. Subject의 상태가 변경되면, 자신을 관찰하는 Observer들에게 변경사항을 통지한다. Subject로 변경사항을 통지 받은 Observer는 부가적인 처리를 한다. observer 패턴은 Subject와 Ob..

비동기-논블로킹 프로그래밍

동기 프로그래밍 작업의 실행 흐름이 순차적으로 동작한다. 순차적으로 동작하는 프로그램은 코드를 파악하기 쉽고, 결과를 예측하기 쉬우므로 디버깅이 쉽다. 특정 작업을 실행하는 동안 다른 작업을 할 수 없다는 단점이 존재한다. 비동기 프로그래밍 작업의 실행흐름이 기본적으로 순차적이지 않다. 비동기 처리 방식은 현재 실행 중인 작업이 끝나는 것을 기다리지 않고 다른 작업을 할 수 있다. 서버, 클라이언트 등 모든 환경에서 유용하게 사용된다. UI 애플리케이션의 경우 특정 이벤트가 발생할 경우에 반응하는 동작을 구현해야 하는데, 이럴 때 필수적으로 비동기 프로그래밍을 사용하게 된다. 대부분 프로그래밍 언어들은 각 언어의 철학에 맞는 다양한 비동기 처리 방법을 지원한다. 대표적으로 callback, promise..

코멘트 수정/ 코멘트 삭제

코멘트 수정 Controller @PutMapping("/{id}") fun edit( authUser: AuthUser, @PathVariable id: Long, @RequestBody request: CommentRequest, ) = commentService.edit(id, authUser.userId, request) Service @Transactional fun edit(id: Long, userId: Long, request: CommentRequest): CommentResponse? { return commentRepository.findByIdAndUserId(id, userId)?.run { body = request.body commentRepository.save(this).t..

코멘트 등록

Domain comment @Entity @Table class Comment( @Id @GeneratedValue(strategy = IDENTITY) val id: Long? = null, @ManyToOne(fetch = LAZY) @JoinColumn(name = "issue_id") val issue: Issue, @Column val userId: Long, @Column val username: String, @Column var body: String, ): BaseEntity() { } Issue 필드 추가 @Entity @Table class Issue( //... @OneToMany(fetch = EAGER) val comments: MutableList = mutableListOf(..

이슈 수정 / 이슈 삭제

이슈 수정 Controller @PutMapping("/{id}") fun edit( authUser: AuthUser, @PathVariable id: Long, @RequestBody request: IssueRequest, ) = issueService.edit(authUser.userId, id, request) Service @Transactional fun edit(userId: Long, id: Long, request: IssueRequest): IssueResponse { val issue = issueRepository.findByIdOrNull(id) ?: throw NotFoundException("이슈가 존재하지 않습니다.") return with(issue) { summary =..

이슈 목록 조회/ 이슈 상세 조회

이슈 목록 조회 IssueController @GetMapping fun getAll( authUser: AuthUser, @RequestParam(required = false, defaultValue = "TODO") status: IssueStatus, ) = issueService.getAll(status) parameter로 status를 받는다(필수로 입력받지 않아도 기본값은 TODO로 입력받게 한다) IssueService @Transactional(readOnly = true) fun getAll(status: IssueStatus) = issueRepository.findAllByStatusOrderByCreatedAtDesc(status) ?.map { IssueResponse(it) ..