@Controller

컨트롤러 클래스에 @Controller 어노테이션을 쓴다.

해당 어노테이션이 적용된 클래스는 "Controller"임을 나타내고, bean으로 등록되어 해당 클래스가 Controller로 사용됨을 Spring Framework에 알린다.

 

@RequestMapping

요청 URL을 어떤 method가 처리할 지 mapping 해주는 어노테이션.

Controller나 Controller의 method에 적용한다.

요청 받는 형식을 정의하지 않으면, 자동으로 GET으로 설정.

ex) "/school" 요청에 대해 공통적으로 처리해야 될 클래스를 의미.

또한, 요청 url에 대해 해당 메소드에서 처리해야 되는 경우에도 사용.

@RequestMapping에 대한 모든 매핑 정보는 Spring에서 제공하는 HandlerMapping Class가 가지고 있다.

@Controller
@RequestMapping(path="/school")
public class SchoolApiController {
	@Autowired
	private schoolService schoolService;
	
	@GetMapping
	public String getSchoolInfo(@RequestParam int schoolId, ModelMap model) {
		School shcoolInfo = schoolService.getSchoolInfoBySchoolId(schoolId);
		model.addAttribute("schoolInfo", schoolInfo);
		return "list";
	}

}

@Controller 어노테이션을 통해 해당 클래스가 컨트롤러 클래스임을 spring framework에 전달하고, "/school" 로 들어오는 공통 요청 url 중 get 방식으로 들어오는 url을 처리하는 메소드인 예제.

 

@RestController

@Controller + @ResponseBody 이며, 메소드의 return 값을 문자열(JSON) 형태로 반환.

Spring의 Controller 중 View로 응답하지 않는 Controller.

API만 지원하는 클래스에 사용되며, json이나 xml과 같은 문자열 return이 주 목적.

 

@ResponseBody

메소드에 @ResponseBody 어노테이션이 있다면 리턴값이 View를 통해 출력되지 않고, HTTP Response Body에 직접 쓰여지게 된다.

이 때, 쓰여지기 전에 리턴되는 데이터 타입에 따라 MessageConverter에서 변환이 이뤄진 후 쓰여진다.

@RestController
@RequestMapping(path="/school")
public class SchoolApiController {
	@Autowired
	private SchoolService schoolService;
	
	@PostMapping
	public School saveSchoolInfo(@RequestBody School param) {
		School saveInfo = schoolService.setSchoolInfo(param);
		return saveInfo;
	}
}

@Controller 어노테이션이 아닌, @RestController 어노테이션이므로 return을 view 페이지 대신 saveInfo 라는 객체를 JSON 형태로 변환한 데이터를 return한다.

 

@Controller vs @RestController

@Controller @RestController
API 사용과 View return을 동시에 하는 경우에 사용.
API 서비스로 사용하는 경우는 @ResponseBody를 사용하여 객체 반환
view가 필요없는 API 만 지원시 사용.
@RestController = @Controller + @ResponseBody
view 화면 return data(JSON, xml 등) return

 


아직 정리를 못한 어노테이션이 많다.

알지 못하는 어노테이션도 많다.

천천히 추가해나가자.

라우팅

사용자가 접속한 주소에 따라 페이지(컴포넌트)가 달라지는 것을 "라우팅" 이라고 한다.

Vue와 같은 SPA(단일 페이지 애플리케이션)의 경우 페이지를 이동할 때마다 서버에 요청해서 페이지를 새로 갱신하는 것이 아니라 클라이언트에서 미리 가지고 있던 페이지를 라우팅을 이용해서 화면을 갱신하게 된다.

 

즉, 라우팅이란 클라이언트에서 url 주소에 따라 페이지가 전환되는 것으로 이해하면 된다.

 

Vue 프로젝트 내부에서는 미리 url 주소를 정의하고, 각 주소마다 Vue 페이지를 연결해 둔다.

사용자가 메뉴를 클릭하거나, 브라우저 주소를 직접 갱신했을 때 미리 정의된 url 주소에 해당하는 Vue 페이지로 화면을 전환한다.

 

Vue는 vue에서 제공하는 공식 플러그인인 vue-router를 이용해서 라우팅을 쉽게 구현할 수 있다.

 

Vue-Router 설치

vue add router

위 명령어를 통해 vue-router 설치 및 기본 설정을 모두 완료할 수 있다.

history mode 사용 여부

설치 중간에 history mode 사용 여부를 묻는 질문이 나오는데, Y를 입력한다.

router, views 폴더

@vue/cli-plugin-router가 설치된다.

설치가 끝나면 src 폴더 내에 router, views 폴더와 파일이 생성된다.

 

이 상태에서 다음 명령어를 통해 서버를 재시작한다.

npm run serve

크롬에 http://localhosts:8080 을 입력하여 아래 화면을 확인한다.

localhost

화면 상단에 Home, About 두 개의 링크가 있다.

번갈아서 링크를 클릭해보면 화면이 전환되는 것을 확인할 수 있다.

vue-router를 설치했더니 자동으로 시작 화면에 링크가 추가되고, router가 동작되는 샘플 파일이 자동으로 생성되었다.

새로 추가된 파일들을 좀 더 자세히 확인해보자.

 

App.vue

App.vue

링크에 대해 정의된 부분이 나온다.

브라우저의 url을 보면 Home을 클릭했을 때는 localhost:8080,

About을 클릭하면 localhost:8080/about 으로 바뀌는 것을 확인할 수 있다.

 

이제 router 폴더의 index.js 파일을 확인해보자.

 

index.js

index.js

routes 배열에 2개의 라우트가 등록되어 있다. 

첫번째는 Home 컴포넌트이고, 두번째는 About 컴포넌트에 대한 라우트이다.

 

{path: '/', name: 'Home', component: Home}

-> path: 브라우저에서 접속하는 url 주소를 정의

