먹고 사는 이야기/프로그래밍

[toby의스프링] 8장/9장 - 스프링이란 무엇인가? / 스프링 프로젝트 시작하기

Kunner 2011. 11. 3. 01:30

이 책은 1장 부터 8장까지를 1부로, 나머지 9장부터 16장까지를 2부로 하고 있다.
1부에서 자바와 스프링 프레임워크에 대한 이론적인 접근을 하고 있다면, 2부에서는 이를 실전에서 어떻게 활용하는가를 다루고 있다.
그러므로 8장과 9장을 한번에 정리한다는 것은 일견 잘못된 것이 아닌가 생각할 수 있다.
하지만 1부 마지막 장에서 스프링 프레임워크에 대해 정리하고, 이 정리된 내용을 2부 첫 장에서 다시 다루고 있기 때문에 이 두 장을 한번에 정리하는 게 좋을 것이다. 


8장. 스프링이란 무엇인가?

'스프링이란 무엇인가?' 라는 화두를 놓고 책에서 수십쪽에 걸쳐 다루었는데, 이를 다시 몇개의 문장으로 정리한다는 것은 쉬운 일이 아니다.
하지만 누군가, 스프링이 뭐냐고 물었을 때 『toby의 스프링』8장(649p)을 참조하라고 대답해 줄 수는 없지 않은가?
그래서 대충이라도 정리를 해 놓자면..

책에서 언급한대로 스프링이란 자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크 이다.

물론 이 문장을 듣고 바로 이해하는 사람이라면 스프링이 뭐냐고 물을 일도 없었을 것이다.
실제로 저 말을 제대로 알아 들으려면 아주 긴 학습의 시간이 필요할 것이다.
또한 나를 비롯해 스프링을 이용해 개발하는 많은 개발자들 또한 스프링의 개념을 완벽히 숙지하고 있지는 못 할 것이다.(안타깝게도)

어떻든.. 정리를 위한 정리라도 해 보자면.

스프링이 도입되기 전 기존 자바 개발 환경은 매우 복잡하고 어려웠다. 실무에서는 비즈니스 로직 처리하기도 어렵지만, 이 비즈니스 로직을 트랜잭션이나 동기화, XML 인터페이스 등 다양한 외부 기술과 접목하고 시스템의 각 장치와 연결하는 등의 타겟 애플리케이션 外적인 부분의 처리까지 개발, 관리해야 했기 때문이다. 이에 대항하기 위해 EJB 가 도입되었지만, 이는 EJB의 통합 환경에만 국한되어 사용할 수 있어 폐쇄성의 문제 때문에 근본적인 해결이 될 수 없었다. 


지나치게 장황한 설명이지만, 실무를 해 본 사람이라면 충분히 이해할 수 있는 이야기일 것이다.
하다 못해 아주 간단한 개발에서라도 DB 연결, 트랜잭션, 레코드셋의 연결과 이를 다시 개체에 담고 비즈니스 로직에 따라 사용자에게 전달하기까지 얼마나 많은 것들을 신경써야 했는가?

무엇보다 개발은 어찌어찌 됐다 쳐도 나중에 유지보수 할 때의 고달픔은 겪어보지 않은 사람은 상상도 할 수 없다.
말이 유지보수지 실은 재개발이었던 것이다.
그 때문에 얼마나 많은 밤들을 새웠던가, 망할...[각주:1]


이를 해결하기 위해 고안된 것이 스프링이다.

스프링의 핵심 기술은 IoC/DI, AOP, 서비스 추상화를 통해 POJO(Plain Old Java Object)를 구현하는 것이다. 
이는 앞장에서 누누히 말했던 내용들로, 결합도는 낮추고 응집도는 높인다는 자바 개발의 기본 원리에 충실하게 설계된 자바 오브젝트를 가지고 개발하는 것이다.

이렇게 스프링을 활용하면 개발자가 업무 외 다른 기술이나 기능들에 대해 신경쓰지 않고 오로지 개발에만 집중할 수 있다.



9장. 스프링 프로젝트 시작하기

본격적으로 스프링 프로젝트를 시작하기 앞서, 개발 도구에 대한 안내 및 1부에서 얘기한 주요 원리들을 어떻게 설계에 반영시켜야 하는가에 대해 이야기하고 있다.

개발도구와 개발환경에 대한 이야기는 딱히 정리할 필요가 없을 것 같아 skip 하기로 한다.

