3장.

앗...? DB가 없는 환경에서 동작하게 만들라고...!??!


처음 go를 쓰면서 커피 어드민 툴을 만들 때 제가 들었던 말이예요 .

지금 남는 서버가 있긴 한데, 그 서버에 있는 DB는 사용하면 안 되는게 서버를 사용할 수 있는 조건 이였어요.


그래서 FileIO를 통하여 프로그램을 작성하기로 결심했어요.


파일 io는 2가지 정도의 조건이 있을 것 같아요.

1. CSV(comma seperate version )

2. normal version.


자, 이 두 가지를 사용하기 앞서서,

앞으로 우리가 사용할 모델을 정의해 줄거예요.

앞에서 이야기 한 조건들을 생각해 보면,

"개발자 말고 다른 직군(디자이너, 기획자)도 같이 먹을 수 있게 해주세요"

"하루 이틀은 제가 빠질 수 있도록 조정하고 싶어요"

이 말을 바탕으로 생각해보면,


이름, 직군, 이메일, 참가여부

정도의 정보를 갖는 모델이 필요해요. (이메일은 결과를 메일로 받아야하기 때문이예요!)

이를 바탕으로 모델을 만들면 다음처럼 될 수 있을 것 같아요.

type Colleague struct {
Name string
Position string
Email string `gorm:"PRIMARY_KEY"`
Attend string
}


여기서 email에서 gorm을 사용했는데요, golang에서 많이 사용하는 orm이예요 . 

이거에 대해서도 하나의 포스팅으로 분리할게요!



csv파일을 컨트롤 하기 위해서는 encoding/csv 패키지의 기본 라이브러리를 사용 할거예요.

백문이 문여일견, 먼저 읽어들이는 코드를 보고 갈게요.

func getColleagueInfoFromCsv(filename string) []Colleague {
// 파일 오픈 !
file, _ := os.Open(filename)

// csv reader 생성
rdr := csv.NewReader(bufio.NewReader(file))

// csv 내용 모두 읽기
rows, _ := rdr.ReadAll()

colleagues := []Colleague{}

var temp Colleague

// 행,열 읽기
for i := range rows {
temp.Email = strings.TrimSpace(rows[i][0])
temp.Name = strings.TrimSpace(rows[i][1])
temp.Position = strings.TrimSpace(rows[i][2])
temp.Attend = strings.TrimSpace(rows[i][3])

colleagues = append(colleagues, temp) // 1
}
return colleagues
}

나 아직 여기에서 어떻게 최적화를 해야할지 모르겠어요

// 1에 있는 부분도 최적화가 가능할 것 같은데,

일단은 돌아가는 코드를 만들고, 리팩토링 하는 리뷰도 한번 만들게요.


---- 여기부터는 작성중인 문서입니다. ---- 

2장.

Golang을 이용하여 hello-world restful api 만들기.

개발 환경.

IDE : goland

web framework : echo



이 글에서는 기초적인 go를 알고 있다는 전제조건으로 진행할거예요.


그래도 go가 처음이신 분들이 있을터이니 공부할 수 있는 링크를 같이 첨부해 둘게요.


go를 익힌 다음으로 어떤 웹 프레임워크를 사용해야하나 고민이 많았어요.


java는 spring을 쓰면 되고,

javscript는 node+express를 사용하면 되고,

python은 django를 쓰면 되는데


go는 한번도 뭘 사용해야할지 잘 모르겠더라구요.

그래서 읽은 문서들이 다음 문서들이예요.


https://wikinote.bluemir.me/golang/choose-web-framework.md

https://jaehue.github.io/post/go-my-way-1-webframework/

https://okky.kr/article/386116

https://www.buzzvil.com/ko/2018/02/12/tech-blog-go-%EC%84%9C%EB%B2%84-%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%B0/

https://dev.to/speedwheel/top-6-web-frameworks-for-go-as-of-2017-34i 


결국에 제가 고른 웹 프레임워크는 echo 에요

마지막 업데이트가 1년전이라, 요즘엔 iris를 보고있긴 해요

처음부터 iris를 봤으면 좋을텐데..

맨 마지막 링크를 보시면 알다싶이, iris가 learning curve가 가장 낮아요. 

마지막 업데이트도 글 쓴 날 기준(2019년 1월 6일)으로 두 달 전이구요.


그래도 다른걸 써봐야지 어떤게 더 좋은지 아니까 ㅎㅎ


