웹사이트 특정 페이지를 비밀번호로 보호하기

이 프로젝트에 대해

아루나님이 만들어주신 나만의 학습허브 페이지에 학습일지를 추가해보았습니다.
그동안의 학습일지를 로컬에만 저장해두기에는 아깝다고 생각했거든요.

사이트는 크게 두 부분으로 나뉘어요:

  • 공개 부분: 사례글, 개념페이지, 로드맵 (4주 뒤 전자책이 됨)

  • 비공개 부분: 학습일지 (매일 배운 것을 솔직하게 기록)

학습일지는 실수, 막힘, 고민까지 다 담기 때문에 비밀번호로 보호하기로 했습니다.

한국어가 포함된 웹사이트 스크린샷

참고로, 개인작업한 내용을 사례글로 올린 것도 [개인작업] 섹션을 만들어 정리해보았습니다.

이제 길어지면 '접히기' 기능으로 토글 처럼 만들어둘까 해요.

한국어 앱 스크린샷

👥 이런 분께 추천

  • 개인 블로그나 학습 기록을 비공개로 유지하고 싶은 분

  • 웹사이트의 일부만 비밀번호로 보호하고 싶은 분

  • 개발자 없이 간단한 인증 기능을 구현해보고 싶은 분

  • “보안”이 겁나지만 기초부터 배우고 싶은 분

(수정)

이럴수가.. 알고보니 비밀번호 페이지를 추가해도 내용은 아주 손쉽게 확인할 수 있었습니다.

진짜 암호화를 하려면 다른 방법이 필요한데 그 방법은 아래 사례글을 통해 확인했습니다..!

https://www.gpters.org/dev/post/beuraujeo-amhohwa-bimilbeonho-seoljeongeun-jinjja-jamgeumi-anieossda-iezFOOiedZfDDWH

한국사이트 스크린샷

📝 한줄 요약

누구나 들어갈 수 있는 학습허브 사이트에서 개인 학습기록만 비밀번호로 보호했습니다.

Before: 학습일지도 모두에게 공개 (비공개 옵션 없음)
After: 비밀번호 입력 후 접근 가능 (같은 브라우저에서 2시간 유지)

🙋 내 스펙 & 환경

항목

내용

직업

비개발자. 이번이 처음 웹사이트 운영

코딩 경험

1달차 (Astro, JavaScript 초급)

보안 경험

”암호화”=“비밀번호”로 알았던 수준

환경

Windows, Claude Code + AI

고민

비밀번호 저장 방식, 암호화가 필요할까


진행 방법

1. 문제 상황: 개인 정보를 공개하고 싶지 않은데

학습허브는 전자책으로 나올 사례글과 개념페이지만 공개하려고 했어요. 하지만 그 과정을 적는 “학습일지”는 개인 노트라 실수, 고민, 막힘까지 솔직하게 적었습니다.

“학습일지”는 비공개, “사례글”은 공개 하고 싶었는데, 기술적으로 어떻게 해야 할지 몰랐어요.

사이트 전체를 비공개하거나 학습일지 폴더를 없애는 방법밖에 없을 줄 알았습니다.

해결하고 싶던 것:

  • 같은 사이트에서 특정 페이지만 비밀번호 보호

  • 비밀번호를 입력하면 같은 브라우저에서 계속 접근 가능 (매번 입력하는 건 불편)

  • 개발자 없이 구현

2. 첫 번째 벽: “어디에서” 비밀번호를 확인할까

가능한 방법들을 생각해봤어요:

  1. 서버에서 확인 (전통적 방식): 비밀번호를 서버 데이터베이스에 저장하고 검증

    • 장점: 더 안전하다고 느껴짐

    • 단점: 서버 구축 필요, 복잡함, 관리 비용

  2. 브라우저에서 확인 (클라이언트 측): 비밀번호를 JavaScript로 직접 비교

    • 장점: 간단함, 개발자 불필요

    • 단점: “보안이 약하지 않을까?” 하는 불안감

AI에게 물었어요:

학습일지 페이지만 비밀번호로 보호하고 싶은데, 
서버가 없으니 클라이언트 측에서 비밀번호를 확인해도 괜찮을까?
이 수준의 보안으로 충분할까?

답변의 핵심:

“학습일지는 기밀 정보가 아니라 ‘공개하고 싶지 않은’ 개인 기록입니다. 비밀번호는 ‘실수로 들어오는 사람’을 막는 정도면 충분합니다. 클라이언트 측 인증은 이 목적에 맞습니다.”

