ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (Spring, MyBatis)첫 CRUD 게시판 만들어 본 개발 후기
    개발 완료 2020. 8. 29. 17:11
    반응형

    해당글은 첫 CRUD 게시판을 만들었었던 후기이며, 2021년 현재 기준으로 매우 허접합니다. 

    REST API를 적용한 좀 더 세련된(?) 코드는 아래 깃허브 저장소를 참고해주세요.

    https://github.com/YeonCheolGit/springboot-restful-api-board

     

    1. 서론


    그동안 무식하게 이론만 공부하는 방법으로 공부를 했었습니다. 그러던 어느 날 경험 삼아 카카오 인턴을 지원이라도 해보자는 생각으로 지원서를 작성하던 중 "그동안 개발 혹은 프로젝트를 하던 중 어려웠던 점과 해결했다면 어떻게 해결했는지 작성하시오"라는 질문을 작성해야 했습니다.

     

    저는 4학년이지만, 컴퓨터공학과 복수전공으로서 고작 1학기밖에 되지 않아 프로젝트나 스스로 개발을 해본 적이 없습니다. 학교에서는 운영체제, 컴퓨터 구조와 같은 이론과목에 대해서 공부를 했고, 스스로는 자바, 스프링과 스프링 부트의 이론에 대해서만 공부했습니다. 그러면서 난 많이 안다는 오만한 생각을 가지고 있었습니다. 실제로 그 이론조차 많이 아는 수준은 아니었지만요.

     

    위의 질문을 보고 한 글자도 작성할 수가 없었습니다. 왜냐하면 해본 게 없었으니까요. 망치로 얻어맞은 듯했습니다. 지원서를 작성하며 많이 깨달았습니다. 이론도 중요하지만, 결국엔 내가 공부했던 이론들은 Product를 만들기 위해서 존재하는 도구일 뿐이구나. 

     

    그래서 생애 첫 아주 간단한 CRUD 게시판을 만들어 봤습니다. 지속적으로 업데이트하여 실제 게시판과 같은 모습을 갖추도록 할 것입니다. 실력이 부족해서 언제쯤 될지는 모르겠습니다. 

     

    2. 사용된 기술


    • Server - Spring Framework (Spring Boot X), Spring MVC, Spring Security
    • Client - JSP, JavaScript, Jquery
    • DB - MyBatis, MySQL (AWS 서버와 연결)
    • Hosting - AWS EC2
    • 채팅 - Kafka, Docker
    • 기타 - Lombok, Maven, BootStrap, Log4j2

     

    3. 코드 및 실제 사이트


    github.com/YeonCheolGit/mybatis_wine_price

     

    YeonCheolGit/mybatis_wine_price

    Contribute to YeonCheolGit/mybatis_wine_price development by creating an account on GitHub.

    github.com

     

    코드는 GitHub Repository로 대체하겠습니다. 또한 코드를 자세히 설명하는 것은 이 글의 성격과 맞지 않으니 생략하겠습니다. 혹시나 따라서 만들어 보고 싶으신 분들은 저장소를 참고하시고, 이해가 안 되는 부분은 댓글 남겨주시면 알려드리겠습니다.

     

    애플리케이션에 대해서 간략히 설명하겠습니다. 기본적으로 이마트, 롯데마트 온라인 사이트에서 와인 정보를 가지고 온 후, 게시판 형식으로 구현했습니다. 구현된 기능들은 아래를 참고해주세요. 

     

    아래는 구현한 실제 사이트 주소입니다. 모바일 화면에서는 UI가 많이 틀어집니다...

     

    15.164.46.83:8080/mybatis_board/main

    AWS에서 요금이 너무 많이 나와서... 일단 내렸습니다.

     

    3. 1. 구현된 기능

    회원 (Spring MVC/Security, Rest API, Interceptor, Ajax, Modal 적용)

    • 가입 / 탈퇴 / 수정 / 로그인 / 로그아웃
    • 가입 시 - 이메일 중복 체크, 비밀번호 유효성 체크, 비밀번호 암호화
    • 로그인 / 회원가입 시 미 기입 정보 체크
    • 미 로그인 시 와인 게시판 접근 차단
    • 임시 비밀번호 이메일 전송 (String --> SringBuilder.setLength(initial capacity 100) 수행 시간 단축)
      • 참고: yeon-kr.tistory.com/157?category=857330

     

    크롤러 (Jsoup, Selenium, Multithreading)

    • 롯데마트, 이마트의 와인들 크롤링 (이미 존재하는 경우 가격만 업데이트) 
    • 와인 데이터 임시 저장 배열 (LinkedList --> ArrayList inital capacity 변경으로 수행 시간 단축)
      • 참고: yeon-kr.tistory.com/152?category=857330
    • DB 저장 (For loop, Collection.size() 연산 수행 시간 단축)
      • 참고: https://yeon-kr.tistory.com/158?category=857330
    • 마트 크롤러 각각 작성 후 쓰레드로 등록해 멀티스레드 실행 (크롤링 속도 향상 위함)

     

    본문 내용 (Spring MVC, Paging, Ajax)

    • 크롤링한 와인들을 게시판 형식으로 나열 (Paging)
    • 와인 이름 클릭 시 해당 와인을 판매하는 사이트로 이동
    • 검색창 - 검색어 자동완성 및 검색 기능 (Ajax Autocomplete)
    • 와인 가격 순서대로 정렬 가능

     

    관리자 

    • 관리자 계정 로그인 시 관리자 버튼 나타냄
    • 와인 검색 기록 통계 확인

     

    디자인 (JS, JQuery, BootStrap)

    • 다크 모드 버튼 - 회원의 컴퓨터 설정 값이 다크모드일 경우 자동 ON
    • 전체 디자인 - BootStrap
    • 모바일, PC 화면 사이즈 변화 적용

     

    채팅방

    • Docker를 이용한 Kafka 서버 운영

     

    호스팅 (AWS)

    • AWS EC2 

     

    4. 어려웠던 점


    4. 1. 클래스, 메서드, 변수 이름

    생각지도 못 한 어려움이었습니다. 

     

    클래스, 메소드 같은 것들의 개수가 많지 않을 때는 아무렇게나 지어도 괜찮았습니다. 어차피 구현된 기능이 복잡하지 않았기 때문입니다. 일단 작성하고, 돌아가면 놔두는 식이었습니다.

     

    하지만 프로젝트가 복잡해지면서 이름이 명확하지 않은 것들은 어떻게, 왜 동작하는지 쉽게 이해하기 어려웠습니다. 심지어 제가 작성한 코드인데도 불구하고, 며칠 뒤에 수정하려고 보면 어떤 동작을 하는 메서드인지 파악이 안 됐습니다. 만약에 이름만 보더라도 기능의 유추가 될 수 있다면 좀 더 빠르게 파악 후 수정을 할 수 있었을 것 같습니다. 

     

    지금은 혼자서 프로젝트를 하고 있지만, 만약에 협업을 하게 된다면 더 어려웠을 것입니다. 제가 작성했지만 이해가 되지 않는 이름을, 과연 다른 사람이 알 수 있을까라는 생각이 들었습니다. 협업을 하게 된다면 이름 작성 규칙을 명확히 정한 후 쉽게 기능을 유추할 수 있게 작성해야 할 것 같습니다. 

     

    4. 2. MyBatis 사용

    그동안 스프링 프로젝트를 할 때는 스프링 부트 + JPA를 사용했었습니다. 하지만 이번에는 부트 없이 스프링만 사용했고, MyBatis로 DB와 연결을 했습니다.

     

    스프링 부트 + JPA를 사용할 때는 Configuration의 편리함은 당연하고, Entity 클래스를 활용한 DB layer 구성하고 Repository 인터페이스를 활용하면, JPA가 알아서 쿼리를 날려줍니다. 하지만 MyBatis는 Mapper.xml 파일 생성 후 쿼리를 직접 작성해야 했었습니다. 그동안 SQL 쿼리에 대해서 잘 몰랐었기 때문에 처음에는 막막했지만, 구글에서 검색을 하면서 SQL 쿼리에 대해 많은 공부가 됐었습니다. 

     

    사실 처음에는 어려웠지만, 막상 쿼리를 직접 작성하다 보니 눈으로 직접 볼 수 있어 오히려 더 명확하게 느껴지고, 에러가 발생했을 때 직접 제가 짠 쿼리를 보면서 해결을 할 수 있다는 점에서는 더 좋게 느껴지기도 했습니다. 

     

    하지만 그럼에도 불구하고 많은 회사에서 새로운 프로젝트를 시작할 때는 JPA를 사용하는 이유를 알 수 있었습니다. 이미 인터페이스에 모두 구현된 추상 메서드의 편리함을 체감할 수 있었습니다. 

     

    4. 3. DB 설계

    예전에 우연히 DB를 설계한다는 말을 본 적 있습니다. 사실 DB를 설계할게 뭐가 있나라는 생각도 했었습니다. 그냥 대충 쿼리 만들어 놓고 넣고, 빼면 되는 거 아니냐는 생각이었습니다.

     

    하지만 프로젝트가 커지고, 중간에 변경이 일어나면서 DB를 수정해야 하는 경우가 많이 생겼습니다. 

     

    아주 간단하게는 컬럼(column)의 타입을 바꿔야 하는 경우입니다. 최초에는 int 값으로 설정한 것을 로직을 수정하면서 varchar로 수정하고 이런 경우입니다. 물론 지금은 프로젝트가 실제로 사람들이 사용하는 서비스도 아니고, 아주 복잡하지는 않습니다. 하지만 복잡한 프로젝트에서는 이러한 컬럼의 변경은 심각한 에러를 가지고 올 수도 있습니다. 참조하는 로직을 변경해야 할 수도 있습니다. 

     

    컬럼의 타입, 속성들의 변경으로 로직도 같이 변경해야 하는 경우를 맞이하며, 프로젝트의 시작에는 단순히 기능에 대한 설계를 하는 것도 중요하지만, DB와 동작하는 부분에서도 설계를 신경 써야 한다는 것을 느꼈습니다.

     

    4. 4. 스프링 설정

    스프링 부트를 없이 사용했을 때 가장 불편한 점입니다.

     

    부트 없는 스프링 프레임워크는 XML 설정 파일을 많이 작성해줘야 합니다. 물론 애노테이션 덕분에 빈을 직접 주입하는 불편함은 사라졌지만 DipatcherServlet, Web.xml 같은 것들을 작성해줘야 합니다. 특히 MyBatis를 사용한다면 Mapper 파일뿐만 아니라, MyBatis 설정 파일도 작성해야 합니다. 

     

    설정 파일을 직접 작성하면서 눈으로 볼 수 있다는 것은 좀 더 명확한 느낌이 들어서 좋지만, 그럼에도 불구하고 스프링 부트를 사용해야 할 것 같습니다. 초기에 수많은 설정 파일을 작성해야 하는 심리적 압박과, 변경이 일어났을 때 번거로움도 줄어들 것 같습니다.

     

    4. 5. View 페이지

    그동안 자바스크립트, CSS를 별도로 공부해본 적이 없습니다. 필요하면 그때그때 기능들을 검색해서 사용하곤 했는데요. 

     

    단순히 몇 개의 기능을 사용할 때는 복사/붙이기로 가능했습니다. 하지만 여러 가지 기능을 원하는 대로 변경하고, 적용하려면 자바스크립트에 대한 이해가 필요했습니다. 

     

    자바스크립트를 전혀 사용하지 않는, 백엔드 엔지니어라고 하더라도 클라이언트에서 사용되는 언어를 알아야 할 것 같습니다. 왜냐하면 결국에는 클라이언트에서 서버로 넘겨주고 데이터 반환을 통해 동작을 해야 하는데, 어떻게 넘어오는지를 모르면 서버 프로그래밍에서도 문제가 생긴다고 생각합니다. 

     

    4. 6. AWS 호스팅

    백엔드 엔지니어를 희망한다면 최소한 자신이 만든 사이트 호스팅은 해봐야 한다는 생각이었습니다.

     

    AWS, GCP, 카페 24 등등 많았습니다. 하지만 현업에서 가장 많이 사용하는 것은 AWS라는 통계를 봤고, 한 번쯤 사용해보자는 생각을 했습니다.

     

    겨우 애플리케이션을 배포했고, 드디어 애플리케이션이 세상에 공개가 됐습니다. 하지만 문제는 이것이 어떻게 동작을 하는지 이해가 가지 않습니다. 

     

    AWS의 우분투 서버를 대여해서 사용하고 있었는데, 사용되는 Bash Shell이 익숙하지 않았습니다. 물론 쉘 스크립트에 대한 약간의 이해는 있었지만, 정확히 어떤 동작을 하는지 깊이 알지 못했습니다. 

     

    사실 학교에서 리눅스 수업을 들으면서 "과연 이게 프로그래밍하는데 뭐가 도움이 될까"라는 생각을 하곤 했었는데, 필요한 경우가 생기는 것을 경험하면서 반성을 하고, 어떤 것이 부족한지 느낄 수 있었습니다. 역시 지식을 바탕으로 무엇인가를 만들어 봐야 하는 이유인 것 같습니다. 

     

    AWS 자체에 대한 이해도 부족했었습니다.

     

    실제로 데이터베이스를 연결하는 과정에서 기존의 DB는 localhost로 연결되어 있었는데, 어떻게 AWS 서버로의 URL 주소를 바꿀 것인가 고민과 어려움이 있었습니다. 

     

    또한 Git 저장소의 애플리케이션을 clone 후 바로 배포하려고 했지만, jar 파일이 아닌 war 파일로 지속적으로 저장이 됐고 이것을 배포하는 방법을 찾지 못했습니다. Maven 설정도 jar 파일로 바꿨지만 아직까지 이해가 가지 않습니다. 그래서 차선책으로 Filezilla 프로그램을 이용해 직접 war 파일을 서버에 배포했습니다. 

     

    그동안 호스팅이라고 하면 "그냥 코드 넘겨주면 알아서 실행시켜주지 않을까?"라는 막연한 생각을 가지고 있었습니다. 물론 크게 보자면 맞는 말입니다. 하지만 AWS가 작동하는 방식과 설정에 대해서 더 깊이 알면 좋을 것 같습니다.

     

    4. 7. 크롤러 

    홈플러스, 이마트 웹 사이트의 와인 정보들을 가지고 오기 위해서 크롤러를 만들었습니다. 

     

    일단 대량(?)의 데이터를 입력, 출력하는 것이기 때문에 동작 시간이 너무 오래 걸렸습니다. 어떻게 하면 단축할 수 있을까 하는 고민을 했고, 위에서 언급한 대로 openJDK의 자료구조까지 보면서 개선했습니다.

     

    그리고 너무 빠른 속도로 데이터를 가지고 온 후 다음 페이지를 넘어가는 것을 반복하다 보니, 웹 사이트에서는 반복적인 새로고침으로 인식을 해 에러 페이지를 띄웠습니다. 그래서 크롤링이 잘 안됐었습니다. 

     

    그래서 Selenium, Jsoup의 다음 페이지 넘어간 후 Thread.sleep을 걸어줬습니다. 웹 사이트에서 반복적인 새로고침으로 느끼지 못하기 위함입니다.

     

    추가적인 에러는 Selenium에서 다음 페이지 버튼을 찾은 후 바로 클릭이 되지 않는 것이었습니다. 왜냐하면 버튼을 찾는데 시간이 걸리는데, 찾기도 전에 click이 이루어졌습니다. 그래서 Selenium의 'ExpectedConditions.visibilityOfElementLocated' 메서드를 사용해서 버튼을 찾아서 클릭할 수 있을 때까지 대기하는 로직을 추가하는 것으로 해결했습니다.

     

    5. 추가하고 싶은 기능

    다음에는 스프링부트, JPA, REST API를 활용해서 좀 더 트렌디(?)한 개발을 하려고 합니다.

     

    또한 프론트에서 jQuery가 아니라 자바스크립트 + 프레임워크를 활용해보려고 합니다. 

     

    6. 수정 사항

    2020년 9월 4일 

    제목 및 내용 변경

     

    2021년 2월 17일

    깃허브 링크 변경 및 내용 추가

     

    2021년 2월 19일

    사용된 기능 추가

     

    2021년 6월 14일

    기능, 크롤러, 추가하고 싶은 기능 파트 추가 

    반응형

    댓글

Designed by Tistory.