-> component: 지정된 path로 들어왔을 때 보여줄 vue 컴포넌트, 앞으로 구현할 vue 파일을 연결하고, 해당 파일을 실행시킨다.

 

index.js 파일 두번째 줄에 있는 import 문이 실제 src/views 경로 내에 있는 Home.vue 파일을 참조한다.

앞으로 개발할 화면에 해당하는 vue 파일을 이렇게 import하고, routes 안에 특정 path와 맵핑을 해주면 사용자가 접속하는 브라우저 url 주소에 따라 원하는 vue 파일을 보여줄 수 있다.

 

routes 배열의 두번째 값에 path와 name 밑에 주석 처리된 부분이 있다.

// route level code-splitting

=> 라우트 레벨에서 코드를 분할하는 방법.

// this generates a separate chunk (about. [hash].js) for this route

=> 이 라우트에 대한 chunk 파일이 분리되어 생성된다.

// which is lazy-loaded when the route is visited

=> 이 라우트에 방문했을 때 lazy-load(지연 로드) 된다.

component: () => import(/* webpackChunkName: "about" */  '../views/About.vue')

=> 주석처럼 라우트 레벨에서 코드를 분할한 후 별도의 chunk 파일을 생성하고, 실제 이 라우트를 방문했을 때 리소스를 다시 로드하게 된다. 여기서 chunk 파일은 about이라는 이름으로 생성된다. 컴포넌트 import 시 /* webpackChunkName: "about" */ 라는 주석으로 chunk 파일 이름을 정의했기 때문이다.

 

첫번째 라우트와 두번째 라우트의 가장 큰 차이는 첫번째는 사용자가 해당 경로에 접근하지 않아도 이미 vue 파일을 import 하는 것이고, 두번째 방법은 path에 접근하기 전까지는 vue 파일에 대한 import 가 일어나지 않는다.

 

Lazy Load(비동기 컴포넌트)

Vue CLI를 통해 빌드를 진행하면 소스 코드가 하나의 파일로 합쳐지는데, 프로젝트가 클수록 전체 코드가 하나로 합쳐지면서 파일 용량이 커지게 된다.

이로 인해, 사용자가 웹사이트에 처음 접속했을 때 한 번에 큰 파일을 다운로드하느라 초기 랜더링 시간이 길어지게 된다.

 

페이지가 한번 로드되고 나서는 페이지 전환이 매우 빠르기 때문에 굉장한 이점이 있긴 하다.

하지만 사용하는 페이지가 별로 없다고 한다면, 사용하지도 않을 페이지를 로드하는게 불편해지게 되는 것이다.

 

Lazy Load는 리소스를 컴포넌트 단위로 분리하여 컴포넌트 혹은 라우터 단위로 필요한 것들만 그때 그때 다운받을 수 있게 하는 방법이다.

Vue CLI3부터 prefetch 기능이 추가가 되었는데, prefetch 기능은 미래에 사용될 수 있는 리소스(about과 같은 비동기 컴포넌트)를 캐시에 저장함으로써 사용자가 접속했을 때 빠르게 리소스를 내려줄 수 있다.

굉장히 유용한 기능이지만, 비동기 컴포넌트로 정의된 모든 리소스를 당장 사용하지 않더라도 캐시에 담아야 하는 단점이 있다.

 

Vue CLI에서 prefetch 기능은 기본값으로 true이다.

때문에 Lazy Load가 적용된 컴포넌트는 모두 prefetch 기능이 적용되어 캐시에 저장된다.

 

prefetch 기능을 사용하지 않을 때

  • 요청 수가 훨씬 줄어든다.
  • 라우터가 이동될 때마다 해당 라우터에서 필요한 리소스를 그때 그때 가져온다.
    (한번 가져온 리소스는 다시 요청하지 않는다.)

prefetch 기능을 사용할 때

  • 요청 수가 많아진다.
  • 애플리케이션의 첫 화면 접속 시 랜더링 속도가 느려질 수 있다.
  • 첫 화면에서 사용되는 리소스는 마지막에 다운받게 되는데, 아직 사용하지 않는 화면의 리소스를 모두 내려받고 첫 화면의 리소스를 다운받기 때문이다.

오히려 초기 랜더링은 prefetch 기능을 사용하지 않아야 로딩이 빠르다.

prefetch 기능은 다른 화면에서 사용할 리소스를 미리 내려 받아, 빠른 화면 전환을 위해 사용되기 때문에..

"정말 필요한 컴포넌트에 대해 prefetch 기능을 적용하는 것이 좋다."

 

Vue CLI에서 prefetch 기능이 디폴트로 true이기 때문에 prefetch 기능을 끄는 법을 알아보자.

vue-project/blob/master/ 경로에 Vue.config.js 파일을 생성하고 다음 코드를 추가한다.

prefetch 기능을 삭제해도, 비동기 컴포넌트인 Lazy Load로 컴포넌트를 사용할 수 있다.

컴포넌트를 import할 때, 다음과 같이 처리하면 된다.

import(/* webpackPrefetch: true */ './views/About.vue');

/* webpackPrefetch: true */ 를 넣어주면 해당 컴포넌트에 대해 prefetch가 적용된다.

Vue 개발 시 기본적으로 prefetch 기능은 끄는 것을 추천한다.

 

routes/index.js의 첫번째 줄을 보면 vue에서 라우팅을 처리하기 위해 vue-router를 import 하는 것을 볼 수 있다.

이렇게 정의된 router는 main.js 에 등록을 해줘야 실제 적용이 되어 사용할 수 있다.

 

main.js 파일을 살펴보자.

main.js 파일

3번째 라인을 보면 './router' 를 통해 router 폴더의 index.js가 import 된다.

마지막 라인에서는 최상위 컴포넌트인 App.vue로 app을 생성하고, use(router) 코드로 App.vue에서 router가 사용될 수 있도록 추가했다.

