<script language="javascript" type="text/javascript">
var request = false;
try {
request = new XMLHttpRequest(); // 생성 시도. IE이외의 브라우저라면 생성됨.
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}
if (!request)
alert("Error initializing XMLHttpRequest!");
</script>
생성 로직을 별도의 함수로 만들어서 사용하면(위와 같이 정적 자바스크립트가 아닌), 생성 시 문제 발생에 대한 에러 통지기능을 지연시키므로 대부분의 Ajax 프로그래머들은 위의 방법을 활용하지 않는다.
10/15 필드가 있는 복잡한 형태에 선택상자 등등이 있다고 상상해보자. 사용자가 필드 14에 있는 텍스트를 형식에 나온 대로 기입할 때 몇 가지 Ajax 코드를 전송한다고 하면, 이 시점에서 생성 함수를 실행해 XMLHttpRequest 객체를 생성하려 했지만 실패한다. 그러면 사용자에게 이 애플리케이션을 사용할 수 없다는 것을 경고로 알리게 된다 (많은 경우). 하지만 사용자는 이미 형식 상에서 데이터를 기입하느라 시간을 보냈다. 아마도 상당히 짜증을 내게 되면서 사용자는 결국엔 사이트로 관심을 기울이지 않게될 것이다.
XMLHttpRequest로 요청 전송하기
샌드박스
Ajax는 샌드박스 보안 모델이 포함되어 있다. 그 결과 Ajax 코드(특히 XMLHttpRequest 객체)는 실행 중인 동일한 도메인에만 요청을 생성한다.
서버 URL 설정
우선 결정할 것은 연결할 서버의 URL이다. URL은 Ajax에서만 있는 것은 아니다. 분명URL을 구성하는 방법에 대해 알아야 한다. 하지만 URL은 연결 설정 시 여전히 필수적인 것이다. 대부분의 애플리케이션에서 사용자가 다루는 형식에서 나온 데이터와 정적 데이터 세트를 결합해 URL을 구성한다.
function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}
escape() 메소드는 정확히 명백한 텍스트로 전송될 수 없는 문자를 변환하는데 사용된다. 예를 들어, 전화번호에서의 임의의 공간은 %20 문자로 바뀌며 이로 인해 URL과 같이 문자를 전송할 수 있게 된다.
요청 열기
XMLHttpRequest 객체 상의 open() 메소드를 사용해 요청을 구성한다.
request-type: 전송 요청 형태. GET/POST가 일반적인 값이고 HEAD 요청도 전송함.
url: 연결된 URL.
asynch: 비동기 요청을 설정할 경우 true값, 동기식 요청인 경우에는 false임. 이 매개변수는 옵션이고 기본값이 true값임.
username: 사용인증을 요구할 경우 사용자이름을 지정한다. 옵션 매개변수고 기본값이 없다
password: 사용인증을 요구할 경우 암호를 지정한다, 옵션 매개변수고 기본값이 없다.
비동기성에 대한 문제
동기식은 다시 말하면 클라이언트는 서버로부터의 응답이 올 때까지 대기한다. 버튼을 누르면 트리거된 요청이 응답되기 전까지는 애플리케이션을 사용할 수 없다.
비동기식 요청은 서버가 응답할 때까지 대기하지 않는다. 요청을 전송한 다음에는 애플리케이션을 계속 실행한다.
요청 전송
send() 메소드는 단 하나의 매개변수인 전송 컨텐트만 있으면 된다. 그 메소드에 대해 너무 깊게 생각하기 이전에 이미 URL 자체를 통해 데이터를 전송했음을 기억하라.
콜백 메소드 지정
비동기 식 XMLHttpRequest의 경우, 자바 메소드(예에 나온 getCustomerInfo())는 서버 상에서 대기하지 않는다. 따라서 서버에 XXMLHttpRequest객체에 의해 전송된 요청에 관한 처리과정을 완료할 경우 서버는 몇 가지 형태의 명령어를 포함해야 한다. 없다면 브라우저는 서버가 요청을 처리했는지 안했는지 어떤 상태인지 알 수 없다. 이런 상황에서 바로 onreadystatechange 속성이 작용한다. 이 속성으로 콜백 메소드를 지정한다. 웹 페이지 자체에서 벌어지는 현상에 관계없이 웹 페이지로 다시 호출할 때 서버에서 개시하기 때문에 콜백이라 부르는 것이다. 예를 들어, 사용자가 의자에 앉아 키보드를 사용하지 않는 동안 콜백 메소드를 호출하기도 한다. 하지만 사용자가 입력하고 마우스를 움직이고, 화면 이동시키고 버튼을 클릭하는 동안에도 콜백 메소드를 호출하기도 한다. 사용자가 하는 업무는 그다지 중요하지 않다. 이런 상황에서 비동시성이 작용한다.
특 히 onreadystatechange 속성이 결정된 코드 위치에 주의를 기울인다. 그 위치는 바로 send()가 호출되기 전의 위치다. 요청을 전송하기 전 onreadystatechange 속성을 설정해야 한다. 그래야만, 서버에서 요청 응답을 종료할 때 onreadystatechange 속성을 탐지하게 된다.
서버 응답 처리
요청을 만들면 사용자는 웹 형식에서 여유롭게 작업하며 (서버에서 요청을 처리하는 동안에는) 서버는 요청 처리과정을 완료한다. 서버는 onreadystatechange 속성에서 나타나며 호출방법을 결정한다.
function updatePage() {
alert("Server is done!");
}
이렇게 하면 간단한 경고가 울리면서 서버가 종료될 때를 알려준다. 하지만 확인을 클릭한 경우에도 경고는 팝업을 연속한다. 브라우저에 ‘따라 웹 형식에서 경고 팝업을 중지할 때까지 경고가 두 번, 세 번, 심지어는 네 번까지 울린다. 그러면 무슨 일이 벌어지고 있는 것인가? 요청/응답 사이클의 중요 구성요소인 HTTP 준비상태에 대해 고려하지 않았다.
function updatePage() {
if (request.readyState == 4)
if (request.status == 200)
alert("Server is done!");
}
복잡성을 줄이고 더 강력한 에러 처리기능을 추가하려면 기타 상태코드에 관한 점검기능/두 가지 기능을 추가할지도 모른다.
function updatePage() {
if (request.readyState == 4)
if (request.status == 200)
alert("Server is done!");
else if (request.status == 404)
alert("Request URL does not exist");
else
alert("Error: status code is " + request.status);
}
응답 텍스트 읽기 이제 요청을 준비상태를 통해 완전히 처리하고, 서버로 정상적인 확인 응답을 상태 코드를 통해 받았으므로 서버에서 재전송되는 데이터를 최종적으로 처리한다. 이 데이터는 XMLHttpRequest객체의 responseText 속성에 저장된다.
포맷/길이에 의한 responseText 속성의 텍스트 모양에 관한 상세사항은 이 장에서는 논하지 않기로 한다. 이렇게 되면 서버는 이 텍스트를 실지로 임의로 설정한다. 예를 들어, 한 스크립트로 콤마-분리 값 및 파이프-분리 값이 나오고 또 다른 파이프-분리 값은 텍스트의 긴 문자열로 나올 수도 있다. 이런 현상은 서버에 따라 다르게 된다.
이 글에서 사용된 예의 경우, 서버는 파이프 기호로 분리된 고객의 마지막 순서 및 주소가 나오게 된다.
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var response = request.responseText.split("|");
document.getElementById("order").value = response[0];
document.getElementById("address").innerHTML = response[1].replace(/\n/g, "<br>");
} else
alert("status is " + request.status);
}
}
XMLHttpRequest 객체의 중요한 속성 중 하나인 responseXML 속성에 대해 언급한다. 이 속성은 서버가 XML과의 응답을 선택한 경우, XML 응답을 포함한다. XML 응답 처리는 평범한 텍스트 처리과정과 상당히 다르며, 문장분석 및 문서 객체 모델(DOM)을 포함한다. 많은 단순 Ajax 애플리케이션의 경우, responseText만 있으면 된다.
Ajax는 근본적으로 자바 스크립트 기술 및 웹 양식 및 서버 간의 XMLHttpRequest 객체를 결합한다. 사용자가 웹 양식을 기입할 때 데이터는 직접 서버 스크립트에 전송되지 않고 자바 스크립트 코드에 전달된다. 대신 자바 스크립트 코드는 양식 데이터를 포착해 Request를 서버에 전송한다. 이 과정이 일어나는 동안, 사용자 스크린 상의 양식은 순식간에 나타나거나 깜빡이거나 사라지거나 정지하지 않는다. 즉 자바 스크립트 코드는 몰래 Request를 전송하며 사용자는 Request가 만들어졌는지도 알지 못한다. 게다가 Request를 비동기적으로 전송하기 때문에 더 좋은 상황이 된다. 이는 자바 스크립트에서 서버 응답을 그냥 대기하지 않는다는 것을 의미한다. 따라서, 사용자는 데이터를 계속 기입하고 화면이동하고 애플리케이션을 사용한다. 그런 다음 서버는 자바 스크립트 코드(웹 양식에 대해 아직도 대기 중임)에 데이터를 다시 전송한다. 자바 스크립트 코드에서는 데이터와의 상호기능을 결정하며 연속적으로 양식 필드를 업데이트 하면서 애플리케이션에 즉각적인 응답을 준다. 결국 사용자는 양식을 제출/재생하는 작업 없이 새로운 데이터를 얻게 된다. 자바 스크립트 코드는 데이터를 얻고 계산도 수행하며 또 다른 Request를 전송하며 이런 모든 과정은 사용자 개입 없이도 된다! 이것이 바로 XMLHttpRequest 객체의 장점이다. XMLHttpRequest 객체는 서버와 같이 커뮤니케이션을 주고받고 사용자는 그 과정에서 벌어지는 과정을 알지 못한다.
일련의 수행 순서
1. 자바 스크립트 코드로 HTML 양식에서 데이터를 꺼내 이를 XMLHttpRequest 객체를 이용해서 서버에 전송
2. 서버에서 연산을 거친 결과값을 역시 XMLHttpRequest 객체를 이용해서 받아옴(XML/JSON 등으로)
3. 받아온 결과값을 필드 값 설정이나 연속적인 이미지 교체작업 등의 업데이트 작업을 수행
위의 모든 건 자바 스크립트에서 가능. 데이타는 DOM 등으로 처리.
XMLHttpRequest 객체 생성
다중 브라우저 방식으로 XMLHttpRequest 객체 생성하기
/* Create a new XMLHttpRequest object to talk to the Web server */
var xmlHttp = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e2) {
xmlHttp = false;
}
}
@end @*/
if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
xmlHttp = new XMLHttpRequest();
}
1. 변수 xmlHttp를 생성해 앞으로 생성할 XMLHttpRequest 객체를 참조한다.
2. Microsoft 브라우저에서의 객체를 시도, 생성한다.
* Msxml2.XMLHTTP 객체를 사용해 XMLHttpRequest 객체를 시도, 생성한다.
* 과정이 실패할 경우, Microsoft.XMLHTTP 객체를 사용해 XMLHttpRequest 객체를 시도, 생성한다.
3. xmlHttp가 아직도 설정되지 않은 경우 비-Microsoft 방식으로 XMLHttpRequest 객체를 생성한다.
function callServer() {
// Get the city and state from the web form
// 자바스크립트로 폼에서 데이터를 가져온다
var city = document.getElementById("city").value;
var state = document.getElementById("state").value;
// Only go on if there are values for both fields
if ((city == null) || (city == "")) return;
if ((state == null) || (state == "")) return;
// Build the URL to connect to
// 데이터를 보낼 주소를 설정
var url = "/scripts/getZipCode.php?city=" + escape(city) + "&state=" + escape(state);
// Open a connection to the server
// 서버로의 connection 열기 - 데이터 넘기는 방식(GET/POST), 주소, 연결방식(true:비동기/false:동기)
// 비동기 연결이기 때문에 사용자는 서버의 응답을 기다리지 않고 다른 작업이 가능
xmlHttp.open("GET", url, true);
// Setup a function for the server to run when it's done
// XMLHttpRequest 객체의 상태변경 시마다 호출할 함수. 즉 서버로부터의 응답이 있을 때마다 호출할 함수
xmlHttp.onreadystatechange = updatePage;
// Send the request
// null - request에 추가해 보낼 것이 없다.
xmlHttp.send(null);
}
// xmlHttp.onreadystatechange = updatePage;에서 설정한 상태변경 시마다 호출되는 함수
// 상태가 바뀔 때마다 호출되지만, 상태에 대한 조건문을 이용해서 전부 OK일 경우에만 결과에 대해 처리한다.
function updatePage() {
if (xmlHttp.readyState == 4) { // Loaded
// if(xmlHttp.status == 200) { // OK
var response = xmlHttp.responseText;
document.getElementById("zipCode").value = response;
// }
}
}
책의 제목은 웹2.0 개발자입니까? 이지만, 단순히 개발자들만이 보아야 하는 책은 아니다.
웹2.0의 개발방법론, 기술 등에 대한 이야기가 주를 이루고 있지만,
그런 기술의 사용법보다는 왜 그 기술이 필요한가에 대한 점이 훨씬 중요하다고 생각한다.
웹1.0이든 2.0이든, ajax든 json이든, 태그든 HTML마이크로포맷이든간에
이 모든 것들의 목적은 결국 사용자를 불러들이기 위한 방법이다.
그리고 사용자를 불러들일 수 있다면 수익을 얻을 수 있기 마련이다.
사용자를 불러들이기 위해선 양질의 컨텐츠가 필요하고,
양질의 컨텐츠의 생산력을 높이기 위해서 위에서 언급한 기술들이 필요하다라는 것이 이 책을 읽고 난 뒤의 감상이랄까.
결국 컨텐츠의 생산력이라는게 사용자의 참여에 달려있기에
웹2.0은 궁극적으로 사람중심의 서비스라는 말이 가슴깊이 동감한다.
웹2.0이란 용어도 정확하게 언제가 1.0이고 언제부터가 2.0이다라는 것이 아니라,
닷컴버블을 거치면서 살아남은 기업들이 가지고 있는 특징들을 정리하면서 나온 개념일 뿐이지만,
그건 다시 말하면 어려운 시기를 거치며 살아남아 지금도 잘 나가고 있는 회사들이 가진 특징이기에 그런 회사들과 경쟁하기 위해서는 당연히 가져야 할 필수조건이랄까.
이런 점에서 단순히 개발자를 위한 책이라고만은 말하기 뭐하다.
'갑'의 높으신 양반들이 좀 읽고 고민해 주었으면 좋겠다.
Query Explorer에서 DB의 정보를 가져오는 객체들을 만든 다음,
Page Explorer에서 Query Explorer가 관리하는 객체들을 가지고 원하는 형태로 리포트를 작성한다.
그밖의 리포트 생성용 조건은 Prompt Page에서, 특정 조건에 따라 리포트 형태변화 등은 Condition을 이용해서.
이미 700만이 넘게 본 영화에 대해서 이제와서 감상이라니 엄청나게 뒤늦은 감이 있지만,
그래도 일단 써놓는 걸로...
개봉한지도 오래되었으니 네타고 뭐고 없을듯?
2008년뿐 아니라 2009년에도 최고의 코미디 영화가 되지 않을까 한다.
주제의식? 뭐 그런거 없다. 생각하지 말 것! 그냥 보고 즐기면 된다.
미혼모/혼전임신 등등에 대해 떠드는 사람들도 있겠지만, 영화는 영화일 뿐.
부탁하건데 그냥 웃으면서 보길 바란다.
전반적으로 상당히 경쾌한 속도로 전개되는 점이 맘에 들고,
약간씩 분위기가 다운되려 할 때 한마디씩 던지는 기동이는 정말 최고다 ㅋ~
종반에 진짜 심각한 분위기가 한번 연출되나, 그것마저도 코믹하게 풀어내는 점이 최고였다.
기왕 웃길려면 끝까지 웃겨주는 것이 좋지 않은가~
거기서 이상하게 주제의식 드러내거나 했더라면 이렇게까지 흥행하진 못했으리라 생각한다.
우선 세계사에 약간의 관심이 있거나, 아니면 중고등학교때 배운 것을 까먹지 않은 사람이라면
히틀러가 어떻게 죽었는지는 알고 있으리라 생각한다.
그걸 기초로 하면 이 영화를 어떤 식으로 봐야하는가 답이 나온다.
일단 히틀러는 암살 당하지 않았다.
그렇다면 이 발키리라는 히틀러 암살작전은 당연히 실패했다는 걸 알게되고, 그럼 영화를 보는 관점이 바뀐다.
작전의 성공/실패에 초점을 두는 것이 아닌, 작전을 수행해 나가는 과정을 보게 된다.(물론 나의 경우....)
슈타펜버그 대령이 어떤 식으로 히틀러를 죽이려 하는가에 대한 내용을 조금만 더 스릴있게 넣어주었으면 좀더 재밌었을지도?
실패한 작전이라는 것을 영화로 만들려다 보니 뭔가 메시지는 던져야겠고
그러다 보니 영화가 조금 어중간해진 느낌도 없지 않지만, 그래도 나름 재밌게 보았다.
네이버 영화평을 보면 독일인의 관점에서 본 어쩌구... 하는 얘기도 있지만 사실 그건 잘 모르겠고,
주제를 그쪽으로 잡았다고 보기엔 내용이 빈약해서...
차라리 히틀러가 아닌, 독일을 위해 암살을 시도한다는 내용으로 갔으면 톰 크루즈의 마지막 장면이
정말 멋지게 나왔을지도 모르겠다.(지금 이대로도 괜찮긴 하지만..)
2차 세계대전이 배경이라 뭔가 액션 기대하는 분들이 있을지도 모르겠지만,
그런거 전혀 없으니 기대 마시길.
쓰다 보니 120분짜리 영화치고는 딱히 이거다 싶은 주제가 잘 안보인다는 느낌이다.
그래도 작전실행까지는 나름 긴장감있게 진행된다.
보실 분들은 마음 비우고 가서 보시길 권한다.
ROUND
ROUND는 반올림 함수이다.
형식: ROUND(숫자, 자릿수)
ROUND는 자릿수만 조심하면 된다. 2번째 결과는 8을 반올림하여 그 앞의 9에 1이 더해진것이고 3번째 결과는 9가 반올림된것이다.
CEILING, FLOOR
CEILING은 소수점 첫번째 값을 기준으로 올림을 하고 FLOOR는 소수점 첫번째 값을 기준으로 내림을 한다.
형식: CEILING(숫자) ... FLOOR도 동일
CEILING과 FLOOR는 소수 첫번째값이 5 이상이든 이하든간에 무조건 올림, 내림을 수행한다.
REPLACE
REPLACE함수는 지정한 문자열을 다른 문자열로 바꾸어준다.
형식: REPLACE(문자, 타겟문자, 바꿀문자)
REPLICATE
REPLICATE함수는 문자열을 지정된 횟수만큼 반복한다.
형식: REPLICATE(문자, 횟수)
STUFF
STUFF함수는 문자열에서 특정 시작위치에서 지정된 길이만큼 문자를 바꾸어준다.
형식: STUFF(문자, 시작위치, 길이, 바꿀문자)
SUBSTRING
SUBSTRING은 STUFF와 비슷하지만 문자를 바꾸는 것이 아니라 그 문자를 반환한다.
형식: SUBSTRING(문자, 시작위치, 길이)
PATINDEX, CHARINDEX
PATINDEX와 CHARINDEX는 문자열에서 지정한 패턴이 시작되는 위치를 뽑아준다.
형식: PATINDEX(문자패턴, 문자) - 문자패턴은 Like 사용과 같다.
형식: CHARINDEX(문자패턴, 문자) - 문자패턴은 일반형식을 사용한다.
SPACE
SPACE함수는 지정한 수 만큼 공백을 추가한다.
형식: SPACE(횟수)
시간 및 날짜 함수
GETDATE()
GETDATE()는 현재 시간을 표시해준다.
DATEADD
DATEADD함수는 날자에 지정한 만큼을 더한다.
형식: DATEADD(날자형식, 더할 값, 날자)
DATEDIFF
DATEDIFF함수는 두 날자사이의 날자형식에 지정된 부분을 돌려준다.
형식: DATEDIFF(날자형식, 시작 날자, 끝 날자)
DATENAME
DATENAME함수는 지정한 날자의 날자형식의 이름을 돌려준다.
형식: DATENAME(날자형식, 날자)
DATEPART
DATEPART함수는 날자에서 지정한 날자형식부분만 추출해줍니다.
형식: DATEPART(날자형식, 날자)
주일은 일요일부터 1로 시작해서 토요일날 7로 끝나게 된다.
--*******************************************************************
-- 함수(Conversion)
--*******************************************************************
--cast, convert : 문자로 치환/number와 date를 문자로 치환.
-- /간단한 형 변환(CAST)
-- /날짜를 문자로 변환 시 여러가지 형식이 가능하므로 주로 사용하는 함수는(CONVERT)이다.
select convert(char, 123456789) result1,
cast(123456789 as char) result2
--
select convert(varchar,456789) result1,
cast(456789 as varchar) result2,
str(456789, 10) result3
/* 숫자를 바꾸는 convert함수를 썼는데 2번째줄의 경우는 '300567'이라는 6섯자를
'char(4)' 4자로 바꾸라는 것: 이것은 말이 안되므로 * 표시가 프린트됨!(주의 사항) */
select convert(char(7),300567) result1,
convert(char(4),300567) result2
--
select convert(char,getdate(),0) result1,
cast(getdate() as char) result2
--
select convert(CHAR, GETDATE(), 109) RESULT
select convert(CHAR, GETDATE(), 111) RESUlT
select convert(CHAR(10), GETDATE(), 121) RESULT
select convert(CHAR, GETDATE(), 114) RESULT
--1. 방법1
select mem_id "회원ID",
left(mem_id,1) + right(convert(char(4),right(mem_id,3) + 1010),3) "조합회원ID"
from member
where mem_name = '이쁜이'
--2. 방법2
select mem_id "회원ID",
left(mem_id,1) + right(convert(char(4),substring(mem_id,2,4)+1010),3) "조합회원ID"
from member
where mem_name = '이쁜이'
--***********************************************************************
-- 함수(conversion) : 날짜로 치환
--***********************************************************************
--날짜로 치환/모양만 날짜형인 문자를 DATE로 치환
select'19990101'result1,'1999-01-01'result2,
'1999-01-01 00:00:00.000'result3
--
select convert(datetime,'20201025',112)" result1",
convert(datetime,'20201025')" result2",
convert(datetime,'2020-10-25 10:15:20.000') " result3",
cast('2020-10-25 10:15:20.000' as datetime) " result4"
--
--회원테이블에서 주민등록번호1을 날짜로 치환한 후 검색!
--(Alias는 회원명, 주민등록번호1, 치환날짜)
select mem_name 회원명, mem_regno1 주민등록번호1,
convert(datetime,'19'+mem_regno1) 치환날짜
from member
--1900년대 사람들만 있다고 가정했을 경우 19를 더해서 밀레니엄버그를 없앨 수 가 있다.
--회원테이블에서 주민등록번호1을 날짜로 치환한 후 500일을 더한 날짜를 검색!
--(Alias는 회원명, 주민등록번호1, 치환날짜)
select mem_name 회원명, mem_regno1 주민등록번호1,
convert(datetime,'19'+mem_regno1) + 500 치환날짜
from member
--회원테이블에서 주민등록번호1을 날짜로 치환한 후 '1974-01-01'부터 '1975-12-31'사이의 날짜를 검색!
--(Alias 회원명, 주민등록번호1, 치환날짜)
select mem_name 회원명, mem_regno1 주민등록번호1,
convert(datetime,'19'+mem_regno1) 치환날짜
from member
where convert(datetime,'19'+mem_regno1)between'1974-01-01'and'1975-12-31'
--회원테이블에서 생일을 문자로 치환한 후 LIKE '1975%'의 조건을 사용하여 해당회원을 검색!
--Alias는 회원명, 생일)
select mem_name 회원명, mem_bir 생일
from member
where convert(char, mem_bir, 121) like '1975%'
--******************************************************************
-- 함수(NULL)
--******************************************************************
/* ## 데이터를 처리할 때 NULL값의 사용은 최대한 줄여야 하지만 사용해야 할 경우가 있다.
## 학생에 대한 정보를 입력할 때 '전화번호' 속성은 전화번호가 없는 학생이 있을 수가 있다 .이런 경우에는 NULL값을 사용한다.
## NULL값은 0.1과 같은 특정한 값이 아니고 아무 것도 없는 것을 뜻한다.
## SQL에서 NULL값을 허용하지 않는 속성에 대해 NULL값으로 수정하려 한다면 에러가 발생한다. */
--null값을 찾을 때에는 is null
select buyer_name buyer_charger
from buyer
where buyer_charger is null
--null인 값을 찾을 때 '='은 성립되지 않는다.
select buyer_name buyer_charger
from buyer
where buyer_charger=null
--
select buyer_name buyer_charger
from buyer
where buyer_charger =''
--null값이 아닌 값을 찾으려 할 때 is not null
select buyer_name buyer_charger
from buyer
where buyer_charger is not null
--ISNULL(c,d) / c가 NULL값이면 d값으로 치환
--null값일 때 '이름없다' 로 출력!
select buyer_name, buyer_charger, isnull(buyer_charger, '이름없다')
from buyer
--null에다 100을 더하면 null이다.
select null + 100
--
select isnull(null,0)+100
--
select mem_name, mem_mileage, mem_mileage+100
from member
--
select mem_name, mem_mileage, mem_mileage + 100
from member
where mem_name like '[바-
WHILE @i>=@j
BEGIN
INSERT INTO @temp(date) values(@temp_date)
SET @j=@j +1;
SET @temp_date= DATEADD(dd,@j,@s_date)
END
/*SELECT date FROM @temp*/
INSERT INTO DUAL_CALENDAR
SELECT
DATENAME(yy, date), DATENAME(mm, date),
/*DATENAME(dd, date), */
SUBSTRING(CONVERT(char(10), date,121), 9, 10),
CONVERT(char(10), date,121) AS date
FROM @temp
/*여기까지 한번에 실행할 것. 100년까지는 한번에 안되는듯. 50년은 됨.
50년 마다 한번씩 실행되게 스케줄러에 등록 또는 1년마다 한번씩 되도록 등록*/
오늘(13일) 확인해 보니 노출 중지 되어있던 것이 풀렸다.
담당자분이 일일이 TTB로 글쓴 사람의 블로그를 확인해서 풀어주는 듯.
암튼 개운한 느낌.
이건 덤...
노출 중지 확인해보러 갔는데 특이한 걸 발견했다.
내가 TTB리뷰를 단 책에, 모두 6개의 TTB리뷰가 달려있는데 어떤 리뷰는 2줄 가량 리뷰의 첫머리를 보여주고
어떤 건 아니다.(내 리뷰는 보여주는 쪽.)
그래서 일일이 리뷰를 확인해 봤는데 딱히 차이를 모르겠다.
내 리뷰는 첫머리에 "볼만한 책이다"라고 써놔서 뽑힌건가 했는데, 다른 리뷰를 보니 그게 원인인 것 같지도 않고..
시간 순서도 아니고..
그냥 담당자 맘인가?
뭐랄까, 그거 2줄 보여지게 되는 것도 리뷰어로써 좀 기분좋은 느낌이랄까. 뭐 그런 식의 작용을 할 듯도 한데.
마케팅에 써먹고는 있는건지...
열심히 감상을 써서 그냥 내 블로그에만 달랑 올려놓기 뭐해서, 책을 구입한 알라딘에도 올려볼까 하다가 TTB라는 게 있길래 한번 해보았다.
알고 보니 개인 블로그에 올리는 리뷰/감상 등을 알라딘의 책소개와 연동해서 광고효과 등을 통해 이익을 배분하는(간단히 말해서) 시스템인 듯. 대충봐서 잘은 모르겠다.
하지만 글을 올리자마자 "TTB 노출 중지"라는 경고문구 비슷한게 떡하니 붙어있길래 뭔가 하고 찾아봤다.
알라딘의 TTB관련 페이지에서는 모르겠어서 네이버에 물어봤더니만,
* 올린 글이 책 리뷰가 아니면 알라딘 검색에서 내 글 노출을 중지하는듯
자동으로 중지로 설정이 되어 있고 로그인 상태에서만 내 글이
보인다.
꼭 책을 들여다 봐야 하는 리뷰여야 하는가 싶지만....
from http://www.ddibo.com/135
란다. 뭔지 잘은 모르겠지만 책 리뷰가 아니라고 판단되면 자동으로 노출을 막아버리는 듯.
알라딘의 리뷰 판단 기준이 무언지는 잘은 모르겠으나(어딘가 적혀있나?) 기껏 열심히 작성했는데 한마디 말도 없이 막아버리는 시스템은 정말 관리자 중심인 듯. 이런 일 한두번 겪으면 누가 TTB을 사용하려고 들까?
TTB라는게 심심해서 만들어 놓은 시스템이라면 정말 돈 많군이라는 생각밖에는 안든다.
p.s.
TTB작성 시, 이미 티스토리에 쓴 글을 copy&paste했는데 줄바꿈이 하나도 적용이 안되었다. 그냥 한 문단이 되어버리는 ㅡ.ㅡ;
그래서 TTB서 작성되어 티스토리에 등록된 글을 수정/태그 추가 했는데 이게 노출 금지된 원인인지? 알 수 없군.
책사는데 알라딘 밖에 이용하지 않아서 감상 쓸때 아마 앞으로도 계속 TTB을 이용하지 않을까 하는데 문제군..
p.s.2.
관련 사항이 있나해서 뒤져봤더니 이런 글이... "아직 판매수익 및 광고수익 회원자격 승인이 이루어지지 않았습니다.
판매수익 및 광고수익 회원자격
승인이 이루어지지않으면 정산이 이루어지지 않습니다.
본인확인이 된 블로거님에 대해, TTB 운영팀이 신청하신 블로그를 직접 방문한 후
판매수익 및 광고수익 회원자격 승인이 이루어집니다."
아직 승인이 안되서 그랬던 것인가...라고 지금 생각중...
그렇더라도 리뷰 판단의 기준은 무엇인지 궁금하긴 하군.
p.s.3
"- 방문자의 검색, 클릭, 서핑 등을 통해 보상프로그램을 운영하는 사이트"의 경우에는 승인이 안된단다.
흠. 혹시 구글 애드센스 달면 승인안되는건가? 궁금하군.
그래서~ 베스트셀러 책하나 골라서 TTB에 들어가 봤는데, 별문제 없는듯? 멀쩡히 구글광고가 달려있더라...
읽을 만한 책.
알라딘 서평에서 어느 분이 개발자만 읽어야 할 것이 아니라 고객도 읽어봐야 하는 책이라고 했는데 심히 공감간다.
IT관련해서 일하는 사람이라면 누구든지 한번쯤은 읽어볼만한 책이라고 생각한다.
내용자체는 아주 당연한 얘기들이지만, 그런 당연한 얘기가 와닿는 것은 그만큼 현실이 당연한 것을 지키고 있지 않기 때문이리라. 게다가 요즘하는 프로젝트가 제대로 안 돌아가서 더욱 그렇게 느끼는지도.
가장 감명 깊었던 부분은 "고객의 요구사항을 개발하라(Requirements Development)"라는 부분.
단순히 고객의 요구사항대로 개발하라는 얘기가 아니라, 고객이 원하는 요구사항을 수집해서 정의하는 작업을 말한다.
하지만 고객이 "이거이거 해주세요" 라고 말한 것만에 한정한 것이 아닌, (1)요구사항 누락을 막고 (2)실 사용자층을 정확히
파악하고 (3)고객을 프로젝트에 제대로 참여시키는 등의 작업을 통해서 최종적으로 미래의 요구사항까지도 개발하라는 얘기였다.
그밖의 공감가는 부분들...
- 사무공간 이야기
개인을 위한 공간을. 이라는 말에 심히 공감. 개인적으로 좀 민감한 편이이서 더욱 그런듯.
- 출혈경쟁/저가수주
잔업수당이 없는 것(일반적으로)과 더불어, 우리나라 개발자들이 힘들게 살아가는 가장 큰 원인이 아닐까.
- 실패하는 프로젝트의 7가지 습관
(1)사람이 무시된다 (2)추정이 모호하고 비현실적이다 (3)요구사항이 불안정하다 (4)계획 수립이 엉성하다 (5)진행 상황을 파악하지 못한다 (6)위험을 관리하는 활동이 없다 (7)품질 보증 활동이 미흡하다
- 명세없이 코드없다
일본서 일하면서 느꼈던 가장 큰 점. 문서화 문서화 문서화. 첨엔 엄청 짜증나고 그랬지만, 명세 없이 일한 경험과 비교해보면 명세란 없어선 안되는 것이라고 생각한다.
- 소프트웨어 개발을 위한 3가지 제언
(1)팀 단위 개발로의 의식전환 (2)Work Hard가 아닌 Work Smart (3)일의 보람을 문제해결 보단 고객만족에서.
개인적으로 2번은 당연한 것이라고 생각해왔으나, 1, 3번은 나 자신의 의식전환 필요성이 있다고 생각한다.
- 품질중시
개발자 자신만이 아닌, 고객의 의식전환이 선행되야 함. 아직도 어떤 고객은 터무니없는 일정/가격으로 고품질을 요구한다는. 고객이 왕인 것에도 정도가 있다.
- 프로젝트 성공 비결의 첫째가 사용자 참여란다. 고객을 참여시켜 자기편으로 만드는 것이 성공의 요체다.
개인적으로 이번 프로젝트는 고객은 참여하고 있으나, 우리편은 아니라는 ㅡ.ㅡ;;;
- 사람을 최우선으로 대하라/드림팀을 꿈꾸며.
이 부분은 나 자신의 희망사항과도 닮아있다. 나중에 여건이 되면 자신만의 팀을 조직해서 팀단위로 일해보고 싶다.
- 1. 수집단계 : 관심을 끄는 사물들을 수집
- 2. 관리 및 가공 단계 : 실행할 수 있는 것인가? 아니면 쓰레기/보류/창고, 맞으면 -> 다음 행동이 무엇인가? 프로젝트 계획으로 옮긴다. 2분내에 해결되는가? 안되면 위임/연기, 된다면 직접한다.
가공한 결과물은 달력과 행동리스트로 남게 된다. 또한 가공과정에서 특별한 행동이 요구되지 않는 것은 쓰레기, 보류, 참고에 분류된다.(조직화)
- 3. 조직화 단계 :
- 달력에 기입할 것 : 특정 시간이 정해진 행동, 특정 날짜가 정해진 행동, 특정 날짜가 정해진 정보
- '보류' : 언젠가, 어쩌면 리스트 - 지금 당장 추진하지 않아도 되는 것, 추후 확인 리스트 - 지정된 날짜에 확인할 것 지정
- 4. 검토 단계 : '주간 검토' - 핵심적인 성공 요소 ; 모든 업무를 모아 가공한다. 시스템을 점검한다. 리스트를 새로 고친다. 명확하게, 최신의 것들로 완벽하게 정리한다.
- 5. 실천 단계