echo는 document를 봤을 때 정리가 너무 잘 되어있어서 사용 해야겠다고 결심했어요.


시작 전, 다음 코드를 터미널에서 실행하여 다운로드 해주세요


go get -u github.com/labstack/echo/...


최종코드.

reference : https://github.com/KwonGiho/go-starter/blob/master/go-simple-restful-api.go

package main

import (
"github.com/labstack/echo"
"net/http"
)

func main() {

e := echo.New() // 1

e.GET("/say", func(c echo.Context) error { // 2
return c.JSON(http.StatusOK, "hi")
})

e.Logger.Fatal(e.Start(":1331"))
}





1번. 

echo는 echo.New() 함수를 호출하면 

Echo 변수를 생성하고, 포인터 변수에 이 변수의 주소를 저장해요.

그리고 이 변수의 주소를 반환해요.


c언어를 좀 더 많이 하셨던 분을 위해서 좀 더 명확하게 작성해 드리면,

다음과 같이 작성할 수도 있어요.

var e echo.Echo
e = *echo.New()
e.GET("/say", sayHi)

e.Logger.Fatal(e.Start(":1332")) // 3


변수 사용 & 미사용 버전

reference : https://github.com/KwonGiho/go-starter/blob/master/go-simple-restful-api-seperate.go



2번.

앞으로 URI:1331/say로 오는 모든 요청을 이 함수가 책임질 예정이예요.


실행 url : localhost:1331/say

curl localhost:1331/say 

아래로 요청하면, "hi"라는 결과가 노출되요.

쿼리 스트링으로 요청을 보내고 싶으시면,

다음과 같이 사용하시면 됩니다.

name := c.QueryParam("name")


하위 url을 두고 싶으시면, 다음과 같이 사용하시면 되요.

e.GET("/say/:name", func(c echo.Context) error {
name := c.Param("name")
return c.JSON(http.StatusOK, name)
})


3번.

Fatal은 에러가 있을 시, 에러 메시지를 노출하고, os.Exit(0이 아닌 정수)을 호출하여 프로그램을 종료합니다.

이상이 없을 경우엔 아무 로그도 발생시키지 않아요.

1 장

"왜 이 시리즈를 작성 하는가?"


엄청 오랜만에 포스팅 하네요~


작년 하반기 회고 때 이런 말이 나왔어요.

"요즘 팀 내에서 사람들이 이야기 할 시간이 별로 없는 것 같아요"


그리하여, 커피 마시기 스크립트를 만들었는데요.

이 스크립트는 매일 3시~4시에 커피 마실 팀원들을 랜덤으로 3명 골라서

그 팀원들보고 커피를 마시라고 메일을 보내주는 스크립트예요.


팀 막내이기도 하고, 최근 일정이 바쁜 작업이 없기도 하고 재미있어 보여서 단번에 이렇게 말 했어요.

"앗 ㅎㅎ 이건 제가 만들어야 할 것 같습니다"


이 글을 쓰게 된 시초가 되어버렸네요.

처음에는 groovy로 작성하여,

정말 3명씩만 골라서 메일을 보내주는 스크립트를 작성했는데요.


원래 요구사항은 항상 변하는 것 같아요


1.0v을 만든 뒤, 많은 사람들이 저에게 가면서 던져준 퀘스트가 있었어요.


"교님 저2일 전에도 걸리고, 어제도 걸렸는데 오늘도 걸렸어요.. 한 번 걸리면 2일동안 안 걸리게 해주세요"

"교님, 저 저때만 프리미엄 커피 걸렸는데, 또 제 타임에 프리미엄 커피로 걸렸어요. 프리미엄 커피를 사야 할 확률을 우리가 변경할 수 있게 만들어 주세요"

"교님 우리 팀 내의 사람뿐만 아니라, 기획자랑 디자이너 분들도 추가해서 같이 마시는게 어때요 ?"

"교님 이거 코드 사내 깃에 올려서 공유좀 해주세요"

...



그래서 coffeeScriptAdmin을 만들기로 결심 했는데요.

요즘 NEXTERS에서 smart contract language을 만들고 있는데,

이거 만들면서 go를 많이 보고있어서 go로 다시 짜기로 결심했습니다.


그리하여, 2장부터는 간단한 restful api를 만들기부터, 

file-io, mysql을 이용한 DB연동까지 해볼 예정이예요.

안녕하세요~ 정말 오랜만에 블로그에 로그인하네요.