다음으로 스프링 프레임워크를 이용해 개발할 때 설계 시 고려할 점에 대해 많은 이야기들을 하고 있다.
이를 간략하게 정리하면 이런 것이다.

Application을 개발할 때는 Application이 다루는 정보를 관점으로 데이터 중심 설계와 오브젝트 중심 설계로 나눌 수 있다. 스프링 프레임워크를 이용해 개발 할 때는 데이터 중심 설계가 아닌 오브젝트 중심 설계를 이용해야 한다.


다시 말하면..

모든 Application은 결국 DB의 정보나 기타 특정 정보를 가공하여(또는 그대로), 비즈니스 로직에 따라 사용자에게 전달하는 것을 목표로 하고 있다.

그런데 스프링을 이용하지 않던 기존의 개발에서는 데이터를 중심으로 설계를 한다.
보통 DB를 사용한다면 메소드에서 SQL 질의를 통해 얻어 낸 정보를 List나 기타 오브젝트에 담는데 비즈니스 로직에 따라 그때 그때 다른 SQL 질의를 날리거나, 아니면 정보를 잔뜩 가져와서 오브젝트에 담은 다음 그걸 가지고 재처리를 한다거나 하는 방식이다. 

전자의 경우에는 DB에 너무 종속된 개발을 하게 될 우려가 있어 사후 변경이나 유지보수가 어려워지는 단점이 있다. 또 프로그램 규모가 커지면 커질 수록 SQL 질의의 수는 폭발적으로 증가하는 특성 상 프로그램 자체가 몹시 복잡해지기도 한다.
또 후자의 경우에는 자칫 리소스를 낭비하게 될 우려가 크다. 애플리케이션의 각 기능들에서 다루는 정보들은 모두 같지 않기 때문이다.

이를테면 게시판을 만든다고 할 때 목록을 표시할 때의 정보와 내용보기를 할 때의 정보는 서로 다를 수 밖에 없는데 이를 매번 각각의 오브젝트로 만들어 낸다면 전자의 경우일 것이고, 몽땅 한 오브젝트에 담아 목록 표시할 때도 쓰고, 내용보기 할 때도 쓴다면 리소스의 낭비를 부르는 후자의 경우가 될 것이다. 수만건의 게시물이 있는 게시판의 목록을 표시할 때 이런 방식을 사용한다고 생각해 보자. 그야말로 끔찍한 일이 될 것이다.[각주:2]

이에 대한 대안으로 지연된 로딩 기법(lazy loading)[각주:3]을 이용한 오브젝트 중심 설계를 들 수 있다. 하이버네이트와 같은 ORM 기술을 이용하면 쉽다. 



이렇게 오브젝트 중심 설계는 다시 오브젝트의 활용 방법을 기준으로 빈약한(anemic) 도메인 오브젝트 방식과 풍성한(rich) 도메인 오브젝트 방식이 있는데 이에 대해서는 그림을 참조하기로 한다.

그림 9-20. 빈약한 도메인 오브젝트 방식 (본문 p744)



그림 9-21. 풍성한 도메인 오브젝트 방식. 



풍성한 도메인 오브젝트 방식을 쉽게 설명하면, DB에서 조회한 정보를 그대로 오브젝트에 담는 것이 아니라, 서비스 상 필요한 다양한 파생 정보들을 미리 도메인 오브젝트에 할당해 놓는 것을 말한다. 이를테면 어떤 쿼리의 결과에 대한 목록 수를 집계할 때, 별도로 count(*) 질의를 날리거나 불러 온 목록의 length를 집계하거나 하는 방법을 사용한다. 이를 코드화하면 비즈니스 로직에서 많은 별도의 처리가 필요해질 것이다.[각주:4] 하지만 이를 도메인 오브젝트로 처리한 후 서비스 계층에서 .getCount() 와 같이 오브젝트의 속성값을 불러 오는 정도로 쓸 수 있다면 코드가 간결해지고 소스 관리가 간편해질 것이다.

하지만 풍성한 도메인 오브젝트 방식의 경우 설계 전에 이런 것들이 모두 고려되고, 각 개발자가 이렇게 사전에 정의된 오브젝트를 숙지하지 않는다면 각 모듈에서 계속 새로운 메소드나 오브젝트를 생성하게 되어 소스의 복잡도만 가중시키는 결과를 초래할 수도 있다. 이래서는 풍성한 도메인 오브젝트를 사용하는 것이 프로젝트의 발목을 잡는 이유가 될 수도 있다.


