Post

이강현님 포트폴리오 4주차 작업 내용 피드백

메가스터디IT아카데미 SpringBoot 백엔드 개발자 과정 주말반 (2025.02.22 ~ 2025.09.13). 이강현님의 포트폴리오 4주차 작업 내용에 대한 피드백

이강현님 포트폴리오 4주차 작업 내용 피드백

이강현님 포트폴리오 4주차 작업 내용 피드백

작성일: 2025-09-13 github에 push된 코드를 바탕으로 장점, 단점, 그리고 개선사항을 정리했습니다. 아래 사항은 참고만 하시고 적용 여부는 본인이 직접 판단하시면 됩니다.


안녕하세요, 강현님. 마지막 프로젝트 피드백입니다. 벌써 마지막이라니 시간이 참 빠르네요. 마지막인 만큼 이번 주 작업 내용과 더불어 프로젝트 전반에 대한 총평을 함께 정리했습니다.

이번 주에는 데이터베이스 연동을 주요 목표로 설정했었는데, 제출된 코드에서는 관련 변경 사항을 찾기 어려웠습니다. 주로 헤더와 푸터 등 공통 UI 요소에 대한 개선 작업이 이루어진 것으로 보입니다. 이 부분에 대한 피드백과 함께, 데이터베이스 연동 및 백엔드 코드에 대한 전반적인 리뷰와 최종 총평을 전달해 드릴게요.

1. 금주 작업 및 UI/UX 개선사항

잘된 점 (Good Points)

1) 일관성 있는 UI/UX 개선

  • 파일: header.html, _footer.html, main.css

전체 페이지에 공통으로 사용되는 헤더와 푸터의 디자인을 실제 하겐다즈 사이트와 유사하게 개선하여 전체적인 통일성과 완성도를 높였습니다. 특히 header.html에 추가된 메가 메뉴와 소셜 미디어 링크는 사용자가 사이트의 다른 부분으로 쉽게 이동할 수 있도록 돕는 좋은 기능입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- E:\Web개발-주말반-프로젝트\이강현\src\main\resources\templates\_fragments\header.html -->
<!-- 상단 탑바 -->
<div class="hd-topbar">
    <div class="container">
        <div class="top-left">
            <a href="https://www.facebook.com/HaagenDazsKR/?locale=ko_KR"><i class="fab fa-facebook-f"></i></a>
            <a href="https://www.instagram.com/haagendazskorea/"><i class="fab fa-instagram"></i></a>
            ...
        </div>
        <div class="top-right">
            <a href="#">로그인</a>
            ...
        </div>
    </div>
</div>

2) 동적인 메뉴 UI 구현

  • 파일: header.html

햄버거 버튼을 클릭했을 때 메가 메뉴가 나타나고, 아이콘이 ‘X’로 바뀌는 등 동적인 UI를 JavaScript로 깔끔하게 구현했습니다. 사용자의 인터랙션에 즉각적으로 반응하는 UI는 좋은 사용자 경험을 제공합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- E:\Web개발-주말반-프로젝트\이강현\src\main\resources\templates\_fragments\header.html Line 131 -->
<script>
    document.addEventListener("DOMContentLoaded", function() {
        const menuToggle = document.getElementById("menu-toggle");
        const megamenu = document.getElementById("megamenu");

        menuToggle.addEventListener("click", function() {
            megamenu.classList.toggle("active");

            // 아이콘 토글
            if (megamenu.classList.contains("active")) {
                menuToggle.classList.remove("fa-bars");
                menuToggle.classList.add("fa-xmark");
            } else {
                menuToggle.classList.remove("fa-xmark");
                menuToggle.classList.add("fa-bars");
            }
        ...
    });
</script>

개선점 (Areas for Improvement)

1) CSS 클래스 중복 선언

  • 파일: main.css
  • 구분: 수정 제안

.all-products.product-card-all 등의 클래스가 여러 번 중복으로 선언되어 있습니다. CSS 파일이 길어지고 유지보수가 어려워질 수 있으니, 중복되는 스타일은 하나로 합치고 필요한 부분만 별도로 재정의하는 것이 좋습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* E:\Web개발-주말반-프로젝트\이강현\src\main\resources\static\assets\css\main.css Line 415 */
/*추천 상품 페이지*/
.product-wrapper { ... }

.product-section { ... }

.section-title { ... }

/* 상품 카드 */
.all-products { /* <-- 중복 선언 */
  display: flex;
  ...
}
.product-card-all { /* <-- 중복 선언 */
  position: relative;
  ...
}

2) HTML 구조의 중첩 오류

  • 파일: products.html
  • 구분: 필수 수정

