336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

ime-mode는 크롬에서 동작하지 않는다.

그러므로 정규식을 활용한다.


영어입력 : onkeyup="this.value=this.value.replace(/[^a-zA-z]/g,'')"

숫자입력 : onkeyup="this.value=this.value.replace(/[^0-9]/g,'')"

한글입력 : onkeyup="this.value=this.value.replace(/[^ㄱ-ㅎ가-힇]/g,'')" <- 인코딩 에러남....



'IT > ASP' 카테고리의 다른 글

asp DB 연결 string 관리.  (0) 2014.03.12
ASP 수치 변환 함수  (0) 2014.02.26
ASP 서버(Server) 정보. Request.ServerVariables.  (0) 2014.01.02
Asp 객체, 전역변수, global.asa  (0) 2013.12.30
ASP Round, Cint, Int 함수  (0) 2013.11.20
Posted by 당양부부34

2014. 2. 13. 14:23 IT/MSSQL

MSSQL STUFF, FOR XML PATH

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

STUFF 와 FOR XML PATH  테스트 !

CREATE TABLE #TABLE1 (T1_ID INT)

CREATE TABLE #TABLE2 (T2_ID INT, T1_ID INT)


INSERT INTO #TABLE1 VALUES(1) -- 테이블 생성
INSERT INTO #TABLE1 VALUES(2)

INSERT INTO #TABLE2 VALUES(1, 1) -- 테이블 값 생성
INSERT INTO #TABLE2 VALUES(2, 1)
INSERT INTO #TABLE2 VALUES(3, 1)
INSERT INTO #TABLE2 VALUES(4, 2)
INSERT INTO #TABLE2 VALUES(5, 2)
INSERT INTO #TABLE2 VALUES(6, 2)


SELECT * FROM #TABLE1 -- 테스트 준비 완료
SELECT * FROM #TABLE2


테스트 시작 - TABLE2의 데이터를 한 ROW로 나타냄 : 결과

 SELECT  T3.T1_ID,
 STUFF(
(
SELECT ',' + CAST(T2.T2_ID AS CHAR)
FROM #TABLE1 AS T1 
        INNER JOIN #TABLE2 AS T2 ON T1.T1_ID = T2.T1_ID  
WHERE T1.T1_ID = T3.T1_ID
GROUP BY T2.T2_ID, T2.T1_ID
ORDER BY T2.T1_ID
FOR XML PATH('') 
)
 , 1, 1, '') AS T2_ID
 FROM #TABLE1 AS T3
 WHERE T3.T1_ID IN (1,2)
 GROUP BY T3.T1_ID

 


STUFF 제거 : 앞에 , 살아남

 SELECT T3.T1_ID,
 --STUFF(
 (
SELECT ',' + CAST(T2.T2_ID AS CHAR)
FROM #TABLE1 AS T1 
        INNER JOIN #TABLE2 AS T2 ON T1.T1_ID = T2.T1_ID  
WHERE T1.T1_ID = T3.T1_ID
GROUP BY T2.T2_ID, T2.T1_ID
ORDER BY T2.T1_ID
FOR XML PATH('')
AS T2_ID 
 --  , 1, 1, '') AS T2_ID
 FROM #TABLE1 AS T3
 WHERE T3.T1_ID IN (1,2)
 GROUP BY T3.T1_ID

 


 실제 여러 ROW의 데이터를 ,로 구분하는 역할은 FOR XML PATH('') 가 수행한다.

안의 SELECT 쿼리 테스트 결과 

 SELECT ',' + CAST(T2.T2_ID AS VARCHAR) AS T2_ID
 FROM #TABLE1 AS T1
 INNER JOIN #TABLE2 AS T2 ON T1.T1_ID = T2.T1_ID 
 --WHERE T1.T1_ID = T3.T1_ID
 GROUP BY T2.T2_ID, T2.T1_ID
 ORDER BY T2.T1_ID

 


 SELECT ',' + CAST(T2.T2_ID AS VARCHAR)
 FROM #TABLE1 AS T1 
 INNER JOIN #TABLE2 AS T2 ON T1.T1_ID = T2.T1_ID
 --WHERE T1.T1_ID = T3.T1_ID
 GROUP BY T2.T2_ID, T2.T1_ID
 ORDER BY T2.T1_ID
 FOR XML PATH('')

 



 SELECT ',' + CAST(T2.T2_ID AS VARCHAR)  AS TAG
 FROM #TABLE1 AS T1 
 INNER JOIN #TABLE2 AS T2 ON T1.T1_ID = T2.T1_ID 
 --WHERE T1.T1_ID = T3.T1_ID
 GROUP BY T2.T2_ID, T2.T1_ID
 ORDER BY T2.T1_ID
 FOR XML PATH('')


- STUFF

STUFF(문자열, 시작위치, 변경할 문자길이, 변경할 문자)

EX) STUFF('ABCDEF', 2, 2 , 'abc') => 'AabcDEF'
두번째부터 시작하여, 2 길이의 문자를 abc로 변경

Posted by 당양부부34
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

기본적으로 SQL 에서 제공해주는 데이터로 우리는 원하는 기간동안의 날짜를 모두 출력 해 낼 수 있다. 

 

select convert(char(10),dateadd(증가시킬데이터(m:월, d:일, hh:시간, mm:분) ,number,'시작날짜'),120) as regdate
from master..spt_values with(nolock) 
where type = 'P' 
and convert(char(10),dateadd(d,number,'시작날짜'),120) < '마지막날짜'

이렇게 원하는 기간 내의 날짜를 출력 해 낼 수 있다.

 

 

ex)

select convert(char(10),dateadd(d,number,'2012-04-24'),120) as regdate
   from master..spt_values with(nolock) 
   where type = 'P' 
   and convert(char(10),dateadd(d,number,'2012-04-24'),120) < DateAdd("m", 1, '2012-04-24')  

 

 마지막 날짜를 mssql 에서 제공하는 DateAdd 함수를 이용해서 한달을 더해 출력 해 보았다

결과는 다음과 같다.

 

2012-04-24
2012-04-25
2012-04-26
2012-04-27
2012-04-28
2012-04-29
2012-04-30
2012-05-01
2012-05-02
2012-05-03
2012-05-04
2012-05-05
2012-05-06
2012-05-07
2012-05-08
2012-05-09
2012-05-10
2012-05-11
2012-05-12
2012-05-13
2012-05-14
2012-05-15
2012-05-16
2012-05-17
2012-05-18
2012-05-19
2012-05-20
2012-05-21
2012-05-22
2012-05-23 

 

 

이걸 이용하여 left조인 하여 원하는 날짜에 원하는 데이터를 추출 해 낼 수 있다.. 

 

보너스. 

활용을 조금 더 하자면 시간대 별 데이터 까지 출력이 가능하다. 

 

select right(convert(char(13),dateadd(hh,number,'시작날짜'),120),2) as regdate
from master..spt_values with(nolock) 
where type = 'P' 
and convert(char(10),dateadd(hh,number,'시작날짜'),120) < '마지막날짜' 

 

이렇게 해서 원하는 기간내에서 해당되는 날짜와 또한 그 날짜의 시간대 별 데이터까지  

group by 시킬 수가 있다. 

 

실전활용예제 )

 

select 
   regdate,
   isnull(tot,0),
   isnull(cnt,0)
