Academic Suite 인증 및 인가
Source: Dev.to
(번역할 텍스트를 제공해 주시면 한국어로 번역해 드리겠습니다.)
3.1 Academic Suite의 인증 접근 방식
Academic Suite는 **JSON Web Token (JWT)**을 사용한 무상태 인증 방식을 사용합니다.
세션 기반 인증 (서버 메모리나 Redis에 로그인 상태를 저장)과 달리 JWT는 클라이언트가 매 요청마다 전송하는 토큰 안에 사용자 정보를 직접 포함합니다.
이 방식을 선택한 이유는 온라인 시험 시스템이 다음과 같은 특성을 갖고 있기 때문입니다:
- 높은 요청량
- 동시에 많은 사용자가 활동
- 수평 확장성 필요
3.2 왜 JWT (JSON Web Token)?
JWT는 온라인 시험 시스템 환경에서 몇 가지 중요한 장점을 제공합니다:
Scalability – 토큰 검증은 매 요청마다 데이터베이스 조회를 필요로 하지 않습니다. 서버는 단순히 토큰 서명을 검증하여, 수천 명의 학생이 동시에 활동하더라도 데이터베이스 부하를 제어할 수 있습니다.
Stateless – 서버가 세션 상태를 저장할 필요가 없으므로, 애플리케이션을 수평으로 스케일하기가 더 쉬워집니다.
Mobile‑ready – JWT는 웹 클라이언트와 모바일 클라이언트 모두에서 동일하게 작동하여, 향후 클라이언트 개발 기회를 열어줍니다.
이 접근 방식은 Academic Suite에서 사용되는 프론트엔드‑백엔드 분리 아키텍처와도 일치합니다.
3.3 인증 흐름
로그인 프로세스는 백엔드, 구체적으로 backend/handlers/auth.go 파일에 구현되어 있습니다.
전체 흐름은 다음과 같습니다:
- 요청 – 클라이언트가 JSON 형식으로 자격 증명을 전송합니다:
{ "email": "...", "password": "..." }. - 사용자 조회 – 서버가 데이터베이스에서 이메일을 기준으로 사용자를 검색합니다.
- 비밀번호 검증 – 제공된 비밀번호를 저장된 해시와 비교하여 검증합니다.
- 토큰 생성 – 자격 증명이 유효하면 서버가 사용자 정보를 포함한 JWT(claims)를 생성하고 클라이언트에 반환합니다.
클라이언트는 이후 모든 요청에 Authorization: Bearer <token> 헤더에 이 토큰을 포함시켜 전송합니다.
Bcrypt를 이용한 비밀번호 보안
Academic Suite 절대로 평문 비밀번호를 저장하지 않습니다. 비밀번호 해싱을 위해 bcrypt를 비교적 높은 비용으로 사용합니다.
// During registration or data seeding
hashed, _ := bcrypt.GenerateFromPassword([]byte("password123"), 14)
// During login
err := bcrypt.CompareHashAndPassword(
[]byte(user.Password),
[]byte(inputPassword),
)
bcrypt를 사용하면 데이터베이스가 유출되더라도 원래 비밀번호를 복원하기 어렵습니다.
3.4 JWT 및 클레임 구조
시스템에서 생성된 JWT는 claims 섹션에 중요한 데이터를 포함합니다.
claims := jwt.MapClaims{
"userId": user.ID,
"role": user.Role, // admin, teacher, student
"exp": time.Now().Add(time.Hour * 1).Unix(),
}
토큰에 저장되는 정보
userId– 사용자 식별role– 권한 요구 사항exp– 토큰 유효 기간
role을 토큰에 포함시킴으로써, 시스템은 매 요청마다 users 테이블을 조회하지 않고도 접근 권한을 확인할 수 있습니다.
3.5 인증 미들웨어
API 엔드포인트를 보호하기 위해 Academic Suite는 인증 미들웨어를 사용합니다. 이 미들웨어는:
Authorization: Bearer <token>헤더를 가져옵니다.- 비밀 키를 사용해 JWT 서명을 검증합니다.
- 클레임에서
userId와role을 추출합니다. - 해당 데이터를 요청 컨텍스트에 저장하여 하위 핸들러에서 사용할 수 있게 합니다.
예시 스니펫
c.Locals("userId", claims["userId"])
c.Locals("role", claims["role"])
return c.Next()
체인 뒤쪽에 있는 핸들러들은 인증 로직을 다시 구현하지 않고도 userId와 role에 접근할 수 있습니다.
3.6 역할 기반 접근 제어 (RBAC)
Authentication은 사용자가 누구인지 알려주고, authorization은 사용자가 무엇을 할 수 있는지 결정합니다.
Academic Suite는 RBAC를 세 가지 주요 역할로 구현합니다:
adminteacherstudent
예를 들어, teacher와 admin만 퀴즈를 생성하거나 관리할 수 있습니다.
핸들러에서 역할 검사 패턴
func CreateQuiz(c *fiber.Ctx) error {
role := c.Locals("role").(string)
if role != "teacher" && role != "admin" {
return c.Status(403).JSON(fiber.Map{
"error": "Forbidden",
})
}
// Quiz creation logic …
}
이 간단한 패턴은 제한되고 명확히 정의된 역할 집합을 가진 시스템에 효과적입니다.
3.7 Production용 보안 주의사항
프로덕션에 배포하기 전에 다음 사항을 고려하십시오:
jwtSecret소스 코드에 하드코딩해서는 안 됩니다.- 비밀 키는 환경 변수(예:
JWT_SECRET)에 저장하십시오. - 토큰 유효 기간(
exp)은 보안 요구 사항에 맞게 설정하십시오. - 더 긴 세션이 필요하면 토큰 재발급 메커니즘을 구현하십시오.
이러한 단계는 토큰 오용을 방지하고 전체 시스템 보안을 유지하는 데 필수적입니다.
장 요약
이 장에서는 다음을 통해 Academic Suite 보안의 기반을 구축했습니다:
- JWT 기반 인증 시스템 (무상태, 확장 가능, 모바일 친화적).
- 토큰에 저장된 클레임을 활용하는 역할 기반 권한 부여 메커니즘 (RBAC).
견고한 인증 및 권한 부여가 구현되면, 시스템은 이전 장에서 설명한 시험 기능을 안전하게 지원할 수 있습니다.
Nature can only be accessed by authorized users.
In **Chapter 4**, we will begin to enter the functional core of the LMS: **quiz management and question bank**, which serves as the basis for the entire online exam process.