이런 한계들을 극복하기 위한 대안으로, 도메인을 계층으로 끌어 올리는 방안이 있다.

스프링은 도메인 오브젝트를 빈으로 관리하지 않으므로 AOP를 이용해 DI를 적용하고, 이렇게 생성된 도메인 오브젝트에 도메인과 관련된 제처리를 하게 한다. 도메인 오브젝트를 DI받을 수 있으므로 3계층과 도메인 계층은 서로 원활하게 소통할 수 있게 된다. 따라서 도메인 계층이 서비스 계층의 일부 처리를 떠안기도 하고, 서비스 계층과 협력하여 보다 복잡한 처리를 할 수도 있다. 개발자는 자바의 오브젝트를 불러들이는 것만으로 DB의 정보를 조작할 수 있게 된다.

이런 경우 자바 오브젝트에서 그저 Object.addObject(ObjectData); Object.deleteObject(ObjectKey); 하는 것만으로 DB 정보의 저장이나 변경, 삭제도 가능해진다. (권한이 있는 경우) 그런데 각 개발자가 모두 이런 접근권한을 가지게 된다면, 또 모든 소스에서 공통적으로 DB에 같은 권한으로 접속을 하게 된다면 이는 보안 상 심각한 위협이 될 수도 있다. 물론 개발자가 보안 관련 규칙을 준수한다면 문제가 없겠지만, 모두가 규정을 준수할 것이라고 믿는 것은 지나치게 낙관적인 일이다.

따라서 AspectJ 를 이용해 특정 계층의 오브젝트가 사용할 수 있는 메소드의 범위를 지정해 주거나, 도메인 오브젝트가 도메인 계층을 벗어나지 못하도록 제한하는 방법이 있다. 도메인 오브젝트를 제한할 때는 읽기 전용의 DTO(Domain Transfer Object) - 정보 전달용 도메인 오브젝트를 생성해 이 오브젝트가 도메인 오브젝트를 대신해 정보를 전달하도록 한다. 실제 DB 정보를 안전하게 보호하기 위함이다.


이런 기술들이 실제 개발에서 어떻게 활용되는지는 11장 이후에서 다뤄질 것이다.






매번 학습 내용을 정리할 때 마다 느끼는거지만...
프로그램을 말로 표현하는 것, 그것도 짧게 정리한다는 건 참 어려운 일이다.
다섯살 아이도 이해할 수 있도록 할 수 없다면 그건 확실히 아는게 아니라고 했던가?
하지만 그렇다면 그건 이 책의 저자도 마찬가지일 것이라는.. 궁색한 변명을 해 본다. -ㅅ-;










  1. 물론 스프링이 이 모든 것들을 확 해결해 줄 리는 없다. 그 정도를 기대하는 것은 아니다. 다만 조금 더 편리해 지기를바라는 것이지. 더구나 실제 현업에서 개발할 때는 스프링을 그냥 공식처럼, 일종의 패턴에 따라 기계적으로 적용하기도 한다. 실제로 나는 왜 그렇게 하는지도 모르고 그냥 Ctrl + C, Ctrl + V로 사이트 하나를 구축해 내는 사람을 보기도 했다. 아무리 좋은 연장이라도 그걸 쓰는 사람에 따라 보도(寶刀)가 되기도 하고 부엌의 식칼이 되기도 하는 법 - 대개의 경우 문제는 기술이 아니라 사람에게 있지 않을까? [본문으로]
  2. 한 10년도 더 된 옛날, 실제로 이렇게 프로그램을 짜던 사람들이 있었다. 목록을 불러 올 때 select * from ~ 해 버리는 용자들이.. -ㅅ-; [본문으로]
  3. 지연된 로딩 기법이란 일단 최소한의 정보를 가져온 후 필요에 따라 추가 정보를 다시 가져오는 방법을 말한다. [본문으로]
  4. 도메인 오브젝트는 스프링에서 관리하는 빈이 아니므로 3계층의 오브젝트를 사용할 수 없기 때문에 데이터 액세스 계층이나 서비스 계층과 정보를 주고 받기 위해서는 비즈니스 로직에서 직접 DAO를 건드려야 하는 부담이 따른다. [본문으로]