from 
(
 select right(convert(char(13),dateadd(hh,1,'2012-04-24'),120),2) as regdate
 from master..spt_values with(nolock) 
 where type = 'P' 
 and convert(char(10),dateadd(hh,number,'2012-04-24'),120) < DateAdd(d, 1, '2012-04-24')
) as t1 
left join 
(
 SELECT right(CONVERT(char(13), d_regdate, 120),2) as 열1, sum(열1) as tot, count(열1) as cnt 
 FROM 데이터를 조회할 테이블
 WHERE convert(char(10),D_REGDATE,120) >= '2012-04-24'
 AND convert(char(10),D_REGDATE,120) <= '2012-04-24'
  group by right(CONVERT(char(13), d_regdate, 120),2)
) as t2
on t1.regdate = t2.d_regdate
group by t1.regdate, t2.d_regdate, tot,cnt
order by t1.regdate; 

 

난 하루치만 조회할 예정이었으므로 음하하핫. 

이렇게 left join문을 써서 복잡하게 조회 한 까닭은 데이터를 페이지에 뿌려주는데, join을 하지 않고 그냥 쿼리문을 썼을 때 데이터가 없는 시간대에는 0을 해주고 싶은데, 데이터 자체가 없기에 그 시간대는 아예 결과에 나타나지 않았다.

예를 들면

01    1233      4

02    1234      2

04    3412      4

 

이런식으로 3시 대의 결과가 빠져서 된다.

이를 해결해 주기위해서 웹언어로 구현을 해도 되겠지만, 그렇게 되면 조회되는 데이터에 따라 달라지기에 소스가 복잡해 질 수 있기에, 모든 시간대를 결과로 출력하고 isnull(열이름,0) 을 통해

null일때는 0을 출력하게 만들어줌으로 결과가 없는 시간대에는

 

01 1233 4

02 1234 2

03    0  0

04 3412 4

  

이라는 결과를 얻을 수 있다. 


자세한 설명은 읽어보지 않았지만 써보면 master..spt_values 단순히 0, 1, 2, 3, 4,  쭉 증가하는 값을 가진 테이블이라고 보면 될 것 같다.

'IT > MSSQL' 카테고리의 다른 글

MSSQL DateTime Convert.  (0) 2014.02.24
MSSQL STUFF, FOR XML PATH  (0) 2014.02.13
중첩 트랜잭션(Nested Transaction)  (0) 2014.02.06
@@IDENTITY, SCOPE_IDENTITY(), IDENT_CURRENT() 차이점.  (0) 2014.01.14
MSSQL Identity 초기화 DBCC  (0) 2013.10.01
Posted by 당양부부34
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

1. jQuery로 선택된 값 읽기

 

$("#selectBoxoption:selected").val();

$("select[name=name]").val();

 

2. jQuery로 선택된 내용 읽기

 

$("#selectBoxoption:selected").text();

 

3. 선택된 위치

 

var index =$("#test option").index($("#test option:selected"));

 

4. Addoptions to the end of a select

 

$("#selectBox").append("<optionvalue='1'>Apples</option>");

$("#selectBox").append("<optionvalue='2'>After Apples</option>");

 

5. Addoptions to the start of a select

 

$("#selectBox").prepend("<optionvalue='0'>Before Apples</option>");

 

6. Replaceall the options with new options

 

$("#selectBox").html("<optionvalue='1'>Some oranges</option><option value='2'>MoreOranges</option>");

 

7. Replaceitems at a certain index

 

$("#selectBoxoption:eq(1)").replaceWith("<option value='2'>Someapples</option>");

$("#selectBoxoption:eq(2)").replaceWith("<option value='3'>Somebananas</option>");

 

8. 지정된 index값으로 select 하기

 

$("#selectBoxoption:eq(2)").attr("selected", "selected");

 

9. text 값으로 select 하기

 

$("#selectBox").val("Someoranges").attr("selected", "selected");

 

10. value값으로 select 하기

 

$("#selectBox").val("2");

 

11. 지정된 인덱스값의 item 삭제

 

$("#selectBoxoption:eq(0)").remove();

 

12. 첫번째 item 삭제

 

$("#selectBoxoption:first").remove();

 

13. 마지막 item 삭제

 

$("#selectBoxoption:last").remove();

 

14. 선택된 옵션의 text 구하기

 

alert(!$("#selectBoxoption:selected").text());

 

15. 선택된 옵션의 value 구하기

 

alert(!$("#selectBoxoption:selected").val());

 

16. 선택된 옵션 index 구하기

 

alert(!$("#selectBoxoption").index($("#selectBox option:selected")));

 

17. SelecBox 아이템 갯수 구하기

 

alert(!$("#selectBoxoption").size());

 

18. 선택된 옵션 앞의 아이템 갯수

 

alert(!$("#selectBoxoption:selected").prevAl!l().size());

 

19. 선택된 옵션 후의 아이템 갯수

 

alert(!$("#selectBoxoption:selected").nextAll().size());

 

20. Insertan item in after a particular position

 

$("#selectBoxoption:eq(0)").after("<option value='4'>Somepears</option>");

 

21. Insertan item in before a particular position

 

$("#selectBoxoption:eq(3)").before("<option value='5'>Someapricots</option>");

 

22. Gettingvalues when item is selected

 

$("#selectBox").change(function(){

           alert(!$(this).val());

           alert(!$(this).children("option:selected").text());

});

Posted by 당양부부34
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

먼저 중첩 Transaction에 대해서 알아보도록 하겠습니다. 중첩 Transaction은 말 그대로 Transaction 안에 Transaction을 또 다시 정의하는 것을 말합니다.

예제의 그림을 보면서 설명을 드리도록 하겠습니다.



그림을 보시면 상당히 복잡한 문장 같은 데요. 하나하나 살펴보도록 하겠습니다.

이 문장은 기존에 임대되었던 임대내역을 갱신하는 문장입니다. 즉 고객이 테이프를 빌려가면서, 이미 임대에 대한 지불을 끝내고 나서, 테이프를 하나 더 빌리는 경우, 임대정보를 기존에 입력한 내역에 대해서 추가를 하는 업무입니다. 따라서 임대정보 Table에 있는 총계 정보를 갱신하고, 임대품목에는 하나의 임대내역을 추가하여야 합니다.

먼저 BEGIN TRAN TEST_1은 Transaction에 대해서 TEST_1이라는 명칭을 부여하였습니다. 이 Transaction은 모든 전체적인 문장의 Transaction입니다. 먼저 임대정보 Table에 있는 임대번호가 '2000010602'인 Data에 대해서 총계를 1500으로 갱신을 하는 문장입니다. 그리고 그 다음 문장을 보시면, BEGIN TRAN TEST_2로 또 하나의 BEGIN TRANSACTION 문장을 사용하고 있습니다. 이것이 바로 중첩 Transaction입니다. 자세한 설명은 잠시 후 그림을 통해서 드리도록 하겠습니다.

그 다음은 임대품목에 하나의 임대내역을 추가하는 문장과 해당 테이프의 대여여부를 갱신하는 문장입니다.

다음의 문장이 좀 중요한데요 보시는 바와 같이, Error에 대한 검사를 하여, 에러가 발생된 경우에는 ROLLBACK TRAN 문장을 수행하고, 그렇지 않은 경우, 즉 에러가 발생하지 않은 경우에는 두 개의 Transaction을 모두 COMMIT하여 Database에 적용을 하는 문장입니다. Transaction은 두 개이기 때문에 COMMIT문장은 두 번 쓰인 것은 이해할 수 있지만, ROLLBACK 구문이 한 번 쓰인 이유는 무엇일까요?

