192
보다 나은 애플리케이션 설계 @EBvi

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

Embed Size (px)

Citation preview

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

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

@EBvi

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

이 문서는 spring과 myBatis를 처음 도입하는 팀을 위해 작성

되었습니다

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

spring을 선택해야 하는 이유

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

왜 spring을 써야 합니까?

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

결코 쉽지 않은 질문입니다만

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

차근차근 이유를 알아가보도록 합시다

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

우선 별로 spring과 관계없는 것부터 시작해보죠

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

우리가 그동안 작성해왔던소스코드

Page 9: 보다 나은 웹 어플리케이션 설계
Page 10: 보다 나은 웹 어플리케이션 설계

입력값 검증

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

서버단에서 사용자에게에러를 보여줘야할 의무가

있습니까?

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

보여줄 필요가 있는 것만 구현

Page 13: 보다 나은 웹 어플리케이션 설계
Page 14: 보다 나은 웹 어플리케이션 설계

그렇다면 반드시 필요한파라메터는 어떻게 검증?

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

@RequestParam

spring에서는 이렇게 간단하게 지정

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

파라메터가 들어오지 않으면아예 접근되지 않음

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

그래도 사용자에게 알려줘야 하지 않을까요?

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

jQuery로 간단하게 해결

Page 19: 보다 나은 웹 어플리케이션 설계
Page 20: 보다 나은 웹 어플리케이션 설계

alt 속성을 가진input 태그만을 검증

Page 21: 보다 나은 웹 어플리케이션 설계
Page 22: 보다 나은 웹 어플리케이션 설계

필드가 삭제되거나 늘어나도 검증부를 수정할 필요가전혀 없습니다

Page 23: 보다 나은 웹 어플리케이션 설계
Page 24: 보다 나은 웹 어플리케이션 설계

기존소스는 필드가 변경되면javascript 오류가날 수 있었죠

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

위험요소를 원천적으로 차단하는 것이 좋은 설계입니다

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

이 원칙은 대단히 중요합니다

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

Expression Language

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

왜 EL 태그를 써야 할까요?

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

웹 티어에 비지니스 로직이절대로 존재해서는 안된다

Page 30: 보다 나은 웹 어플리케이션 설계
Page 31: 보다 나은 웹 어플리케이션 설계

사실 이정도는비지니스 로직이 포함되었다고

보기 어렵습니다만

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

모 회사 모 프로젝트의 소스

Page 33: 보다 나은 웹 어플리케이션 설계
Page 34: 보다 나은 웹 어플리케이션 설계

중간중간 로직은 물론 데이터베이스까지 접근하고 있는 악질코드입니다

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

이런 소스코드의 디자인을수정하라고 하면

그냥 새로 만드는 게 더 쉽습니다

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

로직 없이EL만 들어간 깔끔한 코드

Page 37: 보다 나은 웹 어플리케이션 설계
Page 38: 보다 나은 웹 어플리케이션 설계

로직이 비지니스단에만존재하게 되면 프리젠테이션의 변경이 매우 쉬워집니다

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

어쩔 수 없는 특별한 상황을제외하고 비지니스 로직은비지니스단에만 구현합시다

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

Duplicate code

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

중복된 코드는 쓸데없는 데다가 코드를 확장, 유지하기 어렵게 만드는 주범입니다

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

등록폼과 수정폼을 나눠서 만들었었죠이 소스간의 차이는 그리 크지 않습니다

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

그렇다면 하나로 합치면 안될까요?

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

jsp에서는 attribute에 담겼는지 아닌지만 알면 됩니다

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

담겨있지 않으면 등록담겨있으면 수정

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

해당 객체가 null일 경우 그냥 출력되지 않습니다

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

action의 주소도 조건에 따라 가리키게 만듭시다

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

단 EL에서는 IF ELSE가 없기 때문에 choose를 사용할 수 밖에 없습니다

사실 FN을 정의해서 만들면 되지만 이건 나중에

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

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

아참! 이거 중요합니다

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

그동안은 이미지가 클릭될 때 submit되는 javascript 함수를 구현했었죠

이전 소스

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

이렇게 만들면 다양한 문제가 발생합니다

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

그중에서도 특히 사용성, 접근성이 크게 떨어지게 됩니다

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

input[type=image]로 구현

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

서버에서 검증할 거니까 잘못 등록될 수 없습니다

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

javascript를 오용하고 있는대표적인 사례입니다

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

Dispatcher Servlet

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

spring은 기본적으로모든 서블릿을 가로채 가도록

설정합니다

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

web.xml에 설정

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

이렇게 하면 나머지 동작은spring이 모두 보증합니다

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

보증한다는 의미는 더이상 여러분이 신경쓰지 않아도 된다

는 의미입니다

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

UTF-8에서 한글처리는filter를 사용

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

이렇게 설정해도 get으로 보낼 때 한글이 깨지는 경우가 생길

수 있습니다

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

그 경우는 server.xml의 charset을 utf-8로 변경하면 됩

니다

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

이제 web.xml에applicationContext 주소를

