2023년 리뉴얼 프로젝트 회고

yourjin·2023년 5월 30일
1

dev.log

목록 보기
12/14

➕ 시작하며


작년 말부터 준비했던 APP-홈페이지 리뉴얼 프로젝트가 올해 3월에 오픈했다. 바로 이어서 영문 홈페이지 구축 작업에 투입되어 좀 늦어졌지만, 더 잊어버리기 전에 회고록을 작성해보려고 한다. 입사 후 같은 곳에서 운영 업무만 진행하다 처음으로 맡은 프로젝트였기 때문에 설렘이 컸다. 운영만 할 때 보다 더 많은 것을 배울 수 있을 거라고 생각했고, 실제로도 짧은 기간이었지만 많은 분들에게 도움 받아 성장할 수 있었던 것 같다.

프로젝트 착수 문서를 보니 기간이 2022.06.30 ~ 2023.02.14(7.5개월)로 잡혀있는데, 실제로는 좀 밀려서 3월 초에 오픈을 했다. 앞에 기획, 프론트 개발 단계가 있기 때문에, 내가 작업하는 부분의 퍼블본을 받은 건 11월 말이었다. 그래서 실제 개발 기간은 약 3개월 정도밖에 되지 않았다. App/Mobile Web, PC Web을 다 해야 해서 개발 범위가 꽤 많았는데, 남은 시간은 부족하니 당연히 야근도 잦았다. 막판에는 새벽 3~4시까지 작업하다 다음날 출근하기를 반복했다. 힘들었지만 밤새서 코딩하던 때도 생각나고, 오래간만에 코딩하는 즐거움을 느껴본 것 같다.

➕ 배운 점


개발 환경 일부 개선

리뉴얼을 하면서 가장 잘한 것을 꼽으라면, 답답하던 이클립스를 버리고 인텔리제이로 갈아탄 것이다. 처음 세팅할 때 가이드 받은 대로 이클립스를 쭉 쓰고 있었는데, 회사에서 개인 라이센스여도 사용할 수 있다고 해서 새로 프로젝트 구축하는 김에 옮겼다. (진작에 라이센스를 사줬으면 좋았을텐데,,, 결국 개인 라이센스 쓰다가 프로젝트 다 끝나고 나서 받았다.) 새로운 IDE의 단축키와 기능에 적응하는데 조금 시간이 걸렸지만, 예쁜 다크모드와 다양한 플러그인을 제공한다는 면에서 개인적으로 훨씬 좋았다.

두 개의 IDE를 경험해 보면서, IDE에 따라서 프로젝트 구조가 다르다는 것도 알 수 있었다. 이클립스는 하나의 workspace 안에 서로 의존할 수 있는 여러 개의 프로젝트를 둘 수 있다. 이클립스를 쓸 때는 하나의 workspace 안에 branches, trunk 프로젝트를 전부 다 넣어 놨었다. 하지만 인텔리제이에서는 workspace 개념이 없고, 한 번에 하나의 프로젝트만 작업할 수 있다. 그래서 이클립스에서 의존 관계에 있는 프로젝트였다면, 인텔리제이에서는 한 프로젝트 안에 여러 개의 모듈로 구성해야 한다. 우리는 Model, Repository 쪽을 별도 모듈로 빼서 공통으로 사용하고 있었기 때문에, 멀티 모듈로 프로젝트를 구성했다.

설정 파일도 달랐는데, 이클립스에서는 .project, .classpath , .settings\ 가 있다면 인텔리제이에서는 .idea\ 가 있다. 프로젝트 생성 시 IDE에서 자동 생성되는 부분이기 때문에, 개발자가 자세하게 알고 있을 필요는 없을 것 같다. 다만 VCS에 올릴 때는 개발자마다 다른 툴을 사용할 수 있기 때문에 이런 설정 파일들은 제외하고 올리는 게 좋을 것 같다.

추가로 Subversion Client Tool 인 TortoiseSVN(a.k.a. 거북이)도 설치해서 사용하고 있는데, 이것도 개발 속도 향상에 크게 기여했다. update, merge, tag 등에서 인텔리제이에서 하는 것보다 훨씬 빨라서 자주 사용했다.

프로젝트 구조와 공통 로직 처리

운영 업무를 할 때는 보통 기능 추가/수정과 관련된 건이 많았기 때문에, 전체적인 구조를 확인해야 하는 경우가 거의 없었다. 그래서 이번 프로젝트에서 구조나 공통 로직 부분을 좀 더 많이 알아보려고 했다.