우선 중첩 Transaction에 대해서 설명을 드리고 ROLLBACK 구문이 한 번 사용된 이유에 대해서 설명을 드리도록 하겠습니다.

아래의 그림은 앞선 문장의 Transaction을 간략하게 정리한 것입니다.



보시는 바와 같이 BEGIN TRANSACTION 구문을 이용하여 Transaction을 시작을 한 경우에는 반드시 COMMIT을 이용하여 Transaction을 마무리 하여야 합니다.

또한 처음 시작한 Transaction 안에 여러 개의 Transaction을 중복하여 사용을 할 수 있습니다. 즉 Transaction 안에 또 다른 Transaction을 만들 수 있다는 것입니다.

앞선 예제에서는 Transaction 마다 이름을 주었지만, 이들은 생략이 가능합니다.

만약 이들 이름을 생략하게 된다면 COMMIT TRAN TEST_2는 바로 앞서서 BEGIN TRANSACTION TEST_2를 이용하여 시작하였던 Transaction에 대해서 COMMIT를 실행합니다. 즉 COMMIT 구문에서 명칭을 부여하지 않은 경우에는 가장 가까이 위치한 Transaction에 대해서 COMMIT 구문을 적용하게 된다는 것입니다.

그럼 ROLLBACK 구문은 어떨까요?

물론 Transaction이 하나의 BEGIN TRANSACTION의 문장으로 시작한 경우, ROLLBACK구문은 해당 Transaction의 모든 연산을 취소하게 됩니다. 하지만 하나 이상의 Transaction. 즉 방금 전 살펴보았던, 중복 Transaction일 경우 어떻게 될까요?

ROLLBACK의 경우에는 중복된 Transaction의 개수와는 상관없이, 가장 먼저 시작한 Transaction에 대해서 Rollback을 수행하게 됩니다. 즉 해당 Transaction 안에서 몇 개의 Transaction이 있는지에 상관없이 전체 Transaction에 대한 실행취소를 하게 됩니다.

즉 BEGIN TRANSACTION에 의해서 시작된 수 만큼 COMMIT 문장을 실행하는 것과는 조금 다른데요. 앞선 예제에서 ROLLBACK 구문이 한 번 사용된 이유는 여기에 있습니다. 따라서 앞서 예제 문장에서 만약 에러가 발생되었다면, 모든 문장에 대한 연산을 취소하고 맨 처음 시작한 TEST_1 Transaction이 시작되기 전의 상태로 되돌아가게 됩니다.


2. SAVEPOINT

조금은 불편하죠? 예제는 몇 개 되지않은 연산이었지만, 만약 여러 연산을 한 번에 실행하여야 하는 경우에, 마지막 연산에서 에러가 발생하여 Rollback으로 Transaction을 취소하였다면, 서버자원의 상당한 낭비도 초래하게 됩니다. 앞선 예제에서 만약 TEST_2 Transaction에 대한 내역만 취소하고 나머지 연산은 성공할 수 있도록 한다면 이러한 낭비는 줄일 수 있을 것입니다.

이렇게 특정 시점까지만 ROLLBACK을 할 수 있도록 지원하는 것이 바로 SAVEPOINT입니다.

우선 SAVEPOINT의 기본적인 구문을 살펴보도록 하겠습니다.

SAVE TRAN[SACTION] {savepoint_name | @savepoint_variable}

보시는 바와 같이 COMMIT 구문이나 ROLLBACK 구문과 사용방법은 같습니다.

예제를 통해서 설명을 드리도록 하겠습니다.



그림을 보시면 우편번호 Table에 Data를 입력하는 3개의 입력연산이 있습니다.

보시는 바와 같이 두 번째 Line을 보시면, SAVE TRAN 구문 다음에 SAVEPOINT의 명칭을 명시하여 SAVEPOINT를 정의하고 있습니다.

이렇게 SAVEPOINT를 정의하고, 다시 ROLLBACK을 하기 위해서는 ROLLBACK TRANSACTION 문 다음에 SAVEPOINT로 지정된 명칭을 명시하여 주면 됩니다.

자세한 내용은 실습을 통해서 설명을 드리도록 하겠습니다.

3. Transaction의 처리순서

이렇게 SQL Server는 Transaction을 이용하여 Data의 일관성을 유지할 수 있도록 지원하고 있습니다. 그럼 SQL Server가 어떻게 내부적으로 Transaction을 처리하는지에 대해서 알아보도록 하겠습니다.



그림에서 보시는 것과 같은 문장을 실행하였을 경우, MSSQL Server는 어떠한 처리과정을 거치는지 알아보도록 하겠습니다. 앞선 강좌에서 미루었던 Log에 대한 부분도 여기서 설명을 드리도록 하겠습니다.

설명을 드리기 전에 우선, Cache에 대한 부분에 대해서 알아보도록 하겠습니다. 앞서서 MSSQL Server는 Data에 대한 부분은 Data 파일에, Log에 대한 부분은 Log 파일에 저장을 한다고 하였습니다.

이렇게 Data는 SQL Server가 설치된 Computer의 Hard Disk 상에 존재하게 됩니다. 그렇다면 사용자에 의해서 Data에 대한 반환요구가 있을 경우, 매번 Hard Disk에서 해당 Data를 읽어와서 반환을 하는 작업을 거쳐야 하는데요. 이는 사용자가 느끼는 SQL Server의 속도와도 관계가 있기 때문에 성능상의 문제로 발전하게 됩니다.

이미 알고 계시듯이 Hard Disk에서 Data를 읽는 속도는 RAM의 속도와는 비교가 안될 정도로 차이가 나게 됩니다. MSSQL Server는 이렇게 성능향상을 위해서 Computer에 있는 RAM에 일부 Data를 저장하여 놓게 되는데요. 이를 Cache라고 합니다. Data와 Log에 대한 부분이 Hard Disk 상에 다른 파일로 존재하듯이, Cache에도 Data와 Log를 따로 저장하도록 하고 있습니다. 이를 Data Cache와 Log Cache로 나누어서 RAM을 사용하고 있습니다.

다시 앞선 예제문장으로 돌아가도록 하겠습니다.

1) 먼저 Transaction을 시작하는 BEGIN TRAN 문장이 수행되면, MSSQL Server는 Log Cache에 Transaction이 시작되었음을 알리는 내용을 기록합니다.

2) 두 번째로 UPDATE문이 실행이 되면, MSSQL Server는 갱신할 Data가 Data Cache에 있는지를 보고서, 만약 있다면 이를 사용하게 되고, 그렇지 않은 경우에는 Hard Disk로부터 해당 Data를 읽어와 해당 Data의 복사본을 Data Cache에 기록을 하고, 갱신문장을 수행하여 Data를 갱신하게 됩니다. 이때 Data에 대한 갱신하는 작업은 Log Cache에 기록되어 집니다. 이때 Dirty Page라는 것이 발생하게 되는데요. 이는 Cache 상의 복사본 Data와 Hard Disk 상에 있는 Data의 내용이 틀린 것을 말합니다. 앞서서 UPDATE 문장에서 기존에 있던 주소 Data(즉, Hard Disk에 저장되어 있는 Data)와 UPDATE 문장에 의해서 변경된 복사본 Data(즉, Cache에 저장되어 있는 Data)의 내용이 다른 Page를 말하는 것입니다.