그리고 App.vue를 public 폴더의 index.html에 정의되어 있는 id="app"인 html element에 마운트 시키는 것이다.

 

Home, About을 클릭할 때마다 연결되어 있는 vue 파일이 호출이 되고, 해당 파일의 코드가 실행되어서 화면에 나타나는 것을 보았다.

이렇게 .vue로 작성된 파일을 컴포넌트로 한다.

 

'Study > Front' 카테고리의 다른 글

[Vue.js] Vue CLI로 Vue 프로젝트 생성하기  (0) 2021.11.14
VSCode 단축키  (0) 2021.03.02
VSCode 확장 기능 설정하기  (0) 2021.02.23

Vue CLI - Vue Command Line Interface

Vue 프로젝트를 빠르게 구성하고, 빌드, 배포할 수 있게 도와주는 플러그인

 

Vue CLI 설치

npm install -g @vue/cli

 

npm에 등록된 패키지는 npm install 패키지명 을 통해 설치할 수 있다.

패키지를 설치할 때 사용가능한 옵션이 여러 가지 있지만, -g와 --save에 대해서만 짚고 넘어간다.

 

npm install -g 패키지명

-g(global) 옵션은 설치하는 패키지가 현재 디렉토리뿐만 아니라 앞으로 생성하게 되는 모든 프로젝트에서 사용할 수 있는 global 패키지로 등록된다.

 

npm install 패키지명 --save

현재 작업중인 디렉토리 내에 있는 ./node_modules에 패키지를 설치한다.

그 다음에 package.json 파일에 있는 dependencies 객체에 지금 설치한 패키지 정보를 추가한다.

설치되는 모든 패키지는 node_modules 디렉토리에 설치된다.

node_modules 디렉토리에서 현재 사용하고 있는 모든 패키지를 확인할 수 있다.

 

--save 옵션을 사용하면 package.json 파일에 설치한 패키지 정보가 추가되기 때문에

package.json 파일을 팀원들에게 공유하면 명령어 npm install을 통해 현재 내 프로젝트 디렉토리에 없는 패키지 전체를 한번에 설치할 수 있다.

 

vue create vue-project

디렉토리명을 vue-project 로 하여 프로젝트를 설치한다.

Vue 3 버전을 사용할 것이므로 아래의 Vue 3을 선택하여 설치를 진행한다.

그렇게 되면 왼쪽 패널에 Vue 프로젝트를 생성하면서 vue-project 의 이름으로 폴더가 생성되고,

프로젝트 폴더 하위로 Vue 프로젝트 개발을 위한 기본적인 파일들이 자동으로 생성된다.

 

Vue 프로젝트 실행

프로젝트 생성이 끝나면 터미널에 표시된 가이드대로 명령어를 입력하여 프로젝트를 실행해본다.

 

cd vue-project

프로젝트 폴더로 이동

 

npm run serve

서버가 시작되며, 프로젝트가 기본 포트 8080으롷 실행된다.

 - 기본 포트 이외의 포트를 사용하려면 npm run serve -- --port 포트번호  명령어로 직접 포트번호를 지정할 수 있다.

 ex) npm run serve -- --port 3000

 

크롬을 켜서 확인을 해보고, 아래 화면이 나타나면 Vue 프로젝트가 정상적으로 설치된 것이다.

Vue 프로젝트 실행 화면

 

 

Vue 프로젝트 파일 구조

설치된 프로젝트에 어떤 파일들이 생성되었는지 기본적인 구조를 살펴보자

Vue 프로젝트 파일 구조

node_modules npm으로 설치된 패키지 파일이 모여 있는 디렉토리
public 웹팩(webpack)을 통해 관리되지 않는 정적 리소스가 모여 있는 디렉토리
src/assets 이미지, css, 폰트 등을 관리하는 디렉토리
src/components Vue 컴포넌트 파일이 모여 있는 디렉토리
App.vue 최상위(root) 디렉토리
main.js 가장 먼저 실행되는 자바스크립트 파일로써, Vue 인스턴스를 생성하는 역할
.gitignore 깃허브에 업로드할 때 제외할 파일 설정
babel.config.js 바벨(Babel) 설정 파일
package-lock.json 설치된 package의 dependency 정보를 관리하는 파일
package.json 프로젝트에 필요한 package를 정의하고 관리하는 파일
README.md 프로젝트 정보를 기록하는 파일

 

package.json 파일 구성

name 프로젝트 이름을 입력
version 프로젝트의 버전 정보를 입력
private 이 옵션을 true로 설정 시, 해당 프로젝트를 npm으로 올릴 수 없다. 개발자가 실수로 해당 프로젝트를 npm에 올리더라도 이 옵션이 true로 되어 있으면 배포를 막을 수 있다.
scripts 프로젝트 실행과 관련된 명령어들을 등록한다.
프로젝트 실행, 빌드 등과 같이 프로젝트 개발, 운영 시 사용되는 다양한 scripts 명령어를 등록하고, 쉽게 사용할 수 있다.
개발자가 직접 정의한 script는 npm run 명령어로 사용하고, npm에서 제공되는 명령어는 npm 명령어로 사용한다.
dependencies 사용중인 패키지 정보를 입력한다.
devDependencies 프로젝트 배포 시 필요없는, 개발 시에만 필요한 패키지 정보가 등록되는 곳
eslintConfig ESLint는 일관성 있게 코드를 작성하고 버그를 식별하고 회피할 목적으로 ECMAScript/Javascript 코드에서 발견된 패턴을 개발자에게 알려주는 플러그인이다.
구문 분석을 위해 babel-eslint를 파서로 사용
browserslist 전 세계 사용 통계 속에서 상위 1% 이상 사용된 브라우저, 각 브라우저의 최신 버전 2개를 지원하도록 한다.

패키지를 설치하면 dependencies, devDependencies, eslintConfig 등은 자동으로 채워지며, 

name, version, private 등은 사용자가 직접 입력해서 등록한다.

 

