Academic Suite 인증 및 인가

발행: (2025년 12월 29일 오후 12:09 GMT+9)
8 min read
원문: Dev.to

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 파일에 구현되어 있습니다.

전체 흐름은 다음과 같습니다:

  1. 요청 – 클라이언트가 JSON 형식으로 자격 증명을 전송합니다: { "email": "...", "password": "..." }.
  2. 사용자 조회 – 서버가 데이터베이스에서 이메일을 기준으로 사용자를 검색합니다.
  3. 비밀번호 검증 – 제공된 비밀번호를 저장된 해시와 비교하여 검증합니다.
  4. 토큰 생성 – 자격 증명이 유효하면 서버가 사용자 정보를 포함한 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는 인증 미들웨어를 사용합니다. 이 미들웨어는:

  1. Authorization: Bearer <token> 헤더를 가져옵니다.
  2. 비밀 키를 사용해 JWT 서명을 검증합니다.
  3. 클레임에서 userIdrole을 추출합니다.
  4. 해당 데이터를 요청 컨텍스트에 저장하여 하위 핸들러에서 사용할 수 있게 합니다.

예시 스니펫

c.Locals("userId", claims["userId"])
c.Locals("role", claims["role"])

return c.Next()

체인 뒤쪽에 있는 핸들러들은 인증 로직을 다시 구현하지 않고도 userIdrole에 접근할 수 있습니다.

3.6 역할 기반 접근 제어 (RBAC)

Authentication은 사용자가 누구인지 알려주고, authorization은 사용자가 무엇을 할 수 있는지 결정합니다.

Academic Suite는 RBAC를 세 가지 주요 역할로 구현합니다:

  • admin
  • teacher
  • student

예를 들어, teacheradmin만 퀴즈를 생성하거나 관리할 수 있습니다.

핸들러에서 역할 검사 패턴

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.
Back to Blog

관련 글

더 보기 »

JSON Web Token (JWT) 이해하기

어떤 시점에 웹 애플리케이션을 만들 때, 시스템을 위한 인증 솔루션을 개발해야 합니다. 이를 위한 다양한 전략이 있으며, 예를 들어…