3) 마지막으로 COMMIT TRANSACTION 문에 의해서 Transaction이 성공적으로 마치게 되면, Dirty Page의 내용은 Hard Disk 상의 Log 파일에 기록이 됩니다.

이렇게 SQL Server는 복사본의 내용을 Data 파일에 기록하기 전에, Log Cache를 Hard Disk의 Log 파일에 기록을 하게 됩니다. 이를 Database에서는 먼저 쓰기 로그(Write Ahead Log)라고 부릅니다.

Log만 기록하면 Data Cache에 기록된 Data는 언제 Hard Disk로 기록을 할까요? 다른 사용자가 해당 Data를 Hard Disk에서 읽어가면 갱신된 Data가 아니라 갱신되기 이전의 Data를 읽어가게 되는데, 그럼 Data의 일관성을 해치는 결과를 낳게 되는데. 이 문제들은 어떻게 할까요?

우선 첫번째로 Data Cache에 있는 변경된 Data는 Checkpoint나 Lazy Writer에 의해서 Hard Disk로 변경된 Data를 옮기게 됩니다. 바로 뒤에서 설명을 드리겠습니다.

두 번째, 다른 사용자가 Hard Disk 상에 있는 갱신되기 전의 Data를 읽어가면 어떻게 할까요? 이 문제는 걱정을 하지 않으셔도 됩니다. 앞서서 Data Cache에 대한 부분을 말씀을 드렸는데요. 만약 해당 Data에 대해서 다른 사용자가 사용을 하려 한다면, MSSQL Server는 Data Cache에 해당 Data가 있는지를 찾아보고 있다면, 그 Data를 사용하기 때문에, 다른 사용자가 갱신되지 않은 Data를 Hard Disk로부터 읽어가는 불상사는 일어나지 않습니다.

자, 그럼 방금 전 말씀을 드렸던 Checkpoint와 Lazy Writer는 무엇일까요? 하나하나 설명을 드리도록 하겠습니다.

- Checkpoint

우선 Checkpoint는 말 그대로 '검사점'입니다. 이 검사점 명령이 발생되면, SQL Server는 Cache에 있는 Data와 Log를 Hard Disk에 기록하게 됩니다. 즉, Hard Disk에 있는 내용과 사용자의 변경에 의해서 달라진 내용. 즉 Dirty Page의 내용을 Hard Disk로 넘겨주는 것입니다. 이는 언제 발생되는지는 알 수 없으며, 다만 Transaction의 사용정도와 Memory의 cache의 크기에 따라서 비주기적으로 발생됩니다.

- Lazy Writer

Computer 상의 RAM은 그 크기가 한정되어 있기 때문에, Cache 역시 그 크기가 한정되어 있습니다. 만약 Cache가 꽉 찬다면 어떻게 될까요? 이러한 경우에도 걱정하실 필요가 없습니다. Lazy Writer라는 것이 바로 Cache에 있는 내용을 바로 Hard Disk로 옮겨 적어주기 때문입니다.

이렇게 Cache에 있는 내용을 물리적인 Disk로 적어주는 기능은 Checkpoint와 Lazy Writer에 의해서 이루어지게 됩니다.

앞서서는 BEGIN TRANSACTION, COMMIT, ROLLBACK 등의 구문을 이용하여 Data의 일관성을 유지하는 것에 대해서 알아보았습니다. 이 외에도 MSSQL Server는 정전 또는 기타 다른 문제에 의해서 오류가 발생했을 경우에도 Data의 일관성을 유지할 수 있도록 지원을 하고 있습니다.

4. Transaction의 Recovery(복구)

Database에서 System 실패가 발생하는 경우는 여러 가지가 있습니다. 우선 Transaction 안에서 Overflow가 발생된다든지 하는 지역적인(Local) 고장과 정전이나 CPU의 고장, Hard Disk의 고장 등의 전역적인(Global) 고장 등이 있습니다. 지역적인 고장의 경우에는 해당 Transaction에만 영향을 미치지만, 전역적인 고장의 경우에는 고장 시 진행 중이던 Transaction에 치명적인 영향을 미치게 됩니다. 이런 경우 Database의 Data의 일관성이 깨어지게 되기 때문에, 이전의 일관된 상태로 되돌리기 위한 복구(Recovery) 작업이 필요로 하게 됩니다.

이러한 시스템 복구(Recovery)작업에 대해서 고장유형별로 알아보도록 하겠습니다. 먼저 시스템 고장일 경우의 시스템 복구에 대해서 알아보도록 하겠습니다.

▣ System 고장

시스템 고장은 예를 들어 정전과 같은 경우가 발생되는 경우, 현재 진행 중인 Transaction에 치명적인 영향을 미치게 됩니다. 이러한 경우에는 운영체제가 다시 시작될 때, MSSQL Server가 자동적으로 Transaction에 대한 내용을 다시 시작하거나(redo, roll forward), Transaction에 대한 내용을 취소하든지(undo, rollback) 하도록 지원을 합니다. 이러한 경우 시스템이 실패하였기 때문에, Cache에 기록된 내용은 이미 알 수가 없으므로, Log 파일의 기록에 의존할 수밖에 없습니다. 따라서 Log 파일에 기록된 내용을 읽어서 Database의 내용을 바꾸게 됩니다.

그럼 어떻게 Transaction의 내용을 복구하는지에 대해서 알아보도록 하겠습니다.



우선 그림을 보시면 5개의 Transaction이 시간별로 실행되고 종료되는 것을 표로 작성을 하였습니다. 보시는 바와 같이 일부는 Checkpoint가 발생되기 전에 이미 Commit이 되었고, 또 다른 Transaction은 Commit이 되기 전에 정전으로 인해서 Transaction에 대한 정보를 잃어버리게 되었습니다. 이들 각각의 Recovery(복구)작업은 다른 형태로 진행되게 됩니다.

자세한 내용은 실습을 통해서 설명을 드리도록 하겠습니다.

▣ 장치고장

다음은 장치고장의 경우입니다. 장치고장은 예를 들어 Hard Disk의 고장 또는 Disk Controller와 같은 Hardware의 고장 등이 있을 수 있습니다. 이러한 경우는 시스템 고장보다 더욱 심각한 경우인데요. 이 경우에는 앞서 시스템 고장과 같이 SQL Server가 자체적으로 복구를 할 수 없는 경우입니다. 따라서 관리자에 의해서 Data에 대한 복구가 이루어져야만 합니다. 장치고장에 대한 복구는 Database의 Backup과 Restore와 관련된 부분에서 자세하게 설명을 드리도록 하겠습니다.

5. Consideration for Using Transactions

Data의 일관성을 위해서 Transaction을 사용하는 것은 좋은 습관입니다. 하지만 무분별하게 Transaction을 오랫동안 사용하고 있다든지, 중첩 Transaction을 남용하는 것은 상당히 위험합니다. 이렇게 Transaction을 사용하는데 있어서 몇 가지 주의해야 할 점이 있습니다.

▣ Transaction Guidelines

