Recording/멋쟁이사자처럼 BE 13기

[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_113일차_"2차 팀 프로젝트 마무리"

LEFT 2025. 12. 8. 10:37

🦁멋쟁이사자처럼 백엔드 부트캠프 13기 🦁
TIL 회고 - [113]일차

🚀113차에는 프로젝트의 최종 마무리를 위해 개발된 기능들을 테스트하고 수정 및 기능추가를 진행하였다. (2025.05.27)


이메일 인증 및 게스트 회원가입 테스트


  • 이메일 인증완료 확인완료

 

로컬 설정파일 수정

MAIL_USERNAME: 이메일 주소
MAIL_PASSWORD: 이메일 패스워드
  • 이메일 관련 설정에 대해 추가해준 후 위의 정보들로 수정해주어야함

API 명세 테스트

 

백엔드와 프론트엔드 간의 API 명세 공유의 중요성

프론트엔드 개발자가 작업을 시작하기 위해서는 백엔드 개발자(서버 로직 담당)가 만든 API의 명세(Specification)가 필요

- 백엔드 개발자 : 특정 URL(api/v1/auth/login), 요청 방식(POST), 필요한 데이터(email, password)를 정의하고 구현
- 프론트엔드 개발자 : 백엔드 개발자가 만든 명세에 따라 정확한 주소로 데이터를 전송하고, 서버가 보낸 응답 데이터를 받아
화면에 로그인 성공/실패 메시지를 표시

정리 :

프론트엔드 파트 담당 :
ex. API를 만들어서 달라는 요청 ➡️ 백엔드 개발자에게 API 엔드포인트(auth/login)의 구현을 완료해달라는 것
ex. Swagger를 만들어달라는 요청 ➡️ 백엔드 개발자가 API 명세를 Swagger 도구를 사용해 문서화해 달라는 요청

Swagger는 API의 모든 엔드포인트, 필요한 입력 값, 예상되는 응답을 자동으로 시각화해주는 도구이므로
프론트엔드 개발자는 이 Swagger 문서를 보고 curl 요청에 필요한 모든 정보를 바로 파악할 수 있게됨

따라서 curl 요청은 '백엔드 개발자가 만든 API 명세에 따라 요청을 테스트하는 행위'


회원가입된 정보로 로그인

curl -X POST "http://localhost:8090/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "xxx@xxx.com",
"password": "xxxxxx1!"
  • 예를 위해 임의로 넣어놓은 이메일과 패스워드
  • curl 명령어를 통해 CLI 환경에서 호스트 로그인을 테스트 진행 (위의 회원가입에서 등록된 회원정보)
  • 이를 통해 토큰값이 반환

DB에서는 패스워드가 이처럼 암호화되어서 저장되어있는데 이는 BCrypt 방식을 사용하여 암호화한 것


BCrypt (비크립트)

  • 비밀번호를 안전하게 저장하기 위해 사용되는 해시 함수
  • Spring Security를 사용하는 Spring Boot 백엔드에서 기본적으로 채택하는 암호화 방식

 

BCrypt 구조 = (알고리즘 + 비용계수 + 솔트/해시된비밀번호)

ex. $2a$ + $10$ + lof.R4/Bq.....Fy

- 알고리즘 : BCrypt 알고리즘을 사용했음을 나타냄 (ex. $2a$ 또는 $2b$, $2y$)

- 비용계수 (Cost Factor) : 해시를 생성하는 데 필요한 계산 횟수(강도), 숫자가 높을수록 더 안전하지만, 해시 생성 시간이 길어짐
(ex. $10$)

- 솔트(Salt) + 해시된 비밀번호 : 무작위로 생성된 솔트(22자리)와 최종 해시된 비밀번호가 Base64 인코딩되어 결합
(ex. lof.R4/Bq.z9PZnVinwEYukhhWe5mKp6h1/QKV6xXmbGpUFajhaFy)

최종 예시 비밀번호 문자열 : $2a$10$lof.R4/Bq.z9PZnVinwEYukhhWe5mKp6h1/QKV6xXmbGpUFajhaFy


이미지 업로드

curl -X POST "http://localhost:8090/api/v1/spaces/images/upload" \
-H "Authorization: Bearer 반환된토큰" \
-F "files=@/c/Workspace/Lion_Project/loco_project/test_image.jpg" -v
  • 로그인을 통해 얻은 토큰으로 이미지 업로드의 헤더에 주입
  • 이 curl 명령어를 통해 data의 이미지 URL을 반환받음
    ["global/data/image/534231e3-76a0-402b-9970-dec78db296b3.jpg"]
    (내용 정리를 위해 임의로 작성된 이미지 URL)

공간 등록

curl -X POST "<http://localhost:8090/api/v1/spaces>" \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer 반환된토큰" \\
-d '{
  "name": "DB연동 테스트공간",
  "description": "curl 명령어로 등록한 테스트 공간입니다.",
  "address": "서울시 강남구",
  "detailAddress": "역삼동 123-45",
  "zipCode": "06130",
  "latitude": 37.498095,
  "longitude": 127.027610,
  "price": 50000,
  "openingHours": "09:00",
  "closingHours": "18:00",
  "phoneNumber": "010-1234-5678",
  "imageUrls": ["global/data/image/534231e3-76a0-402b-9970-dcdasd296b3.jpg"],
  "type": "PHOTO",
  "maxCapacity": 10,
  "parkingAvailable": true,
  "petAvailable": false,
  "smokingAvailable": false,
  "hasKitchen": true,
  "hasRestroom": true,
  "facilities": ["WIFI", "PROJECTOR"]
}' -v

