본문 바로가기

프로젝트/중고 거래 플랫폼

[회고]중고 거래 플랫폼을 마무리하며

목차

    1. 프로젝트 기간과 역할

    2023.08.21 ~ 10.06

    팀장 및 발표, 백엔드 사용자 도메인

    2. 내가 배운 것

    Spring Security

    인가 및 인증 처리의 이해, Filter 개념과 filterChain의 개념. 스프링 시큐리티의 경우 배우는데 꽤 난관이 있었다.
    언뜻 개념 자체는 알고 있었지만, 인가와 인증 처리의 개념이 모호했기 때문에 기초부터 천천히 학습했던 것 같다.
    이번 프로젝트에서는 CORS와 내가 만든 JwtFilter를 위주로 사용하였다.
    기본적인 세션 방식 대신 서버의 효율성과 확장성을 고려하여 토큰 방식을 사용하였다.
    로그인, 메인 화면 등 권한이 필요없는 사이트 외 토큰을 입력받을 수 있도록 하였다.

    JWT

    사용자 관리를 JWT를 사용한 토큰 방식으로 인가를 진행하였다.
    Payload에는 사용자 식별 번호인 userNo외에 특별한 값은 넣지 않은 것 같다. 파싱의 위험도 있었고, 서버내에서 결국 no만 알면 해당 유저의 정보를 가져올 수 있기 때문이다.
    Access Token, Refresh Token 둘 다 운용하였고, 주로 액세스 토큰 위주로 요청을 주고받았다.
    예전 프로젝트에서는 RT를 MySQL에 저장하였는데, 이는 상당히 비효율적인 방식임을 깨닫고 이번에는 다른 방식을 사용하였다.
    Redis를 활용하여 RT를 Redis의 인바운드 메모리에 저장하였다.
    HTTP Only의 쿠키로 토큰을 전송, 그 외 액세스 만료 시 RT 재발급 처리, RT도 만료일 경우 200 리턴으로 프론트도 로그아웃 시키는 과정을 수행하였다.

    Redis

    토큰의 유효성을 판단하기 위해, 그 외 임시적으로 사용하는 인증 처리를 위해 Redis를 활용하였다.
    로그인, 로그아웃 시 RT를 Redis에 저장(이는 재발급 처리 시 서버에서 해당 RT를 가지고 있는지 여부를 판별한다.), 회원가입 시 메일 인증 번호, 비밀번호 찾기 등 주로 상용 서비스에서 "이 요청은 xx분간 유효합니다" 등의 임시 데이터들을 아낌없이 Redis에 활용했다.
    이 과정에서 랜덤키를 Redis key값으로 넣고, value에서는 해당 요청을 시행한 IP를 서블릿의 header에서 파싱하여 저장하였으나, 서버 관리 문제로 인해 명확한 원인을 찾을 수 없이 값이 튀는 문제가 발생했고, 안타깝게도 개발 일정 중요도 문제로 적용하지 못했다.
    아쉬웠던 점은 Redis 역시 결국은 캐시 메모리에 데이터가 저장되는 만큼, 서버가 꺼지는 경우 해당 메모리가 휘발된다는 단점이 있는데 이를 극복하지 못한 것 같다. 주기적으로 AOF, 혹은 RDB 설정 등으로 데이터를 저장하는 기능을 만들었다면 어땠을까 싶다. 다음에는 이 부분을 극복하기 위한 방안을 생각해 볼 것이다.

    Kakao API(Oauth)

    kakao developer에 API 요청을 통해 직접적으로 소셜 로그인을 구현하였다.
    자체적으로 jwt token을 했기 때문에 카카오에서 제공하는 토큰과 코드를 사용하지는 않았다.
    필요한 정보는 회원가입 시 개인정보(프로필, 이름 등)인데, 이는 최초 회원가입 과정에서만 필요했다.
    kakao url 로그인 시 받은 인가 코드를 다시 파싱하여 개인 정보를 받아오고, 그 외에 추가적으로 데이터를 사용하지는 않았다.
    이 기능을 다른 레퍼런스등을 살펴보면 FE에서 kakao로 직접 axios로 요청을 보내 실행하는 것 같기도 한데, 이번 프로젝트에서는 순전히 BE 로직에서 WebClient로 백엔드 서버에서 통신하여 대부분의 로직을 담당했다.

    이슈 :
    kakao 회원가입을 진행할 때, 해당 계정의 직접적인 이메일을 아이디로 하여 자동 가입되는 구조이다,
    소셜 로그인 과정에서 마찬가지로 해당 이메일의 여부로 계정을 확인하는데, 악의적인 유저가 특정 이메일만 스크래핑하여 요청을 보낼 경우 로그인이 될 수도 있었다.
    이러한 상황을 방지하기 위해 실제 kakao 로그인 프로세스의 결과로 나오는 카카오 자체 인가 코드를 레디스에 저장하고, 클라이언트 측에서는 이메일 + 인가 코드 두 가지를 보내 검증하며 로그인을 확인할 수 있었다.

    Swagger

    문서화의 필요성을 여실히 느꼈다.
    스웨거는 도움이 되지만, 직접적인 명세와는 비교도 할 수 없었다..

    하지만 그럼에도 스웨거는 유용하다고 생각한다.
    직접적으로 API endPoint에 맞는 설명을 제공하며, 서버 관련 지식이 부족한 프론트 팀원이 직관적으로 이해하기 쉽기 때문이다.
    나와 매칭한 프론트 팀원이 스웨거를 확인하며 도움이 되었다고 말했다. 부가적으로 가능하다면 해당 기능을 구현하는 것이 좋을 것 같다.

    사담으로 Security 및 처리 예외에 계속 걸려서 상당히 짜증났다.

    // /api는 기본 제공이 아닌 우리 프로젝트에서 적은 점이라는 것을 유의할 것.
                "/api/swagger-ui/",
                "/api/swagger-resources",
                "/api/webjars/",
                "/api/v2/api-docs",

    다음 4개의 엔트포인트를 전부 필터링 예외처리 해 주어야 명확하게 문서를 확인할 수 있다.
    혹시 이 글을 보는 누군가가 있다면 참고할 것.

    mail 및 S3

    JavaMailSender 사용 및 RDS S3 사용하여 이미지 업로드
    이전에도 구현 자체는 가능했지만, 본격적으로 규격을 맞춰서 사용해본 건 이번이 처음인 것 같다.

    3. 전반적인 회고

    벌써 싸피의 두 번째 프로젝트가 끝났다.
    첫 번째 프로젝트에서는 인프라와 CI/CD 배포를 주로 맡았다.

    이번에는 백엔드 개발쪽에 힘을 실어 사용자 도메인을 담당했다.

    어느 웹 프로젝트에서든 필요하다고 생각하는 핵심 로직이고, 서비스의 기본이라고 생각했기 때문이다.

    Git과 일정 관리, 기획에 대해

    그 외 팀장으로서 Git flow에 따른 브랜치 관리와 일정 수립 및 관리, 계획 설정 등도 담당했었다.

    팀원분 중 git 관리를 해온 팀원이 있었고, 이분의 조언과 Git flow를 따라가며 git 관리를 명확하게 수행했다. 이것이 기억에 많이 남는다. 처음 Gitlab을 사용할 때는 "도대체 Branch를 왜 지우는 거야???" 같은 의문이 이번 기회로 명확하게 해결됐다. 버전 관리의 중요성을 이제야 깨달았을 뿐이다.

     

    Merge 하며 간략하게 코드를 체크했으나, 전반적인 코드 리뷰를 하지 못했던 점은 아쉽다. 매주차 금요일, 코드리뷰를 하는 날이 있었으나 개발 일정이 밀려 제대로 시행하지 못한 탓이다.

    개발 일정이 밀린 이후는 기획에 너무 많은 시간을 쏟았기 때문이다. 아이디어는 많았고, 서로 각자 다른 생각을 가지고 있었다.


    실행 가능성 역시 낮았고(다시 회고하자면 역량 역시도 부족했다고 생각된다.), 이 부분을 조율하는데 많은 시간을 쏟았다.

    팀원들 개개인이 요구하는 아이디어들을 최대한 반영하고, 최적의 효율을 내는 기획을 하고자 했다. 해당 과정에서 수 차례의 컨설턴트님과의 미팅, 내부 회의 등을 거쳤다. 많은 아이디어들이 반려되고, 팀원들 모두가 지쳤던 시간이었다. (몇몇은 그냥 이제 피곤하니 아무거나 했으면 좋겠다 - 정도로 지치기도 했다.)

     

    최종적으로 각자의 요구사항이 다수 반영된 '중고거래 플랫폼'을 기획하였지만 시간이 많이 지난 후였다. 해당 기획 시간을 조금 더 빠르게 앞당겼다면 프로젝트 개발 과정에서 조금은 여유로웠을 텐데, 아쉬움이 많이 남는다.

    하지만 그럼에도 모두의 요구사항이 포함되고 긍정적으로 반영되었기에, 기획 자체는 나쁘지 않았다고 생각한다.

    무능력한 팀원?

    열정도 없고, 실력도 없고, 무기력한 팀원은 사실 정말 화가 났었다.

    비슷한 팀원들과 개발 실력도 차이가 많이 나고(사실 같은 취준생으로서 실력 자체는 비슷하다고 생각하지만, 그냥 시간과 노력을 투자하지 않는 것 같았다. 구현이나 기반 지식 공부에서 차이가 났다.) 간단한 기능 하나를 연휴를 포함해서 5일 내내 하지 못했다는 말을 들었을 때는 너무 허탈했다. 자기가 무기력하다고, 제대로 못 해서 미안하다는 말을 들었을땐 정말 포기해야 하나 싶었다.

     

    그럼에도 최대한 공감하고자 노력했던 것 같다. 어찌되었든 같이 공부하는 동기이자, 같은 프로젝트 구축을 위해 노력하는 팀원이기도 했다.

    무기력하고 무엇을 할 지 모르는 팀원에게 목표와 계획부터 짜라고 조언했었다. 남은 프로젝트 일정동안 본인이 무엇을 수행해야 하는지, 그것을 위해 어떻게 학습하고 구현해야 할 지, 물론 내가 전부 짜줄 수는 없지만, 피드백 정도는 줄 수 있었다.

     

    그리고 옆에서 일대일로 전담하며 포기하지 않도록 이끌었다.

    목표와 계획했던 기능을 개발했는지 확인하고 같은 기능을 동시에 개발하며 팀원의 의욕을 끌어냈다. 기능 개발을 먼저 끝냈을 경우, 개발중인 FE 로직을 확인하고 백엔드 로직을 다시 맞춰나갈 때도 있었다.

    같은 사용자 도메인을 담당하는 프론트 페어였기에, 로직에 대해 모르는 부분을 충분히 설명해줄 수 있었다. 알아갈 수 있도록, 목표를 이룰 수 있도록 최대한 서포트했던 것 같다. 누군가는 도와줘야 했고, 그게 나였을 뿐이다.

     

    결론적으로는 해당 팀원을 이끌고 계획했던 대로 기능을 구현해낼 수 있었다. 이 부분이 기억에 많이 남는다.

    그냥 내버려두고 포기할 수도 있었지만 그렇지 않고 어떻게든 같이 붙잡고 해냈다는 부분과 같이 해냈다는 점이 큰 의의가 있다고 생각한다.

     

    혼자서도 기능 구현 자체는 할 수 있었다. 사실 호흡을 맞춰가는 것보다 혼자 하는게 더 빨랐을 수도 있다.

    하지만 개발 일정과는 별개로, 같이 해냈다는 점에서 팀워크를 다지는 계기가 되었다고 확신한다. 결국 혼자보다는 두명, 더 많은 팀원과 함께하는 것이 전체적으로는 좋은 성과를 낼 것이고, 이를 위해서는 팀원들과의 협력과 도움이 필요하기 때문이다. 다른 팀원과 호흡을 맞춰가는 과정에서 대화와 의견 공유를 통해 협업 역량을 기를 수 있었다. 아마 다음 프로젝트에서 해당 팀원과 같이 한다면 지금보다는 더욱 좋은 성과를 낼 수 있을 것이다.