우선 Transaction에 대한 주의할 점에 대해서 알아보도록 하겠습니다.

  • 가능하면 Transaction은 짧게 사용하여야만 합니다. 특히 WHILE문과 같이 Loop를 수행하는 문장이나 Data Definition Language와 같은 구문은 짧게 사용할수록 좋습니다. 이는 Lock과도 연관이 되는데요. Lock에 대해서는 뒤에서 설명을 드리도록 하겠습니다.
  • Transaction을 시작하기 전에, 필요한 사용자의 정보는 미리 받아 놓는 것이 좋습니다. 만약 Transaction이 정의된 상태에서 사용자의 정보를 얻거나 사용자에 의해서 입력을 받아야 하는 경우에는 Transaction이 수행되고 있는 동안에, 사용자가 해당 Data를 입력하지 않고 있다면, Transaction은 종료되지 않고 사용자의 입력을 계속해서 기다리게 됩니다.
  • Transaction 내에서 INSERT, UPDATE, DELETE 구문이 주가 되어야만 합니다. 또한 이들 구문에 의해서 영향을 받는 Row는 적어야만 합니다.

▣ Issues in Nesting Transactions

다음은 중첩 Transaction에 대한 내용입니다.

중첩 Transaction의 사용은 제한이 없지만, 가능하면 사용하지 않는 것이 좋습니다. 앞서 중첩 Transaction에서 설명을 드린 것과 같이 중첩된 Transaction과는 상관없이 가장 먼저 정의된 Transaction이 Commit 되었는지, 아니면 Rollback 되었는지에 따라서 Transaction의 성공여부가 결정되기 때문에 중첩 Transaction은 의미를 가지지 못합니다.

@@trancount라는 전역변수를 사용하여 현재 정의되어 있는 Transaction의 수를 반환 받을 수 있습니다. 만약 @@trancount가 0인 경우에는 어떠한 Transaction도 정의되어 있지 않다는 것을 뜻합니다. 또한 DBCC OPENTRAN 구문을 이용하여도 Transaction에 대한 정보를 얻을 수 있습니다.

6. Setting the Implicit Transactions Option

앞서서 묵시적 Transaction에 대해서 설명을 드렸습니다. 묵시적 Transaction 역시 나름대로 장점을 가지고 있지만, 항상 BEGIN TRAN으로 Transaction을 시작하고, COMMIT이나 ROLLBACK 구문을 이용하여 Transaction을 종료하는 것이 잘못된 입력을 막아서 Data의 일관성을 지킬 수 있도록 할 수 있기 때문입니다.

묵시적 Transaction Option은 이렇게 Transaction을 정의하는 것을 좀 더 쉽게 할 수 있도록 지원을 하고 있습니다. 묵시적 Transaction을 설정하는 기본적인 문장은 다음과 같습니다.

SET IMPLICIT_TRANSACTIONS {ON | OFF}

만약 IMPLICIT_TRANSACTION의 Option을 ON으로 하였다면, 특정 문장이 시작되면, 그 전에 BEGIN TRAN이라는 구문을 SQL Server가 자동으로 실행하여 줍니다. BEGIN TRAN 구문을 사용자가 직접 정의하지는 않았지만, SQL Server에서 정의를 해주었기 때문에 이 문장은 반드시 COMMIT 또는 ROLLBACK 구문을 이용하여 종료하여야 합니다.이렇게 MSSQL Server가 자동으로 BEGIN TRAN 문장을 실행하여 주기 때문에, 중첩 Transaction에 대한 정의는 불가능합니다.

또한 다음의 문장이 실행되면, MSSQL Server는 암시적으로 BEGIN TRAN 구문을 실행하여 Transaction을 시작하게 됩니다.

  • ALTER TABLE
  • CREATE
  • DELETE
  • DROP
  • FETCH
  • GRANT
  • INSERT
  • OPEN
  • REVOKE
  • SELECT
  • TRUNCATE TABLE
  • UPDATE

묵시적 Transaction Option의 기본값은 OFF이기 때문에 이를 사용하기 위해서는 반드시 SET 구문을 이용하여 암시적 Transaction의 Option을 ON으로 변경하여 주어야 합니다.

자세한 사용 예는 실습을 통해서 설명을 드리도록 하겠습니다

여기서 주의하여야 할 점은 묵시적 Transaction으로 정의된 문장은 반드시 COMMIT나 ROOLBACK 구문을 이용하여 Transaction을 종료하여야만 합니다.

7. Restrictions on User-Defined Transactions

사용자 지정 Transaction에는 몇 가지 제약이 있습니다. 몇몇 System Stored Procedure는 사용자 지정 Transaction에서 사용될 수 없습니다. 그 이유는 임시 Table을 생성하기 때문입니다. 예를 들어 sp_dboption과 같은 System Stored Procedure는 사용될 수 없습니다.

또한 다음의 문장들 역시 명시적 Transaction에서는 사용될 수 없습니다.

  • ALTER DATABASE
  • BACKUP LOG
  • CREATE DATABASE
  • DROP DATABASE
  • RECONFIGURE
  • RESTORE DATABASE
  • RESTORE LOG
  • UPDATE STATISTICS

 


Posted by 당양부부34
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
테이블을 생성할 때, 일련번호를 할당하기 위하여 IDENTITY를 사용하게 됩니다.

IDENTITY를 사용하할 때, 삽입한 행의 일련번호를 얻기 위하여 흔히 @@IDENTITY 함수를 자주 이용하게 되는데, @@IDENTITY 함수를 사용할 때 주의할 점이 있습니다. @@IDENTITY 함수는 현재 세션에서 삽입된 마지막 IDENTITY 값을 반환합니다. 따라서 트리거에서 다른 테이블의 IDENTITY가 새로 추가되거나 하게 되면 원치 않는 결과를 가져오게 됩니다.(@@IDENTITY 함수가 트리거에서 삽입된 IDENTITY 값을 반환함) 그래서 현재 범위(하나의 저장프로시저 내, 하나의 쿼리문 내 ...)내에서 마지막으로 추가된 IDENTITY 다음 값을 얻을 때는 SCOPE_IDENTITY() 함수를 사용해야 합니다. IDENT_CURRENT() 함수는 해당 테이블의 호출 시점의 마지막 IDENTITY 값을 반환합니다. 따라서 그 값이 다음에도 마지막 값이라고 보장할 수 없습니다. 다른 세션에서 새로운 행을 추가한 경우에는 그 값이 달라지기 때문입니다.


Posted by 당양부부34
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

코딩 표준 (HTML/ASP/JavaScript)


September 15, 2006 taggon Tip&Tech, Translation, 3

돌아다니다 주운 글인데, 일부는 좀 안맞는 것도 있지만 참고할만한 글인 것 같아서 번역해서 올린다.

http://www.csuchico.edu/web/resources/standards/code.html


코딩 표준 (HTML/ASP/JavaScript)


일반적으로 웹서비스에서는 파일, 테이블, 필드, 변수 네이밍에 첫글자를 소문자로 쓰고 복합단어를 대문자로 구분(e.g., “itemAdd.asp”, “rsStudentList”, “mlHours” 등)하는 헝가리안 표기법을 사용한다.


파일과 폴더 이름

폴더 이름 표준

변수명 (JavaScript, ASP)

HTML/ASP 코딩

Cascading Style Sheets

자바스크립트

SQL formatting

SQL 테이블과 필드

파일과 폴더 이름