사실 package.json을 이루는 옵션은 매우 많다.

표로 정리한 내용은 그 중에서도 Vue CLI를 통해서 작성된 옵션들이다.

 

 

'Study > Front' 카테고리의 다른 글

[Vue.js] Vue Router 설정  (0) 2021.11.15
VSCode 단축키  (0) 2021.03.02
VSCode 확장 기능 설정하기  (0) 2021.02.23

테이블 함수

  • 여러 로우를 가진 컬렉션을 반환하는 함수
    • 컬렉션 타입을 반환, 연관 배열은 반환하지 못하고 중첩 테이블이나 VARRAY만 반환 가능
  • 기본 함수는 하나의 값만 반환이 가능하지만 테이블 함수로는 여러 행, 열의 반환이 가능
    • Oracle Table Function은 Multi Column + Multi Row로 값을 return할 수 있는 PL/SQL Function

 

문법

  • 일반 함수와 다를 건 없지만, 대상이 되는 컬렉션 타입이 먼저 만들어져 있어야 함.
  • 다음 예시는 DEPT와 EMP 테이블을 예를 들어, DEPT 번호를 파라미터로 전달하여 부서 및 직원 정보를  가져오는 쿼리를 TABLE 함수 형태로 변환
  1. OBJECT 타입 생성
    1. 행을 리턴받는 역할
    2. 함수에서 반환하는 레코드의 스키마
  2. (임시) TABLE TYPE 객체 생성
    1. 함수에서 반환하는 레코드의 집합(테이블) 정의
  3. Table Function 생성 (테이블 Return)
  4. "Table" 키워드를 사용하여 조회

 

예시

-- 1. OBJECT 타입 생성 
CREATE OR REPLACE TYPE DEPT_TYPE AS OBJECT ( 
	DEPTNO NUMBER(2), 
	DNAME VARCHAR2(14), 
	LOC VARCHAR2(13), 
	EMPNO NUMBER(4), 
	ENAME VARCHAR2(10) 
)

 

-- 2. TABLE 타입 생성 
CREATE OR REPLACE TYPE DEPT_TABLE AS TABLE OF DEPT_TYPE;

 

-- 3. 함수 생성 (테이블 리턴) 
CREATE OR REPLACE FUNCTION GET_DEPT_FN(P_DEPT_NO IN NUMBER) 
	RETURN DEPT_TABLE 
IS 
	V_RSLT DEPT_TABLE; 
BEGIN 
	SELECT DEPT_TYPE(A.DEPTNO, A.DNAME, A.LOC, B.EMPNO, B.ENAME) 
	BULK COLLECT INTO V_RSLT 
	FROM DEPT A , EMP B 
	WHERE A.DEPTNO = B.DEPTNO 
	AND A.DEPTNO = P_DEPT_NO; 
	RETURN V_RSLT; 
END GET_DEPT_FN;

 

-- 실행예시 
SELECT * FROM TABLE(GET_DEPT_FN(30));

 

 

Pipelined Table Function

  • Table Function과 거의 유사, 한 행 단위로 바로바로 즉시 값을 리턴하는 함수
  • 한 Row씩 처리하므로 결과값들이 바로 출력되기 시작
  • Oracle 9i부터 사용
  1. OBJECT 타입 생성
  2. (임시) TABLE TYPE 객체 생성
  3. Pipelined Table Function 생성
  4. 조회
-- 1. OBJECT 타입 생성 
CREATE OR REPLACE TYPE DEPT_TYPE AS OBJECT ( 
	DEPTNO NUMBER(2), 
	DNAME VARCHAR2(14), 
	LOC VARCHAR2(13), 
	EMPNO NUMBER(4), 
	ENAME VARCHAR2(10) 
)

 

-- 2. TABLE 타입 생성 
CREATE OR REPLACE TYPE DEPT_TABLE AS TABLE OF DEPT_TYPE;

 

-- 3. Pipelined 함수 생성 (테이블 리턴) 
CREATE OR REPLACE FUNCTION GODDAEHEE.GET_DEPT_PIPE_FN(P_DEPT_NO IN NUMBER) 
	RETURN DEPT_TABLE 
	PIPELINED 
IS 
	V_RSLT DEPT_TYPE; 
BEGIN 
	FOR DEPT_CUR IN ( 
	SELECT A.DEPTNO, A.DNAME, A.LOC, B.EMPNO, B.ENAME 
	FROM DEPT A 
		, EMP B 
	WHERE A.DEPTNO = B.DEPTNO 
	AND A.DEPTNO = P_DEPT_NO 
	) 
	LOOP 
		V_RSLT := DEPT_TYPE(DEPT_CUR.DEPTNO, DEPT_CUR.DNAME, DEPT_CUR.LOC, DEPT_CUR.EMPNO, DEPT_CUR.ENAME); 
		PIPE ROW(V_RSLT); 
	END LOOP; 
	RETURN; 
END;

 

-- 실행예시 
SELECT * FROM TABLE(GET_DEPT_PIPE_FN(30));

'Study > Oracle' 카테고리의 다른 글

PL/SQL 기본_5 - 함수  (0) 2021.05.17
PL/SQL 기본_4 - 프로시저  (0) 2021.05.10
PL/SQL 기본_3 - 커서  (0) 2021.05.10
PL/SQL 기본_2 - 반복문과 제어문  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

함수

  • 특정 기능들을 모듈화, 재사용할 수 있어서 복잡한 쿼리문을 간결하게 만듬
    • 함수 사용이 쿼리 속도를 느리게 만드는 원인이 될 수 있으니 필요한 경우만 사용
  • 호출한 곳으로 반드시 하나의 값을 리턴해야 하는 PL/SQL Stored Program
    • 즉, PL/SQL 블록 내에서 RETURN문을 통해 반드시 값을 리턴
  • 프로시저는 PL/SQL문으로 실행, 함수는 식의 일부로서 사용
  • RETURN 절에 지정된 것과 동일한 데이터 타입으로 RETURN 값을 설정해야 함
  • 함수 작성 시 권한 필요
    • 자신의 스키마 : CREATE PROCEDURE 권한
    • 다른 사용자의 스키마 : CREATE ANY PROCEDURE 권한
  • 기본적으로 DML(INSERT/UPDATE/DELETE)문 사용 불가