상품 목록을 표시하는 부분에서 .all-products 클래스를 가진 div가 불필요하게 두 번 중첩되어 있습니다. 이는 의도하지 않은 레이아웃 문제를 일으킬 수 있으므로, 바깥쪽 div나 안쪽 div 중 하나를 제거하여 구조를 단순화해야 합니다.

1
2
3
4
5
6
7
8
<!-- E:\Web개발-주말반-프로젝트\이강현\src\main\resources\templates\products\products.html Line 26 -->
<div class="all-products">
    <div class="all-products"> <!-- 불필요한 중첩 -->
        <div class="product-card-all" th:each="p : ${products}">
            ...
        </div>
    </div>
</div>

2. 백엔드 및 데이터베이스 연동 총평

이번 주 목표였던 데이터베이스 연동 부분이 진행되지 않은 점이 아쉽습니다. 현재는 실제 데이터베이스 연동 없이 모든 로직이 구현되어 있어, “데이터를 조회한다”는 기능의 핵심이 빠져있는 상태입니다. 아래 내용은 강현님이 앞으로 프로젝트를 완성해 나가는 데 도움이 될 만한 백엔드 관련 총평과 개선 제안입니다.

개선점 (Areas for Improvement)

1) MyBatis Mapper의 동적 SQL 활용 미흡

  • 파일: ProductMapper.java
  • 구분: 수정 제안

현재 ProductMapper에는 SelectCakeAll, SelectCake, SelectSingleAll, SelectSingle 등 특정 카테고리나 조건에 따라 별도의 메소드가 많이 선언되어 있습니다. 이는 유지보수를 어렵게 만듭니다.

예를 들어, ‘케이크’ 상품 4개를 가져오는 SelectCakeAll과 모든 ‘케이크’ 상품을 가져오는 SelectCake는 MyBatis의 <if> 태그를 사용하여 하나의 메소드로 합칠 수 있습니다. LIMIT 절을 파라미터로 받아 동적으로 처리하는 것이죠.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// E:\Web개발-주말반-프로젝트\이강현\src\main\java\kr\khlee\icecreamhaggendazs\mappers\home\ProductMapper.java

// AS-IS: 유사한 목적의 메소드가 여러 개 존재
@Select("<script>... WHERE category = '케이크' ... LIMIT 0, 4 ...</script>")
public List<Product> SelectCakeAll();

@Select("<script>... WHERE category = '케이크' ...</script>")
public List<Product> SelectCake();

// TO-BE: 파라미터를 받아 하나의 메소드로 처리
/*
  Mapper.xml
  <select id="selectProductsByCategory" resultType="Product">
    SELECT * FROM products
    WHERE category = #{category}
    <if test="limit > 0">
      LIMIT #{limit}
    </if>
  </select>
*/
// Mapper.java
public List<Product> selectProductsByCategory(@Param("category") String category, @Param("limit") int limit);

이렇게 하면 SelectByCategory 메소드도 파라미터를 추가하여 재활용할 수 있으므로, 전체적인 코드의 중복을 크게 줄일 수 있습니다.

2) Service와 Controller의 책임 분리

  • 파일: ProductServiceImpl.java, ProductController.java
  • 구분: 수정 제안

현재는 대부분의 로직이 Mapper의 메소드를 그대로 호출하는 수준에 머물러 있습니다. 앞으로 기능을 확장할 것을 고려하면 Service 계층의 역할을 더 명확히 할 필요가 있습니다.

예를 들어, getProductCount 메소드에서 category 값의 유무를 확인하는 로직은 좋은 예시입니다.

