토비의 스프링 ~p60

 

 

 

 

초난감 DAO를 리펙토링 하는 과정에서 알 수 있었던 템플릿 메소드 패턴과 팩토리 메소드 패턴.

 

 

리펙토링?

기존의 코드를 외부의 동작방식에는 변화 없이 내부 구조를 변경해서 재구성하는 작업 또는 기술

 

 

템플릿 메소드 패턴?

이는 상속을 통해 슈퍼클래스의 기능을 확장할 때 사용하는 가장 대표적인 방식이다. 변하지 않는 기능은 슈퍼클래스에서 만들어두고 자주 변경되며 확장할 기능은 서브클래스에 만들도록 한다.

슈퍼클래스에 기본적인 로직의 흐름을 만들고(커넥션 가져오기, SQL 생성, 실행, 반환), 그 기능의 일부를 추상 메소드나 오버라이딩이 가능한 protected 메소드 등으로 만든 뒤, 서브클래스에서 이런 메소드를 필요에 맞게 구현해서 사용하도록 하는 방식이다.

 

 

팩토리 메소드 패턴?

템플릿 메소드 패턴과 마찬가지고 상속을 통해 기능을 확장하게 하는 패턴이다. 슈퍼클래스 코드에서는 서브클래스에서 구현할 메소드를 호출에서 필요한 타입의 오브젝트를 가져와 사용한다. 

UserDAO에서 getConnection()메소드는 Connection타입 오브젝트를 생성한다는 기능을 정의해놓은 추상 메소드이다. 그리고 UserDAO의 서브클래스의 getConnection() 메소드는 어떤 Connection클래스의 오브젝트를 어떻게 생성할 것인지 결정하는 방법이다. 이렇게 서브클래스에서 구체적인 오브젝트 생성방법을 결정하게 하는 방식이다.

UserDAO는 Connection 인터페이스 타입의 오브젝트라는 것 이외에는 관심을 두지 않는다. 그저 Connection 인터페이스에 정의된 메소드를 사용할 뿐이다. 이를 사용하는 클래스는 서버의 DB커넥션 풀에서 가져올 수도 있고, 드라이버를 직접 이용해 새로운 DB커넥션을 만들수도 있고...

 

발췌 : 토비의 스프링 3.1 <UserDao의 팩토리 메소드 패턴>

 

Spring4.0이상부터 지원하는 Spring Socket을 이용하여 내가 만든 프로젝트에 실시간 채팅이 가능한 메뉴를 추가해보려고 한다. web socket에 대해서 공부해본적이 없어서 여러 자료들을 찾아보았다..

먼저, 3가지의 Spring Socket 종류에 대해서 알아보자.

 

1. WebSocekt

WebSocket은 W3C표준이다. 브라우저와 서버의 소켓통신을 할때 사용한다. WebSocket은 http상에 존재한다. 

프로토콜은 ws를 사용하지만 이 안에서는 http를 충족한다.

WebSocket은 IE10 이상버전부터 지원이 가능하다. 훨씬 이전에 개발된 방식이지만 여러가지 문제로 10버전 이상부터 지원한다고 한다...

 

2. SocketJS

SocketJS는 브라우저의 소켓을 사용한다. sockjs-client library를 사용하며, IE8 이상버전부터 지원이 가능하다. 

 

 

3. STOMP(Streaming Text Oriented Messaging Protocol) : 토픽 구독방식

스트리밍 텍스트 기반의 간단한 스트리밍 메세지 프로토콜로서 topic/queue방식이다. 토픽에 서브토픽을 주어서 채팅방의 room이름으로서 사용할수 있다. 

SockJS의 Sub Protocol으로서 SockJS를 올려놓고 사용한다. Client는 stomp js library를 쓴다. 이는 spring에 종속적인 방식이라고 할 수 있다.

 

 

 

 

일단 기본적인 WebSocket에 대해서 조금더 자세하게 알아보았다.

 

WebSocket은 사용자의 브라우저와 서버 사이의 인터렉티브 통신 세션을 설정할 수 있게 하는 고급(?)기술이다.

웹 소켓은 HTTP 위에서 돌아간다. (Socket over HTTP) 따라서 https://의 소켓은 wss:// 으로 사용할 수 있다.

wss는 https의 SSL인증서로 암호화 된것이다!!

 

WebSocket은 Long Polling 방식이다.. 폴링과 롱폴링에 대해서 조금 알아보았다.

 

Polling방식이란?

