LabHub
배우기 러닝패스 코스

Goでサーバを作る

標準ライブラリだけでサーバを作る

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

표준 라이브러리만으로 HTTP 서버를 만들면서 Go 가 무엇을 강제하는지 봅니다. 프레임워크를 고르기 전에 net/http 가 이미 무엇을 주는지 확인합니다.

왜 중요한가

Go 를 처음 쓰는 사람은 if err != nil 이 지겹다고 말합니다. 그런데 그 길이는 비용이 아니라 명시성의 가격입니다 — 어느 줄이 실패할 수 있는지가 타입에 적혀 있고, 무시하려면 무시한다고 적어야 합니다.

이 실습에서는 그 대가와 이득을 둘 다 만져 봅니다. 그리고 Go 에서 실제로 사고가 나는 자리(고루틴 누수, 취소 미전파)를 직접 만들어 봅니다.

환경

네트워크가 없어 go get 은 동작하지 않습니다. 이 실습은 표준 라이브러리만 쓰므로 상관없습니다 — 오히려 그게 이 코스의 논점입니다.

go mod init <이름>     모듈 시작
go build -o srv .      빌드
go vet ./...           흔한 실수 찾기
gofmt -l .             포맷이 어긋난 파일 나열

단계

  1. 모듈 초기화 → /root/work/gosrv/go.mod
  2. /health 서버
  3. 에러를 값으로 (%w 로 감싸기)
  4. errors.Is/As/root/work/gosrv/04-errors.txt
  5. JSON 응답 → /root/work/gosrv/05-json.txt
  6. context 로 취소 전파 → /root/work/gosrv/06-ctx.txt
  7. 고루틴 누수 → /root/work/gosrv/07-leak.txt
  8. go vet / gofmt/root/work/gosrv/08-vet.txt

참고

모듈을 만든다

모듈 초기화 → /root/work/gosrv/go.mod

mkdir -p /root/work/gosrv && cd /root/work/gosrv && go mod init labhub.local/gosrv. 네트워크가 없으므로 외부 패키지는 못 받습니다 — 이 실습은 표준 라이브러리만 씁니다. go.mod 가 생기면 됩니다.

HTTP 서버 한 개

/health 서버

main.gonet/http/health 를 만들고 8080 에서 듣게 합니다. go build -o srv . 로 빌드한 뒤 ./srv & 로 띄우고 curl -s localhost:8080/health 로 확인하세요. 프레임워크 없이 이만큼이 표준 라이브러리에 있습니다.

에러를 값으로 돌려준다

에러를 값으로 (%w 로 감싸기)

parseAge(s string) (int, error) 를 만들어 숫자가 아니면 에러를 돌려주게 합니다. 감쌀 때는 fmt.Errorf("나이 파싱(%s): %w", s, err) 처럼 %w 를 쓰세요. %v 로 감싸면 원본을 잃어 errors.Is 로 물어볼 수 없게 됩니다.

원인을 물어본다

errors.Is/As/root/work/gosrv/04-errors.txt

errors.Is 또는 errors.As 로 감싼 에러의 원인을 판별하는 코드를 넣고, 그 출력을 /root/work/gosrv/04-errors.txt 에 저장하세요. 감싼 에러에서 원본을 꺼낼 수 있다는 것을 눈으로 확인하는 것이 목적입니다.

JSON 을 돌려준다

JSON 응답 → /root/work/gosrv/05-json.txt

encoding/json 으로 구조체를 응답합니다. 필드 태그(json:"name")를 붙이지 않으면 대문자 그대로 나갑니다 — Go 의 export 규칙 때문입니다. curl -s localhost:8080/api | jq . 결과를 /root/work/gosrv/05-json.txt 에 저장하세요.

취소를 전파한다

context 로 취소 전파 → /root/work/gosrv/06-ctx.txt

느린 핸들러를 만들고 r.Context()Done() 을 감시해 클라이언트가 끊으면 일을 멈추게 하세요. curl --max-time 1 로 끊고 서버 로그에 취소가 찍히는지 봅니다. 출력을 /root/work/gosrv/06-ctx.txt 에 저장하세요.

고루틴이 새는 것을 본다

고루틴 누수 → /root/work/gosrv/07-leak.txt

일부러 새는 고루틴(받는 쪽 없는 채널로 보내기)을 만들고 runtime.NumGoroutine() 을 전후로 찍어 /root/work/gosrv/07-leak.txt 에 저장하세요. 숫자가 늘어난 채로 안 줄어드는 것이 누수입니다.

도구에게 먼저 물어본다

go vet / gofmt/root/work/gosrv/08-vet.txt

go vet ./...gofmt -l . 을 돌려 결과를 /root/work/gosrv/08-vet.txt 에 저장하세요. 둘 다 조용하면 통과입니다. Go 는 포맷을 논쟁하지 않습니다 — gofmt 가 정답이고, 그래서 리뷰에서 그 얘기가 사라집니다.