딸기말차
[Java web] 12. MVC, 외래키, Oracle 함수, 계층형 쿼리 본문
엔코아 플레이데이터(Encore Playdata) Backend 2기 백엔드 개발 부트캠프 (playdata.io)
백엔드 개발 부트캠프
백엔드 기초부터 배포까지! 매력있는 백엔드 개발자 포트폴리오를 완성하여 취업하세요.
playdata.io
1. Web Application Model
웹 어플리케이션 개발은 일반적으로 많이 사용하는 표준화 소스 구조를 만들어 개발을 진행하는데,
이러한 표준화된 소스 구조가 웹 어플리케이션 모델이다.
웹 어플리케이션의 모델 종류에는 모델1과 모델2(MVC)가 있다.
1. 모델 1 방식
DB를 연동해야하는 비즈니스 로직과 로직의 결과를 화면에 뿌려주는 작업을 동일한 파일 내에서 수행한다.
즉, 클라이언트의 요청과 비즈니스 로직 처리 등 모든 과정을 한 JSP가 담당한다.
해당 방식은 분리가 되어있지 않기에 기능 구현이 쉽고 편리하지만, 웹 사이트 화면 기능이 복잡해지면 화면 기능과 비즈니스 로직 기능이 섞이며 유지보수에 문제가 발생한다.
디자이너가 화면을 빈번하게 수정하려면 JSP에 개발자가 관계되는 비즈니스 로직 기능도 알아야하므로, 작업하기 쉽지 않을 뿐더러 비즈니스 로직과 화면 기능이 섞여 코드 재사용성도 비효율적이다.
2. 모델 2 방식
웹 어플리케이션의 각 기능 (클라이언트의 요청 처리, 응답처리, 비즈니스 로직 처리) 를 분리해 구현하자는 것으로,
객체 지향 프로그래밍에서 각각의 기능을 모듈화해서 개발하자는 것과 같은 원리이다.
즉, 웹 프로그램 개발 시 개발자가 전체 기능을 몰라도 각 기능이 모듈화되어 있으므로 자신이 맡은 부분만 개발한 후 각 부분을 조립만 하면 전체 프로그램을 완성할 수 있기 때문에 개발 효율성이 증가한다.
모델 2 방식으로 개발하기 위해서는 필요한 기술이나 개념을 숙지해야하는 번거로움이 있지만, 개발 초급자라면 우선 자신이 맡은 부분만 개발하면 되므로 훨씬 효율적이다.
또한 개발 후 서비스를 제공할 때도 디자이너와 개발자의 작업이 분업화가 되어있고 모듈 또한 분리되어 있기 때문에, 유지보수가 편할 뿐만아니라 개발 완료 한 모듈들을 비슷한 프로그램을 만들 때 사용할 수 있어 코드 재사용성이 높다.
2. MVC 패턴
1. MVC ?
모델2 구조에는 여러 개념들이 사용되는데, 그 중 가장 자주 사용되는 개념이 MVC 이다.
MVC란 Model - View - Controller 의 약자로, 일반 PC 프로그램 개발에 사용되는 디자인 패턴을 웹 어플리케이션에 도입한 것이다.
즉, 웹 어플리케이션을 로직 처리부분(model), 화면 부분(view), 요청 처리부분(controller), 으로 나누어 개발하는 방법이다.
2. MVC 구성요소과 기능
1. Model : DB연동과 같은 비즈니스 로직을 처리한다.
2. View : 모델에서 처리한 결과를 화면에 구현하여 클라이언트로 전송한다.
3. Controller : 사용자로부터 요청을 받아 어떤 비즈니스 로직을 호출 해야할지 제어한다.
여기서 Model을 조금 더 세분화해, service 라는 개념이 들어간다.
service는 클라이언트 입장에서 업무 단위, 즉 트랜잭션(transaction)으로 작업을 수행한다.
여기서 업무 단위란 단위 기능이라고도 하며, 사용자 입장에서 하나의 논리적인 기능을 의미한다.
실제 개발 시 에도 service 클래스의 메서드를 이용해 큰 기능을 단위 기능으로 나눈 후,
service class의 각 메서드 내에서 DAO의 SQL문들을 조합해서 구현한다.
왜냐하면, 유지보수나 시스템의 확장성 면에서 훨씬 유리하기 때문이다.
3. 대표적인 구조
1) Controller
Controller는 요청이 들어올 시 Servlet을 거친 후 가장 먼저 만나는 부분이기 때문에, 클라이언트와 굉장히 밀접한 관계를 가지고 있다.
그런데 이 Controller 내에서 DAO를 호출하여 모든 비즈니스 로직을 수행하면, 사실상 모델 2 방식이아니라 모델 1 방식으로 구현하는 것과 마찬가지가 되어, 계층 구조가 깨지게 된다.
우리가 클라이언트라 생각하면, Controller의 코드를 보고 기능을 요청하고 싶은데 해당 기능이 어딨는지 찾기가 너무 힘들어지는 것이다.
때문에 이를 분리하기 위해, Controller는 어떤 요청이 들어왔는지만 파악해 해당 요청에 맞는 Service만 호출해준다.
복잡한 비즈니스 로직이 아니라 Controller는 어떤 서비스를 요청하면 되는지에 대한 단 한 줄의 코드만 들어가게 되고, 만약 새로운 개발자가 오더라도 Controller 및 Service만 보면 어떤 기능이 존재하는지 확인할 수 있게 된다.
결과적으로, 유지보수성이 증가하게 된다.
2) Service
Controller에서 호출한 요청을 구현하기 위해, DAO에 구현해둔 비즈니스 로직들을 짜깁기 한다.
하나의 로직을 구현하려면 많은 코드가 들어가야하고, 하나의 기능을 구현하려면 여러 로직들을 합쳐서 만들어야한다.
그래서 Service는 DAO에 구현되어있는 각각의 로직들을 호출해 묶어, 하나의 기능을 만들어내는 역할을 해준다.
이를 통해 우리는 Controller와 Service에 있는 메서드만 확인해도 어떤 요청이 들어왔을 때 어떤 기능을 무엇을 실행해 구현했는지 확인할 수 있게 되고, 복잡한 비즈니스 로직을 일일이 확인하지 않아도 프로그램의 구조를 파악할 수 있게된다.
즉, 유지보수성이 증가하게 된다.
3) DAO (Data Access Object)
DB에 직접 접근할 수 있는 객체로, Query를 통하여 실제 클라이언트가 요청한 기능을 수행하기 위해 필요한 여러 비즈니스 로직을 작성하는 객체이다.
4) VO (Value Object)
DB 테이블의 한 레코드와 일치하는 클래스이다. DB와 동체라고 볼 수있는데, 그렇기 때문에 setter는 생성하지 않고 데이터를 생성자로 주입만 해준다.
왜냐하면 setter는 객체 생성 후 데이터를 넣어주는 것이기 때문에, 이 후 데이터가 바뀔 가능성이 존재하기 때문이다.
3. DB 내 데이터 참조 (Foreign Key)
DB 내에서 두개 이상의 테이블을 연결해 사용하고 싶으면, Foreign Key(외래키)를 사용해야한다.
즉, 외래키는 두 테이블을 서로 연결하는 데 사용되는 키이다.
이때 외래키가 포함된 테이블을 자식 테이블이라고 하고, 외래키 값을 제공하는 테이블을 부모 테이블이라한다.
1. 주의사항
1) 자식 테이블이 참조하는 필드의 값
부모 테이블의 해당 칼럼은 중복값이 존재하거나 NULL이면 안되기 때문에 Primary Key 여야한다.
2) CREATE TABLE 시
부모 테이블이 존재하지 않는다는 것은 참조할 곳이 아예 없다는 것이기 때문에, 반드시 부모 테이블이 먼저 만들어져 있어야 한다.
3) INSERT 시
부모 테이블의 참조 되는 값과 자식 테이블이 참조하려는 값이 다르면 안되기 때문에, INSERT 시 반드시 부모 테이블에 존재하는 데이터와 동일하게 insert 해야한다.
4) DELETE 시
부모 테이블의 레코드를 삭제하면, 자식 테이블이 참조하는 값이 없어지기 때문에, DELETE 시 자식 테이블의 레코드를 먼저 삭제해야한다.
5) DROP TABLE 시
마찬가지로 부모 테이블을 먼저 DROP하면 자식 테이블이 참조하는 값이 없어지기 때문에, 자식 테이블을 먼저 DROP 해야한다.
2. 외래키를 사용하는 테이블 선언 예시
create table 테이블명(
articleNo number(10) primary key,
parentNo number(10) default 0,
title varchar2(500) not null,
content varchar2(4000),
imageFileName varchar2(30),
writedate date default sysdate not null,
id varchar2(10),
CONSTRAINT FK_ID FOREIGN KEY(id)
REFERENCES t_member(id)
);
1) CONSTRAINT FK_ID
제약조건을 추가해라 (constraint) FK라는 제약조건을 (FK) ID라는 칼럼에 (ID)
2) FOREIGN KEY(id)
id 칼럼을 외래키로 설정한다.
3) REFERENCES t_member(id)
부모 테이블 t_member의 id를 참조할 것이다.
* 참조 무결성 제약조건
외래키 값은 NULL이거나 부모 테이블의 기본키 값과 동일해야한다.
4. Oracle 함수
오라클의 LPAD, RPAD, LTRIM, RTRIM 함수를 활용하면 문자열의 정렬, 채우기, 삭제와 같은 다양한 작업을 효율적으로 할 수 있다.
이 함수들은 데이터의 가공과 정리에 유용하고, DB에서 문자열 처리를 할 때 유용한 도구로 사용할 수 있다.
1. LPAD (원본 문자열, 전체 길이, 채울 문자)
오른쪽으로 정렬 된 문자열을 왼쪽에 지정한 문자로 채울 수 있는 함수이다.
* 사용 예시 & 결과
SELECT LPAD('123', 5, '0'); -> '00123'
SELECT LPAD('SQL', 8, '*'); -> 결과 : '*****SQL'
2. RPAD (원본문자열, 전체길이, 채울문자)
왼쪽으로 정렬 된 문자열을 오른쪽에 지정한 문자로 채울 수 있는 함수이다.
* 사용 예시 & 결과
SELECT RPAD('ABC', 6, '-') -> 'ABC---'
SELECT RPAD('Python', 10, '_'); -> 'Python____'
3. LTRIM (원본 문자열, 삭제할 문자)
문자열 왼쪽의 지정한 문자를 삭제할 수 있는 함수이다.
* 사용 예시 & 결과
SELECT LTRIM(' Hello'); -> 'Hello' (공백은 별도의 삭제 문자열로 지정하지 않아도 삭제가 된다.)
SELECT LTRIM('00123', '0'); -> '123'
4. RTRIM (원본 문자열, 삭제할 문자)
문자열 오른쪽의 지정한 문자를 삭제할 수 있는 함수이다.
* 사용 예시 & 결과
SELECT RTRIM('Hello '); -> 'Hello'
SELECT RTRIM('123000', '0'); -> '123'
5. 계층형 Query
1. 계층형 쿼리 ?
오라클은 CONNECT BY 절을 사용하여 계층형 데이터를 표현할 수 있다.
즉, CONNECT BY 를 사용하여 데이터의 상하 관계를 연결하고, PRIOR 절의 컬럼(articleNO)과 연결 된 컬럼 (parentNO)의 데이터를 반복적(RECURSIVE)으로 탐색하여 연결 된 데이터를 찾는다.
1) CONNECT BY
계층적으로 탐색하면서 깊이 혹은 계층레벨인 LEVEL을 갖는다.
2) START WITH
위 결과에서 원하는 루트 노트를 지정하여 계층구조를 나타낼 때 사용한다.
3) CONNECT_BY_ISLEAF
단말노드 (하위노드를 갖지않는 노드) 여부를 0, 1로 리턴한다.
4) ORDER SIBLINGS BY
계층구조 쿼리에서 일반적인 ORDER BY를 사용하여 정렬하면 계층구조가 틀어진다.
5) ORDER SIBLINGS BY
계층구조를 유지하며 같은레벨(형제, SIBLING)에 대해 정렬할 수 있다.
6) 최하위(단말노드) 계층 데이터 찾기
위에서 살펴본 것처럼 CONNECT_BY_ISLEAF를 사용하여 최하위 계층 데이터를 찾을 수 있다.
2. 계층형 쿼리 사용 예
SELECT LEVEL, articleNO, parentNO,
LPAD(' ', 4*(LEVEL-1)) || title as title,
content, writeDate, id
FROM t_board
START WITH parentNO=0
CONNECT BY PRIOR articleNO=parentNO
ORDER SIBLINGS BY articleNO DESC;
1) LPAD(' ', 4*(LEVEL-1)) || title as title (LPAD : Left Padding)
답글 제목의 왼쪽을 기준으로 공백 집어넣어준다.
2) START WITH parentNO=0
최상위 루트를 누구로 잡을것인지 설정한다.
3) CONNECT BY PRIOR articleNO=parentNO
articleNO와 parentNO를 사용해 계층을 만들어준다.
4) ORDER SIBLINGS BY articleNO DESC
계층형 구조를 정렬할 땐 기존 ORDER BY로는 안되기 때문에 해당 쿼리를 사용한다.
해당 쿼리의 진행 구조는 다음과 같다.
LEVEL | parentNO | articleNO | |
원 글 | 1 | 0 | 2 |
답글 | 2 | 2 | 3 |
답답글 | 3 | 3 | 5 |
6. 24일차 후기
Spring Framework는 MVC 패턴을 기반으로 만들어진 프레임워크이다. 처음 MVC 패턴을 공부할 땐 굳이 이렇게 나눠야 하나? 한곳에 모아서 개발을 하면 되지않나? 라는 의문을 갖고 있었다.
하지만 우연한 기회로 모델 1 방식으로 개발한 웹 어플리케이션을 접하게 되었고, 어디에 어떤 기능이 있는지 찾기가 너무 힘들다는 것을 알게 되었다. 이 후 MVC 패턴을 적용한 어플리케이션을 보니, 유지보수성이 어마어마하게 차이가 난다는 것을 깨달았다.
게시판의 답글 기능은 일반적으로 많이 사용하는 기능이다. 오늘 수업에 해당 기능을 계층형 쿼리를 사용해 구현했는데, 해당 방식으로 구현하니 자바 내에서 계층을 나눠야하는 로직을 만들 필요가 없어서 편리함을 느꼈다.
또한, 같은 로직을 실행시키더라도 DB에서 실행하는 것이 더 빠르기 때문에 더 효율적이라고 생각했다.
'Bootcamp > Java web' 카테고리의 다른 글
[Java web] 14. Mini_Project_3 (0) | 2023.08.10 |
---|---|
[Java web] 13. MVC 실습 (0) | 2023.08.08 |
[Java web] 11. File Up/Download, JQuery, Ajax, Json (0) | 2023.08.01 |
[Java web] 10. Cookie, Session, Filter, Listener (0) | 2023.07.28 |
[Java web] 9. Servlet Context, Servlet Config (0) | 2023.07.27 |