그동안 많은분들이 질문을 남겨주시고, 그 질문에 서로 대답해주는 모습을 보니 마음이 뿌듯하네요 ㅎㅎ


스타트업에 합류하고 나서, 주구장창 안드로이드만 해왔는데, 이번주부터 API서버를 만들게 되었습니다.

그 중 가장 재미있었던 파트는 API서버에서 AWS의 S3(Simple Storage Service)로 파일을 업로드하는 부분입니다.

기존의 JavaScript, JQuery 등으로 업로드 하는 부분은 많이 나와있는데, Front-end framework(or library)를 이용해서 업로드 하는 부분에 대해서 설명이 잘 되어있는 부분이 없어 포스팅을 마음먹게 했네요.


Spec

Back-end : Spring-boot

Build tool : Maven.

Front-end : Vue.js 2.0


업로드 하는 부분만 보자면 이 스펙만 따라하시면 될 것 같습니다.



Front-end.


테스트 하기 위해서 순수 JavaScript , HTML5 , CSS3로만 작성했습니다.


이렇게 작성해주면 정상적으로 작동하는데, 이번에 회사에서 Front-end 로, React or Vue를 자유롭게 선택해서 사용하라고 하셨는데,

React+Spring조합은 뭔가 세팅해줘야할게 너무 많더라구요.

그래서 Vue.js를 선택했습니다. ( 페이스북 페이지 Vue.js Kroea에 많은 정보를 항상 받아왔었거든요! )


그래서 Vue.js를 선택해 다음과 같이 코드를 작성했습니다.

이렇게 작성하니

Uncaught TypeError: Cannot set property 'ondragenter' of null

    at window.onload (updates.html:120)


이런 에러를 내뱉더라구요 이런 나쁜쉐키 -_-;

확인해보니 다음코드랑 충돌이 발생했습니다.

별에 별 짓을 다해봤습니다

onDragEnter로도 바꿔보고, addEventListener로도 바꿔보고 사용하지 말라고 했지만 혹시 몰라서 JQuery로도 작업을 해봤는데 계속 작동하지 않더라구요.

키워드로 "Vue.js 2.0 drag and drop when file upload"로 검색하니

npm을 이용해서 업로드하는 예제, 오픈소스만 주구장창 나왔습니다.

npm을 이용해서 했으면 React썻지 이사람아..


그러다 이렇게 설정해주니 되더라구요.


일단 작동하지 않는 Javascript 코드를 일부 삭제했습니다.


그리고 Vue.js에 한개의 메소드를 추가했고, 기존의 div코드에도 코드를 일부 수정해줬습니다.



이렇게해서 Front-end부분은 마무리지었습니다.


이제 남은건 Back-end인데,


Maven에 다음 코드를 넣어줍니다.


그리고 사용하시는 Controller에 @RestController 어노테이션을 적용해주시고,

s3Wrapper는 .. 알아서 만드시고..

upload메소드는 다음과 같습니다.


코드를 자세히 보신분은 이해가실테지만, 호출하는 메소드는 Multipart[]를 전달인자로 보내주는데, 받는곳은 Multipart 하나의 인스턴스로만 받습니다.


upload(Multipart[] multiparts) 메소드를 하나 만드시고, 위의 메소드를 length만큼 호출하는 메소드를 만들어주시면 됩니다! :)

코드 보시면 아시겠지만, 쓸때없는 코드라고 생각되는 부분이 조금 있습니다.

지우시고 사용하셔도 됩니다.



이렇게 작성하면 정상작동합니다.


보안상 문제로 많은 코드를 보여드릴 순 없었지만 핵심적으로 제가 맞이했던 에러들과, 작동에 필요한 코드를 모두 포함해드렸습니다.


ㄷㅐ학교 다닐때는 시간이 널널해서 포스팅 하나하나에 많은 정성을 기울여 포스팅 하고 그랬는데..


이제는 시간도 없고 코딩할 시간도, 잠 잘 시간도, 모두 부족하니 대충대충 핵심만 적게 되네요 ㅋㅋㅋㅋㅋㅋㅋ

제가 좀 더 개발을 잘하게되서 시간이 넉넉해지면 선생님의 마음으로 한땀한땀 알려드릴게요!


궁금한 점 있으시면 댓글 주세요!(언제 볼 진 잘 모르겠습니다.)


즐거운 주말 보내세요~ :')

