보다 나은
웹 애플리케이션 설계
    @EBvi
이 문서는 spring과 myBatis를
처음 도입하는 팀을 위해 작성
     되었습니다
spring을 선택해야 하는 이유
왜 spring을 써야 합니까?
결코 쉽지 않은 질문입니다만
차근차근 이유를 알아가보도록
      합시다
우선 별로 spring과 관계없는
   것부터 시작해보죠
우리가 그동안 작성해왔던
     소스코드
입력값 검증
서버단에서 사용자에게
에러를 보여줘야할 의무가
    있습니까?
보여줄 필요가 있는 것만 구현
그렇다면 반드시 필요한
파라메터는 어떻게 검증?
@RequestParam


     spring에서는 이렇게 간단하게 지정
파라메터가 들어오지 않으면
  아예 접근되지 않음
그래도 사용자에게 알려줘야
   하지 않을까요?
jQuery로 간단하게 해결
alt 속성을 가진
input 태그만을 검증
필드가 삭제되거나 늘어나도
 검증부를 수정할 필요가
    전혀 없습니다
기존소스는 필드가 변경되면
  javascript 오류가
     날 수 있었죠
위험요소를 원천적으로 차단하
 는 것이 좋은 설계입니다
이 원칙은 대단히 중요합니다
Expression Language
왜 EL 태그를 써야 할까요?
웹 티어에 비지니스 로직이
절대로 존재해서는 안된다
사실 이정도는
비지니스 로직이 포함되었다고
   보기 어렵습니다만
모 회사 모 프로젝트의 소스
중간중간 로직은 물론
데이터베이스까지 접근하고
 있는 악질코드입니다
이런 소스코드의 디자인을
    수정하라고 하면
그냥 새로 만드는 게 더 쉽습니다
로직 없이
EL만 들어간 깔끔한 코드
로직이 비지니스단에만
존재하게 되면 프리젠테이션의
 변경이 매우 쉬워집니다
어쩔 수 없는 특별한 상황을
제외하고 비지니스 로직은
비지니스단에만 구현합시다
Duplicate code
중복된 코드는 쓸데없는 데다
가 코드를 확장, 유지하기 어렵
   게 만드는 주범입니다
등록폼과 수정폼을 나눠서 만들었었죠
이 소스간의 차이는 그리 크지 않습니다
그렇다면 하나로 합치면 안될
      까요?
jsp에서는 attribute에 담겼는
   지 아닌지만 알면 됩니다
담겨있지 않으면 등록
 담겨있으면 수정
해당 객체가 null일 경우 그냥 출력되지 않습니다
action의 주소도 조건에 따라
     가리키게 만듭시다
단 EL에서는 IF ELSE가 없기 때문에 choose를 사용
           할 수 밖에 없습니다




            사실 FN을 정의해서 만들면 되지만 이건 나중에
아참! 이거 중요합니다


폼의 submit을 제어할 땐 이렇게 구현하세요
이전 소스


그동안은 이미지가 클릭될 때 submit되는
   javascript 함수를 구현했었죠
이렇게 만들면 다양한 문제가
     발생합니다
그중에서도 특히 사용성, 접근
 성이 크게 떨어지게 됩니다
input[type=image]로 구현
서버에서 검증할 거니까 잘못
  등록될 수 없습니다
javascript를 오용하고 있는
   대표적인 사례입니다
Dispatcher Servlet
spring은 기본적으로
모든 서블릿을 가로채 가도록
       설정합니다
web.xml에 설정
이렇게 하면 나머지 동작은
spring이 모두 보증합니다
보증한다는 의미는 더이상 여
러분이 신경쓰지 않아도 된다
    는 의미입니다
UTF-8에서 한글처리는
    filter를 사용
이렇게 설정해도 get으로 보낼
때 한글이 깨지는 경우가 생길
     수 있습니다
그 경우는 server.xml의
charset을 utf-8로 변경하면 됩
           니다
이제 web.xml에
 applicationContext 주소를
잡아주기만 하면 설정이 끝납니다
Application Context
다양한 설정을 하는
xml 형태의 파일입니다만
여기에서 bean을 선언하면
서블릿을 가로챌 때 spring이
  bean을 주입시킵니다
이제 매 서비스마다 new를
  쓸 필요가 없습니다
객체를 생성하고 주입하는 걸
 spring이 모두 보증합니다