1
2
3
4
5
6
7
8
9
10
11
12
// E:\Web개발-주말반-프로젝트\이강현\src\main\java\kr\khlee\icecreamhaggendazs\services\impl\ProductServiceImpl.java Line 68
@Override
public int getProductCount(String category) throws Exception {
    int count = 0;
    if (category != null && !category.isEmpty()) {
        count = productMapper.getProductCount(category);
    } else {
        // 카테고리 없으면 전체 개수
        count = productMapper.getAllProductCount();
    }
    return count;
}

이처럼 Service 계층에서는 단순히 데이터를 전달하는 것을 넘어, 비즈니스 로직(예: 여러 데이터를 조합, 가공, 트랜잭션 처리 등)을 처리하는 역할을 담당해야 합니다. Controller는 오직 사용자의 요청을 받아 Service에 전달하고, 그 결과를 View에 넘겨주는 역할에만 집중하는 것이 좋습니다.

3. 최종 총평

강현님, 지난 4주간 프로젝트를 진행하시느라 정말 고생 많으셨습니다. 처음의 막막함에서 시작해 지금처럼 눈에 보이는 결과물을 만들어낸 것만으로도 정말 대단한 일입니다.

장점:

  • HTML과 CSS를 사용하여 클론 사이트의 디자인을 상당히 높은 수준으로 구현해냈습니다. UI/UX에 대한 감각이 좋으십니다.
  • Spring Boot의 기본적인 구조(Controller-Service-Mapper)를 이해하고 적용하려고 노력한 점이 돋보입니다.
  • 꾸준히 문제점을 해결하고 코드를 개선하려는 의지가 보였습니다.

보완할 점:

  • 백엔드 로직의 깊이: 현재는 데이터 조회 및 표시라는 기본적인 기능에 머물러 있습니다. 앞으로는 회원가입/로그인, 장바구니, 주문, 결제 등 실제 웹 애플리케이션의 핵심적인 백엔드 기능을 구현하며 깊이를 더해야 합니다.
  • 데이터베이스 설계 및 활용: 지금의 product 테이블 외에 user, cart, orders 등 더 복잡한 관계를 가진 테이블을 설계하고, JOIN 등을 활용하여 원하는 데이터를 효율적으로 가져오는 연습이 필요합니다.
  • 테스트 코드의 부재: 현재 테스트 코드가 거의 없습니다. 단위 테스트(Unit Test)는 코드의 안정성을 높이고, 리팩토링을 두렵지 않게 만들어주는 안전장치입니다. JUnitMockito 같은 도구를 사용해 Service 로직을 테스트하는 습관을 들이는 것이 중요합니다.

앞으로의 학습 방향 제안:

  1. 백엔드 핵심 기능 구현: 지금부터는 로그인, 장바구니 등 핵심적인 백엔드 기능 구현에 집중해 보세요. 이 과정에서 Spring Security(인증/인가), JPA(객체-관계 매핑), 트랜잭션 처리 등 더 깊은 기술을 학습하게 될 것입니다.
  2. RESTful API 설계: 화면을 직접 그리는 지금의 방식(SSR)도 좋지만, 프론트엔드와 백엔드가 분리된 현대적인 웹 개발 트렌드에 맞춰 JSON 형태의 데이터를 제공하는 RESTful API를 설계하고 구현하는 연습을 해보는 것을 강력히 추천합니다.
  3. 포트폴리오 완성: 지금의 프로젝트를 여기서 멈추지 말고, 위에 제안한 기능들을 추가로 구현하여 ‘나만의 무기’가 될 수 있는 완성도 높은 포트폴리오로 발전시켜 나가시길 바랍니다.

비록 수업은 끝나지만, 개발자로서의 진짜 시작은 지금부터입니다. 지난 4주간 보여주신 열정과 노력이라면 앞으로 어떤 어려움이든 충분히 극복하고 훌륭한 개발자로 성장하실 수 있을 겁니다. 그동안 정말 수고 많으셨습니다! 항상 응원하겠습니다.

This post is licensed under CC BY 4.0 by the author.