[TOC]
[ 2편, 3편, 4편, 5편, 6편 / 다음편보기→ ]
결과물 git주소 : https://gitlab.ntiple.com/developers/study-202403
1. 개요
근래 몇년간 유행하는 방법론과 프레임워크로 스터디에 활용할 만큼 간단한 게시판 프로젝트를 만들어 보자 는 취지로 시작했다.
본 게시물은 2024.03.25 일 부터 대략 1주일 간격으로 3차례 진행된 스터디 내용을 바탕으로
정리하였다.
사용된 프레임워크 및 기법들 : spring-boot
, spring-security
, JWT
, JPA
, open-api
, SPA
, RSA
, AES
, next-js
, react-js
, redux
본 프로젝트 결과물들은 직후 실전 프로젝트에서 유용하게 써먹고 있다.
GIT 주소는 다음과 같다. (현재 정리중이라 소스작업이... 좀..... 일단 최신 소스는 react-mui
브랜치로 접근해야 한다.)
> https://gitlab.ntiple.com/developers/my-first-app
GIT 주소는 다음과 같다 (현재 블로그 내용을 토대로 새로 작성하여 운영 중이다)
스터디 협조에 응해주신 미모의 개발자 L 님에게 감사드립니다. ㅋㅋ
2. 범위
오늘 글에 포함된 범위는 일단 준비작업. 분석 및 설계단계를 정리해 볼거다.
(실제 스터디에서는 이딴거 없이 닥돌 gradle 프로젝트부터 생성했음....)
2번째 레포트에서 Java (Backend)
3번째 레포트에서 React (Frontend)
를 다룰 예정이다.
3. 분석 및 설계
3-1. 데이터 Entity
-
TB_USER
: 사용자 -
TB_ARTICLE
: 게시물erDiagram TB_USER { long id PK "사용자 고유번호(자동)" string(32) user_id UK "로그인 아이디" string(32) user_nm "사용자 이름" string(128) passwd "사용자 비밀번호" string(128) email "사용자 이메일" datetime ctime "생성일시" datetime utime "수정일시" } TB_ARTICLE { long id PK "게시글 고유번호(자동)" long board_id "게시판 ID" string(32) num "게시글 번호" string(128) title "게시글 제목" string(32) user_id "글쓴이 ID" string(32) user_nm "글쓴이 이름" string(9999) contents "내용" datetime ctime "생성일시" datetime utime "수정일시" } TB_USER ||--o{ TB_ARTICLE : has
3-2. 프론트엔드 / 백엔드 데이터 통신
-
프론트-백엔드 간 데이터 통신은
Restful
방식 (GET
,POST
,PUT
,DELETE
)을 사용한다.구분 URI 예시 세부 내용 예시 예시설명 GET
/api/atc/atc01001/1 게시물 상세조회 (id = 1) POST
/api/atc/atc01001 { "searchType": "", ... } 게시물 검색 PUT
/api/atc/atc01001 { "boardId": "", ... } 게시물 입력 DELETE
/api/atc/atc01001/1 게시물 삭제 (id = 1)
3-3. 프로그램 모듈 설계
-
프로그램명은 대분류(영문3자리), 중분류(숫자2자리), 소분류(숫자3자리), 구분자(a/s) 세분류(숫자2자리) 로 정해진다
-
예를들어 프로그램명
cmn01002a03
은 다음과 같이 설명된다.분류 구분 설명 cmn
대분류 대분류 (공통, 메인... 등등 성격에 따른 영문약어) 01
중분류 중분류 (대분류 내 업무, 등록순에 따른 순차번호) 002
소분류 소분류 (중분류 내 작업, 등록순에 따른 순차번호) a
구분자 a
: 프로그램(메소드) /s
: 화면(파일명)03
세분류 세분류 (소분류 C/R/U/D
,uri
에 포함되지 않음) -
프로그램명의 중분류 까지 8자리는
Restful
의 주체 (URI)가 된다. 예:cmn01002003
->cmn01002
-
Restful
의 주체가 되며GET
,POST
,PUT
,DELETE
등Method
에 의해C/R/U/D
가 정해진다구분 설명 기타 GET
단일조회 PATH-VARIALBLE
활용POST
목록조회(검색) / 또는 데이터 전달 PUT
데이터입력(및 수정) ID 유무에 따라 입력 / 수정 구분 DELETE
데이터삭제 PATH-VARIALBLE
활용 -
프로그램 대분류 코드는 다음과 같다
대분류 구분 설명 cmn 공통 공통서비스 mai 메인 메인화면 usr 사용자 회원가입, 마이페이지 등 사용자 관련 lgn 로그인 로그인, 로그인연장 등 로그인 관련 atc 게시물 게시물 작성, 조회, 검색 등 게시물 관련 smp 샘플 개발샘플 (운영환경 에서 비활성) -
코드 상세에 따른 프로그램 목록 은 다음과 같다
프로그램명 URI 인증 서비스 파일명 설명 기타 cmn00000a00
GET /api/cmn/cmn00000
CommonService.java
서비스 활성화 여부 체크(PING) cmn01001a01
GET /api/cmn/cmn01001
CommonService.java
최초 접속 환경정보 조회 mai01001a01
GET /api/mai/mai01001
MainService.java
메인 공지사항 등 정보 usr01001a01
GET /api/usr/usr01001
UserService.java
아이디 중복확인 usr01001a02
PUT /api/usr/usr01001
UserService.java
회원가입 usr01002a01
GET /api/usr/usr01002
필요 UserService.java
마이페이지 본인확인 usr01002a02
PUT /api/usr/usr01002
필요 UserService.java
마이페이지 수정 본인확인 lgn01001a01
POST /api/lgn/lgn01001
LoginService.java
로그인 토큰발급 lgn01002a01
GET /api/lgn/lgn01002
필요 LoginService.java
로그인연장 토큰발급 atc01001a01
PUT /api/atc/atc01001
필요 ArticleService.java
게시물 작성/수정 글쓴이확인 atc01001a02
GET /api/atc/atc01001
필요 ArticleService.java
게시물 조회 atc01001a03
DELETE /api/atc/atc01001
필요 ArticleService.java
게시물 삭제 글쓴이확인 atc01001a04
POST /api/atc/atc01001
필요 ArticleService.java
게시물 검색 -
구현할 화면명은 다음과 같다.
화면명 URI 설명 기타 mai01001s01
/mai/mai01001s01
메인화면 usr01001s01
/usr/usr01001s01
회원가입 입력폼 usr01001s02
/usr/usr01001s02
회원가입 결과 usr01002s01
/usr/usr01002s01
마이페이지 수정폼 usr01002s02
/usr/usr01002s02
회원정보 수정 결과 lgn01001s01
/lgn/lgn01001s01
로그인 페이지 lgn01001s02
/lgn/lgn01001s02
로그인 결과 페이지 atc01001s01
/atc/atc01001s01
새글 작성 페이지 atc01001s02
/atc/atc01001s02
게시물 편집 페이지 atc01001s03
/atc/atc01001s03
게시물 조회 페이지 atc01001s04
/atc/atc01001s04
게시물 목록 페이지
3-4. 암호 교환 및 검증 절차
-
프론트엔드 에는 기본적으로 private-key 가 입력되어 있다.
-
프론트엔드에서 백엔드 최초 접근시
AES-key
를 요청 한다 -
백엔드 에서 프론트엔드로
AES-key
전송 시 public-key 로 암호화 하여 내려보낸다 -
전송받은 암호화 데이터 (
AES-key
) 는 프론트엔드에서 private-key 로 복호화 한다 -
이후 상호 데이터 암호화는
AES
방식으로 통신한다. -
DB 저장시 프론트엔드에서 전송받은 데이터를 백엔드에서 한번 평문화 한 후 DB 암호화 모듈을 적용한다.
-
DB 암호화는 대부분 단방향 이므로 복호화는 일반적으로 사용하지 않는다 (비밀번호 등의 데이터 검증은 암호화 된 상태에서만 비교)
sequenceDiagram Frontend->>Backend: AES-key 요청 Backend->>Frontend: public-key 암호화된 AES-key 데이터 Frontend->>Frontend: private-key 로 AES-key 복호화 Frontend->>Backend: AES 암호화 데이터 전송 Backend->>Backend: AES 데이터 복호화 Backend->>DB: DB 암호화 모듈 사용 DB->>Backend: DB 암호화 데이터 Backend->>Frontend: AES 암호화 데이터 전송 Frontend->>Frontend: AES 데이터 복호화
3-5. Auth Token 발급 및 검증 절차
- Auth Token 은
JWT
형태를 사용하며TokenProvider.java
를 사용하여 발급한다.
3-6. 업무분석
3-6-1. 초기화
-
순차흐름
sequenceDiagram Actor User User->>Frontend: 최초접근 Frontend->>cmn01001: 환경정보 cmn01001->>cmn01001: AES-key 암호화 (public-key) cmn01001->>Frontend: AES-key 암호데이터 Frontend->>Frontend: AES-key 복호화 (private-key) Frontend->>User: 페이지
3-6-2. 회원가입
-
전송 데이터 타입 (가입정보)
erDiagram User { long id "사용자 고유번호(자동)" string(32) userId "로그인 아이디" string(32) userNm "사용자 이름" string(128) passwd "사용자 비밀번호(DB 암호화)" string(128) email "사용자 이메일" datetime ctime "생성일시 (자동)" datetime utime "수정일시 (자동)" }
-
순차흐름
sequenceDiagram Actor User User->>Frontend: 회원가입 (usr01001s01) Frontend->>usr01001: 중복확인 (usr01001a01) usr01001->>Frontend: 중복여부 Frontend->>Frontend: 비밀번호 AES 암호화 Frontend->>usr01001: 회원가입 (usr01001a02) usr01001->>usr01001: 비밀번호 AES 복호화 usr01001->>DB: 비밀번호 DB암호화 요청 DB->>usr01001: DB암호화 데이터 usr01001->>DB: save(가입정보) DB->>usr01001: 성공여부 usr01001->>Frontend: 성공여부 또는 오류정보 Frontend->>User: 완료페이지 (usr01001s02)
-
기타
-
로그인 아이디 규칙설정 : 4글자 이상의 영숫자, 반드시 영문자로 시작
-
admin
,user
,system
,root
,staff
,actor
,common
등 불용어 설정 (property)
-
3-6-3. 마이페이지
-
가입정보
데이터 수정 가능 항목구분 수정가능여부 기타 id userId userNm 가능 passwd 가능 email 가능 ctime utime 가능 자동수정 -
순차흐름
sequenceDiagram Actor User User->>Frontend: 마이페이지(usr01002s01) Frontend->>usr01002: usr01002a01(userId) usr01002->>DB: findOneByUserIdEquals(userId) DB->>usr01002: 가입정보 usr01002->>Frontend: secureOut(가입정보) Frontend->>User: 마이페이지 User->>Frontend: 수정(가입정보) Frontend->>Frontend: 비밀번호 AES 암호화 Frontend->>usr01002: usr01002a02(가입정보) usr01002->>usr01002: 비밀번호 AES 복호화 usr01002->>DB: 비밀번호 DB암호화 요청 DB->>usr01002: DB암호화 데이터 usr01002->>DB: findOneByUserIdEquals(userId) DB->>usr01002: 가입정보 usr01002->>usr01002: 수정가능항목만 덮어쓰기 usr01002->>DB: save(가입정보) DB->>usr01002: 성공여부 usr01002->>Frontend: 성공여부 또는 오류정보 Frontend->>User: 완료화면(usr01002s02)
-
기타
- 비밀번호는 입력시에만 업데이트 한다. (공백일 경우 기존 비밀번호 유지)
3-6-4. 로그인
-
로그인정보
erDiagram Login { string(32) userId "로그인 아이디" string(128) passwd "사용자 비밀번호 (AES 암호화)" }
-
순차흐름
sequenceDiagram Actor User User->>Frontend: 로그인(lgn01001s01) Frontend->>Frontend: 비밀번호 AES 암호화 Frontend->>lgn01001: 로그인정보 lgn01001->>lgn01001: 비밀번호 AES 복호화 lgn01001->>DB: 비밀번호 DB 암호화 DB->>lgn01001: DB암호화 데이터 lgn01001->>DB: findOneByUserIdEquals(userId) lgn01001-->>Frontend: ![사용자없음] 오류정보 lgn01001->>lgn01001: 비밀번호 비교 lgn01001-->>Frontend: ![비밀번호안맞음] 오류정보 lgn01001->>TokenProvider: createToken TokenProvider->>lgn01001: authToken (accessToken, refreshToken) lgn01001->>lgn01001: authToken AES 암호화 lgn01001->>Frontend: authToken 전달 Frontend->>Frontend: authToken AES 복호화 Frontend->>Frontend: authToken 저장 (API / Bearer) Frontend->>User: 로그인 결과 화면(lgn01001s02)
3-6-5. 로그인 연장
-
순차흐름
sequenceDiagram Actor User Frontend->>User: ![2분이내 만기시] 연장여부확인 User->>Frontend: 연장요청 Frontend->>lgn01002: refreshToken lgn01002->>TokenProvider: createToken TokenProvider->>lgn01002: authToken (accessToken, refreshToken) lgn01002->>lgn01002: authToken AES 암호화 lgn01002->>Frontend: authToken 전달 Frontend->>Frontend: authToken AES 복호화 Frontend->>Frontend: authToken 저장 (API / Bearer) Frontend->>User: 연장요청결과
3-6-8. 게시물작성
-
게시물정보
erDiagram Article { long id "게시글 고유번호" long boardId "게시판 ID" string num "게시글 번호" string title "게시글 제목" string userId "글쓴이 ID" string userNm "글쓴이 이름" string contents "내용" datetime ctime "생성일시" datetime utime "수정일시" }
-
순차흐름
sequenceDiagram Actor User User->>Frontend: 새글저장 Frontend->>atc01001: 게시물 작성 (atc01001a01) atc01001->>DB: save(게시물정보) DB->>atc01001: 성공여부 atc01001->>Frontend: 성공여부 또는 오류정보 Frontend->>User: 완료페이지
3-6-9. 게시물상세조회
-
순차흐름
sequenceDiagram Actor User User->>Frontend: 게시물 조회 Frontend->>atc01001: 게시물 조회 (atc01001a02) atc01001->>DB: findOneByIdEquals(id) DB->>atc01001: 게시물정보 atc01001->>Frontend: 게시물정보 Frontend->>User: 게시물 상세 페이지
3-6-10. 게시물삭제
-
순차흐름
sequenceDiagram Actor User User->>Frontend: 게시물 삭제 Frontend->>atc01001: 게시물 삭제 (atc01001a03) atc01001->>DB: delete(id) DB->>atc01001: 성공여부 atc01001->>Frontend: 성공여부 또는 오류정보 Frontend->>User: 결과페이지
3-6-11. 게시물검색
-
검색정보
erDiagram SearchEntity { string searchType "검색타입" string keyword "검색키워드" integer rowStart "검색시작" integer rowCount "검색수량" integer pagePerScreen "한화면에 표기할 페이지갯수" integer rowTotal "결과리스트총갯수" list list "결과목록" }
-
순차흐름
sequenceDiagram Actor User User->>Frontend: 게시물 검색 Frontend->>atc01001: 게시물 검색(atc01001a04) atc01001->>DB: searchArticle(검색정보) DB->>atc01001: 게시물정보 목록 atc01001->>Frontend: 검색정보 Frontend->>User: 결과페이지
4. 결과물
-
본 결과물은 backend 까지 완성된 결과물로서 swagger-ui 로 표현되어있다.
-
실행 결과물은 다음과 같다.
결과물 git주소 : https://gitlab.ntiple.com/developers/study-202403