2024 12 31
2024-12-31¶
Play Framework Controller¶
- 개요
- Controller는 추상 클래스, 트레이트로 구성되어 있음
- Play 2.8 기준 다음과 같음
-
1. BaseController
- Play에서 Controller가 가져야 할 기본 동작(Action 생성, request/response 헬퍼 메서드) 모아둔 트레이트
- Controller의 가장 기본 베이스가 되는 트레이트
BaseController직접 상속(믹스인) 시, 아래 중 하나 충족 필요implicit val controllerComponents: ControllerComponents스코프 내에 두기def controllerComponents: ControllerComponents메서드 오버라이드
- 특징
- Play 제공 액션 메서드 사용 가능 (
Action,Action.async) - DI를 통해
ControllerComponents받아올 것 BaseController자체는 기본 골격만 제공, 다양한 편의 메서드는 타 트레이트나 추상 클래스를 통해 제공됨
- Play 제공 액션 메서드 사용 가능 (
- Play에서 Controller가 가져야 할 기본 동작(Action 생성, request/response 헬퍼 메서드) 모아둔 트레이트
-
2. AbstractController
- BaseController 상속 받고, 필요한 헬퍼들을 믹스인한 추상 클래스.
- 생성자에서
ControllerComponents주입 받아 보관
- 특징
ControllerComponents생성자에서 직접 주입받아 내부 필드로 보관. DI 간편- Play 제공 헬퍼 메서드(
OK,NotFound,Redirect등) 바로 사용 가능
- 3. InjectedController
BaseController상속,@Inject()로ControllerComponents를 멤버로 자동 주입하는 추상 클래스class MyController extends InjectedController형식으로 정의한 뒤, 별도 생성자 주입 없이 DI 프레임워크 설정에 따라controllerComponents를 알아서 주입
- 4. (구 버전) Controller
- Play 2.7 이전에 쓰이던 trait.
BaseController및 추가 헬퍼를 섞어둔 형태 - Play 2.8 기준 deprecated 되었거나, 사용 권장되지 않음.
AbstractController,InjectedController사용이 권장됨
- Play 2.7 이전에 쓰이던 trait.
- 정리
/** * Defines utility methods to generate `Action` and `Results` types. * * This is intended to provide the idiomatic Play API for actions, allowing you to use "Action" for the default * action builder and "parse" to access Play's default body parsers. You may want to extend this to provide your own * base controller class, or write your own version with similar code. */ trait BaseController extends BaseControllerHelpers { /** * The default ActionBuilder. Used to construct an action, for example: * This is meant to be a replacement for the now-deprecated Action object, and can be used in the same way. */ def Action: ActionBuilder[Request, AnyContent] = controllerComponents.actionBuilder } /** * An abstract implementation of [[BaseController]] to make it slightly easier to use. */ abstract class AbstractController(protected val controllerComponents: ControllerComponents) extends BaseController /** * A variation of [[BaseController]] that gets its components via method injection. */ trait InjectedController extends BaseController { private[this] var _components: ControllerComponents = _ /** * Call this method to set the [[ControllerComponents]] instance. */ @Inject def setControllerComponents(components: ControllerComponents): Unit = { _components = components } }
-
ControllerComponents
- 컨트롤러를 구성할 때 필요한 핵심 컴포넌트를 담은 객체
- 컨트롤러가 HTTP 요청/응답을 처리하는데 필요한 다양한 요소를 한데 묶어, DI 방식으로 쉽게 전달 받을 수 있도록 함.
trait ControllerComponents { def actionBuilder: ActionBuilder[Request, AnyContent] // Action 생성할 때 인증/권한 체크 공통 로직을 ActionBuilder로 분리 - 재활용 def parsers: PlayBodyParsers // JSON, XML, Form Data 파싱할 수 있는 parser def messagesApi: MessagesApi def langs: Langs def fileMimeTypes: FileMimeTypes def executionContext: scala.concurrent.ExecutionContext // 비동기 로직 실행 시 필요한 ExecutionContext. Play 논블로킹 I/O. 컨트롤러 내부에서 비동기 처리 시 필요 }
- 역할
ActionBuilder,PlayBodyParsers등은 HTTP 요청을 실제로 처리하기 위한 필수 구성 요소Action { implicit request => ... }형태에 대한 처리에서 내부적으로ActionBuilder,BodyParser가 모두 필요함
- Action
- HTTP 요청 받아서 처리, 그 결과로 HTTP 응답을 반환하는 하나의 함수 (컨트롤러 메서드를 감싸고 있은 요청 처리 로직)
- 개념
- 요청 -> 액션 -> 응답
- 클라이언트가 보낸 HTTP 요청을 Action이 받아 처리하고, 최종적으로 HTTP 응답 반환
- 함수형 인터페이스
- Play Scala 기준,
Action은Request => Result형태의 함수 - 내부에서는 요청 파싱, 비즈니스 로직 수행, 응답 생성 과정을 거침
- Play Scala 기준,
- ActionBuilder
Action은 보통ActionBuilder(ex.DefaultActionBuilder,cc.actionBuilder등) 통해 생성- 인증/인가, 공통 로직 등 ActionBuilder 레벨에서 적용해 중복 코드 줄이고 일관성 있는 처리 가능
- 요청 -> 액션 -> 응답
- 특장점
- 간결한 선언
Action { ... }요청 처리로직 작성 -> 컨트롤러 코드 간결
- 미들웨어(필터) 역할
- 인증/인가, 로깅, CORS 공통 로직
ActionBuilder레벨에서 적용. 여러 개의 액션에 일괄적 반영 가능 - ex.
AuthenticatedAction { request => ... }같은 식으로 인증을 거친 액션만 따로 정의 가능
- 인증/인가, 로깅, CORS 공통 로직
- 비동기 지원
- 액션 처리 과정에서 비동기 작업 수행 가능
- 리퀘스트 파싱 기능
- 간결한 선언
-
Custom Action
- 인증/인가 등의 로직을 커스텀 액션으로 만들어 여러 컨트롤러 메서드에 손쉽게 적용 가능
ActionBuilder를 활용하여 구현하는 방식 사용 1. 커스텀 Request 타입 정의- Request를 확장한 WrappedRequest를 만들어, 인증 정보나 사용자 정보 등을 담아 컨트롤러로 전달
- 커스텀 ActionBuilder 구현
ActionBuilder를 상속받아 원하는 인증/인가 로직을 invokeBlock 메서드 안에 구현
- 컨트롤러에서 사용
Slick Versions¶
play-slick 버전 참고 : https://github.com/playframework/play-slick
- 예전 센터 : slick 2.1.0 | play 2.5.19 | scala 2.11.7 - 신규 센터 : play-slick 5.0.2 | play 2.8.x | slick 3.3.2 + | Scala 2.12.x, 2.13.x
- Slick 2.x
.list,.first-> 동기/블록킹식 사용- 내부적으로 Session 사용해 동기적으로 DB 조회하여 결과 반환
- 스레드 블로킹하기에 동기로 리턴
- Slick 3.x
.result와Future기반 -> 비동기/넌블러킹- 비동기로 데이터를 받아온다 : 즉시 Future 반환. DB 처리는 백그라운드 진행. 나중에 결과 준비 완료 시 콜백/완료 상태 알림
- DBIOAction 중심.
db.run(...)호출 시,Future[T]반환