함수 기본 문법

CREATE [OR REPLACE] FUNCTION function_name [(
	
	argument...
	
)]
RETURN datatype -- 반환되는 값의 datatype
    IS [AS]
        [선언부]
    BEGIN
        [실행부 - PL/SQL Block]
    [EXCEPTION]
        [EXCEPTION 처리]
    RETURN 변수; -- 리턴문 필수
END;
  • [] : 대괄호 안의 구문은 생략 가능함을 의미
  • OR_REPLACE : 함수생성 DDL 명령어 / 이미 존재하는 함수라면 기존 내용 지우고 재생성, 생략 가능
  • function_name : 사용자 지정 함수명
  • argument : 매개변수1, 매개변수2, 매개변수3 ... 매개변수 선언
  • datatype : VARCHAR2, NUMBER, DATE 등 반환할 데이터 타입 지정

 

함수 작성 및 사용 예시

  • 함수 작성 예시
CREATE OR REPLACE FUNCTION FN_GET_DEPT_NAME( 
	P_DEPT_NO IN VALCHAR2 
) RETURN VARCHAR2 
IS 
	V_TEST_NAME VARCHAR2(10); 
BEGIN 
	SELECT DELP_NAME 
	INTO V_TEST_NAME 
	FROM DEPT 
	WHERE DEPT_NO = P_DEPT_NO; 
RETURN V_TEST_NAME; 
END;

 

  • 함수 사용 예시
    • SELECT 문에서 편하게 사용 가능
SELECT FN_GET_DEPT_NAME('01') FROM DUAL;

'Study > Oracle' 카테고리의 다른 글

PL/SQL_6 - 테이블 함수  (0) 2021.05.18
PL/SQL 기본_4 - 프로시저  (0) 2021.05.10
PL/SQL 기본_3 - 커서  (0) 2021.05.10
PL/SQL 기본_2 - 반복문과 제어문  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

저장 프로시저

  • 정의
    • Transact-SQL 문장의 집합
  • 용도
    • 어떠한 동작을 절차적 일괄처리 작업하는 데 사용
    • SQL Server에서 사용하는 프로그래밍 기능
  • 특징
    • SQL Server의 성능 향상(첫 실행 시 컴파일, 재컴파일 안 함)
    • 모듈식 프로그래밍 가능
    • 보안 강화(저장 프로시저마다 권한 할당 가능)
    • 네트워크 전송량 감소(긴 쿼리 문장의 단순화)
  • 장점
    • 빠르다
    • 파라미터 사용 가능
    • 여러 애플리케이션과 공유 가능
  • 기본 문법
    • (인수 없는)프로시저 생성 방법
	CREATE OR REPLACE PROCEDURE 프로시저이름 
	IS
	[
	변수이름 데이터타입;  -- 프로시저내에서 사용할 변수선언
	변수이름 데이터타입;
	변수이름 데이터타입;
	..
	]
	BEGIN
	 기능 구현;
	END;

 

 

  • EX) 인수없는 프로시저
	SET SERVEROUTPUT ON; 
	CREATE OR REPLACE PROCEDURE p_test 
	IS 
		I_MESSAGE VARCHAR2(100) := 'https://pdache.tistory.com'; 
	BEGIN 
		dbms_output.put_line(I_MESSAGE); 
	END; 
	EXEC p_test; --프로시저 호출

 

  • (인수 있는) 프로시저 생성 방법
	CREATE OR REPLACE PROCEDURE 프로시저이름(
	변수이름 IN 데이터타입, 변수이름 IN 데이터타입, .... --IN 생략가능
	)
	IS
	[
	변수이름 데이터타입;  -- 프로시저내에서 사용할 변수선언
	..
	]
	BEGIN
	기능 구현;
	END;

 

  • EX) 인수 있는 프로시저
	CREATE OR REPLACE PROCEDURE p2_test( p_name IN VARCHAR2 ) 
	IS 
	BEGIN 
		dbms_output.put_line(p_name||' 님 안녕하세요?'); 
	END; 
	EXEC p2_test; --프로시저 호출 (오류발생 ) 
		-- (프로시저에 in이 있으면서 기본값이 없기 때문에 반드시 인수값 필요함) 
	EXEC p2_test('Pdache');

 

※인수의 타입 선언 부분 정리

  • IN => 내부 프로그램에 제공
        변수이름 IN VARCHAR2;  -- 인수선언할 때 byte 수 지정안함(인수는 크기를 주지 않음)
        변수이름 IN 테이블이름.컬럼명%TYPE;
        변수이름 IN 테이블이름.컬럼명%TYPE:=값;
        변수이름 IN 테이블이름.컬럼명%TYPE DEFAULT 값;

 

  • OUT => 호출자에게 제공
    • 프로시저 실행 시점에 OUT 매개변수를 변수 형태로 전달하고, 프로시저 실행부에서 이 매개변수에 특정 값을 할당
        변수이름 IN VARCHAR2;
        변수이름 IN 테이블이름.컬럼명%TYPE;

 

  • IN OUT => 입력과 동시에 출력용으로 사용할 수 있다.
        변수이름 IN VARCHAR2;
        변수이름 IN 테이블이름.컬럼명%TYPE;

 