잡아주기만 하면 설정이 끝납니다

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

Application Context

Page 66: 보다 나은 웹 어플리케이션 설계
Page 67: 보다 나은 웹 어플리케이션 설계

다양한 설정을 하는xml 형태의 파일입니다만

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

여기에서 bean을 선언하면서블릿을 가로챌 때 spring이

bean을 주입시킵니다

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

이제 매 서비스마다 new를쓸 필요가 없습니다

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

객체를 생성하고 주입하는 걸spring이 모두 보증합니다

Page 71: 보다 나은 웹 어플리케이션 설계
Page 72: 보다 나은 웹 어플리케이션 설계

왜 new를 선언하지 않는설계가 좋은 설계일까요?

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

왜냐하면

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

new를 선언하는 순간

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

인스턴스를 생성하게 되고

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

해당 클래스는

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

반드시 인스턴스에 해당하는 클래스를 알아야 하게 됩니다

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

즉, 의존성이 생겨나게 됩니다

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

의존성이 생겨나는 것은왜 문제가 될까요?

그냥 new하면 안되나요?

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

== 예제 코드 시현 ==

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

물론 interface도 해당 interface에 대한 의존성이 생

기는 것입니다

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

그러나 직접 구현한 클래스를 아는 것과 구상을 가리키는 것은 큰 차이가 있습니다

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

@Controller

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

먼저 spring에게 컨트롤러위치를 알려줍시다

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

spring은 web.xml에 지정한{name}-servlet.xml을

참조합니다

springapp으로 지정했으니까springapp-servlet.xml을 찾습니다

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

{name}-servlet.xml

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

이렇게 알려주면 spring이여기서 컨트롤러를찾게 됩니다

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

@Controller

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

@Controller로 선언된 클래스의 메서드는 각각의 action으로 정의할 수 있습니다

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

이전의 방식

각각의 ACTION을 관리하고IF ELSE(또는 SWITCH)로찾느라 복잡했었죠

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

이제 action resolver를구현할 필요가 없습니다

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

이렇게 구현하면 여러분은url만 보고 바로 검색해서액션을 찾을 수 있게 됩니다

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

View Resolver

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

view resolver를 사용하면 컨트롤러에서 jsp 파일을 리턴할 때 좀 더 편리하게 쓸 수 있습니다

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

이런식으로 뷰를 알려주죠

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

우선 물리적인 파일을 사용자에게 노출시키지 않기 위해

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

모든 jsp 파일을 /WEB-INF/jsp로 이동시킵시다

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

WEB-INF에 들어있는 파일은 외부에서 절대 접근할 수 없기

때문에

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

이렇게 만드는 것이 훨씬 안전합니다

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

외부에 노출되어서는 안되는 관리자 모드의 jsp 파일을 보여

줘선 안되겠죠?

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

그런데 이렇게 만들고 나니

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

매번 /WEB-INF/jsp/...와 같은 경로를 써줘야 하는 번거로움

이 생깁니다

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

{name}-servlet.xml

이렇게 뷰 리졸버를 정의해서 prefix와 postfix를 알려줄 수 있습니다

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

이렇게 하면 경로를 다시 쓸 필요없이 /WEB-INF/jsp/의 경로

를 가리키게 됩니다

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

RESTful

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

REST하지 않은 자원들

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

이러한 주소는 자원으로써의미가 전혀 없습니다

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

개발자 입장에서도 통일성이없기 때문에 중구난방으로생성되고 관리되게 됩니다

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

좋다고 해도 REST한 주소를만들기란 꽤 어려웠습니다

바보라서 안만든게 아니라 만드느라 복잡성이 더 증가했기 때문이죠

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

하지만

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

@RequestMapping을 사용해서정말 손쉽게 만들어낼 수 있습니다

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

직관적이고 통일성있는URL은 모두에게 좋습니다

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

Value Object Pattern

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

VO가 DTO와 어떤 차이가 있는 지에 대해선 조금 논의가 분분합니다. 이 문서엔 Core j2ee patterns를 따라 VO를 DTO와 동일한

패턴으로 정의합니다

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

이전 방식

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

HashMap에 일일히 담고검증하고 초기화했었습니다

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

만약 parameter가 변경된다면컨트롤러를 따라가며전부 수정해야 할 겁니다

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

추가-삭제가 빈번하게 일어난다면 HashMap에 담긴 자원이 유효하다는 걸 어떻게 보증하실 건가요?

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

HashMap은 편리하지만보증할 수가 없습니다

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

위험한 일은 아예 일어나지 않도록 원천적으로 차단합시다

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

private로 된 필드를 만듭시다

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

자동으로 get-set 메소드를만들어 줍시다

Page 123: 보다 나은 웹 어플리케이션 설계
Page 124: 보다 나은 웹 어플리케이션 설계

이러면 get-set 메서드가 자동으로 생성됩니다

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

이렇게 만들면spring이 매핑할 때

get-set 메서드를 지나갑니다

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

get-set 메소드를 만드는 것은 필수적입니다

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