뷰 템플릿 엔진으로는 Apache Tiles 를 사용하고 있는데, 템플릿이라는 말 그대로 화면에서 중복 include를 없애고 레이아웃을 구성할 수 있게 도와주는 프레임워크다. 템플릿으로 사용할 jsp를 template 속성에, 화면 렌더링되기 전에 실행될 로직을 담은 ViewPreparer를 preparer 속성에 지정해서 사용할 수 있다. ViewPreparer에서는 페이지 title이나 리소스 경로 등 공통적으로 정의해야 하는 부분을 지정하고 있어, 관습에 따른 코딩(coding by convention) 이 가능하게 도와주고 있다.

템플릿 엔진은 레이아웃 템플릿 엔진, 텍스트 템플릿 엔진으로 구분하기도 하는데, Apache Tiles는 화면을 조합해서 하나의 페이지를 구성하는 레이아웃 템플릿 엔진으로 분류된다. 텍스트 템플릿 엔진은 화면에 데이터를 조합해주는 것으로(ex. Thymeleaf), 레이아웃 템플릿 엔진과는 역할이 달라 함께 사용할 수도 있다고 한다.

Controller를 개발할 때 먼저 실행되는 로직이나 가공되어 넘어오는 데이터가 있었는데, 이 부분을 파보면서 Filter, Interceptor에 대해서도 새롭게 알게 되었다. 둘 다 공통적으로 처리해야 하는 로직을 다룰 때 사용한다. Filter는 Web Application 설정 파일인 web.xml에 등록하며, 스프링과는 상관 없이 요청이 들어오면 url-pattern으로 매핑 대상을 지정해서 실행된다. Interceptor는 스프링의 Dispatcher Servlet이 요청을 받은 후에 실행되므로, Dispatcher Servlet 설정 파일에 등록되어 있다. (참고로 Dispatcher Servlet 설정 파일은 web.xml에 등록되어 있다.) 단순한 인코딩이나, XSS 방어 로직 등은 Filter로 처리하고 있지만, 스프링 자원(ex. 스프링 빈으로 등록된 Service, Repository, Model 등)이 필요한 경우에는 Interceptor로 처리한다. 이번 프로젝트에서는 Interceptor가 요청을 가로채서 공통으로 필요한 데이터들을 추가해주는 역할을 하고 있다. 이것과 관련된 내용은 따로 블로그 포스팅으로 정리해두었다.

Filter, Interceptor는 요청 경로(url, path)로 구분해서 광범위한 공통 처리를 담당했다면, 좀 더 작은 범위에 디테일한 조건을 걸어 추가하고 싶다면 AOP를 사용했다. AOP에서는 추가하고자 하는 공통 로직을 Aspect(관점)이라고 부르는데, 이를 Filter, Inteceptor에 비해 다양한 방식으로 추가할 수 있다. Class, Method, Custom Annotation 등을 통해 Target(Aspect를 적용하는 곳)을 지정할 수 있고, Aspect 실행 시점도 Target의 이전, 이후, return 이후 등으로 세밀하게 지정할 수 있다. 이 부분과 관련된 내용은 기회가 되면 따로 정리해서 올리려고 한다.

웹 지식 습득

웹 프로젝트이다 보니 자연스럽게 웹 지식도 많이 알게 되었다. 쿠키(Cookie)는 브라우저 안의 작은 저장소라고 생각하면 쉬운데, 반복되는 비동기 통신 데이터를 저장해두고 성능 최적화에 활용할 수도 있었다. [개발자 도구(F12) > Appliction > Cookie] 메뉴에 가면, 페이지에 저장된 쿠키 값을 볼 수 있다. 여기서 쿠키를 수정하거나 삭제할 수도 있다.

헤더(Header) 값을 사용하는 경우도 많았다. 로그인 관련 토큰이나 user-agent 구분이 필요한 경우에 헤더를 활용했다. PC 버전에서는 거의 사용하지 않았고, 주로 앱과 서버 간의 통신에서 약속된 값을 주고 받을 때 사용했다. ModHeader라는 브라우저 확장 프로그램을 잘 사용했는데, Request Header에 대한 조작이 가능하게 해줘 개발할 때 유용하게 사용했다. [개발자 도구(F12) > Network] 에서 현재 URL의 Requset/Response Header 값도 확인할 수 있다.