이제 공간까지 등록하고나면

 

1) 백엔드 서버에서의 공간 등록 성공

200 응답코드와 함께 공간 등록이 성공되었다는 로그메시지 출력

2) Git Bash에서의 공간 등록 성공 로그

$ curl -X POST "<http://localhost:8090/api/v1/spaces>" \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer 반환된토큰" \\
-d '{
  "name": "DB연동 테스트공간",
  "description": "curl 명령어로 등록한 테스트 공간입니다.",
  "address": "서울시 강남구",
  "detailAddress": "역삼동 123-45",
  "zipCode": "06130",
  "latitude": 37.498095,
  "longitude": 127.027610,
  "price": 50000,
  "openingHours": "09:00",
  "closingHours": "18:00",
  "phoneNumber": "010-1234-5678",
  "imageUrls": ["global/data/image/534231e3-76a0-402b-9970-dcasdasd96b3.jpg"],
  "type": "PHOTO",
  "capacity": 10,
  "parkingAvailable": true,
  "petAvailable": false,
  "smokingAvailable": false,
  "hasKitchen": true,
}' -vcilities": ["WIFI", "PROJECTOR"]
Note: Unnecessary use of -X or --request, POST is already inferred.
* Host localhost:8090 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8090...
* Connected to localhost (::1) port 8090
* using HTTP/1.x
> POST /api/v1/spaces HTTP/1.1
> Host: localhost:8090
> User-Agent: curl/8.10.1
> Accept: */*
> Content-Type: application/json
> Authorization: Bearer 반환된토큰
> Content-Length: 653
>
* upload completely sent off: 653 bytes
< HTTP/1.1 200
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 0
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: SAMEORIGIN
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Wed, 28 May 2025 04:46:34 GMT
<
{"resultCode":"S-1","msg":"공간 등록 성공","data":{"id":2,"hostId":3,"imageId":null,"spaceName":"DB연동 공간테스트1","description":"curl 명령어로 등록한 테스트 공간입니다.","uploadDate":"2025-05-28T13:46:34.8586441","spaceType":"PHOTO","price":50000,"address":"서울시 강남구","latitude":37.5665,"longitude":126.978,"maxCapacity":10,"isActive":true,"spaceRating":0,"isFavoritedByMe":null,"imageUrl":"global/data/image/534231e3-76a0-402b-9970-dce79db296b3.jpg","additionalImageUrls":[]},"success":true,"fail":false}* Connection #0 to host localhost left intact
  • 공간 등록 성공이라는 로그를 확인할 수 있음

프로젝트 마무리

  • 팀원들과 매일 아침 전날의 이슈사항 및 오늘 해야할 일들에 대해 정리하는 데일리 스크럼 시간을 가짐
  • git 통합의 경우에는 기능브랜치를 분기한 팀원들이 기능개발을 완료하면 부팀장 (개발팀장)으로써 Git 통합을 진행함
    ➡️코드 리뷰 및 이 코드가 왜 쓰였는지 등등 (on Discord)


  • 최종적으로는 MySQL DB로의 마이그레이션에 성공했고, Amazon S3를 통해 이미지 업로드 구현 및 Spring 으로써 블로그 서비스의 전반적인 환경을 개발해낼 수 있었음

  • 기능정의서, 요구사항 계획 단계에서 기본으로 지정해놨던 기능과
    서비스를 개발하면서 필요해진 기능까지 추가하며 업데이트했던 요구사항 정의서 시트지

  • 팀원들과 각자 해낸 기능개발이 생기면 바로 체크해놓을 수 있도록함
  • 중요도 (MVP)를 나누어서 중요한 기능부터 개발해내는 과정에서 이러한 시각적인 자료가 필수적이었음

  • ⚠️요구사항 정의서에 정의된 기능을 꼭 개발해내야겠다는 생각을 하다보니
    기능 하나하나의 안정성 및 테스트에는 신경을 쓰지 못했음

전체적인 구조의 ERD는 중간 피드백과 팀원들간의 기능개발에 중점을 두어 최종적으로 완성할 수 있었음

 

  • 유저 및 채팅/공간 부분에 대한 ERD도 여러번의 개선 끝에 필요한 부분을 남기고 불필요한 부분은 제거해낼 수 있었음'
  • 중간 피드백 내용 중 유저가 어드민/게스트/호스트로 나눌지
    유저가 게스트/호스트로만 나누어지고 어드민은 따로 둘지 등을 고민하는 과정이 있었음
    ✅최종적으로는 어드민은 분리하여 관리자페이지 (백오피스)에서 권한을 토대로 활용할 수 있도록 설계하였음

트러블 슈팅

  • 도메인 주소는 유효한 기간으로 구입해놓은 상태이지만 배포 관련하여 부족한 부분이 많아 추가하고 싶은 기능에 넣음

LoCo 블로그 서비스 페이지

 

게스트 페이지

1. 메인 페이지

  • 메인화면으로 들어오면 로그인 버튼이 활성화되어있고, 지금까지 등록된 공간들 보여짐
  • 공간을 카테고리 별로 분류하여 빠르게 필요한 공간을 찾을 수 있고
    검색기능에서 필터 및 검색어를 통해 원하는 공간을 상세하게 찾을 수도 있음

2. 로그인 페이지

  • 로그인 버튼을 누르면 게스트 로그인 (공간을 이용하는 유저) 화면으로 이동하고,
  • 회원가입이 되지 않은 상태이면 아래의 "회원가입"버튼을 눌러 회원가입을 진행

3. 회원가입 페이지

  • 이메일 인증 기능과 이메일, 전화번호, 비밀번호 유효성 검증을 통해 회원가입을 원활히 진행
  • 소셜로그인 기능 ➡️카카오 로그인 구현

4. 로그인된 메인페이지

우측 상단으로 로그인이 성공한 유저 정보를 확인할 수 있음


5-1) 검색 페이지 (카테고리 : "카페")

  • 메인 페이지에서 "카페" 카테고리를 클릭하여 "카페" 카테고리로 등록된 공간을 확인할 수 있는 검색 페이지
  • URL에서 /spaces/search?purpose=CAFE 로 API 요청 확인 가능

5-2) 검색 페이지 (검색어 : "인천")

  • 메인 페이지에서 검색창에 원하는 검색어로 검색하게 되면 해당 검색어가 포함된 공간을 확인할 수 있는 검색 페이지
  • URL에서 /spaces/search?query=인천 으로 API 요청 확인 가능

6) 사이드탭

  • 좌측 상단 메뉴 버튼을 눌러 사이드탭을 활성화시킬 수 있음
  • 프로필 관리를 누르게되면 프로필 정보를 변경할 수 있는 마이페이지로 리다이렉트됨

7) 마이페이지

마이페이지에서 닉네임 및 연락처, 비밀번호, 프로필 사진까지 변경할  수 있음


호스트 페이지

 

1) 호스트센터 페이지

  • 호스트페이지에서는 공간 등록/관리, 예약 및 정산 관리를 할 수 있는 페이지로 구성하였음
  • 호스트에 대한 접근은
    1) 게스트로 회원가입 후 호스트로 전환할것인지,
    2) 호스트 자체 회원가입을 별도로 구분할지에 대한 고민들도 있었음
    ➡️현재는 호스트 자체 회원가입을 별도로 두는 방향으로 설계

  • 게스트와 호스트의 페이지를 분리한 이유는 각 유저의 역할 별로의 기능 구분이 명확히 필요함과
    동시에 유지보수의 용이성을 고려했고 게스트와 호스트가 하는 역할이 다르다고 판단하여 이러한 설계로 진행

2) 호스트 로그인 페이지

  • 상단 메뉴의 공간작성을 클릭하면 "로그인이 필요한 서비스입니다" 문구를 통해 인증이 필요한 로직을 구현

 

  • 호스트 로그인 페이지에서도 게스트 로그인 페이지와 같이 소셜로그인 (현재는 카카오 구현) 및 회원가입 페이지로 리다이렉트 할 수 있게 구현

3) 호스트 회원가입 페이지

게스트 회원가입 페이지와 마찬가지로 이메일 인증 로직과 전화번호, 비밀번호 유효성 검증 후 회원가입이 이루어짐


4) 공간 등록 페이지

kakao:
  map:
    javascript-key: API키값
  • application-secret.yml 부분에서 카카오맵 API 키를 발급 받아 사용하여 공간의 상세주소검색이 가능하도록 구현

  • 이처럼 모든 공간의 정보 입력 및 등록을 완료한 후에는 호스트의 공간 정보 페이지 내에서 등록한 공간을 확인할 수 있도록 구현

  • 공간을 눌러 공간정보 페이지에 들어가면 해당 공간의 정보 및 예약을 확인할 수 있음

예약 페이지

 

1) 메인 페이지 (등록된 공간들 확인)


2) 공간 상세 페이지

  • 날짜 선택 및 시간을 선택 후 예약하기 버튼을 클릭하여 예약 페이지로 리다이렉트

2-1) 공간 예약 확인 페이지


2-2) 예약 확인 및 결제하기 버튼 활성화 페이지


3) 결제 페이지

toss:                           # 토스페이먼츠 파트
  payments:
    secret-key: 테스트키 # LoCo 프로젝트 토스페이먼츠 시크릿키
    success-url: "http://localhost:8090/api/v1/payments/success"
    fail-url: "http://localhost:8090/api/v1/payments/fail"
  • 토스페이먼츠 API 와 연동하여 시크릿키를 발급받아 application-secret.yml 에 적용
  • 그 결과 토스페이먼츠를 통해 다양한 은행을 통해 결제할 수 있도록 구현

  • ex. KB국민카드의 경우 KB Pay 앱을 실행하여 QR스캔 후 결제할 수 있도록 구현
  • 배포되기 전 서비스이기때문에 실제 결제까지는 이루어지지 않음

관리자 페이지 (=어드민 페이지, 백오피스)

 

1) 대시보드 페이지

  • 대시보드에서는 사이드탭에서 이동가능한 메뉴들과, 관리자 대시보드의 요약 부분을 한눈에 확인할 수 있도록 구현

2) 사용자 관리 페이지

토글 후 GUEST > HOST 로 변경

  • 사용자 관리페이지에서는 해당 사용자의 권한을 변경할 수 있는 토글 버튼 (GUEST ➡️ HOST 혹은 HOST ➡️ GUEST)과
  • 전체 유저 정보가 담겨있음

3) 예약 결제 관리 페이지

  • 예약 내역 및 결제 내역을 관리할 수 있는 페이지

기능 시연 영상

  • 전체 발표 영상은 개인채널에 별도 업로드 완료

https://www.youtube.com/watch?v=dQzQO2KjDYg

팀원분이 업로드한 기능시연 영상

🚀프로젝트를 마무리하며 :

팀 프로젝트를 진행해보며 Github Project에서의 협업 및 Git 명령어에 익숙해질 수 있었고

데일리 스크럼을 통해 기능 개발 및 요구사항 정의를 기획해나가는 과정도 뜻깊었다.

Git branch를 분기하여 팀원들이 각각 기능을 개발하고 추후 병합할때 충돌된 부분들을 함께 해결해나가는 부분도

도전의식과 함께 희열, 뿌듯함도 느낄 수 있었다.

어려움이 없던 프로젝트라고한다면 거짓말이겠지만 어려웠던 만큼 어떤 부분이 부족한지, 어떤 부분에 강점인지를 파악할 수 있어

개발 공부에 큰 원동력이 될 수 있었다.🎇