자 이렇게 AOP를 만들음


보면 알다싶이,


a -> IO b


혹은


IO b


를 자기 자신으로 보내는 꾸밈음이야.


AOP는 언제나 부작용을 담당하도록 하려고. 이거는 그냥.... 그냥 그렇게 설정했어. 더 일반화하기 싫다

AOP는 항상 부작용을 담당할거고


이번에는 IO 에 대해서만 작동하게 만들었지만, 좀 더 확장가능하게 해서

AOPable Monad 라는 타입클래스를 만들려고 해


왜냐면 IO 말고 더 구체적인 부작용을 제시하는 경우에도 AOP를 추가할 수 있어야하니까.




AOP에서 담당하는건 두가지임.


1. 인자를 살짝 조작해서 집어넣기.(단 이 조작은 순수함수에 의한 계산일 것)

2. 앞 뒤로 부작용을 담당할 것.




그리고 여기에 추가해야할게 하나가 있는데


나는 AOP끼리 서로 정보를 주고받는 모델을 선호함.

하나의 리퀘스트로부터 저장소 하나가 마련되어야한다는 뜻인데,


이걸 구현하려면 AOP 말고 필터나 인터셉터 레이어가 필요함.

필터는 못만들음. 이거는 내가 Servant 웹프레임워크를 해킹하지 않는 이상 못만들고


Interceptor를 구현해야하는데 그거는 이따가 회사 일 다 끝나고 오늘 필터 구현하는 일을 할거고


대충 저장소를 마련하고, 공통의 헤더설정 뭐 그런거를 설정하는 레이어를 만들거임. 이거는 AOP랑은 다른거임.



여하튼 리퀘스트 클라이언트 하나에 대해서 저장소 하나가 마련되면


이제 저장소에 왔다갔다 거리는 모나드를 IO로 진행시키고

해당 IO 입출력을 AOPable monad로 liftIO 시키면 대충 부작용 안에서 처리가 됨.


이걸 위해서라도

AOP는 부작용에 대해서만 한정시킬 필요가 있었었다 ㅇㅇㅇ


아 시발 나 진짜 천잰가? 퍼즐을 결국 다 맞췄네.



여하튼


AOP는 이렇게


인자는 커리잉 불가능하게 설정하고 (즉, 서비스레이어와 레포지토리레이어, 컨트롤러 레이어 같은 비순수함수의 경우에는 자바에서 그랬듯이 커리잉과 파셜어플리케이션을 사용하지 않겠다는 선언이기도 함)



이 커리잉 불가능 조건을 나중에 풀 수 있는지는 차차 생각해볼게.

결국 AOP라는 것을 하나만 선언해두고 여러곳에 재활용 가능하냐 마냐의 문제인데,


뭣하면 인자 갯수마다 만들면 되고

아예 템플릿  하스켈로 만들어볼까... 뭔가 방법 있을만도 함. 찾아봐야겠음.


여하튼 잡설 그만하고


이렇게 AOP를 선언함.


그러면 이제 이 추임새를 내가 원하는 곳에 자유자재로 집어넣을 수 있어야겠지?



일단 원본함수임. Impl 모듈에 선언되어있음


단순함. 그냥 AOP를 받아들이는 시그니처의 원본함수 그 이상도 그 이하도 아님





이게 래핑이 완료된 형태임


존나 단순함. 다른 모듈에서 이새끼를 임포트해서 추임새 붙이고 재 export하면 됨


뭐 빈을 만드니 빈팩토리를 만드니 할 필요가 없음. 그냥 빈과 런타임이라는 구조는

자바가 강력한 이유라고 볼수도있지만

어떻게 보면 컴파일 타임 자바가 병신이기 때문에 생긴 어쩔수없는 대안책이지


하스켈에서는 그냥 이렇게 만들면 AOP가 짜잔 하고 생김


클래스 단위에서 노는게 모듈단위로 바뀐다고 생각하면됨.


Impl 모듈에 있는 함수를 임포트한다음에 추임새를 붙여서 재 export.


그리고 해당 서비스를 사용하는 애들은 Interface 모듈을 사용.


이러면 해당 서비스에 변경이 생길때마다

Interface 코드만 건드리면 되고


서비스 바깥의 코드는 완벽한 추상화가 이루어짐.



자 그러면 컨트롤러 예시만 마저 보여줌.

이 서비스를 어떻게 쓰느냐




이렇게 쓰면 됨.

컨트롤러 임플 모듈임.


ProductService.getProduct 로 가져다쓰면 됨.


이게 그냥 이 자체가 Autowire임.

컴파일 타임 오토와이어


어노테이션 쓰는게 Interface쪽 연결관계 손보고 AOP 체인 직접 순서맞추는거보다 간편한건 맞는데

굳이?

하스켈쪽이 더 가볍잖아


일단 자바 스프링은 부팅속도가 굉장히 느린데

아마 클래스로딩하는 과정이랑 스프링이 런타임 이니시 과정이 있어서 그렇다고 보는데

컴파일타임에 해결한다는게 좋음.



글구 하스켈도 발전하고나면 뭔가 매크로라던지 빌드도구들이 생기고 IDE가 생기면

어노테이션급의 컴파일타임 자동화도구가 나올수도있지.

이거는 언어의 한계라고 보기엔 힘듦. 발전여지가있음. 물론 이대로가면 발전안하겠지만

내가 하스켈을 존나 발전시킬거라서



마지막으로 컨트롤러 인터페이스임



즉 컨트롤러의 빈이라고 봐도 되는데


getProduct는 이제 Impl 쪽에 있던 getProduct에 AOP를 수행한 결과물이고


추가로 컨트롤러 Interface는 라우팅 선언과 핸들러 연결. 즉 서번트쪽과의 연결코드가 필요해서 이렇게 썼음.




재밌네



하스켈 진짜 맘에 든다