그 밖에도 특수 문자 처리를 위해 인코딩(Encoding)을 추가하기도 하고, CORS(Cross-Origin Resource Sharing) 문제도 경험해보고, 이벤트 처리를 하면서 브라우저가 소스를 읽는 방식(DOMContentLoaded, load)도 공부해보았다. 생각보다 웹 기술은 엄청 다양하고, 대응해야 하는 이슈도 많은 것 같다!

보안, 성능에 대한 고민

프로젝트를 마무리 할 때가 되면 소스 코드에 대한 보안 진단이나 성능 개선에 대해 고민을 해보게 된다. SQL Injection 관련해서는 자바의 PreparedStatement를 사용해서 외부에서 구문을 수정할 수 없도록 해야 한다. 이 문제 관련해서는 별도 포스팅으로 정리해보았다.

페이징, 캐싱 처리를 해서 성능을 일부 개선했는데, 여기서 성능 개선이라 하면 페이지가 뜨는 시간을 줄이는 것이라고 생각하면 될 것 같다. [개발자 도구(F12) > Network] 에서 하단에 보면 페이지가 로드되는데 걸리는 시간이 뜨는데, 이 시간을 단축시키는 것이다.

사실 캐싱이라고 해서 Redis와 같은 별도의 캐시 메모리를 사용하거나 한 건 아니고, 임시 저장소에 데이터를 저장해서 데이터 접근 시간을 줄인다는 캐시의 개념을 사용한 것이다. 동일한 데이터가 여러 곳에서 반복해서 사용된다면, 매번 요청해서 가져오는 것이 아니라 임시 저장소에 넣어 놓고 사용하는 것이다. 탭을 전환해서 가져오는 데이터가 매번 같다거나, 모든 페이지에서 공통적으로 사용하는 데이터의 경우 최초 1회만 가져오고 그 이후는 캐시된 데이터를 사용해서 응답 속도를 향상 시킬 수 있다.

➕ 아쉬운 점


아직은 아쉬운 개발 환경

사실 이번 프로젝트 진행하면서 자바 버전은 8이상으로 올렸으면 했는데,,, 여러 사정으로 인해 7로 유지하게 되었다. 8만 되도 람다를 쓸 수 있으니 코드가 더 깔끔해지고, 스트림 API를 지원하니 배열, 컬렉션 처리도 더 쉬웠을 것 같다. 특히 여러 컬렉션 데이터를 합쳐서 중복 제거하고, 최신순으로 정렬하고, 페이징 처리해야 하는 부분이 있었는데 스트림을 썼으면 훨씬 수월하게 개발했을 것 같다.

그리고 프론트와 백이 분리되지 못해서 불필요한 작업량이 늘었다는 점이 가장 힘들었다. 프론트(퍼블리싱)는 그들만의 작업 프로젝트를 가지고 소스를 전달하면 그걸 백엔드 담당자가 실제 운영용 소스에 옮기는 방식이었기 때문에, 퍼블만 수정되어도 백엔드 담당자가 반영을 해줘야 했다. 당연히 프론트 수정 사항이 실시간으로 반영되기 어렵고, 오류가 생겨도 실제 코드가 잘못된 건지 옮기는 과정에서 잘못된 건지 파악하기 어렵다. 객체 지향 설계 원칙 중 단일 책임 원칙(Single Responsibility Principle)의 중요성이 절실히 느껴지는 순간이었다.

기능 외에 소스 운영을 위한 개선 포인트

이제 프로젝트를 마치고 운영 기간에 접어드니 몇 가지 개선 포인트들이 보인다. 일단 지금 로그에서 스레드를 따로 구분할 수가 없어서, 운영 환경 같이 동시에 많은 요청을 받는 경우에 로그 보기가 힘들다. 나중에 필터링 해서 볼 수 있도록 구분 값 추가하는 작업이 필요할 것 같다. 그리고 exception이 발생했을 때 정보가 상세하게 남지 않아서, 어느 경로에서 어떻게 접근했을 때 해당 에러가 발생하는지 알 수가 없다. 이 부분은 ExceptionResolver 쪽 로그 남기는 부분을 수정해서 곧 운영에 반영될 것 같다.

테스트 코드도 추가하면 좋을 것 같은데, 지속적으로 테스트 코드 확인하고 업데이트 하는 환경은 아니라서 제대로 활용될 수 있을지는 아직 의문이다. 그래도 한번 추가는 해보고 싶어서, 시도해보고 조만간 정리해서 올릴 수 있기를 바란다.

profile
make it mine, make it yours

0개의 댓글