이번 프로젝트를 진행하면서 후기 기능 다음으로 필요해진 것이 관리자 페이지였다.
처음에는 단순히 사용자에게 보여지는 홈페이지와 견적 계산 기능만 있으면 된다고 생각했다.
하지만 후기 기능이 추가되면서 운영자가 직접 관리해야 하는 영역이 생겼다.
사용자가 작성한 후기를 모두 그대로 노출할 수는 없다.
테스트로 작성한 글이 있을 수도 있고, 부적절한 내용이 올라올 수도 있다.
또 사이트가 실제로 얼마나 사용되고 있는지 확인하려면 방문 수나 견적 사용 수 같은 간단한 통계도 필요했다.
그래서 별도의 관리자 페이지를 만들게 되었다.
관리자 페이지가 필요해진 이유
관리자 페이지의 목적은 크게 두 가지였다.
1. 후기 관리
2. 사이트 이용 통계 확인
후기 기능을 만들면 자연스럽게 관리 기능이 필요해진다.
사용자는 본인이 작성한 후기만 비밀번호로 삭제할 수 있지만, 운영자는 전체 후기를 관리할 수 있어야 한다.
만약 잘못된 후기가 올라왔을 때 작성자 비밀번호를 모른다는 이유로 삭제하지 못하면 실제 운영에 문제가 생긴다.
또 하나는 통계였다.
사이트를 만들어도 실제로 사람들이 방문하는지, 견적 계산기를 사용하는지 알 수 없다면 운영 판단이 어렵다.
특히 이 프로젝트는 견적 문의로 이어지는 흐름이 중요했기 때문에, 단순 방문 수뿐만 아니라 견적 기능 사용 여부도 확인할 수 있으면 좋겠다고 판단했다.
그래서 관리자 페이지에서는 다음 데이터를 볼 수 있도록 했다.
페이지 방문 수
견적 사용 수
후기 등록 수
복잡한 분석 도구 수준은 아니지만, 운영자가 사이트 활용도를 파악하기에는 충분한 정보였다.
관리자 비밀번호 인증 방식
이번 프로젝트에서는 별도의 관리자 계정 시스템을 만들지 않았다.
관리자가 여러 명인 것도 아니고, 권한을 세분화할 필요도 없었다.
그래서 관리자 페이지는 환경변수로 설정한 관리자 비밀번호를 입력하면 접근할 수 있는 방식으로 만들었다.
흐름은 단순하다.
관리자 페이지 접속
-> 관리자 비밀번호 입력
-> 서버에서 비밀번호 확인
-> 일치하면 관리자 화면 접근
처음에는 프론트에서 비밀번호를 비교하는 방식도 생각할 수 있다.
하지만 그렇게 하면 관리자 비밀번호가 브라우저 코드에 노출될 위험이 있다.
그래서 비밀번호 검증은 반드시 백엔드에서 처리하도록 했다.
프론트엔드는 사용자가 입력한 비밀번호를 서버로 보내고, 서버가 환경변수에 저장된 관리자 비밀번호와 비교한다.
일치하는 경우에만 관리자용 데이터를 요청할 수 있게 했다.
관리자 비밀번호는 코드에 직접 작성하지 않고 Render 환경변수로 관리했다.
ADMIN_PASSWORD=운영용 관리자 비밀번호
이렇게 하면 나중에 비밀번호를 바꾸고 싶을 때 코드를 수정하지 않아도 된다.
Render 환경변수만 변경하면 운영 비밀번호를 교체할 수 있다.
후기 관리 기능
관리자 페이지에서 가장 기본이 되는 기능은 후기 관리였다.
사용자 화면에서는 작성자가 본인 비밀번호를 입력해야 후기를 삭제할 수 있다.
하지만 관리자 페이지에서는 모든 후기를 볼 수 있고, 필요하면 강제로 삭제할 수 있도록 했다.
관리자 후기 관리 흐름은 다음과 같다.
관리자 로그인
-> 전체 후기 목록 조회
-> 삭제할 후기 선택
-> 관리자 권한으로 삭제 요청
-> DB에서 후기 삭제
삭제 방식은 하드 딜리트로 처리했다.
하드 딜리트는 데이터를 DB에서 실제로 삭제하는 방식이다.
반대로 소프트 딜리트는 DB에는 남겨두고 삭제 상태만 표시하는 방식이다.
이번 프로젝트에서는 삭제된 후기를 나중에 복구하거나 보관해야 할 요구사항이 없었다.
후기 데이터는 운영자가 정리하는 공개 콘텐츠에 가깝고, 삭제된 데이터를 계속 보관할 필요가 크지 않다고 판단했다.
그래서 단순하고 명확하게 하드 딜리트로 구현했다.
삭제 버튼 클릭
-> 서버에서 관리자 권한 확인
-> 해당 후기 DB에서 삭제
-> 목록에서 사라짐
이 방식은 구조가 단순하고 관리하기 쉽다. 다만 삭제 후 복구가 어렵기 때문에, 실제 운영에서는 삭제 전에 한 번 더 확인하는 UI가 필요하다고 판단했다.
통계 기능을 추가한 이유
관리자 페이지에는 후기 관리뿐 아니라 간단한 통계 기능도 넣었다.
사이트를 운영할 때 가장 궁금한 것은 결국 “사람들이 실제로 사용하고 있는가?”이다.
단순히 사이트가 배포되어 있다고 해서 운영이 잘 되고 있다고 볼 수는 없다.
방문자가 있는지, 견적 계산기를 눌러보는지, 후기를 등록하는지 확인할 수 있어야 한다.
그래서 다음과 같은 이벤트를 기록하도록 했다.
페이지 방문
견적 사용
후기 등록
이벤트가 발생하면 백엔드에 기록하고, 관리자 페이지에서 통계로 보여주는 방식이다.
처음부터 Google Analytics 같은 외부 분석 도구만 사용하는 방법도 있었다.
하지만 관리자 페이지 안에서 기본적인 사용량을 바로 확인할 수 있으면 운영자가 훨씬 편하게 볼 수 있다고 생각했다.
Google Analytics는 더 자세한 유입 분석에 좋고, 관리자 페이지 통계는 서비스 내부 기능 사용량을 확인하는 데 적합하다.
그래서 두 역할을 다르게 봤다.
Google Analytics: 유입 경로, 사용자 환경, 전체 트래픽 분석
관리자 통계: 견적 사용, 후기 등록 같은 서비스 내부 이벤트 확인
누적, 연도, 월별 데이터 표시
통계는 단순히 전체 숫자만 보여주면 활용도가 떨어진다.
예를 들어 견적 사용 수가 200회라고 해도, 그것이 이번 달에 몰린 것인지, 1년 동안 누적된 것인지 알 수 없다.
그래서 관리자 페이지에서는 기간을 나누어 보여주도록 했다.
누적
올해
이번 달
정확히는 현재 날짜를 기준으로 자동 계산되도록 만들었다.
예를 들어 2026년 6월이면 관리자 화면에는 2026년 데이터와 26년 6월 데이터가 표시된다.
시간이 지나 2027년이 되면 별도로 코드를 수정하지 않아도 2027년 기준으로 바뀌도록 했다.
이렇게 하면 운영자가 매달 또는 매년 수치를 확인할 때 더 직관적으로 볼 수 있다.
통계 구조는 다음과 같은 흐름이다.
이벤트 발생
-> 이벤트 타입 저장
-> 생성 날짜 저장
-> 관리자 페이지에서 기간별 집계
데이터를 저장할 때 날짜를 함께 남겨두면, 이후에 월별/연도별 통계를 계산할 수 있다.
처음에는 단순히 총합만 보여줘도 된다고 생각했지만, 운영 관점에서는 기간별 데이터가 훨씬 의미 있다고 느꼈다.
간단한 관리자 기능에도 보안이 필요한 이유
이번 관리자 페이지는 복잡한 시스템은 아니다.
관리자 계정이 여러 개 있는 것도 아니고, 권한 등급이 나뉘는 것도 아니다.
하지만 그렇다고 해서 보안을 가볍게 보면 안 된다.
관리자 페이지에서는 후기를 삭제할 수 있고, 사이트 통계를 확인할 수 있다. 외부 사용자가 접근하면 안 되는 정보와 기능이 들어 있다.
그래서 최소한 다음 부분은 신경 썼다.
관리자 비밀번호는 프론트 코드에 저장하지 않기
환경변수로 관리자 비밀번호 관리하기
관리자 API 요청 시 비밀번호 헤더 검증하기
비밀번호가 없거나 틀리면 접근 차단하기
CORS를 운영 도메인 기준으로 제한하기
특히 관리자 API는 프론트 화면을 숨기는 것만으로 보호할 수 없다.
사용자가 /admin 페이지에 접근하지 못하더라도, API 주소를 직접 호출할 수 있기 때문이다.
그래서 서버에서 관리자 비밀번호를 확인해야 한다.
이 과정에서 한 가지 개선점도 있었다.
처음에는 관리자 API에 비밀번호 헤더 자체가 없으면 서버 내부 오류처럼 500 응답이 내려오는 문제가 있었다.
데이터가 노출되지는 않았지만, 운영 품질 관점에서는 좋지 않았다.
그래서 비밀번호가 없거나 틀린 경우에는 명확하게 401 또는 403 응답을 내려주는 방식으로 개선했다.
이런 작업을 하면서 “보안”은 거창한 기능에서만 필요한 것이 아니라는 걸 느꼈다.
간단한 관리자 페이지라도 실제 운영에 들어가면 보호해야 할 책임이 생긴다.
구현하면서 신경 쓴 점
관리자 페이지를 만들면서 가장 신경 쓴 것은 너무 복잡하게 만들지 않는 것이었다.
처음부터 관리자 회원가입, 권한 관리, 이메일 인증까지 넣으면 구조는 더 정교해질 수 있다.
하지만 이번 프로젝트 규모에서는 오히려 과한 기능이 될 수 있었다.
그래서 필요한 기능만 넣었다.
관리자 비밀번호 로그인
전체 후기 조회
관리자 후기 삭제
방문 수 통계
견적 사용 수 통계
후기 등록 수 통계
누적/연도/월별 집계
기능은 단순하지만, 운영자가 실제로 필요한 정보는 확인할 수 있도록 구성했다.
또 관리자 화면에서도 긴 후기 내용이 박스 밖으로 나가지 않게 처리했고, 후기가 많아졌을 때를 대비해 페이지네이션도 적용했다.
관리자 페이지는 사용자가 자주 보는 화면은 아니지만, 운영자가 사이트를 관리하는 데 필요한 도구이기 때문에 안정성이 중요하다고 느꼈다.
이번 기능을 만들며 배운 점
관리자 페이지를 만들면서 가장 크게 배운 점은 “관리자 기능은 나중에 붙이는 부가기능이 아니라 운영의 일부”라는 것이다.
사용자 화면만 잘 만들어도 사이트는 그럴듯해 보인다. 하지만 실제 운영이 시작되면 데이터를 관리하고, 문제가 생겼을 때 정리하고, 사용량을 확인할 수 있는 기능이 필요하다.
특히 외주 프로젝트에서는 클라이언트가 개발자가 아닐 가능성이 높다.
그렇기 때문에 운영자가 직접 확인할 수 있는 최소한의 관리자 기능을 제공하는 것이 중요하다고 느꼈다.
또 통계 기능을 만들면서 단순히 데이터를 저장하는 것보다, 운영자가 이해하기 쉬운 형태로 보여주는 것이 중요하다는 것도 배웠다.
숫자 하나를 보여주더라도 누적, 연도, 월별로 나누면 훨씬 의미 있는 정보가 된다.
회고
관리자 페이지는 처음에는 후기 삭제용으로만 생각했다. 하지만 작업을 진행하면서 사이트 운영에 필요한 기능들이 자연스럽게 보이기 시작했다.
후기 관리, 방문 수, 견적 사용 수, 후기 등록 수처럼 작은 기능들이 모이니 운영자가 사이트 상태를 확인할 수 있는 기본 도구가 되었다.
이번 프로젝트에서는 복잡한 관리자 시스템을 만들기보다, 실제 필요한 기능을 가볍고 명확하게 구현하는 방향을 선택했다.
다음 프로젝트에서는 관리자 기능을 기획 단계에서 더 일찍 분리해서 정리해보고 싶다.
“운영자는 무엇을 확인해야 하는가?”, “무엇을 직접 관리할 수 있어야 하는가?”, “어떤 기능은 반드시 보호되어야 하는가?”를 먼저 질문하면 관리자 페이지의 범위도 더 명확해질 것 같다.
'개발 프로젝트 > [외주 프로젝트] 첫 외주 웹사이트 제작기: 기획부터 배포까지' 카테고리의 다른 글
| 외주 프로젝트를 마무리하며: 운영 가능한 사이트를 만든다는 것 (0) | 2026.06.21 |
|---|---|
| 배포하면서 만난 문제들: Vercel, Render, Supabase, 도메인 연결 (1) | 2026.06.20 |
| 후기 기능 만들기: 계정 없이 등록하고 비밀번호로 삭제하기 (0) | 2026.06.16 |
| Google Sheet를 견적 옵션 DB처럼 사용하기 (0) | 2026.06.14 |
| 왜 Next.js와 Spring Boot를 썼나 (0) | 2026.06.12 |