※ IN OUT, OUT 모드로 선언된 파라미터에는 DEFAULT를 적용할 수 없다.

 

 

  • 프로시저 호출 방법
	EXEC 프로시저이름; -- 인수없는 경우 호출
	EXEC 프로시저이름(값, 값, ...);  - 인수있는 경우 호출

 

  • 저장된 프로시저 찾기
    • 작성된 프로시저를 찾기 위해 데이터 사전을 이용할 수 있다.
    • 데이터 사전은 대문자로 값을 저장하기 때문에 대문자로 검색한다.
SELECT * FROM user_objects WHERE object_type = 'PROCEDURE';
SELECT * FROM user_source WHERE name = '프로시저명';

 

  • 프로시저 output 매개변수 사용하기
    • 웹 개발을 하면서 프로시저 결과 핸들링을 위해 많이 사용
    • 프로시저를 실행하여 특정 결과 값을 OUT 변수에 저장하여 보냄
    • OUT 있는 프로시저 작성방법
	CREATE OR REPLACE PROCEDURE 프로시저이름 (
	변수이름 IN 데이터타입, 변수이름 IN 데이터타입, .... --in 생략가능
	변수이름 OUT 데이터타입, 변수이름 OUT 데이터타입 ... --프로시저를 호출하는곳으로 값을 보낸다.
	)
	IS
	[
	변수이름 데이터타입;  -- 프로시저내에서 사용할 변수선언
	..
	]
	BEGIN
	기능 구현;
	END;

 

 

  • EX) 이름을 OUTPUT 해주는 프로시저
	CREATE OR REPLACE PROCEDURE p_outTest(
		p_NAME OUT VARCHAR2
	)
	IS
	BEGIN
		p_NAME := 'Pdache';
	    DBMS_OUTPUT.PUT_LINE('호출 완료');
	END;
	--out이 있는 프로시저 호출방법
	--DECLARE 로 선언되변수는 일회용
	
	DECLARE
	OUT_MSG VARCHAR2(2000);
	
	BEGIN
	p_outTest(OUT_MSG);  -- 프로시저를 실행 한후에 out을 받을 변수지정
	dbms_output.put_line(OUT_MSG); -- 출력하기
	END;

'Study > Oracle' 카테고리의 다른 글

PL/SQL_6 - 테이블 함수  (0) 2021.05.18
PL/SQL 기본_5 - 함수  (0) 2021.05.17
PL/SQL 기본_3 - 커서  (0) 2021.05.10
PL/SQL 기본_2 - 반복문과 제어문  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

PL/SQL의 꽃이라 불리는 "커서"에 대해서 알아보도록 하자.

 

커서(CURSOR)의 정의

  • SQL 커서는 Oracle 서버에서 할당한 전용 메모리 영역에 대한 포인터이다.
  • 질의의 결과로 얻어진 여러 행이 저장된 메모리 상의 위치
  • 커서는 SELECT문의 결과 집합을 처리하는데 사용

 

커서(CURSOR)의 종류

  • 암시적 커서(Implicit Cursor)
    • 정의
      • 오라클 DB에서 실행되는 모든 SQL 문장은 암시적 커서가 생성되며, 커서 속성을 사용할 수 있다.
      • 모든 DML과 PL/SQL SELECT문에 대해 선언
      • 암시적 커서는 오라클이나 PL/SQL 실행 메커니즘에 의해 처리되는 SQL 문장이 처리되는 곳에 대한 익명의 주소
      • Oracle 서버에서 SQL문을 처리하기 위해 내부적으로 생성하고 관리
      • 암시적 커서는 SQL문이 실행되는 순간 자동으로 OPEN, CLOSE 실행
      • SQL 커서 속성을 사용하면 SQL문 결과 테스트 가능
    • 속성
      • SQL%FOUND : 해당 SQL문에 의해 반환된 총 행수가 1개 이상일 경우 TRUE(BOOLEAN)
      • SQL%NOTFOUND : 해당 SQL문에 의해 반환된 총 행수가 없을 경우 TRUE(BOOLEAN)
      • SQL%ISOPEN : 항상 FALSE, 암시적 커서가 열려 있는지의 여부 검색(PL/SQL은 실행 후 바로 CLOSE)
      • SQL%ROWCOUNT : 해당 SQL문에 의해 반환된 총 행수, 가장 최근 수행된 SQL문에 의해 영향을 받은 행의 갯수(정수)
    • EX)
	SET SERVEROUTPUT ON;
	DECLARE
	    BEGIN
	    DELETE FROM emp WHERE DEPTNO = 10;
	    DBMS_OUTPUT.PUT_LINE('처리 건수 : ' || TO_CHAR(SQL%ROWCOUNT)|| '건');
	    END;

-- 결과

처리 건수 : 21건