폴링방식은 요청을 주기적으로 하여 결과를 확인하는 방식이다. 원래 HTTP의 통신방식에 대해서 생각해보면... 클라이언트가 요청을 서버에게 보내고, 이를 받은 서버는 요청에 대한 응답을 보내고 응답을 받으면 연결을 끊는다.

이는 단방향 통신이다. HTTP로는 양방향 통신을 할 수 없다.

폴링방식은 주기적으로 요청을 주어 결과를 받기 때문에 양방향 통신이 가능하지만 실시간으로 주는것은 불가능하다.

실시간처럼 비슷하게 만들 수는 있지만... 그렇게 하려면 요청간격을 줄여햐하는데 이런 방식이면 서버와 클라이언트 모두에게 부담이 된다. 그래서 폴링 방식을 조금 개선한것이 롱폴링 방식이다.

 

Long Polling방식이란?

기본적으로 클라이언트가 계속적(주기적)으로 요청을 하는것은 기존 폴링방식이랑 비슷하다. 차이점은 폴링방식은 주기적으로 요청을 하였다면 롱폴링은 time out이 될 때까지 그 요청에 대한 응답을 기다린다...

임의적으로 끊기 전까지 항상 연결은 유지가 되어있기 때문에 실시간으로 통신이 가능하게 된다.

 

 

         Client ---------(Handshake)------------>server
        <--------(connection open)------

         <---(Bi-directional messages)--->
        <---(one side closes channel)--->

 

 

클라이언트가 서버에게 Handshake방식으로 요청을 하면 그 요청을 받은 server는 connection open을 한다. 웹 소켓으로 연결이 된 클라이언트와 서버는 양방향 통신(Bi-directional)을 하면서 메세지를 주고 받는다. 

server측에서 연결을 끊으면 client의 연결도 끊긴다. client측에서 연결을 끊으면 해당 session에 해당하는 연결이 끊긴다.

 

왜 요청방식이 Handshake일까? Handshake가 무엇일까?????

 

WebSocket Handshake

HTTP에서 WebSocket으로의 프로토콜 전환을 WebSocket Handshake라고 한다. 브라우저가 HTTP에서 WebSocket으로 프로토콜을 전환하려는 요청을 할 때, Header에 Upgrade속성을 추가하여 보내게 된다.

서버는 Upgrade속성을 통해 프로토콜의 전환 요청을 받고 이에 동의하게 되면 서버와 브라우저는 ws프로토콜을 사용하게 되는 것이다.

 

핸드쉐이크는 나중에 실제 코드에서 어떻게 사용하여 헤더에 속성이 어떻게 담겨져서 보내지는지 직접 알아보도록 하자..

'JAVA > Spring' 카테고리의 다른 글

싱글톤 패턴과 스프링 컨테이너  (0) 2021.12.15
Spring Socket에 대해 알아보자! - 2. WebSocket 만들어보자  (0) 2020.06.23
Spring WebSocket에 대한 내용 정리  (0) 2020.06.11
MyBatis  (0) 2020.04.21
Spring JDBC  (0) 2020.04.20

https://wondongho.tistory.com/28?category=672073

 

Springframework WebSocket 정리 해놓은 사이트들

handler 이용해서 채팅 http://blog.naver.com/PostView.nhn?blogId=scw0531&logNo=221052774287&categoryNo=28&parentCategoryNo=0&viewDate=¤tPage=2&postListTopCurrentPage=&from=postList&userTopListO..

wondongho.tistory.com

출처 Tistory - web(사용자 원동호) : Springframework WebSocket 정리 해놓은 사이트들
https://wondongho.tistory.com/28?category=672073

 

개념부터 열심히 공부해보자!

'JAVA > Spring' 카테고리의 다른 글

Spring Socket에 대해 알아보자! - 2. WebSocket 만들어보자  (0) 2020.06.23
Spring Socket에 대해 알아보자! - 1. WebSocket  (0) 2020.06.18
MyBatis  (0) 2020.04.21
Spring JDBC  (0) 2020.04.20
@AspectJ 어노테이션  (0) 2020.04.17

어제 커뮤니티에서 글을 보다가 어떤분이 본인 포트폴리오를 평가해달라며 올린 글을 보게 되었다.

그 글에는 수많은 고수들의 댓글이 달려있었는데, 대부분이 단기간이고 비전공자인데 이정도 수준이면 대단하다.. 뭐 이런 이야기였던것 같다. 물론 그중에는 혼자 한것이 맞냐 이런 의심을 품고 이것저것 물어보는 사람도 있었다.