모든 폴더는 index.html(혹은 .shtml, .asp)파일을 포함하도록 한다.

사이트는 논리적, 상속적인 방법으로 조직되어야 한다. 한 디렉토리에 모든 파일을 집어넣는 짓은 하지마라

모든 파일이름은 소문자라 숫자로 시작한다.

파일이름에서 숫자가 먼저 나오면 뒤에는 소문자를 쓴다 (e.g., “2editImage.asp”).

복합 단어는 대문자로 구분한다 (e.g., “itemEdit.asp”).

밑줄(“_”)이나 대시(“-”)는 파일이름에 사용하지 마세요.

파일이름에 공백을 사용하지 마세요.

같은 그룹의 페이지들은 같은 단어나 문자열로 파일이름을 시작한다(e.g., “itemAdd”, “itemAdded”, “itemEdit”, “itemEdited”). 이렇게하면 서로 연관있는 페이지들을 찾기 편하다.

서버측에서 포함되는 파일(모든 템플릿 기반 파일)에는 .shtml 을 확장자로 사용하고 .htm 이나 .html 을 사용하지 마세요.

파일이나 폴더이름 시작부분에 사용되는 축약어는 소문자로 표기한다 (e.g., “atecStaffList.asp”, “imcResources.shtml”).

예시


좋음: tlpServices.shtml


나쁨: TLPServices.shtml

나쁨: tLPServices.shtml

나쁨: tlp-services.shtml

나쁨: tlp_services.shtml

나쁨: tlpServices.htm

나쁨: tlpservices.shtml


폴더이름 표준


이미지 파일은 “/images/.” 폴더에 저장하세요.

이미지가 적은 사이트라면, 이미지 폴더를 루트 폴더 바로 아래에 두고 사이트의 모든 이미지를 그 폴더에 저장하세요.

이미지가 많고 다단계의 페이지들이 있다면, 사이트의 각 하위 폴더마다 “images” 폴더를 만들어서 각 하위 페이지에서 사용하는 모든 이미지는 각 “images” 폴더에 저장하는게 좋습니다.

큰 이미지 대신 작은 썸네일을 보여주는 사이트라면 모든 썸네일 이미지를 “images” 폴더 아래의 “thumbnails” 폴더에 저장하세요. 썸네일 이미지의 파일명은 원래 크기의 이미지와 똑같게 하세요.

포함하는 파일은 루트 디렉토리 아래의 “/_include/” 에 저장하세요.

자바스크립트 파일은 루트 디렉토리 아래의 “/_scripts/” 에 저장하세요.

CGI 스크립트는 루트 디렉토리 아래의 “/cgi-bin/” 에 저장하거나 스크립트가 사용되는 디렉토리에 저장하세요.

스타일시트 파일은 루트 디렉토리 아래의 “/_styles/”에 저장하세요.

새 사이트를 개발하는데 사용되는 파일은 루트 디렉토리 아래의 “/_dev/” 에 저장하세요.

변수명 (JavaScript, ASP)


변수명은 헝가리안 표기법을 따릅니다.


모든 이름은 소문자로 시작하도록 합니다(숫자는 안됩니다).

복합 단어 이름은 대문자로 구분하도록 합니다(e.g., “firstName”).

변수명에 밑줄(“_”)이나 대시(“-”) 를 사용하지 마세요.

설명이 없거나 심하게 축약된 이름은 피하도록 하세요. 변수가 정확히 무엇을 의미하는지 알 수 있도록 명명하는게 중요합니다(예를 들어, “firstName”을 “fn”으로 쓰지 마세요). “i”나 “x” 같은 이름은 “for” 반복문에만 쓰는게 좋습니다.


HTML/ASP 형식


실제로 사용되는 페이지는 XHTML Transitional 규격을 만족하도록 해야합니다.

모든 ASP 코드는 (Response.Write 문 포함) 올바른 XHTML 코드를 만들어내야 합니다.

모든 ASP 명령과 문장은 첫글자를 대문자로 표기하세요

모든 접속은 포함되는 파일(inculde file)을 이용하세요.

대부분의 경우, 레코드 선언은 문서의 제일 위쪽 태그 이전에 위치시키세요.

모든 레코드셋 이름은 “rs”로 시작합니다 (e.g., “rsItemInfo”).

접속을 사용하는 모든 페이지는 페이지의 마지막에서 접속을 종료해주세요 (태그 아래).

모든 질의문은 구분자가 있어야 합니다(e.g., “itemEdit.asp?itemID=33″, 이건 안됨 “itemEdit.asp?33″).

변수, 레코드셋, 질의 구분자 이름은..

소문자로 시작합니다

변수 내에서의 단어 구분은 대문자를 이용합니다 (e.g., “userFirstName”)

밑줄은 사용하지 않습니다

축약어가 첫글자부터 쓰이면 축약어 전체를 소문자로 표기합니다 (e.g., “sqlString,” 이건 안됨 “sQLString”).

매우 짧은 구문을 제외한 모든 구문은 어떤 목적으로 작성되었는지 설명하는 주석을 달아두어야 합니다.

여러줄에 걸친 구문은 코드와 분리하는 묶음기호를 이용해서 명확히 작성하도록 합니다.

< %

If aspStatement Then

?

?

End If

%>

Cascading Style Sheets


스타일 이름은 모두 소문자로 하세요 (XHTML에선 대문자가 허용되지 않습니다), 밑줄(“_”)도 안됩니다.

포맷팅을 위한 스타일은 배타적으로 사용하세요 (모든 <font>태그는 제거되어야 합니다).

기존의 HTML 요소를 적극 활용하세요. h1 태그로 필요한 스타일을 만들 수 있는데도 .head1 클래스를 추가하지 마세요.

이미 있는 스타일시트를 활용하세요. 정말로 필요할 경우가 아니라면 새 스타일을 만들지 마세요. 링크의 스타일은 전체에 적용하세요.

스타일 시트의 스타일을 알파벳순으로 정렬해놓으면 유지보수 측면에서 좋습니다.

특정 페이지에만 사용하는 스타일은 페이지 헤더에서 정의해주세요.


자바스크립트


정확한 동작을 위해서 모든 script태그는 type 과 language 를 포함해야 합니다. language=”JavaScript” type=”text/JavaScript”. 를 사용하세요.

JavaScript 변수는 ASP 변수 네이밍 규약을 따릅니다.

작성된 자바스크립트 (한페이지에서만 사용되는)는 사용될 페이지의 헤더에 위치시키세요.

여러 페이지에서 사용될 함수는 .js 파일로 만드세요. 우리의 표준에서는 .js 파일을 root/_scripts/ 폴더에 저장합니다.

자주 사용하는 함수도 자바스크립트 파일에 모아놓을 수 있습니다. 이 파일들은 절대경로로 참조하세요.


SQL 형식


모든 SQL 예약어는 대문자로 입력합니다 (e.g., SELECT * FROM tableName WHERE dtStartDate > ’3/3/03′).

여러 테이블을 쿼리할때는 JOIN 문을 이용하세요. 비표준 다중 테이블 쿼리는 자제해주세요.

SQL 테이블과 필드


테이블과 필드 이름은…

소문자로 시작합니다.

변수명 내에서의 구분은 대문자를 이용하도록 합니다 (e.g., “userFirstName”).

밑줄(“_”)은 사용하지 않습니다.

