-- INDEX --
1. 회원가입 작업 | 2. 로그인 작업 | 3. 암호화작업 | 4. 인터페이스 분리 | 5. 결론 |
ss.insert() | ss.selectOne() resultType resultMap |
단방향 암호화 생성자로 관리하기 |
타입 문제 해결 메서드명 문제 해결 |
수정사항 발생 시 수정 부분 최소화와 유지 보수 측면에서 인터페이스로 관리 |
1. 회원가입 작업 시작
1-1 : 서블릿을 통해 화면 보여주기 - doGet()
- 화면에서 회원가입 a링크 클릭하면 – 서버에 요청 보내진다.
- 화면 요청한다 – 서블릿이 doGet 메서드로 처리 - 화면 보여주기
1-2 : 서블릿을 통해 작업 처리하기 - doPost()
- 보여준 화면에서 data 입력해서 회원가입 요청 보낸다
- 서블릿이 doPost메서드로 처리
- 컨트롤러(서블릿)가 할 일 진행 – 데이터 뭉치기 / 서비스 호출 / 화면 선택
1-3 : 서비스 레이어 할 일 하기
- 커넥션 가져오기 ----> SqlSession = SqlTemplate.getSqlSession();
- DAO 호출
- 트랜잭션 처리 ---> ss.commit();
- 커넥션 반납 ----> ss.close()
- 결과 리턴
1-4 : DAO 작업
- 전달받은 SqlSession 이용
- ss.insert( “ namespace . id ”, 전달할 파라미터 )
#1 - config.xml 파일에서 매핑 확인
- 마이바티스 설정 파일 - config.xml파일에서 <mappers> <mapper /> </mappers> 확인
- 연결되어있는지 확인
#2 - namespace에 맞는 매퍼.xml 파일 찾아 가서 id로 쿼리문 확인
- member-mapper.xml파일에서 <mapper namespace =“ ” > <insert id= “ ”> </insert> </mapper>
- namespace로는 마이바티스와 연결된 매퍼.xml파일을 찾고
- id로는 해당 매퍼.xml파일안에 있는 쿼리문을 찾아서 실행한다.
1-5 : 실행 결과를 받아 전달하기
- #4의 실행 결과가 전달 전달되어서 컨트롤러까지 가면 컨트롤러에서 실행결과에 따라 다음 타자 선택
2. 로그인 작업 시작
- # 기본 로직은 회원가입 로직과 동일
2-1 : Controller 작업하기
- 화면 보여주고 ㅡ doGet()
- 로그인 요청 처리하기 ㅡ doPost()
2-2 : Service 작업하기
2-3 : Dao 작업하기
- 셀렉트 쿼리문 - 다른 점 체크
#1 - ss.selectOne()
- ss.insert 가 아닌
- ss.selectOne() 으로 호출한 거 체크 ( if(rs.next() 로 처리된다. ) 1개만 가져온다.
- ss.selectList() 로 호출하면 ( while(rs.next() ) 로 처리된다. ) 모두 가져온다.
#2 - #{ 필드명 }
- 파라미터로, 객체를 전달받으면 - #{ 필드명 } 형식으로
- 쿼리문의 [ ? 부분 ] 채워서 완성해주어야 한다.
- 전달받은 파라미터의 필드명으로 채워준다 #{ 필드 } - getter처럼 작동됨
#3 - resultType = " "
- select 쿼리문의 경우 - resultType 또는 resultMap 지정해주어야한다.
- " " 경로를 패키지부터 다 적어주어야 하지만 설정해놓은 별칭으로도 사용 가능하다.
resultType 체크
- 쿼리문 실행 결과로 나온 resultSet의 칼럼명과
- resultType의 지정한 클래스의 필드명이 같으면
- mybatis가 자동으로 매핑해주어서
- resultSet의 값으로 setter 해준 resultType의 객체를 return 해준다.
- 근데 enroll_date이런애들은?
- 설정.xml 파일에서 <setting> 필요
- 언더바( _ ) 를 카멜케이스로 처리해주는 setting 설정 필요.
#4 - mapUnderscoreToCamelCase
- 스네이크 케이스 ---> 카멜케이스로 인식되도록 세팅해주는 설정 값
- mybatis-config.xml파일 체크
- <settings>
- <setting name=“mapUnderscoreToCamelCase” value=“true” />
- <settings>
- 이 설정해주면 enroll_date --> enrollDate 로 처리되도록 해주었다.
- 그럼 "칼럼명" = "필드명" 되어서 자동 매핑 잘 처리된다.
#5 - <typeAlias type =" " alias = " " >
- 이미 존재하는 타입에 대해서 별칭을 지정하여 쉽게 사용 가능하게 해주는 태그
- mybatis-config.xml파일 에서 설정
- <typeAliases>
- <typeAlias type=“com.kh.mybatis.member.vo.MemberVo” alias=“MemberVo” />
- <typeAliases>
- 이 설정해주면 클래스명 전체 다 쓸 필요 없이 별칭으로 사용 가능
#6 - 실행 결과를 받아 전달하고 처리하기
- #2 실행 결과 = ( 쿼리 실행결과인 - resultSet의 값으로 세팅된 : reulstType에 지정해준 객체 ) 가 전달 전달되어서
- 컨트롤러까지 가면 컨트롤러에서 실행결과에 따라 다음 타자 선택
3. 암호화 작업해보기
3-1 : 단방향 암호화 작업으로 진행
- 암호화 작업해보자
- 양방향 암호화를 사용하면 : 암호화 – 복호화 가능
- 단방향 암호화를 사용하면
- 개발자가 다시 복구할 수 없다. - 복호화 불가능
- 우리는 단방향 암호화 사용
입력받은 pwd를
서비스 레이어에서 어떠한 방식으로 바꿔서
DB에 넣어줄 것이다.
3-2 : 서비스 레이어에서 암호화 작업 진행
- 클라이언트에게 입력받은 암호를
- 내가 만든 암호화 알고리즘을 통해
- 암호화하는 메서드 만들어 놓기
클라이언트에게 입력받은 암호를 -
내가 만든 암호화 알고리즘을 이용하여 암호화하여 -
다시 vo객체의 pwd로 세터 이용하여 변경
3-3 : 로그인 처리는 어떻게 진행해야 하는가?
- 로그인할 때에도 –
- 클라이언트에게 PWD입력받으면 암호화시켜서 pwd 세팅한 후 - 나머지 작업 처리
- 이러면 너무 번거롭다. 방법은?
- VO 게터 세터 만들 때 – 세터 안쪽에 아예 암호화를 진행해서 넣어주면 된다!
4. 인터페이스로 암호화 작업 분리하기
- 인터페이스로 분리하지 않고, 위의 방식처럼 직접 객체를 생성해서 작업하는 경우
- = 내가 만든 암호화 알고리즘을 직접 입력하여 사용하는 경우에 발생할 수 있는 문제점
4-1 : 인터페이스로 분리하지 않으면 생기는 문제점
1. 타입 관련 문제 발생
- 내가 사용하고 있던 암호화 알고리즘이 해커와 같은 외부 요인이나
- 더 좋은 알고리즘의 개발 같은 상황으로 인해 수정이 필요한 경우
- 사용하고 있던 암호화 알고리즘을 다른 것으로 변경할 경우 -
- 알고리즘의 이름이나 타입이 변경된다면
- 해당 알고리즘과 연관된 모든 부분에서 수정 작업이 필요하다.
- 규모가 큰 경우에는 불가능할 수도 있다.
2.메서드명 관련 문제 발생
- 알고리즘명이나 타입이 다행히 같더라도 사용하는 메서드명이 달라졌다면?
- 변경된 암호화 알고리즘에서 사용하는 메서드명이 기존에 사용하던 알고리즘의 메서드명과 다르다면?
- 이 역시 메서드를 사용하고 있던 모든 부분에서 수정이 필요하다. - 규모가 큰 경우에는 불가능할 수도 있다.
.
4-2 : 문제점을 해결하기 위해 인터페이스로 분리하는 작업이 필요하다.
암호화 interface를 사용하는 이유
- 1. 타입 관련 문제 해결 :: 암호화 알고리즘이 바뀌는 상황이 생기면 수정되는 부분을 최소화 하기 위해서
- 2. 메서드명 통일 효과 :: 타입이 달라져도, 메서드명은 동일하게 구현하였으므로, 다른 부분에서 수정 작업 필요 없다.
1. 먼저, 메서드명 문제 해결해보기
- 문제 해결을 위해 암호화 interface를 만들고, 추상 메서드를 하나 선언해놓았다.
- 이제 암호화 알고리즘을 구현하는 모든 애들은
- 방금 만든 암호화 interface를 상속받아 구현하도록 해주었다.
2. 타입 문제 해결 보기
- 생성한 interface를 이용하여 구현하게 함으로써
- 이제 어떤 구현체( 여기선 암호화 알고리즘 객체 )가 오더라도 받아줄 수는 있지만
- 구현체 변경되면 이 부분( 사용되는 구현체 적어주는 부분 )은 아직 직접 변경해주어야 한다.
- 이 부분을 해결해보자
## 1단계 - 객체 생성하는 부분 대신 변수만 만들어 놓는다.
- 그럼 변수에 My가 오던 Second가 오던 괜찮을 거다.
- ( My는 내가 만든 암호화 알고리즘 , Second는 변경할 암호화 알고리즘 )
- ( My,Second모두 암호화 interface 구현해서 만든 애들 )
## 2단계 - 변수가 null이다. 변수 값 채워주기
- MemberService 는 무조건 객체가 만들어지고 수행하는 것이다.
- ( 컨트롤러에서 넘겨줄 때 생각 ) - new MemberService() 해서 객체 만들어서 메서드 호출
- MemberSerive는 보이진 않지만 기본 생성자를 통해 객체가 만들어지고 작업을 수행하는 것이다.
- 이렇게 객체가 생성될 때를 이용해서 해결해보자.
- MemberService 객체가 생성될 때부터 myEnc라는 변수에 값을 채워서 태어나도록 만들어주자
- 어떤 값을 채워서?
- - 암호화 알고리즘을 구현한 애를 - 암호화 interface를 구현한 애를
- 이 상황에서 보면 – MemberService는 태어날 때부터 myEnc라는 변수를 가지고 태어난다.
- 내가 직접 구현체를 만드는 부분 (= 내가 직접 myEnc 변수의 값을 채워주는 부분)을 찾아볼 수 없다.
- myEnc에 들어갈 값(= 암호화interface구현한애)을 - 어디서 만들어서 파라미터로 전달해주고, 그거 사용하는 것이다.
## 3단계 - 서비스 레이어에서만 해결하면 끝?
- 서비스 부분이야 이렇게 하면 변경할게 없어진다 하더라도
- 이렇게 하더라도 컨트롤러에서 멤버서비스 객체를 생성할 때 값을 넣어주어햐는데,
- 그럼 어차피 컨트롤러 부분에서 ‘암호화객체’ 구현해야 하는 거 아니냐??
- 맞다..
조삼모사도 아니고 암호화 알고리즘 객체 수정되면
이제 컨트롤러에서 바뀐 암호화 알고리즘 객체로 수정해서 넣어주는
이런 작업해주어야 된다..
BUT
이 부분을 자동으로 해준다면 ?
컨트롤러와 서비스레이어 모든 곳에서 수정할 것이 없어지는 거겠죠?
스프링 프레임워크가 자동으로 만들어 준다
4. 스프링 프레임워크
- 누군가 컨트롤러를 생성할 때 암호화 객체를 넣어서 만들어준다면?
- 이제 컨트롤러가 생성될 때 가지고 태어나고 – 이거를 서비스에 전달하고 가능
- 이렇게 해놓으면
- 암호화객체가 My인지 – Second인지 상관없이 받아와서 x에 넣어주는 것이다.
- 암호화객체 수정되어도 컨트롤러이든, 서비스이든 -- 수정할 부분 없어졌다.
- 타입 문제 해결되었다!
- 추가적으로 의문점 생긴다
- 그럼 컨트롤러에게 넘겨주는 부분에서 암호화객체 생성하는거아니냐?
- 컨트롤러는 view페이지에서 요청받는 거니까 view 쪽에서 객체 생성하고 수정되면 수정해야 되는 거 아니냐?
- 또 조삼모사 떠넘기기 아니냐
- 아니다!!!!!
- 이 부분! view페이지에서 컨트롤러로 요청을 보내는 부분
- 스프링에서는 이 작업을 자동으로 해준다.
- 컨트롤러가 태어나는데 필요로 하는 객체(암호화 객체)를 자동으로 넣어준다.
- 이 방식으로 컨트롤러가 태어나는데 서비스 객체도 필요하다고 만들어 놓으면 - 자동으로 받아올 수 있다.
서비스 입장에서 억울하다. 나도 직접 Dao객체 만드는 부분 있는데....
나도 태어나려면 DAO객체 필요하다 해놓으면
이것도 스프링이 자동으로 만들어 준다.
5. 결론
이런 이유들로 인해 인터페이스를 사용하여야 한다 !
# 근본 문제는 수정하는 상황이다!
- My객체를 계속 쓰는 게 아니면 Second로 변경된다는 것!
- 하나의 프로그램, 하나의 객체 계속 사용하는 것은 힘들다. 유지보수 필요
# 이렇게 변경되는 경우를 대비하여
- 리턴 타입을 상위 타입으로 ( 추상적인 것으로 ) 받아서 관리를 해야 한다.
- 구현체의 리턴 타입이 바뀐다고 하더라도 받아주는 쪽에서는 리턴 타입을 변경해줄 필요 없다
- (상위 타입으로 받아주고 있으므로)
# 예시 사항
ex ) 구현체의 리턴 타입이AraayList라서 AraayList로 받아주고 있었는데,, 구현체의 리턴 타입이LinkedList로 바뀌면?
받아주는 쪽에서도 변경 작업 필요하다. --
따라서 애초에 처음부터 구현체의 리턴 타입이AraayList였더라도 받아주는 쪽에서
List 로 받아서 관리하고 있었으면, 구현체의 리턴 타입이 링크드 리스트로 바뀌었어도 받아주는 부분 변경해줄 필요 없다..
# 실제 사용 방식
- 이런 방식으로 구현체의 리턴 타입이 MemberDao라고 받아주는 쪽도 MemberDao로 받아주지 말고
- – 보다 상위 타입인 인터페이스를 만들어서 받아주도록 하자
- MemberDaointerface를 상속받아서 구현하게 만들어놓았으면!!!
- 구현체의 리턴 타입이 UserDao()이던 MemberDao()이던 MemberDaointerface 로 다 받아줄 수 있다.
이제 이렇게 만들 것이다 – 인터페이스 하나 만들고 구현체 쭉 만들기
구현체를 추가적으로 만드는 경우는 - 변경 필요하면 만들 것이다.
'Java 기반 클라우드 융합 개발자 과정 - KH 정보교육원 > 9월' 카테고리의 다른 글
22.09.08 - [ Spring ] @Component , @Autowired , injection , IoC 와 DI (0) | 2022.09.15 |
---|---|
22.09.07 - [ Spring ] DispatcherServlet, spring legacy 프로젝트 생성 및 구조 살펴보기 (0) | 2022.09.14 |
22.09.06 - [ Mybatis ] - 게시글 검색, 검색 게시글 페이징처리, 동적sql (1) | 2022.09.08 |
22.09.05 - [ 11차 시험! - 인터페이스 구현 ] (0) | 2022.09.07 |
22.09.02 - [ Mybatis ] 게시글 - { 작성, 전체조회, 페이징처리 } 작업 (0) | 2022.09.07 |