'Web' 카테고리의 다른 글

HTTP 스펙  (2) 2016.03.29

안녕하세요~ 웹에 대하여 첫 포스팅을 하네요~


웹에 대하여 첫 포스팅은 Servlet/JSP을 이용한 간단한 예제코드를 포스팅 하려 했는데 이렇게 빗나가네 ㅎㅎㅎㅎ


해당 포스팅은 OSI7계층의 7계층인 응용 계층과 많은 연관이 있습니다. ( 통신에서의 WWW, HTTP에 대해서는 나중에 포스팅 할 예정입니다. )

이게 웹인지 OSI인지 분류를 선택하는것도 많이 어렵네요ㅋ;


HTTP스펙에 대해서 첫 포스팅을 하는 이유는 이렇습니다~

1. 저 역시 백엔드쪽을 조금 다루는 법을 알고 있지만 사용하고 있는 프로토콜의 정확한 동작 원리와 이론 등 잘 모름

2. 안드로이드 스터디에서 HTTP스펙을 발표 해야됨

3. 요즘 OSI7계층에 대해서 포스팅을 여럿 했는데 이거 공부하면 도움 많이 될거같은 느낌이 옴

4. 오늘 공강 ( 이틀 연속으로 썻..)

5. 이 포스팅은 얼마나 걸릴려나...........


스펙에 대한 내용 내용에 전반적으로 녹아들어 있으며, 포스팅의 첫 부분은 개발을 시작하는 학생/신입 개발자가 알고 있어야 할 내용으로 구성되어 있습니다.



요즘 모든 프로그램들이 MVC패턴이 적용되어 있죠. MVC패턴을 적용하는 이유는, 각 클래스가 단일 책임만을 갖기 때문에 가독성이 높아지고 유지보수가 편하며 기타 등등 많은 이유가 있습니다. 요즘 Java로 서버개발을 할 시 MVC패턴을 적용하기 위해서 스트럿츠 혹은 스프링을 많이 사용하죠. ( 전 날코딩 했었죠ㅜ )

그런 MVC 패턴이 프로그래밍 뿐만 아니라 저희 생활 어디서나 볼 수 있습니다. 뭐~ 예를 들면  부품만드는공장 조립하는공장 이런것도 MVC처럼 나눈것과도 같죠.


이런 MVC패턴이 저희가 사용하고 있는 컴퓨터, 웹 브라우저에도 적용되어 있습니다.

그림에선 Browser라 되어 있지만, 제가 사용하는 Servlet Jsp 기준으로는 WAS(Web Application Server)도 있을 수 있고,

WAS속에는 서블릿 컨테이너 뭐 이런 종류가 있을 수 있죠~!

보통 브라우저는 클라이언트의 프로토콜 해석기,제어기 이렇게 세 부분으로 나뉘어 집니다

제어기(보통 하드웨어-키보드,마우스) 로부터 입력을 받아서 브라우저를 통하여 데이터를 전송하고, 데이터를 전송할 때 HTTP,FTP,TELNET 과 같은 프로토콜을 사용하여 데이터를 전송합니다. ( 데이터를 받는애들 - 클라이언트의 요청마다 웹 서버가 해당하는 웹 페이지를를 보내줍니다! 또한 요즘에는 요청이 많은 파일을 메모리에 캐시를 해주죠! )

이렇게 전송된 데이터는 해석기에 따라 HTML 또는 Java , JavaScript 그리고 요즘 많이쓰는 파이썬등등 많이 있습니다.

문서 해석기는 상업적인것들을 예를 들면, 인터넷 익스플로러(IE), 넷스케이프 네비게이터, 파이어폭스,크롬 등등등 많은 종류가 있습니다.


이런 웹 페이지에 접근하기 위해서는 클라이언트 ( 유저 )는 주소를 필요로 합니다. 전 세계에 퍼져있는 웹 페이지들에 대한 접근을 가능하기 위하여, HTTP는 위치 지정자( resource locator )라는 개념을 사용합니다 ! URL( Uniform Resource Locator)는 인터넷에서 어떤 종류의 정보든 지정할 수 있는 표준입니다.





URL은 다음 그림과 같이, 프로토콜, 호스트(호스트컴퓨터) 포트, 경로 네 가지를 정의한놈 입니다.

그림을 2개를 첨부했습니다. 처음 포스팅 할 당시 URL은 "프로토콜 , 호스트 , 포트 , 패스"로 이루어져 있다 라고 생각을 했습니다.

