이 글은 골든래빗 《Tucker 의 Go 언어프로그래밍》의 3단계 써머리입니다.
목차
- 객체지향 설계 원칙 SOLID
- 테스트와 벤치마크
- Go 언어로 만드는 웹 서버
- RESTful API 서버 만들기
객체지향 설계 5가지 원칙 SOLID
설계
→ 프로그램 코드를 이루는 각 모듈 간 의존 관계 정의
나쁜 설계
→ 상호 결합도가 매우 높고 응집도가 낮다
- 경직성 (Rigidity): 모듈간의 결합도가 높아서 코드 변경하기 어려운 구조
- 부서지기 쉬움 (Fragility): 한 부분 수정 후 다른부분까지 망가지는 경우
- 부동성 (Immobility): 모듈간 결합도가 높아서 옮길 수 없는 경우(코드 재사용률 감소)
좋은 설계
→ 상호 결합도가 낮고 응집도가 높다
객체지향 설계 5가지 원칙 SOLID
- 단일 책임 원칙: Single Responsibility Principle (SRP)
- 개방-폐쇄 원칙: Open-Closed Principle (OCP)
- 리스코프 치환 원칙: Liskov Substitution Principle (LSP)
- 인터페이스 분리 원칙: Interface Segregation Principle (ISP)
- 의존 관계 역전 원칙: Dependency Inversion Principle (DIP)
1. 단일 책임 원칙: Single Responsibility Principle (SRP)
→ 모든 객체는 책임을 하나만 져야한다.
→ 코드 재사용성을 높여줍니다.
2. 개방-폐쇄 원칙: Open-Closed Principle (OCP)
→ 확장에는 열려 있고 변경에는 닫혀 있다.
→ 상호 결합도를 줄여 새 기능을 추가할 때 기존 구현을 변경하지 않아도 됨
3. 리스코프 치환 원칙: Liskov Substitution Principle (LSP)
→ q(x)를 타입 T의 객체 x에 대해 증명할 수 있는 속성인 경우, S가 T의 하위 타입이면 q(y)는 타입 S의 객체 y에 대해 증명 가능
→ 상위 타입을 인수로 받는 함수는 하위 타입 인수에도 동작해야 한다.
→ 예상치 못한 작동을 예방
4. 인터페이스 분리 원칙: Interface Segregation Principle (ISP)
→ 클라이언트는 자신이 이용하지 않는 메서드에 의존하지 않아야한다.
→ 인터페이스를 분리하면 불필요한 메서드들과 의존 관계가 끊어져 더 가볍게 인터페이스를 이용할 수 있다.
5. 의존 관계 역전 원칙: Dependency Inversion Principle (DIP)
→ 구체화된 객체는 추상화된 객체와 의존 관계를 가져야 한다.
→ 상위 계층이 하위 계층에 의존하는 전통적인 의존 관계를 반전(역전)시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있다.
→ 상위 모듈은 하위 모듈에 의존해서는 안된다. (둘다 추상 모듈에 의존)
→ 추상모듈은 구체화된 모듈에 의존해서는 안된다. (구체화된 모듈은 추상모듈에 의존)
→ 구체화된 모듈이 아닌 추상 모듈에 의존함으로써 확장성이 증가
→ 상호 결합도가 낮아져서 다른 프로그램으로 이식성이 증가
테스트와 벤치마크
테스트 코드
→ 파일명이 _test.go로 끝나야함
→ import "testing" 패키지 임포트
→ func TestXxxx(t *testing.T)형태
→ $go test -run 테스트명
→ 테스트하고 테스트 실패를 알려주는 외부 패키지: stretchr/tesetify
블랙박스 테스트
→ 제품 내부를 오픈하지 않은 상태에서 진행되는 테스트
→ 사용자 입장에서 테스트
→ 사용성 테스트: usability test
→ 프로그램을 실행한 상태로 실행 동작을 검사하는 방식
→ 전문 테스터, QV, QA 직군에서 주로 담당
→ 내부 코드를 검증하지 않고 제품 전체의 사용성을 검사하는 방식 (코드 내부에 잠재되어 있는 버그 찾는 데 어려움)
화이트박스 테스트
→ 프로그램 내부 코드를 직접 검증하는 방식
→ 유닛 테스트(단위 테스트): unit test
→ 직접 테스트 코드를 작성해서 내부 테스트를 검사하는 방식
→ 코드를 직접 검사할 수 있지만 사용자 입장에서 전체 서비스를 검사하는데 어려움
테스트 주도 개발
- Test Driven Development (TDD)
- 테스트 코드 작성 시기를 코드 작성 이전으로 옮긴 방식
- 테스트 코드 작성 → 테스트 실패 → 코드 작성 → 테스트 성공 → 개선 → 완성
벤치마크
- 코드 성능 검사
- 파일명이 _test.go로 끝나야함
- import "testing" 패키지 임포트
- func BenchmarkXxxx(b *testing.B) 형태
- $go test -bench .
Go 언어로 만드는 웹 서버
웹서버 시작
package main
import (
"fmt"
"net/http"
)
func main() {
// 웹 핸들러 등록
// http.HandleFunc("경로",func(w http.ResponseWriter, r *http.Request) {
// fmt.Fprint(w, "Hello World")
// })
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello World")
})
// 웹 서버 시작
// func ListenAndServe(addr string, handler Handler) error
http.ListenAndServe(":3000", nil)
// <http://127.0.0.1:3000/>
// <http://localhost:3000/>
}
쿼리값 받기
package main
import (
"fmt"
"net/http"
"strconv"
)
func barHandler(w http.ResponseWriter, r *http.Request) {
values := r.URL.Query() // 쿼리 인수
name := values.Get("name") // 특정 키값 있는지 확인
if name == "" {
name = "World"
}
id, err := strconv.Atoi(values.Get("id"))
if err != nil {
// 에러처리
}
fmt.Fprintf(w, "Hello %s! id:%d", name, id)
}
func main() {
http.HandleFunc("/bar", barHandler)
// 웹 서버 시작
http.ListenAndServe(":3000", nil)
// <http://localhost:3000/bar> = Hello World! id:0
// <http://localhost:3000/bar?name=joy&id=7> = Hello joy! id:7
// <http://localhost:3000/> = 404 page not found
}
ServeMux
→ multiplexer: 멀티플렉서의 약자 (Router: 라우터)—————
→ 여러입력 중 하나를 선택해서 반환하는 디지털 장치
package main
import (
"fmt"
"net/http"
)
func main() {
// serveMux 인스턴스 생성
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World")
})
mux.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello Bar")
})
// mux 인스턴스 사용
http.ListenAndServe(":3000", mux)
}
'STUDY > Go Lang' 카테고리의 다른 글
[Go / 백준 18108번] 1998년생인 내가 태국에서는 2541년생?! (0) | 2024.09.09 |
---|---|
[3단계] Go 프로그래밍에 유용한 기법 익히기 (2) (0) | 2023.11.13 |
[Go Lang] 고급 기법으로 Go 레벨업하기 (2) (0) | 2023.10.29 |
[GoLang] 고급 기법으로 Go 레벨업하기 (1) (1) | 2023.10.22 |
[GoLang] 가볍게 Go 입문하기 (2) (1) | 2023.10.15 |