Go 1.19 제네릭 도입 후 실무 적용기
배경
사내 API 서버는 Go 1.17로 운영 중이었다. 공통 유틸리티 함수들이 interface{}를 남발하고 있어 타입 안정성이 부족했다. Go 1.19로 업그레이드하면서 제네릭을 실무에 적용해봤다.
개선 사례
1. 슬라이스 유틸리티
기존 코드는 reflection을 사용하거나 interface{}로 처리했다.
// 기존
func Contains(slice []interface{}, item interface{}) bool {
for _, v := range slice {
if v == item {
return true
}
}
return false
}
제네릭 적용 후:
func Contains[T comparable](slice []T, item T) bool {
for _, v := range slice {
if v == item {
return true
}
}
return false
}
타입 변환 없이 사용 가능해졌고, 컴파일 타임에 타입 체크가 된다.
2. Response Wrapper
API 응답을 감싸는 공통 구조체에도 적용했다.
type ApiResponse[T any] struct {
Data T `json:"data"`
Message string `json:"message"`
Code int `json:"code"`
}
func NewSuccessResponse[T any](data T) ApiResponse[T] {
return ApiResponse[T]{
Data: data,
Message: "success",
Code: 200,
}
}
각 엔드포인트마다 응답 구조체를 만들 필요가 없어졌다.
주의사항
- 메소드에는 제네릭을 쓸 수 없다. 타입 파라미터는 함수나 타입 정의에만 가능하다
- 기존 라이브러리들이 아직 제네릭을 지원하지 않는 경우가 많다
- 과도한 사용은 오히려 코드를 복잡하게 만든다
결론
슬라이스 처리, 옵셔널 타입, 공통 래퍼 정도에만 선택적으로 적용했다. 당장 모든 코드를 바꿀 필요는 없고, 새로 작성하는 유틸리티 위주로 점진적으로 도입하는 게 현실적이었다.