하지만

를 보고 난 후부터 스키마라는 단어를 포함시켜서 포스팅을 해야겠다는 마음이 들었습니다.


프로토콜은 서버와 대화하기 위하여 사용하는 커뮤티케이션(웹 페이지(혹은 문서)를 불러오는데) 사용되는 클라이언트 서버 응용 프로그램 입니다. 웹 페이지를 불러오는 데 프로토콜들도 사용될 수 있습니다.( 이중에는 Gopher , FTP,HTTP,News,TELNET 등이 있습니다. - 이중 가장 많이 쓰이는것은 HTTP임.)


Host는 URL이라고 인식하면 쉽습니다. Host는 인터넷 상에 둘도 없는 이름입니다. 이 URL은 IP주소에 매핑됩니다. IP주소는 숫자로 구성되어 있고 현재 전 세계적으로는 IPv4를 많이 이용하고 있죠.( 제가 포스팅한 것 중에 IPv4도 포스팅 했었죠! ) 그런데 IP주소를 직접적으로 사용하지 않는 이유는, 사용하는 사람들이 쉽게 기억하기 위해서 이렇게 만든겁니다! 보통 " www "란 글자로 시작되는 별칭 이름을 갖습니다. 그러나 이것은 강제적인 사항은 아니므로, 호스트는 자유로운 URL 이름을 갖을 수 있습니다.


URL에 서버 포트를 사용하는 것은 옵션 입니다. 이는 자동차를 구매할 때 옵션을 달 수 있고 안 달수도 있는것과 같습니다. 만일 포트가 포함된다는 이는 호스트와 경로 사이에 위치해야 하죠. 디폴트값은 80포트 입니다.(HTTP프로토콜이 80번 포트에서 작동하기 때문이라 보면 됩니다!)


경로(Path)는 정보가 위치하고 있는 파일의 경로입니다. 보통 해당 서버가 있는 디렉터리에서의 상대경로를 입력하죠.



파라미터, 질의 는 보통 쿼리스트링이라 부릅니다. GET방식이라면 이 데이터는 URL의 뒷 부분에 파라미터로 쭈욱~~~ 붙어서 날아옵니다. ?마크를 필두로 파라미터 이름과 파라미터값을 한 쌍으로 해서 여러쌍일 경우 &로 구분되어서 날라오죠.



WWW에서의 웹 페이지는 정적(static), 동적(dynamic) 및 액티브( active ) 의 세 분류로 크게 나눌 수 있습니다.




정적 페이지(동적 문서)

정적 문서(static document)들은 보통 개발당시 *.html의 포맷을 갖는 애들을 정적문서라 생각하죠. 

클라이언트는 해당 웹 페이지의 복사본만을 얻을 수 있습니다. 다른말로 클라이언트가 내용을 변경할 수 없고, 해당 페이지를 관리하는 서버 관리자 혹은 개발자만이 페이지에 변경을 줄 수 있습니다.

보통 정적문서들은 HTML , XML , XSL ,XHTML입니다.( XML,XSML,XHTML 에 대해서는 태그를 정의할 수 있습니다. 보통 XHTML을 이용하여 XML을 만들고, XML을 이용하여 HTML을 만들었죠. 이 부분에 대해서는 멀지 않은 미래에 포스팅 할 수 있기를 기도합니다.)




동적 페이지(동적 문서)

동적 페이지는 브라우저에서 페이지를 요청할 때마다 웹서버에 의해서 생성됩니다. 요청이 들어오면 웹 서버는 동적 문서를 만드는 응용 프로그램이나 스크립트를 수행합니다. 서버는 프로그램의 출력이나 스크립트를 그 문서를 요청한 브라우저에게 응답으로 반환합니다. 각 요청에 대해 새로운 문서가 생성되기 때문에 동적 문서의 내용은 각각의 요청마다 달라질 수 있습니다. 동적 문서의 예는 네이버나, 넥스터즈 홈페이지에서 로그인 하면 서버로부터사용자의 이름, 기타등등 정보를 받는 것입니다.동적 페이지에서는 CGI를 빼놓고 이야기 할 수 없습니다.


