Java 기반 클라우드 융합 개발자 과정 - KH 정보교육원/9월

22.09.01 - [ Mybatis ] 회원가입, 로그인, 암호화 작업해보기

giggs 2022. 9. 7. 10:18

 

 

-- 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 로 다 받아줄 수 있다.

 

 

 

이제 이렇게 만들 것이다 인터페이스 하나 만들고 구현체 쭉 만들기

구현체를 추가적으로 만드는 경우는 - 변경 필요하면 만들 것이다.