축약어가 처음에 사용되면 소문자로 표기합니다 (e.g., “sqlString”, 이건 안됨 “sQLString”)

같은 그룹의 테이블들은 같은 문자열로 시작하도록 합니다 (e.g., “mlHours”, “mlPlatform”, “mlService”).

테이블 이름에 복수형은 사용하지 않습니다.

테이블 이름과 필드 이름에 숫자는 사용하지 않습니다.

필드 이름의 첫문자를 자료형으로 표기하세요.

문자열 자료형은 (char, varChar, etc.) “s” 로 시작합니다(e.g. “sFirstName”).

정수 자료형은 “i”로 시작하되 (e.g., “iFacilityID”), 주키(primary key)로 사용되는 필드라면 “ID”로 명명합니다.

실수형은 “n” (for “numeric”) 으로 시작합니다.

날짜형은 “dt” 로 시작합니다.

비트형은 “b” 로 시작합니다.

모든 테이블은 “ID”라는 이름의 주키(primary key) 필드를 가지고 있어야 합니다. 다중 테이블 쿼리에서 필드가 테이블 이름과 함께 구분(e.g., “userList.ID”)되므로 테이블 이름과 같이 명명하지 마세요 (e.g., “ID,” 이건 안됨 “userListID”).

뷰와 스토어드 프로시저는 “view”와 “proc” 로 시작해서 테이블과 구분짓습니다 (e.g., “viewCurrentStaff,” “procCalcDaysLeft”).

Posted by 당양부부34
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

    <TABLE>

    <% For Each key in Request.ServerVariables %>

        <TR>

            <TD><%=key %></TD>

            <TD>

            <% 

                if Request.ServerVariables(key) = "" Then

                    Response.Write " " 

                else 

                    Response.Write Request.ServerVariables(key)

                end if

            %>

            </TD>

        </TR>

    <% Next %>

    </TABLE>

Posted by 당양부부34
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

1. Asp 객체
Request
Response
Server
Application   클라이언트에 공통으로 적용(=DB)
Session       클라이언트에 개별적으로 적용
 
 
2. 전역변수 (파일공유 전역변수) : 모든페이지에 적용됨
 
전역변수를 적용 할 수 있는 객체는 Application / Session 객체가 있다!
Application 클라이언트에 공통으로 적용(=DB)
Application("변수명")
 
Session 클라이언트에 개별적으로 적용
Session("변수명")   // 기본20분 유지
 
session.sessionid
클라이언트 브라우저 접속시 할당되는 id값으로 브라우저가 닫힐때 소멸된다.! (장바구니 기능등...에 용이)
 
Application & Session - 전역변수 설정 유지
세션초기값 설정페이지 - global.asa 로 작성
 
이벤트로 제어
초기값 부여할때 쓰이는 global.asa 는 처음접속시 있으면 거쳐가고 없으면 그냥 무시하고 접속하게 된다.
 
 
3. global.asa
3-1. 자바스크립트
function 함수명(){
  return 값;
}
 
3-2. VB스크립트
function 함수명()    // 리턴할수 있음
end function
 
Sub 함수명()    // 리턴할수 없음
End Sub
 
 
4. global.asa 예제
<script language=VBscript runat=Server>  'runat=Server"는 서버에서 돌아가라는 뜻!
Sub Application_OnStart  '최초 클라이언트의 접속
  '어플리케이션 변수 설정시작
  '필요없으시면 빼도 됩니다.
  Application.Lock
  Application.contents("current_user") = 0
  Application.Unlock
End Sub
 
 
Sub Session_OnStart  '개인별 클라이언트의 접속
  Session.Timeout=30 '유지시간설정 (기본은 20분)
  'Session("uid")="guest" 
  'static_table = "ccssof_static"
 
  '연결개체 생성
  Set db = Server.CreateObject("ADODB.Connection")
  db.provider = "SQLOLEDB.1" 'SQL서버를 쓴다면 보통 이렇게 쓴다.
  db.Open("Persist Security Info=False;User ID=디비ID;password=디비PW;Data Source=디비IP")
  db.defaultDatabase = "디비name"
 
  '회원통계테이블에서 오늘날짜에 현재시간에 저장되어있는 레코드가 있는지 알아보는 쿼리
  SQL = "SELECT * FROM "&static_table
  SQL = SQL&" WHERE s_year= year(getdate())"
  SQL = SQL&"and s_month=month(getdate()) and s_day = day(getdate()) and s_time = datepart(hh,getdate())"
 
  Set rs= Server.CreateObject("ADODB.Recordset")
  '###레코드 셋 열기
  rs.Open SQL,db
  If rs.eof or rs.bof Then '오늘날짜와 현재시간에 해당하는 레코드가 없다면 레코드 추가
    SQL = "INSERT INTO "&static_table&" DEFAULT VALUES "
  ELSE '아니면 해당레코드에 카운드 1증가
    s_idx = rs("s_idx")
    SQL = "UPDATE "&static_table
    SQL = SQL & " SET s_count=s_count + 1 WHERE s_idx="&s_idx
  End If
  rs.close
  Set rs = nothing
 
  '#### 연결객체를 이용한 쿼리실행(빠른실행을 위해 레코드셋객체를 만들지 않음)
  db.Execute SQL
  db.close
  Set db = nothing
 
  '현재 접속자수 계산 루틴
  '필요없다면 다음 루틴 제거
  If isnull(Application.contents("current_user")) Then
    Application.Lock
    Application.contents("current_user") = 1
    Application.UnLock    
  Else
    Application.Lock    
    Application.contents("current_user") = Application.contents("current_user") + 1
    Application.Lock        
  End If
End Sub
 
 
Sub Session_OnEnd   '개인별 클라이언트의 접속종료
  '현재 접속자수 계산 루틴
  '필요없다면 다음 루틴 제거
  
  If isnull(Application.contents("current_user")) Then
    Application.Lock
    Application.contents("current_user") = 0
    Application.Unlock
  Else
    Application.Lock
    Application.contents("current_user") = Application.contents("current_user") - 1
    Application.UnLock
  End If
End Sub
 
Sub Application_OnEnd  '최종 클라이언트의 접속
End Sub
</script>

Posted by 당양부부34
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

필자는 최전방 개발자로서 자바스크립트를 사용하는 사람들을 많이 만난다. 이들 대부분은 주로 jQuery와 몇 가지 플러그인을 사용해 멋진 라이트박스 효과나 이미지 슬라이더를 추가하는 정도의 작업을 하지만, 그중 일부는 키보드 위로 손을 올려 놓기만 해도 코드가 저절로 써진다는 ‘제다이’급 개발자들이 있다.

이 두 가지 기술 수준의 중간 어딘가에 있는 사람은 때로 어떻게 해야 할지 모르는 상황에 부닥친다. 전문적인 지식을 찾는 길은 많다. 지금 구덩이에 빠져 도움이 필요하다면 모든 자바스크립트 전문가가 알아야 하는 다음과 같은 몇 가지 개념을 살펴보라.

자바스크립트 비밀 1: 클로저(Closures)
자바스크립트의 클로저는 함수에 부모 함수의 범위에 대한 접근성을 제공한다. 개발자에게는 극히 혼란스러운 개념이다. 필자는 자바스크립트를 배울 당시 의도하지 않은 클로저로 인해 코드를 디버깅하는 데 몇 시간을 소비한 적이 있다. 이런 실수를 통해 배운 이후에는 클로저가 상당히 멋지다고 생각했고 다시 몇 시간 동안 클로저를 사용하여 문제를 해결하려 헛되이 노력하기도 했다.