배운 것: 보안에는 레벨이 있다는 것. 은행 계좌는 AES-256 암호화가 필요하지만, 개인 일지는 단순 비밀번호 입력으로도 충분하다는 걸 알았어요.

3. 두 번째 벽: 비밀번호를 “어디에” 저장할까

비밀번호를 맞게 입력했다면, “이미 인증됐다”는 걸 어디에 기억시킬까요?

옵션들:

  1. 메모리에만 저장 (새로고침하면 사라짐)

    • 사용자 경험: 불편 (페이지를 떠났다 돌아오면 다시 입력)

  2. localStorage (반영구 저장)

    • 장점: 편함

    • 단점: 개인 컴퓨터에서만 안전 (공용 컴퓨터는 위험)

  3. sessionStorage (브라우저 탭이 닫힐 때까지만 저장)

    • 장점: 공용 컴퓨터에서 비교적 안전, 편함

    • 단점: 탭을 닫으면 초기화 (하지만 이게 장점이기도)

선택: sessionStorage + 2시간 타이머

const SESSION_DURATION = 2 * 60 * 60 * 1000; // 2시간

function unlockContent() {
  // 인증 상태를 저장
  sessionStorage.setItem('authenticated', 'true');
  
  // 2시간 뒤 자동으로 만료되도록 설정
  const expiry = new Date().getTime() + SESSION_DURATION;
  sessionStorage.setItem('expiry', expiry.toString());
}

배운 것:

  • sessionStorage는 “이 사람이 방금 비밀번호를 입력했다”는 메모 정도

  • 2시간 타이머는 “너무 오래 입력 상태를 유지하는 건 위험하다”는 개념

  • 은행 사이트가 일정 시간 뒤 로그아웃되는 이유가 이것

4. 세 번째 벽: “어느 페이지에서” 비밀번호를 입력받을까

비밀번호를 모든 페이지마다 입력받으면 불편할 것 같았어요. 사용자가 요청했던 건:

“학습일지 목록 페이지에서 한 번만 입력하고, 그 다음부터는 세부 페이지도 바로 들어가게 해줘.”

구조 설계:

① 학습일지 목록 페이지 (/journal)
   ↓ 비밀번호 입력
   ↓ sessionStorage에 저장
   
② 세부 페이지 (/journal/2026-07-28)
   ↓ sessionStorage 확인
   ↓ 있으면 바로 표시, 없으면 목록으로 돌려보냄

코드로:

목록 페이지에서:

const PASSWORD = '[당신의 비밀번호]';

passwordForm.addEventListener('submit', (e) => {
  e.preventDefault();
  
  if (passwordInput.value === PASSWORD) {
    // ✓ 맞으면 sessionStorage에 기록
    sessionStorage.setItem('authenticated', 'true');
    showContent(); // 콘텐츠 표시
  } else {
    // ✗ 틀리면 에러 메시지
    errorMsg.textContent = '비밀번호가 맞지 않습니다.';
  }
});

세부 페이지에서:

// 페이지 로드 시 자동 확인
if (sessionStorage.getItem('authenticated') !== 'true') {
  // 인증이 없으면 목록 페이지로 이동
  window.location.href = '/journal';
}
복사

배운 것: 사용자 경험과 보안의 균형. 매번 비밀번호를 입력하는 건 안전하지만 불편하고, 한 번만 입력하는 건 편하지만 (약간) 덜 안전합니다. 여기선 “개인 기록”이라는 성격에 맞춰 편의성을 선택했어요.

5. 검증: 실제로 작동하는가

dev server에서 직접 테스트했습니다:

  1. 비밀번호 입력 전: 목록만 보이고 콘텐츠 숨김

  2. 비밀번호 입력: 비밀번호 입력 후 “확인” 클릭

  3. 결과: 콘텐츠 나타남, sessionStorage에 인증 정보 저장됨 (개발자 도구 확인)

  4. 페이지 새로고침: 인증 상태 유지 (다시 입력할 필요 없음)

  5. 브라우저 탭 닫고 재오픈: 비밀번호 입력 창 다시 나타남 (sessionStorage 초기화)

✓ 비밀번호 인증 성공
✓ 같은 브라우저에서 2시간 유지
✓ 탭 종료 시 자동 초기화
✓ URL 직접 접근 시에도 인증 확인

🛠 사용한 도구

도구

역할

Astro

웹사이트 프레임워크 (정적 사이트)

JavaScript

클라이언트 측 인증 로직

sessionStorage

임시 인증 상태 저장

Claude

설계 및 코드 작성, 보안 개념 검증


배운 점

💡 핵심 교훈

1. 보안도 목적에 맞춰서 설계한다