만들지 않으면 주입할 수 있는 방법이 없습니다

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

만약 좀 더 제약을 걸고 싶으면get-set 메서드에서

해당 사항을 구현하면 됩니다

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

이러면 절대 null이 리턴되지 않고 xss에도 안전해지겠죠?

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

지금까지 오면서여러분이 느끼셨는지모르겠습니다만

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

제약을 건다는 건좀 더 단순해진다는 걸

의미합니다

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

반드시이렇게 만들어질 수 밖에 없다

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

반드시이것을 통과할 수 밖에 없다

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

반드시유일한 값이 들어가야만 한다

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

반드시로직이 존재해서는 안된다

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

반드시

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

...

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

이러한 제약은문제를 좀 더 단순하게 만드는좋은 설계의 원칙이 됩니다

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

예외가 생기면 문제가 복잡해집니다

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

우리는 그 예외까지도단순하게 설계해야 합니다

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

꼭 기억해주세요

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

아참, 이와 같은 객체를 POJO라고 부르고 이와 같은 패턴을

VO라고 부릅니다

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

POJO는 특정 기능, 프레임워크에 종속되지 않은 순수한 객

체를 말합니다

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

특정 구현을 상속 받거나 의존성이 있는 것도 아니고 그냥 아

무 것도 없죠

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

Data Access Object Pattern

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

마찬가지의 개념입니다

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

persistence단에서비지니스 로직은 절대 있어서

안됩니다

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

오직 데이터베이스와 관련된 행동만 보여주도록 만듭시다

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

이것을 객체지향 설계에서

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

단일책임 원칙(single responsibility principle)이라

고 합니다

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

객체가 단 한 개의 책임만을 가져야 한다는 설계 원칙입니다

Page 152: 보다 나은 웹 어플리케이션 설계
Page 153: 보다 나은 웹 어플리케이션 설계

이게 전부입니다

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

우리는 return type과 parameter type만 알면

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

나머지는 전혀 신경 쓸 필요가 없습니다

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

그렇기 때문에 구현된 클래스가 아닌 인터페이스만 봐도 뭘 어떻게 구현했는지 알 수 있습니다

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

한 6개월 정도 지나서 모든 기억이 가물거리기 시작하면

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

이것만 봐도 DAO가 어떻게 구현됐는지 쉽게 떠올릴 수 있죠

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

그러면 이제 직접 쿼리를 수정하러 가 봅시다

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

applicationContext.xml

myBatis와 관련된 설정은이 지점에서만 확인하면 OK

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

sqlmap-config.xml

여긴 각종 별칭(alias)을 정의해편리하게 갖다 쓸 수 있음

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

별칭을 정하지 않으면 매번 package를 다 써줘야 하니 정해서 편리하게 이용합시다

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

*.xml

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

각각 분리해서 관리하는 것이 편리합니다

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

하나의 xml에서 모두 관리하게 되면 코드가 길어지고 검색하

기도 불편하겠죠

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

다만 중요한 원칙은 물리적인 데이터베이스 모델링에 맞추는

것이 아니라

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

논리적인 데이터베이스 모델링에 맞춰 나누는 것입니다

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

이러한 점은 VO 설계에도 마찬가지입니다

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

VO의 필드를 물리적인 데이터베이스 필드와 동일하게 맞추

지 마세요

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

컴퓨터는 기계지만 여러분은 사람입니다

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

컴퓨터가 융통성이 없다면 여러분이 융통성 있게 코드를 작

성하면 됩니다

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

물론 반드시 다르게 만들라는 말은 아닙니다

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

어째튼 데이터베이스의 필드명과 VO의 필드명이 다르므로

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

alias를 사용해서 매퍼에게 알려줘야 합니다

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

AS로 각각의 필드에 별칭을 만들어주세요

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

alias로 만든 이름과 vo의 이름이 같으면 myBatis가 set 메서드로 넣어서 리턴해줍니다

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

또한myBatis는 강력한 기능을 많이

가지고 있는데

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

dynamic query를 작성하기에도 매우 편리합니다

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

사실 대부분의 검색 조건은 파라메터가 있냐없냐 이거죠

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

myBatis는 data type을 반드시 알려줘야 하기 때문에

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

만약 처음 도입하게 된다면

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

parameter type과 return type 때문에 고생할 수도 있습

니다

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

매퍼와 관련해서 오류가 나는 것은 data type이 달라서 그렇

습니다

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

정리

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

소스 코드를중복하여 작성하지 말라

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

위험요소는원천적으로 차단하라

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

로직은 반드시 존재해야 하는 곳에만 존재해야 한다

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

한 객체에 하나의 책임을 갖도록 설계하라

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

특정 구현이 아닌 인터페이스에 맞춰 프로그래밍하라

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

후라이드 반 양념 반

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

Reference from• One on one J2EE design and

development

• Kent’s beck implementation patterns

• The practice of programming

• The psychology of computer programming

• Professional software development

• Java Development with the Spring Framework

• Spring in action

• Core J2EE patterns

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

고맙습니다