왜 new를 선언하지 않는
설계가 좋은 설계일까요?
왜냐하면
new를 선언하는 순간
인스턴스를 생성하게 되고
해당 클래스는
반드시 인스턴스에 해당하는
클래스를 알아야 하게 됩니다
즉, 의존성이 생겨나게 됩니다
의존성이 생겨나는 것은
 왜 문제가 될까요?
그냥 new하면 안되나요?
== 예제 코드 시현 ==
물론 interface도 해당
interface에 대한 의존성이 생
        기는 것입니다
그러나 직접 구현한 클래스를
아는 것과 구상을 가리키는 것
  은 큰 차이가 있습니다
@Controller
먼저 spring에게 컨트롤러
  위치를 알려줍시다
spring은 web.xml에 지정한
   {name}-servlet.xml을
       참조합니다

          springapp으로 지정했으니까
       springapp-servlet.xml을 찾습니다
{name}-servlet.xml
이렇게 알려주면 spring이
  여기서 컨트롤러를
    찾게 됩니다
@Controller
@Controller로 선언된 클래
스의 메서드는 각각의 action
 으로 정의할 수 있습니다
이전의 방식



   각각의 ACTION을 관리하고
    IF ELSE(또는 SWITCH)로
        찾느라 복잡했었죠
이제 action resolver를
구현할 필요가 없습니다
이렇게 구현하면 여러분은
 url만 보고 바로 검색해서
액션을 찾을 수 있게 됩니다
View Resolver
view resolver를 사용하면 컨트
롤러에서 jsp 파일을 리턴할 때
좀 더 편리하게 쓸 수 있습니다
이런식으로 뷰를 알려주죠
우선 물리적인 파일을 사용자
 에게 노출시키지 않기 위해
모든 jsp 파일을 /WEB-INF/jsp
     로 이동시킵시다
WEB-INF에 들어있는 파일은
외부에서 절대 접근할 수 없기
        때문에
이렇게 만드는 것이 훨씬 안전
      합니다
외부에 노출되어서는 안되는
관리자 모드의 jsp 파일을 보여
    줘선 안되겠죠?
그런데 이렇게 만들고 나니
매번 /WEB-INF/jsp/...와 같은
경로를 써줘야 하는 번거로움
     이 생깁니다
{name}-servlet.xml

       이렇게 뷰 리졸버를 정의해서 prefix
        와 postfix를 알려줄 수 있습니다
이렇게 하면 경로를 다시 쓸 필
요없이 /WEB-INF/jsp/의 경로
  를 가리키게 됩니다
RESTful
REST하지 않은 자원들
이러한 주소는 자원으로써
 의미가 전혀 없습니다
개발자 입장에서도 통일성이
 없기 때문에 중구난방으로
 생성되고 관리되게 됩니다
좋다고 해도 REST한 주소를
  만들기란 꽤 어려웠습니다
바보라서 안만든게 아니라 만드느라 복잡성이 더 증가했기 때문이죠
하지만
@RequestMapping을 사용해서
정말 손쉽게 만들어낼 수 있습니다
직관적이고 통일성있는
URL은 모두에게 좋습니다
Value Object Pattern
VO가 DTO와 어떤 차이가 있는 지에 대해
선 조금 논의가 분분합니다. 이 문서엔 Core
j2ee patterns를 따라 VO를 DTO와 동일한
           패턴으로 정의합니다
이전 방식
HashMap에 일일히 담고
검증하고 초기화했었습니다
만약 parameter가 변경된다면
  컨트롤러를 따라가며
 전부 수정해야 할 겁니다
추가-삭제가 빈번하게 일어난다면
HashMap에 담긴 자원이 유효하
다는 걸 어떻게 보증하실 건가요?
HashMap은 편리하지만
 보증할 수가 없습니다
위험한 일은 아예 일어나지 않
도록 원천적으로 차단합시다
private로 된 필드를 만듭시다
자동으로 get-set 메소드를
   만들어 줍시다
이러면 get-set 메서드가 자동으로
        생성됩니다
이렇게 만들면
     spring이 매핑할 때
get-set 메서드를 지나갑니다
get-set 메소드를 만드는 것은
        필수적입니다
만들지 않으면 주입할 수 있는
   방법이 없습니다
만약 좀 더 제약을 걸고 싶으면
   get-set 메서드에서
해당 사항을 구현하면 됩니다
이러면 절대 null이 리턴되지
않고 xss에도 안전해지겠죠?
지금까지 오면서
여러분이 느끼셨는지
 모르겠습니다만
제약을 건다는 건
좀 더 단순해진다는 걸
   의미합니다
