✅ 프로시저를 구현하게 된 계기
일경험 프로그램에서 게시판 기본적인 기능 구현을 마친 뒤 새로운 기능을 하나 추가하는 과제를 진행하게 되었다.
바로 데이터베이스에서 비즈니스 로직을 수행할 수 있는 프로시저 기능을 활용하여 조회수를 카운트하는 기능이었다.
✅ 프로시저가 뭔가?
프로시저
- 프로시저는 PL/SQL 을 통해서 만들어짐.
- 데이터 베이스 내에서 실행 가능한 저장된 프로그램
- 프로시저는 SQL 쿼리와 제어구조를 포함할 수 있으며 데이터 베이스의 복잡한 작업을 수행하는 데 사용됨.
- 프로시저는 코드의 재사용성, 유지 보수성, 성능 향상, 보안 등을 위해 사용됨.
특징
- 저장된 프로그램 : 프로시저는 데이터베이스 내에 저장. 한 번 작성된 후 여러번 호출할 수 있다.
- 파라미터로 입력값을 받을 수 있고, 출력값을 반환받을 수 있다.
- 보안 : 사용자가 직접 쿼리를 작성하지 않고, 미리 정의된 프로시저를 호출함으로써 보안을 강화할 수 있다.
장점
- 재사용성
- 유지보수성 : 복잡한 로직을 프로시저로 분류하여 코드의 유지보수를 용이하게 한다.
- 성능향상 : 데이터베이스 서버에서 실행되므로 네트워크 트래픽을 줄일 수 있다. 컴파일 된 상태로 저장되어 성능이 향상될 수 있음.
- 보안 : 사용자 권한을 통해 접근을 제어할 수 있음.
간단하게 chat gpt 에게 물어봐서 프로시저가 뭔지 감을 잡았다.
비즈니스 로직을 자바 코드로 짜지 않고도 프로시저를 활용해서 직접 데이터베이스의 값을 업데이트하고 생성할 수 있다니!
아주 편리한 기능이라는 것을 알 수 있었다.
그리고 팀장님이나 다른 인턴분들과 대화해본 결과 프로시저는 현업에서 엄청 많이 사용되고 내가 짠 쿼리는 너무 짧은 편에 속하고 현업에서는 프로시저가 엄청 많을 것이라고 해주셨다.
두근두근!!
정보처리기사 공부를 할 때 항상 들었던 기능인데 이번 기회에 직접 작성하고 활용해볼 수 있어 매우 흥미로웠다!
✅ 내가 작성한 조회 수 증가 프로시저 코드
CREATE OR REPLACE PROCEDURE BASIC.MHBOARD_COUNT_PROC
(
P_BOARD_NO IN NUMBER
-- 이부분은 결과값을 sql developer 콘솔로 결과를 확인하기 위해 작성한 부분이었기에 주석 처리
-- P_RESULT OUT VARCHAR
)
IS
P_EXIST_CHK NUMBER(2) := 0;
BEGIN
SELECT COUNT(*) INTO P_EXIST_CHK FROM VIEWS_MHBOARD WHERE BOARD_NO = P_BOARD_NO;
IF P_EXIST_CHK = 0 THEN
INSERT INTO VIEWS_MHBOARD
VALUES (P_BOARD_NO, 0);
-- P_RESULT :='INSERT';
ELSE
UPDATE VIEWS_MHBOARD
SET VIEWS = VIEWS + 1
WHERE BOARD_NO = P_BOARD_NO;
-- P_RESULT :='UPDATE';
END IF;
COMMIT;
P_EXIST_CHK:=1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO DATA BOARD_NO: ' || P_BOARD_NO);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR: ' || SQLERRM);
RAISE;
END MHBOARD_COUNT_PROC;
CREATE OR REPLACE PROCEDURE BASIC.MHBOARD_COUNT_PROC
(
-- 파라미터로 받을 부분 선언 : 게시글의 번호를 파라미터로 받을 예정
-- IN NUMBER는 파라미터의 타입을 지정
-- IN 은 입력 받을 파라미터
P_BOARD_NO IN NUMBER
-- 이부분은 결과값을 sql developer 콘솔로 결과를 확인하기 위해 작성한 부분이었기에 주석 처리
-- OUT 은 결과값을 리턴받을 파라미터
-- P_RESULT OUT VARCHAR
)
IS
-- 활용할 변수를 선언하는 곳
-- 나는 P_EXIST_CHK 라는 변수에 이미 존재하는지 여부를 확인한 결과를 담기 위해 선언, 기본값은 0
P_EXIST_CHK NUMBER(2) := 0;
BEGIN
-- view_mhboard 테이블에서 파라미터로 입력받은 게시글의 번호랑 일치하는 게시글 번호가 있는지 조회
-- 있으면 그 수를 count 라는 집계함수로 개수로 조회
SELECT COUNT(*) INTO P_EXIST_CHK FROM VIEWS_MHBOARD WHERE BOARD_NO = P_BOARD_NO;
-- 입력받은 파라미터인 게시글 번호와 일치하는 게시글 번호가 없을 경우,
-- 즉, 조회수 카운트하는 테이블에 게시글 번호가 존재하지 않을 경우
IF P_EXIST_CHK = 0 THEN
-- 게시글 조회 테이블에 게시글 번호와 조회수를 1로 설정하여 데이터를 insert 한다
INSERT INTO VIEWS_MHBOARD
VALUES (P_BOARD_NO, 1);
-- 만약 해당 insert 쿼리를 수행한 경우, OUT으로 설정했으니 콘솔에 INSERT 라는 글자를 출력
-- P_RESULT :='INSERT';
ELSE
-- 그 반대의 경우 즉, 이미 게시글 조회 테이블에 파라미터로 입력받은 게시글 번호와 동일한 글이 존재할 경우,
-- 기존의 views 값에 +1 을 하기
UPDATE VIEWS_MHBOARD
SET VIEWS = VIEWS + 1
WHERE BOARD_NO = P_BOARD_NO;
-- P_RESULT :='UPDATE';
END IF;
COMMIT;
P_EXIST_CHK:=1;
-- 예외처리 부분
EXCEPTION
-- 데이터가 존재하지 않을 경우 다음과 같은 글자를 콘솔에 출력하기
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO DATA BOARD_NO: ' || P_BOARD_NO);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR: ' || SQLERRM);
RAISE;
END MHBOARD_COUNT_PROC;
다음과 같이 게시글을 조회 기능 프로시저를 생성했다.
그리고 이제는 이 프로시저를 호출해서 조회수가 정상적으로 올라가는지 확인을 해야한다.
Controller
// controller 에서 조회수를 증가 시키는 서비스 로직 호출
mhBoardService.boardViewCnt(Integer.valueOf(boardNo));
Service
// 게시글 조회 수 올리는 메서드
public void boardViewCnt(int boardNo) {
mhBoardMapper.boardViewCnt(boardNo);
}
✅ Mybatis mapper.xml 파일에서 작성한 프로시저 호출 코드
<select id="boardViewCnt" statementType="CALLABLE">
{CALL MHBOARD_COUNT_PROC(#{boardNo})}
</select>
✅ 게시판 메인 페이지에서 조회 수를 카운트 해오는 mapper.xml 파일의 쿼리
<select id="selectAllBoardList">
<![CDATA[
SELECT RN, BOARD_NO, BOARD_UPDATE, BOARD_TITLE, USER_NAME, views
FROM(
SELECT rownum rn, board_no, board_update, board_title, user_name, views
FROM(
SELECT a.board_no ,a.board_update ,a.board_title,b.user_name, c.views
FROM USER_MHBOARD a
LEFT OUTER JOIN user_info b
ON b.user_no = a.user_no
LEFT OUTER JOIN VIEWS_MHBOARD c
ON a.board_no = c.board_no
WHERE a.board_show = 'Y'
order by BOARD_NO DESC
)
)
WHERE rn BETWEEN (#{pageCnt}-1)*10 + 1 and #{pageCnt}*10
]]>
</select>
하지만 여기서 한번 더 생각해야할 부분이 있다.
조회 수를 누를 때 마다 카운트를 하는 것은 임의로 사용자가 계속해서 카운트를 해서 조작할 수 있게 된다.
사실 아직은 작은 개인 프로젝트이긴 하지만
이런 부분도 함께 처리를 해주는 것이 조금 더 정확한 조회수를 얻기에 적합하다고 생각한다.
중복된 조회 수 증가를 막기 위해서 나는 브라우저 쿠키에 해당 사용자가 브라우저에서 해당 게시글을 방문한 적이 있는지 담아주기로 했다.
쿠키에 사용자가 조회한 게시글의 번호를 기록하여 남겨주는 방식인데
여기서 한번 더 고민한 것이 게시글을 클릭할 때마다 하나의 쿠키를 발행하는 것은 쿠키의 낭비라고 생각한다!
따라서 검색을 열심히 해본 결과 하나의 쿠키에 여러 개의 게시글의 번호를 누적해서 저장하고 이를 확인하는 방법을 찾아냈다.
이 글은 다음편에 계속 작성해보아야겠다!
'👩💻 BackEnd > 📊데이터베이스 [Database]' 카테고리의 다른 글
트랜잭션 격리 수준(Isolation Levels) (0) | 2025.02.03 |
---|---|
[ SQL / DB ] ERD Cloud 작성하기 : 식별 관계와 비식별 관계, 관계차수 (0) | 2024.03.19 |
[ SQL / DB ] 쿼리 저장소 (1) | 2024.03.18 |
[SQLD] 데이터 모델링의 이해 (0) | 2023.10.17 |
[SQL] MySQL 쿼리문 연습 (0) | 2023.10.13 |