공통 게이트웨이 인터페이스(CGI : Common Gateway Interface)는 동적 문서를 생성하고 처리하는 기술입니다. CGI는 동적 문서가 어떻게 작성되야 하는지 입력 데이터가 어떻게 프로그램에 제공되어야 하는지, 출력 결과가 어떻게 사용되어야 하는지를 정의하는 표준들 입니다. ( 제가 읽었던 HeadFIrst Servlet/Jsp에서도 어떤 소림사에서 어떤 CGI를 이용하여 개발을 할 것인가에 대해서 서로 싸우는 전투일화가 떠오르네요 ㅎㅎ )

CGI는 새로운 언어가 아니라, 규약 같은것 입니다. CGI는 언어의 선택은 자유롭게 하되, 따르어야 할 규칙과 용어들의 집합이죠. ( 개발자가 사용하는 언어에 대해서 제한을 받지 않는다는 뜻이죠!)

옛날 프로그램의 대부분은 사용자의 응답에 대응하는 프로그램이 아니라, 사용자가 어떤 응답을 주더라도 같은 응답을 내보내는 고전적인 프로그램들로 이루어져 있었습니다. 많이 멍청하죠??ㅋㅋㅋ 하지만 요즘은 사용자가 입력한 값에 따라 서버는 상황에 맞는 페이지로 응답을 해줍니다. 

보통 데이터는 HTML의 태그인 <form> 태그 Body속에 넣어서 보내주죠. 이것을 폼 파라메터라고도 많이 부릅니다. 

1. 이렇게 form 태그 속에 있는 데이터들의 양이 적고(URL에는 붙을 수 있는 문자의 최대 길이가 정의되어 있습니다.) 보안과 관련이 없으며, 빠른 속도를 요구하는 Get방식이 있습니다. 서버가 URL을 수신하면, URL부분의 물음표 앞부분으로 사용할 프로그램(페이지)를 선택하고, 물음표의 뒤 부분을 클라이언트의 의해 작성된 데이터로 해석합니다. 이 문자열을 변수에 저장하고, CGI프로그램이 실행될 때 이 변수의 값들을 이용합니다.

2. 데이터의 양이 많고(payload 에 데이터를 넣죠~ 편지봉투에 데이터를 넣는다 라고도 표현합니다.) Post방식으로 보내주는 경우가 있습니다.



여기에서는 Get방식과 Post방식만 설명을 했지만 아래의 표(그림)과 같이 실제론 여러가지의 메소드가 존재합니다.


여기에서 사용되는 Get방식은 표에 나와 있는것 처럼 보안에 취약합니다. URL이 사용자에게 노출이 되기 때문에 보여주지 말아야 할 정보도 모두 공개를 해버리죠. 보통 Get방식은 서버로부터 정보를 가져오기만 하는 용도로 사용하죠. 물론 무엇을 가져올 것인지 결정하기 위해서 파라미터의 힘을 빌리기도 합니다. 하지만 핵심은! 서버로 어떤 update,insert를 하기 위해서 사용하는 것이 아니라 오로지 get하기 위해서만 사용한다는것을 인식해야 합니다!

그리고 Get방식에 대해서 주의할 점이 있습니다. Get 방식은 멱등 메소드라고도 부릅니다.

이 글을 읽으시는 분들은 분명 " 멱등이 뭐시기여...하...***" 이럴거라 생각합니다 ㅋㅋㅋㅋ

멱등이란 DB에서의 트랜잭션이라 생각하면 됩니다. 만약 제가 홈쇼핑에서 빈츠 한 박스를 산다고 가정합니다. 구매에 필요한 집주소라든가 이런 정보들을 다 입력한 뒤 구매버튼을 땅~~ 하고 클릭합니다. 이 경우 결제가 진행 되는 동안에는 결제 버튼을 눌리어지면 안됩니다.(혹은 눌리어 지더라도 2중 결제가 진행되면 안되는 것이죠.) 하지만 실수로 결제버튼을 또...........클릭했습니다! 이럴경우 2중결제가 진행되어버립니다.

이렇게 HTTP1.1스펙에서는 GET,HEAD,PUT메소드들을 멱등메소드라 정의하고 있습니다. (트랜잭션이 없는것! - 혹은 비동기 적인것!)

( 아! 멱등이란 말은 여러가지의 의미를 갖습니다. 하지만 제가 주로 개발하는 환경은 HTTP / 서블릿 이므로, 동일한 요청은 서버에 어떤 잘못된 결과를 책임지라 하지 않고 수행한다는 이야기 입니다! )