PL/SQL 처리가 정상적으로 완료되었습니다.

 

 

  • 명시적 커서(Explicit Cursor)
    • 정의
      • 프로그래머에 의해 선언되어 이름이 있는 커서
    • 속성
      • %ROWCOUNT : 현재까지 반환된 모든 행의 수를 출력
      • %FOUND : FETCH한 데이터가 행을 반환하면 TRUE
      • %NOTFOUND : FETCH한 데이터가 행을 반환하지 않으면 TRUE(LOOP를 종료할 시점을 찾을 때 사용)
      • %ISOPEN : 커서가 OPEN 되어 있으면 TRUE
    • 문법
      • DECLARE를 통해서 명명된 SQL 영역 생성
      • OPEN을 이용하여 결과 행 집합 식별
      • FETCH를 통해 현재 행을 변수에 로드(현재 행이 없을 때까지 수행 가능)
      • CLOSE를 통해 결과 행 집합 해제
	DECLARE
		CURSOR [커서이름] IS [SELECT 구문];
	BEGIN
		OPEN [커서이름];
		FETCH [커서이름] INTO [로컬변수];
		CLOSE [커서이름];
	END;

 

  • OPEN(커서 열기)
    • OPEN 문을 사용하여 커서를 연다.
    • 커서 안의 검색이 실행되며 아무런 데이터 행을 추출하지 못해도 에러가 발생하지 않는다.
  • FETCH(커서 페치)
    • 현재 데이터 행을 OUTPUT 변수에 반환
    • 커서의 SELECT 문의 컬럼 수와 OUTPUT 변수의 수가 동일해야 한다.
    • 커서 컬럼의 변수 타입과 OUTPUT 변수의 데이터 타입 역시 동일해야 한다.
    • 커서는 한 라인씩 데이터를 FETCH
    • 문법 : FETCH cursor_name INTO variable1, variable2;
  • CLOSE(커서 닫기)
    • 사용을 마친 커서는 반드시 닫아준다.
    • 필요시 커서는 다시 열 수 있다.
    • 커서를 닫은 상태에서 FETCH는 불가능하다.
    • 문법 : CLOSE cursor_name;
  • EX 1) 커서 사용 예제 1
	SET SERVEROUTPUT ON;
	DECLARE
	    CURSOR emp_cur -- 커서정의
	    IS
	    SELECT * FROM emp WHERE DEPTNO = 10;
	    emp_rec emp%ROWTYPE; -- 변수정의
	BEGIN
	    OPEN emp_cur;
	    LOOP -- 반복
	    FETCH emp_cur INTO emp_rec; -- 하나씩 변수에 넣기
	    EXIT  WHEN emp_cur%NOTFOUND; -- 더이상 없으면 끝내기
	        DMBS_OUTPUT.PUT_LINE(emp_rec.empno || ' ' || emp_rec.name); -- 출력
	    END LOOP;
	    CLOSE emp_cur;
	END;

 

  • EX 2) 커서 사용 예제 2
	SET SERVEROUTPUT ON;
	DECLARE
	    ID_LIST SYS_REFCURSOR; -- 커서정의
	    I_ID VARCHAR2(100); -- 변수정의
	BEGIN
	    OPEN ID_LIST;
	    FOR
	        SELECT USER_ID FROM MY_USER WHERE 조건;
	    LOOP -- 반복
	    FETCH ID_LIST INTO I_ID; -- 하나씩 변수에 넣기
	    EXIT  WHEN ID_LIST%NOTFOUND; -- 더이상 없으면 끝내기
	        DMBS_OUTPUT.PUT_LINE(I_ID); -- 출력
	    END LOOP;
	    CLOSE ID_LIST;
	END;

 

  • EX 3) 커서 사용 예제 3
	SET SERVEROUTPUT ON;
	DECLARE
	    CURSOR ID_LIST IS
	    SELECT 'GOD' AS USER_ID FROM DUAL;
	BEGIN
	    FOR TEST_CURSOR IN ID_LIST
	    LOOP
	        DBMS_OUTPUT.putline(TEST_CURSOR.USER_ID);
	    END LOOP;
	END;

 

  • 명시적 커서 FOR LOOP
    • 서브 쿼리를 활용하여 CURSOR FOR LOOP를 사용하면 CURSOR를 선언할 필요도 없어진다.
    • 명시적 커서 FOR LOOP를 사용하면 FOR LOOP가 자동적으로 커서를 OPEN, 행이 없을 때까지 FETCH하고, CLOSE
    • ROWTYPE에 해당하는 변수를 따로 DECLARE할 필요가 없다. - 암시적으로 선언되기 때문
    • 이 암시적 카운터는 FOR LOOP에서만 사용 가능
    • 이 커서의 데이터 타입(컬럽 데이터 타입의 집합)도 %ROWTYPE 앞으로 이용 가능
  • EX 3) 커서 사용 예제 3을 "명시적 커서 FOR LOOP" 방식으로 변경한 예
	SET SERVEROUTPUT ON;
	DECLARE
	BEGIN
	    FOR ID_LIST IN 
	    (
	        SELECT 'GOD' AS USER_ID FROM DUAL
	    )
	    LOOP
	    DBMS_OUTPUT.putline(ID_LIST.USER_ID);
	END LOOP;
	END;

 

※ CURSOR FOR LOOP은 내부적으로 처리되는 데이터의 양, I/O 측면에서 훨씬 효율적, 가급적 사용 권장

'Study > Oracle' 카테고리의 다른 글

PL/SQL_6 - 테이블 함수  (0) 2021.05.18
PL/SQL 기본_5 - 함수  (0) 2021.05.17
PL/SQL 기본_4 - 프로시저  (0) 2021.05.10
PL/SQL 기본_2 - 반복문과 제어문  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

PL/SQL에서의 반복문은 크게 LOOP, FOR로 볼 수 있다.

 

FOR LOOP

  • 문법
FOR index in [REVERSE] 시작값 .. END값 LOOP
        STATEMENT 1
        STATEMENT 2
        ...
    END LOOP;
    
  • index는 자동 선언되는 binary_integer형 변수이고, 1씩 증가
  • REVERSE 옵션이 사용될 경우 index는 upper_bound에서 lower_bound로 1씩 감소
  • IN 다음에는 cursor나 SELECT 문이 올 수 있다.

 

  • EX 1)
SET serveroutput ON;
	BEGIN
		FOR i in 1..4 LOOP
	  		if mod(i, 2) = 0 then 
				dbms_output.put_line( i || '는 짝수!!');
			else
				dbms_output.put_line( i || '는 홀수!!');
			end if;
		END LOOP;
	END;

 

  • EX 2) 간단한 FOR문 안에 SELECT문이 오는 예제
SET serveroutput ON;
	BEGIN
		FOR NUM_LIST IN 
	    (
	        SELECT 1 AS NUM FROM DUAL
	        UNION ALL
	        SELECT 2 AS NUM FROM DUAL
	        UNION ALL
	        SELECT 3 AS NUM FROM DUAL
	        UNION ALL
	        SELECT 4 AS NUM FROM DUAL
	    )
	    LOOP
		  	if mod(NUM_LIST.NUM, 2) = 0 then 
				dbms_output.put_line( NUM_LIST.NUM || '는 짝수!!');
			else
				dbms_output.put_line( NUM_LIST.NUM || '는 홀수!!');
			end if;
		END LOOP;
	END;

 