“비밀번호 = 무조건 암호화”라고 생각했는데, 실제론:

  • 은행 계좌: AES-256 + HTTPS + 2FA 필요

  • 개인 블로그: 단순 비밀번호로도 충분

  • 공개 폼: 비밀번호 자체가 불필요

왜: 보안은 “비용 vs 위험”의 균형. 개인 학습노트는 도용당할 금전 가치가 없으니, 거기에 수천 달러 보안 시스템을 들일 필요가 없다는 뜻.

2. sessionStorage는 “메모”, localStorage는 “저장소”

  • sessionStorage: 브라우저 탭 닫으면 사라짐. 임시 인증에 좋음

  • localStorage: 반영구 저장. 사용자 설정 저장할 때 좋음

오늘 배운 건데, 이제 헷갈리지 않을 것 같아요.

3. 비밀번호 확인은 “실수 방지용”

비밀번호가 JavaScript 코드에 보이는 건 약점처럼 보였어요. 하지만:

  • 개발자 도구를 열 수 있는 사람은 이미 기술자 수준

  • 이 글을 보는 비개발자는 비밀번호를 코드에서 찾을 수 없음

  • 실제 목적은 “실수로 들어오는 사람” 또는 “조금 관심 있는 사람” 정도 방지

즉, “모든 보안을 완벽하게”가 아니라 “필요한 만큼” 하는 게 현명하다는 걸 배웠어요.

솔직한 소감

처음엔 “비밀번호라는 게 나오니까 암호화부터 시작해야 하나” 하는 부담감이 있었어요. 하지만 AI가 “이 정도면 충분하다”고 확인해주니 안심이 됐습니다.

지금 생각해보니, 보안이라는 게 “100% vs 0%“이 아니라 “필요한 수준”을 찾는 일이었네요. 마치 집 문을 잠그는 것처럼요.


적용할 점

🎯 결과

항목

이전

이후

접근 제어

모든 페이지 공개

학습일지만 비밀번호 보호

사용자 편의

N/A

2시간 자동 유지

보안 수준

N/A

개인 기록 수준에 적합

관리 비용

N/A

거의 없음 (비밀번호 변경만)

📋 복붙 가능한 코드

비슷한 걸 만들고 싶으신 분은 이 코드를 시작점으로:

// 페이지에 추가할 코드

const PASSWORD = '당신의비밀번호'; // ⚠️ 변경하세요
const STORAGE_KEY = 'is_authenticated';
const SESSION_DURATION = 2 * 60 * 60 * 1000; // 2시간

// 비밀번호 입력 폼 처리
document.getElementById('passwordForm')?.addEventListener('submit', (e) => {
  e.preventDefault();
  const input = document.getElementById('passwordInput');
  
  if (input.value === PASSWORD) {
    // ✓ 성공
    const expiry = new Date().getTime() + SESSION_DURATION;
    sessionStorage.setItem(STORAGE_KEY, 'true');
    sessionStorage.setItem('expiry', expiry.toString());
    
    // 콘텐츠 표시
    document.getElementById('passwordLock').style.display = 'none';
    document.getElementById('content').style.display = 'block';
  } else {
    // ✗ 실패
    document.getElementById('error').textContent = '비밀번호가 맞지 않습니다.';
    input.value = '';
  }
});

// 페이지 로드 시 인증 확인
function checkAuth() {
  const isAuth = sessionStorage.getItem(STORAGE_KEY);
  const expiry = parseInt(sessionStorage.getItem('expiry') || '0');
  
  if (isAuth === 'true' && new Date().getTime() < expiry) {
    // ✓ 유효한 인증 상태 → 콘텐츠 표시
    document.getElementById('passwordLock').style.display = 'none';
    document.getElementById('content').style.display = 'block';
  } else {
    // ✗ 인증 필요 → 비밀번호 입력창 표시
    sessionStorage.removeItem(STORAGE_KEY);
  }
}

checkAuth();

🔜 다음 계획

  1. HTTPS 연동 (완전 선택, 하지만 권장)

    • 지금은 localhost이니 문제 없지만, 배포할 때 HTTPS 필수

    • HTTP는 비밀번호가 평문으로 전송돼서 위험

  2. 비밀번호 변경 UI

    • 지금은 코드에 하드코딩

    • 나중에 관리자 페이지에서 변경할 수 있게

  3. 잠금 페이지 디자인 개선

    • 지금은 기능만 만들었는데, 나중에 더 예쁘게

2
2개의 답글
지피터스 뉴스레터

이번 주 AI, 딱 쓸 것만

매주 월요일 오후,
읽고 바로 써먹을 AI 소식만