결국, 배운 것은 클로저는 부모 범위에 대한 접근성을 가진 안쪽 함수(아래 고차 함수 참조)를 반환할 때 유용하다는 점이다. 이로써 변수를 보관하기 위한 일종의 비공개, 또는 보호된 환경이 만들어진다. 아래 예에서 count는 threeTimer가 호출될 때 접근 및 증분되며, 점이나 괄호 기호를 통해 직접 접근할 수는 없다.

// **Closures**
function makeThreeTimer(){
var count = 0;
return function(){
if(count < 3){
console.log('doing work');
count++;
}
else {
throw new Error('No more work');
}
}
}
var threeTimer = makeThreeTimer();
threeTimer(); // logs 'doing work' (count gets incremented)
threeTimer(); // logs 'doing work' (count gets incremented)
threeTimer(); // logs 'doing work' (count gets incremented)
threeTimer(); // throws an error
threeTimer.count; // returns undefined


자바스크립트 비밀 2: 고차 함수
기능적 프로그래밍 언어에서 함수는 1급 구성원이다. 다른 모든 값과 마찬가지로 전달할 수 있으며 이로써 흥미로운 가능성이 열린다. 고차 함수는 다른 함수를 소비 또는 생산하는 함수를 말한다. call 또는 bind와 같은 function 프로토타입의 메소드는 모두 고차 함수다. 커링(currying), 메모이제이션(memoization)과 같은 기법을 고차 함수로 표현할 수 있다. 자바스크립트에서 고차 함수를 사용하면 관점 지향 프로그래밍(Aspect-oriented programming)도 가능하다.

자바스크립트 비밀 3: 함수 호출
함수를 호출하는 가장 일반적인 방법(괄호 연산자를 사용하는 방법)을 이해한 다음에는 call과 apply를 사용하는 방법을 배울 차례다. 괄호 연산자 대비 call/apply를 사용할 때의 장점은 함수가 실행되는 컨텍스트를 지정할 수 있다는 점이다(this의 값). 이러한 형태는 고차 함수, 특히 이러한 고차 함수가 나중에 실행되는 함수를 소비할 때 볼 수 있다. Function 프로토타입에서 bing 메소드의 내부는 call/apply의 훌륭한 예다.

// Possible implementation of bind using apply
function bind(func, context){
return function(){
func.apply(context, Array.prototype.slice.apply(arguments));
}
}


자바스크립트 비밀 4: this는 무엇인가?
this 키워드는 많은 자바스크립트 개발자에게 큰 장애물로, 어떤 사람들은 아예 이 키워드를 외면한다. 필자가 지금까지 접한 이 키워드에 대한 최고의 설명은 예후다 캐츠가 함수 호출에 대한 블로그에 쓴 글이다. call/apply 또는 bind를 사용하지 않을 경우 this 값은 다음과 같은 경우를 제외하고 항상 전역 객체를 참조한다.

1. 문제의 함수가 새로운 연산자를 사용하여 호출된 경우, 현재 만들어지고 있는 새로운 객체를 가리킨다.
2. 문제의 함수가 객체의 멤버인 경우, 이 객체를 가리킨다.

단, 호출되는 함수가 클릭 핸들러 또는 setTimeout 등에서 비동기적으로 호출될 때는 2번 규칙을 무시해야 한다. 다음을 참고하라.

Person.getName(); // 'this' points to Person
setTimeout(Person.getName, 1000); // 'this' points to the global object
JavaScript secret No. 5: Protecting the global scope


자바스크립트 비밀 5: 전역 범위 보호
자바스크립트의 결함 중 하나는 페이지의 모든 스크립트가 공유되는 전역 컨텍스트에서 실행된다는 점이다. 이 결함이 악용될 경우 웹 사이트는 교차 사이트 스크립팅 공격에 취약하게 된다. 공유 전역 컨텍스트는 다른 문제도 일으킨다. 예를 들어 많은 스크립트가 한 페이지에서 실행되는데, 모든 스크립트를 개발자가 결정하는 것은 아니다(광고 스크립트 등이 대표적이다). 이 스크립트들은 전역 공간에서 실행되며 모두 같은 전역 변수에 접근할 수 있다. 이러한 스크립트 두 개가 같은 전역 변수를 사용하게 되면 서로 간섭하기 시작하고, 그러면 코드는 망가지게 된다.

전역 범위의 사용을 최소화하는 것은 간섭을 막고 긴 디버깅 시간을 줄이는 데 도움이 되는 방어적 기법이다. 변수를 전역적으로 저장하는 것을 완전히 없앨 수는 없지만 네임스페이싱과 같은 기법을 사용하면 최소화할 수 있다.

// **Namespacing**
// The global footprint is a single object containing
// all other references needed.

var MyApp = {};

MyApp.id = 42;
MyApp.utils = {
validate: function(){
//do work
}
};


또는 모듈 패턴도 있다.

// **Module pattern**
// This relies on immediately invoked anonymous functions and the
// closure they create to maintain access to variables within the
// function.

var MyApp = (function(){
//declare a local variable
var appId = 42;

function getAppId(){
//referring to a variable in this function's parent scope
return appId;
}

return {
getAppId: getAppId
};
}());

appId; // undefined
MyApp.appId; //undefined
MyApp.getAppId(); // returns 42. (Brought to you by closures)
JavaScript secret No. 6: Inheritance


자바스크립트 비밀 6: 상속
자바스크립트에서 상속은 여러 가지 이유로 긴 혼란의 역사를 갖고 있다. 대부분 개발자(필자가 만난 많은 자바스크립트 개발자들 포함)들은 클래스 모델을 충실하게 이해하지만, 프로토타입 모델에 대해서는 매우 혼란스러워한다. 프로토타입 상속을 사용하는 언어 목록을 살펴보고 나면 아마 이러한 현상을 이해할 수 있을 것이다.

자바스크립트를 제외한 다른 주류 언어에는 프로토타입 상속이 없다. 게다가 자바스크립트에서는 클래스 모델을 에뮬레이션하는 것이 가능하다. 그 결과 상속에 대한 접근 방식이 매우 다양하며, 이들 중 상당수가 독선적, 모순적이다. 의사 클래스 방식(pseudo-classical approach)은 자바스크립트의 함정 중 하나이므로 필자는 절대 사용하지 말 것을 제안한다. 대부분 개발자에게 친숙하게 보이겠지만 사실 근사치일 뿐이므로 금방 깨진다. editor@itworld.co.kr

'IT > jquery_javascript' 카테고리의 다른 글

jquery each callback function  (0) 2014.02.13
jQuery Select Box  (0) 2014.02.10
mouseover 와 mouseenter 의 차이점  (0) 2013.09.03
jquery select selector  (0) 2013.08.23
DOM Script 정리  (0) 2013.08.21
Posted by 당양부부34

블로그 이미지
주요 토렌트를 블로깅하고 있습니다. 토렌트 순위 등은 다른 사이트를 찾아보세요. 주요 웹툰 순위도 게재했어요 경제를 좋아하는 일산의 행복한 프로그래머입니다.
당양부부34
Yesterday
Today
Total

달력

 « |  » 2024.5
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함