그 댓글들을 보다가 의문이 들었다.

 

 

댓글 : 왜 @Inject를 쓰셨어요?? @Autowired와 @Inject의 차이는 알고 쓰신건가요?

작성자 : @Inject를 쓰는게 더 좋다는 글을 어디선가 봐서요..

 

 

곰곰히 생각해보니까 둘이 하는 역할은 비슷한것 같은데 어떤 차이점이 있고 어떤 어노테이션을 쓰는것이 좋은걸까 하는 생각이 들었다. 추가로 @Resource도 생각해보게 되었다.

 

 

 

@Autowired

type기반으로 DI를 해주는 어노테이션. 오토와이어드는 스프링 프레임워크에서 제공하는 어노테이션이다. 혹시나 프레임워크를 바꾸어 작업할 일이 생기면 사용할 수 없다. 빈생성시 싱글톤으로 생성하는 것이 디폴트값이기 때문에 같은타입으로 여러개 빈을 만들때 적합하지 않다. @Qualifier("이름")을 사용하면 이름을 찾아서 주입해줄 수 있긴 하다.

 

 

@Resource

name기반으로 DI를 해주는 어노테이션. 리소스는 자바에서 제공하는 어노테이션(JSR-250)이다. 이름으로 주입을 해주기 때문에 같은 타입의 빈을 여러개 만들때 유리하다.

 

 

@Inject

type기반으로 DI를 해주는 어노테이션. 인젝트는 자바에서 제공하는 어노테이션(JSR-330)이다. 타입기반으로 주입을 해준다.

 

 

 

 

@Autowired는 스프링 프레임워크에서 제공하기 때문에 아무래도 프레임워크에 종속적인 성격이 있을 것이다.

@Inject는 자바에서 제공하는 어노테이션이기 때문에 프레임워크에 상관없이 사용할 수 있다. 오토와이어드가 의존성을 확실하게 보장해주기 때문에 더 유리하다는 글도 꽤 있었는데 상황에 맞게 사용하는게 좋은것 같다. 

'이런저런 생각' 카테고리의 다른 글

MVC에서 Interface의 사용이유  (0) 2020.05.15

여러가지 예제도 보고 책도 보고 강의도 보고 게시판 프로젝트를 만들다가 어느순간보니까 아무생각 없이 DAO와 Service에는 Interface를 만들고 구현 클래스를 만들고 있었다...

 

게시판 기능을 추가하다가 문득 내가 왜 Interface를 쓰는거지 하는 생각을 해보게 되었다.

 

Interface는 구현체에 대한 권한을 구현클래스에게 넘겨서 클래스 사이에 의존성을 줄이기 위함이라고 사전적으로는 알고 있었다. 예를 들어서 Interface한개가 있고 여러개의 기능을 하는 구현체가 있다면 다형성 측면에서 이득을 가져갈 수 있는 프로그램이 될 것이다.

 

그런데 내가 만들고 있는 토이프로젝트의 수준에서 봤을 때 Interface가 굳이 필요없다고 판단이 되었다.

 

Interface한개에 딱 한개의 구현체만이 존재하는데 굳이 필요가 있냐하는 의문이 들었던 것이다.

 

 

DAO는 정말 단순하게 Mapper클래스의 객체를 주입받아서 쿼리문이 있는 메소드를 불러오는 것만 구현이 되어 있어서 Interface를 삭제하였다. Service 같은 경우에도 단순하게 게시판이나 유저를 추가 삭제하는 역할만 하기 때문에 분리를 시킬 필요가 없을 것 같았다. 

 

 

 

삭----제

 

 

 

 

클래스를 잘게 분리하고 각 클래스에 맞는 역할을 잘 구분하는 것이 객체지향 프로그래밍에서 중요하다는 생각을 할 수 있게 해주었다... 

 

'스프링 입문을 위한 자바 객체 지향의 원리와 이해' 라는 책을 어제 구매해서 읽었는데 열심히 읽으면서 공부해야겠다고 생각했다..

'이런저런 생각' 카테고리의 다른 글

@Autowired와 @Inject의 차이?  (0) 2020.05.16

자유게시판을 만들고 나니까 이미지를 올릴 수 있는 이미지 게시판도 만들고 싶어졌다.

이미지 게시판을 만들려면 메뉴를 선택할 수 있는 navigation bar 나 slide bar가 필요했다.