반드시
이렇게 만들어질 수 밖에 없다
반드시
이것을 통과할 수 밖에 없다
반드시
유일한 값이 들어가야만 한다
반드시
로직이 존재해서는 안된다
반드시
...
이러한 제약은
문제를 좀 더 단순하게 만드는
 좋은 설계의 원칙이 됩니다
예외가 생기면
문제가 복잡해집니다
우리는 그 예외까지도
단순하게 설계해야 합니다
꼭 기억해주세요
아참, 이와 같은 객체를 POJO
라고 부르고 이와 같은 패턴을
    VO라고 부릅니다
POJO는 특정 기능, 프레임워
크에 종속되지 않은 순수한 객
    체를 말합니다
특정 구현을 상속 받거나 의존
성이 있는 것도 아니고 그냥 아
     무 것도 없죠
Data Access Object Pattern
마찬가지의 개념입니다
persistence단에서
비지니스 로직은 절대 있어서
      안됩니다
오직 데이터베이스와 관련된
행동만 보여주도록 만듭시다
이것을 객체지향 설계에서
단일책임 원칙(single
responsibility principle)이라
         고 합니다
객체가 단 한 개의 책임만을 가
져야 한다는 설계 원칙입니다
이게 전부입니다
우리는 return type과
parameter type만 알면
나머지는 전혀 신경 쓸 필요가
     없습니다
그렇기 때문에 구현된 클래스가
아닌 인터페이스만 봐도 뭘 어떻
게 구현했는지 알 수 있습니다
한 6개월 정도 지나서 모든 기
 억이 가물거리기 시작하면
이것만 봐도 DAO가 어떻게 구
현됐는지 쉽게 떠올릴 수 있죠
그러면 이제 직접 쿼리를 수정
    하러 가 봅시다
applicationContext.xml


            myBatis와 관련된 설정은
           이 지점에서만 확인하면 OK
sqlmap-config.xml




       여긴 각종 별칭(alias)을 정의해
        편리하게 갖다 쓸 수 있음
별칭을 정하지 않으면 매번
package를 다 써줘야 하니 정
 해서 편리하게 이용합시다
*.xml
각각 분리해서 관리하는 것이
     편리합니다
하나의 xml에서 모두 관리하게
되면 코드가 길어지고 검색하
    기도 불편하겠죠
다만 중요한 원칙은 물리적인
데이터베이스 모델링에 맞추는
     것이 아니라
논리적인 데이터베이스 모델링
 에 맞춰 나누는 것입니다
이러한 점은 VO 설계에도 마찬
     가지입니다
VO의 필드를 물리적인 데이터
베이스 필드와 동일하게 맞추
      지 마세요
컴퓨터는 기계지만 여러분은
    사람입니다
컴퓨터가 융통성이 없다면 여
러분이 융통성 있게 코드를 작
    성하면 됩니다
물론 반드시 다르게 만들라는
    말은 아닙니다
어째튼 데이터베이스의 필드명
 과 VO의 필드명이 다르므로
alias를 사용해서 매퍼에게 알
       려줘야 합니다
AS로 각각의 필드에 별칭을
     만들어주세요
alias로 만든 이름과 vo의 이름
이 같으면 myBatis가 set 메서
  드로 넣어서 리턴해줍니다
또한
myBatis는 강력한 기능을 많이
       가지고 있는데
dynamic query를 작성하기에
    도 매우 편리합니다
사실 대부분의 검색 조건은 파라
  메터가 있냐없냐 이거죠
myBatis는 data type을 반드시
   알려줘야 하기 때문에
만약 처음 도입하게 된다면
parameter type과 return
type 때문에 고생할 수도 있습
           니다
매퍼와 관련해서 오류가 나는
것은 data type이 달라서 그렇
         습니다
정리
소스 코드를
중복하여 작성하지 말라
위험요소는
원천적으로 차단하라
로직은 반드시 존재해야 하는
  곳에만 존재해야 한다
한 객체에 하나의 책임을 갖도
     록 설계하라
특정 구현이 아닌 인터페이스
 에 맞춰 프로그래밍하라
후라이드 반 양념 반
Reference from
•   One on one J2EE design and    •   Professional software
    development                       development

•   Kent’s beck implementation    •   Java Development with the
    patterns                          Spring Framework

•   The practice of programming   •   Spring in action

•   The psychology of computer    •   Core J2EE patterns
    programming
고맙습니다

보다 나은 웹 어플리케이션 설계