이렇게 트랜잭션을 발생시켜야 하는 메소드는 POST메소드를 사용합니다. POST메소드는 HTTP1.1스펙에 의하면 멱등메소드가 아닙니다.


보통 멱등(Idempotent)는 동일한 작업을 한 번이고 두 번이고 몇번이든 계속 할 수 있을 때 사용합니다! (부작용이 없다는 가정하에서 말이죠!)







요청 메소드가 나왔으니, 응답코드를 빼 놓고 갈 순 없죠!! ( 사실 이 부분을 어디에 넣어야되나 고민을 많이 했습니다!!)

개발하면서 보통 400번에러는 클라이언트 에러고, 500번대 에러는 서버에러다 이런식으로 많이 감으로 코딩했지만 포스팅 하면서 이 개념을 명확하게 정리했네요. 해당 표는 위키백과를 참고했고, 세세하게 설명이 잘 나와 있습니다.( URL : https://ko.wikipedia.org/wiki/HTTP_%EC%83%81%ED%83%9C_%EC%BD%94%EB%93%9C )


GCI는 서버에서 CGI프로그램( Servlet / Asp / Php etc..)을 실행하고 그 출력을 클라이언트에게 되돌려 주는것입니다. 보통 되돌려 주는 정보는 HTML의 페이지 혹은 그래픽,2진데이터,상태코드 그리고 결과를 캐시하기위한 브라우저 명령어들 또는 실제 출력 대신 기존의 문서를 전송하기 위한 서버에 대한 명령어들일 수도 있습니다.

GCI의 응답은 항상 헤더와 몸체 두 부분으로 이루어 집니다.  어떤 CGI 프로그램이든 먼저 헤더, 그리고 빈 줄 , 그이후 몸체가 나옵니다. 그리고 브라우저는 이 헤더를 이용하여 몸체에 어떤 정보가 올 지 해석합니다.



앞에서 기본이지만 빼놓고 온 이야기가 하나 있습니다. 바로 요청에는 헤더가 있다는 사실인데요 클라이언트의 요청에 따라 각가에 다른 Header를 사용합니다. (방금 말 했다 싶이 CGI들은 헤더를 통하여 몸체에 어떤 데이터가 오는지 인식합니다.) 그렇다면! 헤더에는 어떤 종류가 있는지 알아봐야겠죠?! 헤더에는 General-header , Request-header, Entity-header 이렇게 3가지 종류가 있습니다. 각 헤더들이 포함하고 있는 정보들이 많더라구요, 포스팅 하면서 이 부분에 대해서 깊게 공부하지 못했습니다 ( 종강하면 꼭 후벼팔꺼야..)

해당 정보는 여기에 있습니다 : http://tools.ietf.org/html/rfc2616#section-2.2

각각의 헤더에 포함되어 있는 종류들만 엮어서 그림으로 표현했습니다.


(언제 다 볼랑가봉가)





액티브 페이지(active document)

우리는 클라이언트 단의 프로그램 또는 스크립트 개발을 필요로 하죠. 이들을 Active document(액티브 문서)라 부릅니다. 

사실상 웹 페이지에서 액티브함을 표현하기 위해서는 JavaScript라는 스크립트 개념의 프로그래밍 언어를 많이 사용합니다. ( 콜백기반이라 빡침... )

페이지의 액티브한 부분이 적다면 이는 스크립트 언어로 많이 작성합니다. 또한 클라이언트의 의해 해석되고 동시에 수행될 수 있죠. 

여기에서 ! 스크립트 소스는 바이너리 형태가 아닙니다! 텍스트로 저장이 되죠~! 



HTTP

이제서야 나오다니... HTTP새낑..

HTTP(Hypertext Transfer Protocol)은 WWW에서 데이터를 Access 하는데 주로 사용되는 프로토콜 입니다. HTTP는 FTP와 STMP의 조합과 비슷하게 동작합니다. 이것은 파일을 전송하고 TCP를 사용한다는 점에서 FTP와 비슷하죠. 그러나 이 프로토콜은 한개의 TCP연결만 사용하기 때문에 FTP보다 훨씬 간단하고 달려져 있습니다. 별도의 제어,연결 없이 데이터만 서버로 전송되기 때문이죠!

HTTP는 클라이언트와 서버 사이에서 전송되는 데이터가 SMTP 메시지와 비슷합니다. 그리고 메시지 형식이 MINE과 비슷한 헤더에 의해 제어됩니다.(아래 부분에서 MINE을 설명하겠습니다!) SMTP와는 달리 HTTP메시지는 사람이 읽을 수 없게 전송되고 오로지 서버와 HttpParser에 의해 읽혀집니다.(앞에서 말한 제어기!! HttpParser! )

또한 여기에서 차이점이 있는데, Http는 데이터를 저장하지 않고 SMTP는 데이터를 저장한 후 전송합니다. 

( SMTP는 메일 서비스를 개발해 본 개발자 혹은 학생들이라면 다 알고 있는 명칭이라고 생각합니다. 저도 Flook-레시피 큐레이션 서비스를 개발할 당시 비밀번호 찾기에서 사용한 기억이 있습니다. )

HTTP는 TCP위에서 돌아간다고 많이 알려져 있죠. 하지만 HTTP자체는 상태가 존재하지 않는(stateless) 프로토콜입니다. 이것은 클라이언트의 대한 정보가 서버에는 저장되지 않는다는 뜻입니다! 이렇게 정한 이유는 HTTP를 설계할 당시, 지구에 있는 모든 장비들이 인터넷과 접속을 하고 있으면, 많은 메모리와 CPU의 성능을 요구했기 때문이죠. 그렇기 때문에 클라이언트트는 서버에 연결을 맺고, 요청을 보낸 뒤, 응답을 받습니다. 그리고는 연결을 끊죠. 즉 연결이라고 하는 것은 한 번의 요청과 응답을 위해만 존재한다고 생각할 수 있습니다. 

그렇다는건 즉, 지속적인 연결이 아니기 때문에 클라이언트가 두 번째부터 맺는 요청은 똑같은 클라이언트언트라 할 지라도 서버는 이를 인식하지 못합니다.서버는 각각 다른놈이 요청했다고 생각하겠죠! UDP처럼!

그렇기 때문에 클라이언트는 서버에게 "나!! 있잖아! 방금전에 ~~ 이거 했었던 클라이언트야! "라는 정보를 흘려줘야 합니다. 

이런 문제떄문에 등장한 기술이 세션,쿠키 입니다! 보통 많은 개발 서적에 쿠키가 정말 맛있는 초콜렛 쿠키 그림을 많이 넣죠! 그래서 전 얼마전에 구입한 빈츠 한 박스를 넣었죠!캬캬캬캬캬캬컄컄캬캬캬컄ㅋㅋㅋ



그럼 서버에게 " 나 있잖아!!! 방금 그놈!! " 하는 과정에 대해서 알아보죠!



먼저 사용자는 서버에게 세션이 필요하다는 뜻을 전달해야 합니다. 그래야 서버가 쿠키안에 세션ID를 채우고, 해당하는 세션을 우리에게 발급해 줍니다.

그럼 다음번 요청부턴 클라이언트가 세션 아이디와 함께 요청을 서버로 전달합니다. 그런 다음부터 서버는 클라이언트를 인식할 수 있는거죠.

요즘의 CGI는 대부분 Session을 기본 API로 제공합니다. 즉, 개발자는 옛날엔 Session을 한 땀 한 땀 손수 만들어야 했지만, 지금은 전혀 그럴 필요가 없는거죠!( 한땀한땀 만들어 보고 싶기도 하고ㅋㅋㅋㅋ)


근데 큰 문제점이 있어요! 저 같은 경우에도 학교 컴퓨터에선 웹 서핑 시 시크릿모드를 많이 이용하곤 합니다. PC방에선 쿠키정보를 클라이언트에 저장하지 않구요. 

개발자는 물론 이런 상황에도 대처해야 합니다! ( 누구나 편하게 사용할 수 있는 서비스를 개발해야되는 개발자님들..) 

이런 경우 URL 재작성 기법을 많이 사용합니다. 그림에서 보여준 JSESSIONID=0AAB6C8DE415를 URL에 붙혀서 재전송 해주도록 개발해야 합니다.

Servlet의 경우 JSESSIONID라 부르고, 다른 CGI에서는 부르는 용어가 다릅니다.


참고 자료

https://blog.outsider.ne.kr/888

http://tools.ietf.org/html/rfc2616#section-2.2

http://c8korea.blogspot.kr/2013/06/http-trace.html

http://devday.tistory.com/2287

http://mindseye.tistory.com/145

HeadFirst Servlets&JSP(O'REILLY 출판사)

TCP/IP프로토콜 제 4판(McGraw-Hill Korea 출판사)

+ Recent posts