바닐라 js 프로젝트에서의 시행착오..
입사 후 과제를 수행하고 있습니다.
그 중 하나는 바로 프레임워크를 사용하지 않고 페이지 개발하기!
기본기가 부족했음을 늬우치며 열심히 하고 있지만
벌써 몇가지 난관에 부딪혀 그동안의 삽질과
앞으로 부딪히는 문제를 기록해두려합니다.
컴포넌트 분리 시 스타일 중복 적용 문제
바닐라 프로젝트에서도 다양한 개발 방법이 있을거라고 생각했고
어떠한 개발 방식이 많이 사용되는지 찾아보았습니다.
찾아본 결과, SPA 프레임워크를 사용하는 분들이라면 잘 아실 컴포넌트를 분리, 재사용하는 방법이
바닐라 js 프로젝트에서도 많이 사용되는 것을 알 수 있었습니다.
아닌 경우도 있겠지만, 보통은 상단바처럼 모든 페이지에 재사용 되는 부분이 있을 수 있습니다.
저는 우선 상단바를 구성하는 여러 태그를 하나의 태그로 사용하면서 재사용할 수 있도록
컴포넌트로 분리하고 분리한 자바스크립트 파일에서 document에 삽입하는 방식을 사용해보았습니다만
이 방식으로 html 안에서 여러 컴포넌트를 함께 사용할 때,
하나의 컴포넌트에서 적용한 margin 등의 스타일이 다른 컴포넌트에서도 중복으로 적용되는 문제가 있었습니다.
(글을 쓰며 생각해보니 프레임워크를 사용했던 경험에 치우쳐
태그에 직접 스타일을 적용하니 안되던 것을
class로 스타일을 주는 방법은 시도해보지 않고 이것마저도 안 된다고 생각하고 넘어갔네요..
확실히 프레임워크에선 별개로 적용되야하지만
직접 구현한 컴포넌트 분리 방식에서는 태그에 바로 작성한 스타일은
같은 유형의 다른 태그에서도 적용될 수도 있겠다는 생각이 드네요.
이 방법은 빠른 시일 안에 시도해보고 글을 수정하겠습니다.)
2024.04.28)
당시엔 프론트엔드 이해도가 전무한 수준이었습니다.
그동안 프론트엔드 공부를 병행했었는데요.
여러 프레임워크와 섀도우 돔도 사용해보고 스타일시트도 꽤나 많이 만져보며
자바스크립트와 dom 이해도가 상승하여 이제는 답을 알 것 같습니다.
섀도우 돔을 사용하면 부모 컴포넌트(요소)의 일부 스타일 속성들의 영향을 배제할 수 있습니다.
아쉽게도 전부는 안되고 font-* 관련 속성 등 영향을 받는 속성이 존재하기 때문에
섀도우 돔 외부의 스타일에 영향을 받게되도 당황하지 않고 해당 속성들만 변경해주면 될 것 같습니다.
또 위의 문제에 대해서는 제가 style 태그로 스타일을 작성했기에 당연히 dom 전역에 스타일이 지정된 것이었습니다.
섀도우 돔에서 부트스트랩이 적용되지 않음..
조금 전의 컴포넌트 분리 시 스타일 중복 문제 때문에
섀도우 돔을 이용한 방식으로 바꿔보았습니다.
섀도우 돔은 기존의 돔과 분리되어 내부의 코드가 외부에 영향을 줄 수 없어
좀 더 독립적으로 컴포넌트를 분리할 수 있다고 합니다.
이 방법을 사용하면 각 컴포넌트의 스타일이 충돌, 중복 적용되는 문제는 발생하지않지만
부트스트랩 스타일이 적용되지 않는 매우 치명적인 단점이 있었습니다..
사전에 과제의 요구사항을 보곤 디자인과 애니메이션의 중요도가 낮다는 것을 알고있었기에
시각적인 퀄리티는 떨어지더라도 부트스트랩을 사용하지 않고 css를 직접 작성하거나
또는 추가적인 해결방법을 계속해서 찾아볼수도 있었겠지만
제가 하려는 방식이 팀의 기존 프로젝트 방식과 크게 달라지는 것 같아
당장은 컴포넌트 분리를 포기하고 기본에 충실하게
각 페이지마다 태그를 직접 작성하는 방법으로 돌아가게 되었습니다.
(사수님의 조언이 도움이 됐습니다.)
모듈 번들러에서 여러 페이지를 제공하는 법
많지는 않지만 필요한 axios, bootstrap 등 몇가지 라이브러리를 사용할 계획이었고
프로젝트 빌드까지 해야하므로 프레임워크와 함께 사용하던 모듈 번들러를
바닐라 프로젝트에서도 사용할 수 있으면 참 좋겠다고 생각했습니다.
vite의 공식문서를 살펴보니 역시나 기본적으로 제공되는 템플릿 중 바닐라 js와 바닐라 ts 템플릿이 모두 있었습니다.
하지만 보통 싱글 페이지 클라이언트 앱에서는 하나의 페이지(root 디렉토리의 index.html)만을 보여주고
라우터를 사용해 페이지를 이동(부분 렌더링)합니다.
과제에서 요구하는 것은 싱글 페이지 어플리케이션이 아니라고 생각했고
여러개의 html을 응답하는 멀티 페이지 방법을 찾아보니 마찬가지로 vite 공식 문서에 방법이 있었습니다.
(사실 페이지마다 html을 직접 작성하는 경우 모듈 번들러를 사용하지 않고
nginx 혹은 다른 웹 서버에서 url마다 각 html의 경로를 지정해도 볼 수 있는 화면은 같습니다만
모듈 번들러는 이점이 많고 템플릿을 제공하는 경우 새 프로젝트를 시작하기 매우 용이합니다.)
자매품: 스프링과 JPA에서의 문제..
JPQL으로 INSERT, UPDATE, DELETE 작업 수행 시 문제 발생
서버 개발도 과제의 일부분이었습니다.
과제를 진행하면서 쿼리가 얼마나 전송되는지에 대해 신경이 쓰여
콘솔 로그를 확인해보니 쿼리메소드를 사용하는 경우
흔히 알려진 연관 관계에 있는 엔티티에 대한 N + 1 문제 뿐만 아니라
SELECT 쿼리가 자주 선행되는 문제도 있었습니다.
가능하면 쿼리가 하나만 전송됐으면 하는 마음에 @Query 어노테이션을 이용해 JPQL을 작성했으나
SELECT 작업이 아닌 경우 예외가 발생했고 어떠한 어노테이션이 필수적이라는 것을 알게되었습니다.
바로 @Modifying 어노테이션을 꼭 추가해야 한다는 것인데요. 공식문서에도 설명되어 있었습니다.
Spring Data JPA - Reference Documentation
Example 121. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del
docs.spring.io
하지만 @Query 어노테이션으로 직접 JPQL을 작성하는 경우엔
영속성 컨텍스트와 SQL 쓰기 지연 등의 이점을 누릴 수 없고
영속성 전이(cascade) 또한 동작하지 않으므로 주의해야합니다.
또한 직접 작성한 JPQL로 영속된 엔티티를 수정하고 다시 조회하는 경우
변경전의 데이터가 조회되는 등 데이터가 일치하지 않는 부정합 문제도 발생하는데
@Modifying 어노테이션의 clearAutomatically 속성의 값을 true로 명시하면 해당 JPQL 수행 시
영속성 컨텍스트가 비워지므로 변경 후의 엔티티를 조회할 수 있습니다. (쿼리를 날려 데이터베이스에서 새로 조회함)
결론적으로 쿼리 최적화는 추후에 여유가 되면 시도해보자는 생각과 함께 롤백하게 되었습니다.