해결된 질문
작성
·
274
7
초심자가 느끼기에는 인터페이스는 사용 설명서 같은 거라서 활용할 때 마음대로 바꾸면 안돼고, 지침대로 사용해야 하는 것, 이라고 받아들여지거든요.
그래서 Filter를 구현하실 때 @Override 함수가 3개 만들어지는데 init함수에는 Filter.super.init(filterConfig); 가 들어있고 destroy 함수에는 Filter.super.destroy();가 들어있잖아요?
영상에서는 표현하지 않으셨지만 필요없다고 여기셨는지 삭제하시고 Log.info 문을 넣으셨습니다. Filter 인터페이스가 HTTP 요청만 받을 수 있도록 만들어진게 아니시라며(HttpServletRequest)로 다운케스팅 하시기도 하고요.
만약 이 영상을 보지 않았다면 저는 Filter 인터페이스를 보고서 Filter.super.init() Filter.super.destroy() 이것들은 뭐지? 뭔가 지우면 큰일날 것 같으니까 가만 놔둬야되는 것 아닐까. 그래 다 프로그래머님들이 뜻이 있어서 놔둬셨을거야. 하면서 가만히 놔뒀을 것이고 HttpServletRequest 이것으로도 다운 케스팅 하지 않고 request에 .점을 딱 찍어보고 어? 아니 내가 원하는 사용법으로 사용할 수 없잖아. 어떻게 하지? 하고 몇시간을 헤맸을 것 같은데...
결론적으로 인터페이스 형태만으로는 내가 인터페이스를 제대로 사용하고 있는지 알 수 없다, 라는 것이고 인터페이스를 사용할 때마다 혹시 다른 인터페이스가 있는게 아닐까 의심하게 될지도 모를거 같습니다.
그래서 이런 인터페이스 형태에서 얻을 수 있는 정보를 넘어서 더 많은 모종의 정보들을 파악해야 비로서 인터페이스를 사용할 수 있는 부조리함?을 어떻게 극복하시는 건지 궁금합니다.
답변 2
19
위의 답변에 이어서 저는 구체적으로 어떻게 궁금증에 대한 해답을 찾는 가에 대해 설명해주고 싶네요.
질문하신대로 인터페이스의 함수선언부만 보고는 어떤 동작의 함수를 구현해야할지 모를 수 있습니다. 자바의 표준함수들은 이해를 돕기위한 주석이나 레퍼런스가 굉장히 친절하게 써져있습니다. 이걸 읽어보시면 됩니다.
Filter 인터페이스에 써져있는 공식 주석으로 질문에 있는 내용을 전부 해결해 보겠습니다.
1. Filter.super.init(), Filter.super.destroy() 는 뭐지?
init(), destroy()를 구현했더니 Filter.super.init(), Filter.super.destroy()를 IDE가 자동으로 호출했습니다. 디폴트 함수로 써져있기 때문이죠. '이걸 왜 디폴트 함수로 썼을까? 디폴트로 정의해 놓은 함수 내용이 뭘까?' 의도를 알고 싶으면 Filter 인터페이스를 열어보면 됩니다.
열어보니 init(), destroy()의 함수 내용은 공백입니다.
주석에는 "The default implementation is a NO-OP." 즉 기본 구현은 아무런 작업도 하지 않는다는 겁니다.
Filter.super.init(); 을 지워도 상관없겠죠?
의도는 Filter를 구현할때 init()이나 destroy()를 사용하지 않을거면 귀찮게 override 하지 않아도 되도록 설정해 놓은 것입니다.
강의에서 만든 LogFilter에서 init()이나 destroy() 함수를 지워보시면 정상작동하는것을 알 수 있을겁니다.
2. HttpServletRequest로 다운 캐스팅은 어떻게 알까?
ServletRequest 만으로는 원하는 기능을 이용할 수 없었습니다. 그래서, ServletRequest 인터페이스의 주석을 살펴봤습니다.
'Interfaces that extend ServletRequest can provide additional protocol-specific data (for example, HTTP data is provided by javax.servlet.http.HttpServletRequest.')
HTTP 데이터를 이용하고자 하면 ServletRequest를 상속하는 HttpServletRequest를 사용하랍니다.
또, Filter의 doFilter() 함수에 다음과 같은 주석이 있습니다. "Optionally wrap the request object with a custom implementation to filter content or headers for input filtering".
request 객체를 필요에 따라 캐스팅해서 쓰랍니다. 즉, HTTP 요청 정보들을 이용할 필요가 있으면 HttpServletRequest를 쓰면 되겠네요.
-------------------------
저도 배우는 입장이라 사전에 모르던 내용이었지만 주석을 읽어봄으로써 궁금증을 해결해 볼 수 있었습니다. 강의를 보고 추가적인 궁금증이 생기거나 사용법을 알고 싶으면 공식 레퍼런스를 참고해보면 좋을 것 같네요.
7
안녕하세요. 컴퓨터공부하자님, 공식 서포터즈 Taewon David Hwang입니다:)
.
저도 동일한 경험이 있었고 답은 하나였습니다. 공부하는 것..ㅎㅎ
.
만약 FilterConfig가 무엇인지, Filter의 init()이 어떤 역할인지에 대해 알고 있다면 과감하게 FilterConfig를 받아서 전달하는 부분을 지우고 log를 쓸 수 있을 것입니다. 모른다면 일단 내버려두어야겠죠.
.
또 인터페이스를 예를 들면
RequestUri가 필요한데 RequestServlet으로는 가져올 수 없네? 어떤게 필요하지?
구글링을 막 하다보면 HttpRequestServlet이 RequestUri 가져올 수 있게 지원하네?
그리고 HttpRequestServlet을 살펴보다보니 RequestServlet을 상속받네, 그럼 Filter에서는 파라미터로 RequestServlet을 받으니깐 이걸 다운캐스팅해서 사용해야겠다.
이런 결론으로 도달할 수 있습니다.
물론 글로만 적으면 굉장히 쉽게 느껴지지만 처음에는 몇시간이 걸릴 수도 있습니다.
만약 인터페이스, 상속, 캐스팅 등에 대한 이해가 없으면 더욱 많은 시간이 소요될 것입니다.
이런 관점에서 컴퓨터공부하자님께서 느끼시는 것에 대한 해답으로 제 생각은 공부(이론, 실습)하는 것입니다. 그리고 이런 시간을 단축시켜주는 강력한 것들 중 하나가 영한님의 강의인 것 같습니다.
.
그 예로 컴퓨터공부하자님께서는 이제 Filter에서 RequestUri를 가져오려면 ReqeustServlet을 다운캐스팅한 HttpRequestServlet에서 RequestUri를 뽑아오면 된다는 것을 알게 되었으니깐요!
.
감사합니다.
감사합니다!