LOOP

  • 문법
    LOOP 
        PL/SQL STATEMENT 1
           다른 LOOP를 포함하여 중첩으로 사용 가능
        EXIT [WHEN CONDITION]
    END LOOP;
  • EXIT 문이 사용되었을 경우, 무조건 LOOP문을 빠져나간다.
  • EXIT WHEN 조건이 사용될 경우, WHEN절에서 LOOP를 빠져나가는 조건을 제어할 수 있다.

 

  • EX 1) 기본 LOOP문 예제
	SET serveroutput ON;
	DECLARE
	    v_num NUMBER := 6; -- 시작숫자
	    v_tot_num NUMBER := 0; -- 총 loop수 반환 변수
	BEGIN
	    LOOP
	        DBMS_OUTPUT.PUT_LINE('현재 숫자 : ' || v_num);
	        v_num := v_num + 1;
	        v_tot_num := v_tot_num + 1;
	        EXIT WHEN v_num > 10;
	    END LOOP;
	    
	    DBMS_OUTPUT.PUT_LINE(v_tot_num || '번의 LOOP');
	END;

 

  • EX 2) WHILE LOOP문 예제
	SET serveroutput ON;
	DECLARE
	    v_num NUMBER := 6; -- 시작숫자
	    v_tot_num NUMBER := 0; -- 총 loop수 반환 변수
	BEGIN
	    WHILE v_num < 11 LOOP
	        DBMS_OUTPUT.PUT_LINE('현재 숫자 : ' || v_num);
	        v_num := v_num + 1;
	        v_tot_num := v_tot_num + 1;
	        -- EXIT WHEN v_num > 10;
	    END LOOP;
	    DBMS_OUTPUT.PUT_LINE(v_tot_num || '번의 LOOP');
	END;

 

 

제어문

IF문, CASE문 등의 제어문을 PL/SQL에서도 사용할 수 있다.

 

IF

  • 문법
    IF 조건1 THEN
        처리문1
    ELSE IF 조건2 THEN
        처리문2
        ...
    ELSE
        처리문
    END IF;
  • IF문은 조건값이 참이면 해당 조건의 처리 문장이 실행
  • 다른 프로그래밍 IF문과 다른 점
    • 조건 다음에 THEN을 붙인다.
    • 보통 ELSE IF를 쓰지만, PL/SQL에서는 ELSIF 명령어를 사용한다.
    • 마지막에는 IF를 끝낸다는 END IF를 붙인다.
  • EX 1) 기본 IF문 예제
	DECLARE
	    v_score NUMBER := 79;
	BEGIN
	  IF v_score >= 90 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : A');
	  ELSIF v_score >= 80 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : B');
	  ELSIF v_score >= 70 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : C');
	  ELSIF v_score >= 60 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : D');
	  ELSE
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : F');
	  END IF;
	END;

 

  • EX 2) IF문 예제 2 - 조건이 NULL인 경우
    • NULL의 비교는 항상 NULL이기 때문에, ELSE 이하 문만 수행
	DECLARE
	    v_score NUMBER;
	BEGIN
	  IF v_score >= 90 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : A');
	  ELSIF v_score >= 80 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : B');
	  ELSIF v_score >= 70 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : C');
	  ELSIF v_score >= 60 THEN
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : D');
	  ELSE
	    DBMS_OUTPUT.PUT_LINE('점수 : ' || v_score || ', 등급 : F');
	  END IF;
	END;

 

CASE문

  • 문법
    • 오라클 CASE문과 유사
	CASE WHEN 조건1 THEN
	    처리문1
	WHEN 조건2 THEN
	    처리문2
	    ...
	ELSE
	    처리문
	END CASE;

 

  • EX 1) CASE 표현식 예제
    • 단순하게 조건문에 따른 값을 대입할 때 사용
	DECLARE
	    v_grade     CHAR(1) := 'C';
	    v_appraisal VARCHAR2(20) ;
	BEGIN
	  v_appraisal := CASE v_grade
	  				WHEN 'A' THEN 'Excellent'
	  				WHEN 'B' THEN 'Very Good'
					WHEN 'C' THEN 'Good'
					ELSE 'No such grade'
	  			END;
	  DBMS_OUTPUT.PUT_LINE ('Grade : '|| v_grade) ;
	  DBMS_OUTPUT.PUT_LINE ('Appraisal: '|| v_appraisal);
	END;

 

  • EX 2) CASE 조건문 예제
    • 단순한 값이 아닌 PL/SQL문(명령문)을 실행하고자 하는 경우에 CASE 조건문 사용
    • CASE 조건문은 끝이 END CASE로 끝남
	DECLARE
	    v_grade     CHAR(1) := 'C';
	    v_appraisal VARCHAR2(20) ;
	BEGIN
	  CASE v_grade
	  WHEN 'A' THEN
	  	v_appraisal := 'Excellent';
	  WHEN 'B' THEN
	    v_appraisal := 'Very Good';
	  WHEN 'C' THEN
	    v_appraisal := 'Good';
	  ELSE
	    v_appraisal := 'No such grade';
	  END CASE;
	  DBMS_OUTPUT.PUT_LINE ('Grade : '|| v_grade) ;
	  DBMS_OUTPUT.PUT_LINE ('Appraisal: '|| v_appraisal);
	END;

'Study > Oracle' 카테고리의 다른 글

PL/SQL_6 - 테이블 함수  (0) 2021.05.18
PL/SQL 기본_5 - 함수  (0) 2021.05.17
PL/SQL 기본_4 - 프로시저  (0) 2021.05.10
PL/SQL 기본_3 - 커서  (0) 2021.05.10
PL/SQL 기본_1  (0) 2021.05.10

+ Recent posts