CODING/스파르타 내일배움캠프 TIL

33_부족한 금액 계산하기_스탠다드 DI, IoC_일정관리 과제 Lv 4,5,6 일부 구현완료_25.1.31(금)

codingTrip 2025. 1. 31. 22:04

코트카타

35) 부족한 금액 계산하기

class Solution {
    public long solution(int price, int money, int count) {
        long answer = -1;
        long total = 0;
        for (int i = 1; i <= count ; i++) {
            total += (long)price * i;
        }

        if(money < total){
            answer = total-money;
        } else {
            answer = 0;
        }
        

        return answer;
    }
}

한 개 정도 테스트에서 틀리는 부분이 있어서

오버플로우 문제인가 생각하고,

if-else문도 넣어주었다.

 

다른 분들의 풀이

class Solution {
    public long solution(long price, long money, long count) {
        return Math.max(price * (count * (count + 1) / 2) - money, 0);
    }
}

출처:https://school.programmers.co.kr/learn/courses/30/lessons/82612/solution_groups?language=java

 


스탠다드반 세션

[Spring 5기] 면접 단골 질문 ! DI, IoC란 무엇일까?

핵심 개념

  1. IoC: 객체의 생성과 관리 주체를 개발자가 아닌 컨테이너(Spring)가 담당.
  2. DI: 의존성을 외부에서 주입받아 객체 간 결합도를 낮춤.

DI와 IoC의 장점

  • 코드의 유연성 증가.
  • 유지보수성 향상.
  • 테스트 용이성 개선(Mock 객체 사용 가능).

일정관리 과제

도전

Lv 4. 페이지네이션 

중복된 매핑

Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'scheduleController' method com.example.schedule.presentation.controller.ScheduleController#findAllSchedule(LocalDate, Long) to {GET [/schedules]}: There is already 'scheduleController' bean method

같은 주소로 같은 메서드가 중복 매핑되어서 발생한 예외이다.

@GetMapping("/page")

페이지네이션 부분을 위의 주소에서 실행하도록 수정하니 정상적으로 작동하였다.

 

 

limit, offset 이용해서 페이징 처리하기

SELECT s.scheduleId, s.todo, w.writerId, w.name, s.createdAt, s.updatedAt
FROM schedule s
JOIN writer w
ON s.writerId = w.writerId
ORDER BY s.updatedAt DESC
LIMIT 5 OFFSET 0

먼저 해당하는 sql문을 먼저 작성했다.

 

@GetMapping("/page")
    public ResponseEntity<List<ScheduleResponseDto>> findAllSchedulePaging(
            @RequestParam(value="pageNo", defaultValue="1") int pageNo,
            @RequestParam(value="pageNo", defaultValue="10") int pageSize) {
        log.info("pageNo={}", pageNo);
        log.info("pageSize={}", pageSize);

        return ResponseEntity.ok(scheduleService.findAllSchedulePaging(pageNo,pageSize));
    }

컨트롤러에서 페이지 번호와 페이지 크기를 각각 pageNo, pageSize 파라미터로 받아왔다.

 

offset 값을 구하는  공식을 노트에 정리하면서  스스로 구했다.(아래 이미지 참조)

offset 구하는 공식 도출 과정

 @Override
    public List<ScheduleResponseDto> findAllSchedulePaging(int pageNo, int pageSize) {
        String sql = "SELECT s.scheduleId, s.todo, w.writerId, w.name, s.createdAt, s.updatedAt\n" +
                "FROM schedule s\n" +
                "JOIN writer w\n" +
                "ON s.writerId = w.writerId\n" +
                "ORDER BY s.updatedAt DESC\n" +
                "LIMIT ? OFFSET ?";

        int offsetValue = (pageNo-1) * pageSize;

        return jdbcTemplate.query(sql,scheduleRowMapper(),pageSize,offsetValue);
    }

따라서 위와 같은 코드가 완성되었다.

 

+ 튜터님께서 자바에서 제공하는 객체인 Pageable에 대해 알려주셨다.

추후 이에 대해 적용할 예정이다.

 

Lv 5. 예외 발생 처리

수정, 삭제 시 요청할 때 보내는 비밀번호가 일치하지 않을 때 예외가 발생

먼저, 구상한 계획은 아래와 같다.

일정관리 레파지토리 - update 메서드

- scheduleId에 해당하는 password를 DB에서 받아오기(dbPassword)- dbPassword와 requestBody에서 입력 받은 비밀번호 일치여부 확인

- 불일치 시 return -1

 

일정관리 서비스 - update 메서드

- 만약 -1이면 비밀번호 불일치 관련 예외처리 발생

 

그러나 튜터님께서 update 메서드에는 update 관련 내용만 있고,

비밀번호를 검증하는 부분에 대한 메서드를 분리하는 것을 제안하셔서 분리했다.

 

@Override
    public int updateSchedule(Long scheduleId, String todo, String password) {
        return jdbcTemplate.update("UPDATE schedule SET todo = ?,updatedAt = NOW()" +
                    "WHERE scheduleId = ? AND password = ?",todo, scheduleId, password);
    }

    @Override
    public String validatePassword(Long scheduleId) {
        return jdbcTemplate.queryForObject("select password from schedule where scheduleId =?", String.class, scheduleId);
    }

    @Override
    public int deleteSchedule(Long scheduleId, String password) {
        return jdbcTemplate.update("delete from schedule where scheduleId=? and password=?",scheduleId,password);
    }

 

@Transactional
    @Override
    public ScheduleResponseDto updateSchedule(Long scheduleId, String todo, String password) {

        if (todo == null || password == null) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "The todo, writer and password are required values.");
        }

        String dbPassword = scheduleRepository.validatePassword(scheduleId);

        if (!dbPassword.equals(password)){
            throw new ApplicationException(ErrorMessageCode.BAD_REQUEST,
                    List.of(new ApiError("password", "비밀번호가 일치하지 않습니다.")));
        }

        int updatedRow = scheduleRepository.updateSchedule(scheduleId, todo, password);

        if (updatedRow == 0) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + scheduleId);
        }

        Schedule schedule = scheduleRepository.findScheduleByIdOrElseThrow(scheduleId);

        return new ScheduleResponseDto(schedule);
    }

    @Transactional
    @Override
    public void deleteSchedule(Long scheduleId, String password) {

        if (password == null) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "The password are required values.");
        }

        String dbPassword = scheduleRepository.validatePassword(scheduleId);

        if (!dbPassword.equals(password)){
            throw new ApplicationException(ErrorMessageCode.BAD_REQUEST,
                    List.of(new ApiError("password", "비밀번호가 일치하지 않습니다.")));
        }

        int deletedRow = scheduleRepository.deleteSchedule(scheduleId, password);

        if (deletedRow == 0) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + scheduleId);
        }
    }

 

Lv 6. null 체크 및 특정 패턴에 대한 검증 수행

Entity가 아닌 reqestDto에 관련 어노테이션 추가

@Getter
public class ScheduleRequestDto {

    @Size(max = 200)
    @NotEmpty
    private String todo;
    private Long writerId;
    @NotEmpty
    private String password;

}

위와 같이 해야 200자 이내 입력과 필수값 처리가 가능하다.

 

 

+ 추후 리팩토링 사항

Repository에서 DTO가 아닌 entity 사용하도록 수정

이는 입문 단계에서 필수는 아니므로 시간적 여유가 있다면 할 것이다.

 

아직 다 하지는 못했지만

일단 도전 과제를 모두 도전하고자 한다.

월요일에는 남은 과제를 도전하고, 리팩토링 및 문서 정리할 계획이다.