부트스트랩을 활용하고 있어서 부트스트랩에서 제공하는 네비게이션 바를 봤는데 마음에 들지 않았다... 내가 css나 클릭이벤트 같은 거를 좀 커스텀하고 싶었다.

 

 

이리저리 검색해가면서 css랑 클릭이벤트에 쓰일 클래스를 만들었다.

 

 

 

 

 

이제 적용을.. 해...

 

 

 

?

 

 

 

 

 

 

 

 

 

아, 경로를 잘못넣었나보다

 

 

 

 

contextPath를 가져와서 경로를 지정했다.

 

다시 실행..

 

 

 

 

 

 

?

 

 

 

 

 net::ERR_ABORTED 404

에러 발생.

 

뭘까.. 구글의 도움을 빌려보았다.

DispathcerServlet의 정적파일 매핑오류인것으로 보였다.

 

 

 

 

 

 

해결방법

 

 

 

Java 파일을 이용해서 Spring 설정을 하였다.

addResourceHandlers라는 메소드는 정적 파일의 경로를 매핑해주는 핸들러이다.

루트가 아닌 다른 위치에서 정적리소스를 제공하기 위한 것이라고 생각하면 될 것 같다.

registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); 를 이용해서 resources파일 아래의 정적메소드를 Handler로 등록해주고 경로도 추가해준다.

 

 

 

 

 

 

 

css파일을 이상없이 불러와서 적용됨을 확인하였다.

 

회원가입시 유효성 검사 기능을 추가하다가 생긴 오류로 인해서 한참을 묶여 있었다......

 

 

 

MemberController.java

 

JoinForm.jsp

 

joinMember라는 이름으로 jsp로 넘겨주었다. 넘겨줄 때, ModelAttribute를 이용하여 이름을 지정해준것이다. 그 이름으로 joinForm에서 form커스텀태그의 속성에 modelAttribute를 이용해서 받아주었다. 

빈의 형식은 MemberVO이기 때문에 joinForm에서 MemberVO의 프로퍼티와 똑같이 action으로 넘겨주면 @Valid어노테이션이 붙어있는 빈을 유효성검사 하게 된다.

 

그런데...

 

이대로 실행하면 자꾸 에러가 났다.

 

 

 

 

db.classname을 못찾는다?

 

 

ServletAppContext.java

 

db.properties에 디비접속정보를 담아서 위와 같이 @Value를 사용하여 변수에 주입받아서 사용했는데 이 부분이 에러가 난다. 분명 유효성검사 기능을 추가하기 전에는 나지 않았던 에러.

 

 

구글링해보니, @ProperySource로 등록하여 @Value를 하고, 또다른 properties파일을 메세지로 등록을 하게 되면 두 파일이 충돌이 나서 모두 인식하지 못하는 오류가 발생한다고 한다.

 

 

 

ServletAppContext.java파일에 PropertySourcePlaceholderConfigurer 라는 빈을 추가해주면 PropertySource에 등록한 properties를 따로 관리하기 때문에 충돌이 발생하지 않는다!!

 

 

PropertySourcePlaceholderConfigurer를 추가해주는 과정에서도 계속 오류가 나서 여기서만 한 3시간 고생했다.......

원인은........... 메소드 이름 자동완성..... 오타였다..

자동완성으로 PropertySourcePlaceholderConfigurer 클래스가 메소드 이름으로 완성되어서 만들어져 버림... 이걸 계속 찾지 못하였다.. 

 

 

 

 

 

암튼 오류 해결이긴한데, 

 

같은 빈으로 다른 valid후 error message를 출력하려고 하면 출력이 안된다.

그러니까 회원가입은 되는데 로그인은 <form:errors>로 출력이 안된다........ 추후에 해결해 보아야겠다.

에러 로그

### Cause: java.sql.SQLIntegrityConstraintViolationException: (conn=4502) Cannot delete or update a parent row: a foreign key constraint fails (`kooboard`.`board`, CONSTRAINT `reply` FOREIGN KEY (`b_index`) REFERENCES `board` (`b_index`)) 

 

board테이블에 있는 글을 삭제할 때, reply테이블의 b_index가 board테이블의 b_index에 외래키로 묶여 있기 때문에 다음과 같은 에러가 발생하였다.

 

 

BoardService.java

 

서비스레벨에서 참조되어있는 테이블의 row를 먼저 삭제 해 준 후, 실행함으로써 오류를 해결할 수 있었다.

+ Recent posts