으음 오늘은 지난주에 만들었던 게시판에, 로그인/회원가입 기능을 추가해보았다.
[https://www.youtube.com/watch?v=RhM1bQ76Tv0&list=PLV9zd3otBRt5ANIjawvd-el3QU594wyx7]
영상을 참고하여 만들었다.
나:걍 기존에 만든거에 로그인/회원가입 기능만 추가하면 되는거 아니냐! 쉬울거같은데?

무도짤 넣는게 유행인것 같아서 유행에 탑승했다.
생각보다,,, 오래걸렸다. 일요일 오늘 하루종일 한거같다.
초보자인 나는 어쩔수 없나보다~~ 얼른 성장해서 뚝딱뚝딱 별거아닌것처럼 이런거 만들고싶다!
첫번째 게시판 만들때 참고한 영상과 이번에 참고한 영상이 아예 다른 사람의 영상이라, 코드 전체적으로 차이가 좀 있어서 기존에 만들었던 게시판 기능에 로그인/회원가입 기능을 합치는데서 꽤 애를 먹었던것 같다.
추가로 로그인/회원가입을 세션기반으로 만드는 강의였어서 처음에 세션기반으로 다 만들었는데, 곰곰히 생각해보니 지난번에 토큰기반으로 만들라고 하셨던것 같아 마지막에 또 갈아엎었다 ^^ 두가지 다 공부하게 되서 좋은것 같다ㅎㅎ
자 그럼 기능 소개부터 해보겠다.

기존에는 메인 페이지 없이인 페이지 없이 CRUD기능만 따로 페이지가 존재했다.
이번에는 실제 웹사이트처럼 그럴싸하게 구현하고 싶었다.
로그인/회원가입의 절차가 있기 때문에 메인페이지가 필요할것 같아, 만들어주었다.
UI는 우주 배경으로 지피티한테 만들어달라 했더니 이렇게 해줬다. 나름 맘에 든다

회원가입 페이지이다. 비밀번호 입력받을때는 input type="password"로 받아 보안을 강화했다.


로그인 페이지이다. alert를 이용해 팝업창이 뜨게 했다.

기존에 만들었던 글 목록에, 작성자 칸을 추가하였다.

마찬가지로, 기존에 만들었던 상세정보에 작성자 칸을 추가하였다.

로그아웃 기능이다. 로그아웃 하면 처음 메인페이지로 돌아간다.

회원목록을 볼 수 있는 기능이다.
로그인 인증방식은 대표적으로 세션/쿠키/토큰 3가지가 있다고 한다. 간단하게 알면 좋을것 같아서 정리해봤다.
✅ 세션(Session)
정의: 서버가 로그인 정보를 저장하고, 클라이언트는 세션 ID를 쿠키에 담아 통신함.
장단점: 구현이 간단하고 보안에 강하지만, 서버 메모리에 사용자 정보를 저장하므로 확장성이 떨어짐.
✅ 쿠키(Cookie)
정의: 클라이언트에 정보를 저장하고, 요청 시 자동으로 서버에 전송되는 작은 데이터.
장단점: 간편하지만 보안에 취약하며, 보통은 단독 인증 수단이 아니라 세션 ID나 토큰 저장용으로 사용됨.
✅ 토큰(Token, JWT)
정의: 로그인 정보를 암호화한 토큰으로 만들어 클라이언트가 저장하고, 이후 요청에 헤더로 전송함.
장단점: 서버가 상태를 기억하지 않아도 되어 확장성에 유리하지만, 탈취 시 위험하고 무효화가 어려움.
+네이버 들어가면 나는 클라이언트, 네이버는 서버!
💡 어떤 방식이 가장 많이 쓰일까?
요즘은 JWT 토큰 방식이 가장 많이 사용된다.
모바일, SPA, 외부 API 연동 등 다양한 환경에서 서버 확장성과 호환성이 좋기 때문이다.
ㅁ /board/save 경로에서 사용자 정보(이메일, 이름, 비밀번호)를 입력받아 DB에 저장


ㅁ Entity-DTO 변환을 통해 깔끔하게 로직 분리
💡 DTO란?
DTO는 Data Transfer Object의 줄임말로, 계층 간 데이터 전달을 위한 객체이다. 예를 들어:
Entity->DTO 변경 코드


설명
toMemberDTO() 메서드를 통해 Entity → DTO로 변환 🔐 JWT란?
JWT (JSON Web Token)는 로그인 인증에 자주 사용되는 토큰 기반 인증 방식이다.
한 번 로그인하면 서버는 클라이언트에게 토큰을 발급하고,
이후 요청은 이 토큰만으로 인증할 수 있다.
토큰 자체에 사용자 정보(Email 등)를 담을 수 있어, DB 조회를 최소화한다.
내가 만든 JwtUtil 클래스
아래와 같이 jwt폴더와 그안에 JwtUtil 파일을 만들어주었다.


설명 요약
| 메서드 | 역할 |
|---|---|
createToken(email) | 이메일 기반으로 토큰 발급 |
isValid(token) | 토큰이 유효한지 확인 |
getEmail(token) | 토큰에 담긴 이메일 추출 |
📌 요약: 로그인 성공 시 서버는
JwtUtil.createToken()을 이용해 토큰을 발급한다.
이후 요청은Authorization헤더에 이 토큰을 담아 인증하게 된다. 이때Authorization헤더란 클라이언트가 서버에 "나 이 토큰 가지고 있어! 인증해줘!" 하고 말할 때 사용하는 HTTP 헤더이다.
1️⃣클라이언트(fetch) → 2️⃣서버(Spring Boot Controller) 구조의 순서로 토큰요청을 한다.
1️⃣ 클라이언트: 로그인 요청 (fetch)
나는 JavaScript에서 http 요청을 보내는 방법인 fetch를 이용했다.

- 사용자가 로그인 폼을 제출하면, fetch가 JSON 형식으로 이메일/비밀번호를 /board/login 경로로 전송함
- 응답으로 JWT 토큰을 받아 localStorage에 저장함 (이후 인증에 사용됨)
- 성공 시 게시판 목록 페이지(/board/list)로 이동
2️⃣ 서버: 로그인 처리 (@PostMapping("/board/login"))

- 클라이언트가 보낸 JSON 요청을 @RequestBody로 받아서 로그인 시도
- 로그인 성공하면 jwtUtil.createToken()을 이용해 JWT 토큰 발급
- 토큰을 응답 body에 그대로 문자열로 담아 반환
나는 세션으로 구현하고, 차마 여기까지는 다 바꾸지 못했다. 아래 코드는 가정사항이다! ㅠㅠ
글 작성 요청했을때 토큰이 있어야 작성이 가능하게 하는 코드이다. GPT의 도움을 받아서 작성한다.
1️⃣ 클라이언트: 글 작성 요청 시 토큰 포함하기

- 🔐 Authorization 헤더란?
- 클라이언트가 "나 이 토큰 가지고 있어!" 하고 서버에 보내는 인증 방식이다.
- 보통 "Authorization": "Bearer <토큰>" 형태로 작성한다.
2️⃣ 서버: 토큰을 꺼내서 이메일 추출 후 처리

- @RequestHeader로 Authorization 헤더 값 추출
- jwtUtil.getEmail(token)을 통해 이메일 추출
- 해당 이메일로 작성자 정보 조회해서 게시글 작성 시 저장
시작하며 말한것처럼 첫번째 게시판 만들때 참고한 영상과 이번에 참고한 영상이 아예 다른 사람의 영상이라, 코드 전체적으로 차이가 좀 있어서 기존에 만들었던 게시판 기능에 로그인/회원가입 기능을 합치는데서 꽤 애를 먹었던것 같다. 특히 DB 연동 부분!

처음에는 Entity와 Repository를 기존 게시판 테이블에 합쳐야 할지, 별도로 만들어야 할지 고민이 많았다.
결국 이메일, 비밀번호, 이름처럼 성격이 완전히 다른 데이터를 다루기 때문에, 회원용 Entity/Repository를 따로 만들어 구현하기로 했다.

그런데 문제는, 글 목록에 작성자 이름을 표시하려고 했을 때 발생했다.
나는 그냥 board.member.memberName 식으로 바로 불러오면 될 줄 알았는데,
처음에는 데이터가 안 나오고 오류가 나서 지피티랑 한참 씨름했다 😂

결국 원인은 Board 엔티티에 Member를 Join하지 않아서였다.
평소 DB 수업 시간에 배웠던 "다른 테이블을 참조하려면 조인을 써야 한다"는 이론이
실제로 이렇게 쓰인다는 걸 처음 체감한 순간이었다. 또 자바에서도 SQL을 이런식으로 다룰수 있다는걸 알게 되었다.
지금까지 SQL문들은 SQL내에서만 사용이 가능한 줄 알고 있었다.
배운 걸 실제로 써보니까 기억도 오래 남고, 코딩이 더 재밌게 느껴졌다!
오늘 토큰 기반으로 회원가입/로그인을 제작해보며 토큰 기반이 어떻게 돌아가는 시스템인지 잘 알게 되었다.
진짜 멋모르고 그냥 계속 하니까, 뭔가 실력이 느는 느낌이다. 코딩이 재밌다! 후후 그럼 이만
재밌다고 하니 다행입니다! 파이팅