Skip to content

[5기 - 조인수] SpringBoot Part 3 Weekly Mission 제출합니다. #974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 98 commits into
base: zzambas
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
6d4d4c5
Chore: 동사형 메서드 이름으로 변경한다.
ZZAMBAs Oct 28, 2023
50704c4
Refactor: stream 형식으로 for문을 변경한다.
ZZAMBAs Oct 28, 2023
f96f455
Chore: 잘못된 값에 대한 로그의 레벨을 변경한다.
ZZAMBAs Oct 28, 2023
279b036
Chore: 상수 네이밍을 변수 네이밍으로 변경한다.
ZZAMBAs Oct 28, 2023
38c3600
Refactor: VoucherType 입력 순서를 CommonConstant에서 가지고 있도록 한다.
ZZAMBAs Oct 28, 2023
5e648dc
Chore: 불필요한 주석들을 제거한다.
ZZAMBAs Oct 28, 2023
aa8eb70
Refactor: 동사형 메서드 명으로 변경한다.
ZZAMBAs Oct 28, 2023
662d31d
Fix: VoucherMemoryRepository 내 필드를 private final로 설정한다.
ZZAMBAs Oct 28, 2023
f3542b5
Refactor: VoucherRepository의 findById 메서드가 Optional을 반환하도록 한다.
ZZAMBAs Oct 28, 2023
0fca27c
Test: VoucherMemoryRepository를 테스트하는 코드를 작성한다.
ZZAMBAs Oct 28, 2023
f7d94d0
Chore: CSV 종속적이므로 이름을 그에 맞게 변경한다.
ZZAMBAs Oct 28, 2023
9c32e33
Feat: VoucherRepository에 삭제, 전체 삭제 기능을 추가한다.
ZZAMBAs Oct 28, 2023
f1e6519
Test: 삭제, 전체 삭제 기능 테스트를 추가한다.
ZZAMBAs Oct 28, 2023
3c6f00b
Feat: @Value를 이용해 파일 경로를 프로파일에 맞게 설정한다.
ZZAMBAs Oct 28, 2023
83c8ad2
Test: CSV 파일로 관리하는 VoucherRepository 테스트를 작성한다.
ZZAMBAs Oct 28, 2023
a821665
Feat: customers 테이블 생성을 위한 스키마 파일을 추가한다.
ZZAMBAs Oct 28, 2023
04b2444
Rename: 패키지를 적절히 이동한다.
ZZAMBAs Oct 28, 2023
124ab3c
Feat: CustomerRepository에 CRUD 기능을 전부 추가한다.
ZZAMBAs Oct 28, 2023
5ee64a4
Feat: DB를 이용한 CustomerDatabaseRepository를 추가한다.
ZZAMBAs Oct 29, 2023
64fb4c1
Feat: final이 아닌 필드에 대한 생성자, 정보 변경 그리고 isBlack 필드의 getter 메서드를 추가한다.
ZZAMBAs Oct 29, 2023
d3e34a1
Feat: MySQL 연결을 위한 설정을 추가한다.
ZZAMBAs Oct 29, 2023
83b6469
Feat: 고객 전체 조회 메서드를 추가한다.
ZZAMBAs Oct 29, 2023
81b816e
Feat: DB에 조회하는 데이터가 없을 때 나타나는 예외를 추가한다.
ZZAMBAs Oct 29, 2023
3e7207c
Feat: queryForObject 시, 데이터가 0개인 경우 예외 처리를 하고, toParamMap에 isBlacked …
ZZAMBAs Oct 29, 2023
1b7c39a
Test: 고객 DB Repository 테스트를 작성한다.
ZZAMBAs Oct 29, 2023
43b5892
Feat: 코드 전체에서 사용할만한 메서드를 모아둔 UtilMethod 클래스를 정의한다.
ZZAMBAs Oct 29, 2023
2d1c408
Chore: VoucherRepository의 create를 save라는 네이밍으로 변경한다.
ZZAMBAs Oct 29, 2023
6d527b6
Feat: vouchers 테이블 정의 SQL문을 추가한다.
ZZAMBAs Oct 29, 2023
a03c585
Chore: 메서드 명을 바꾼다.
ZZAMBAs Oct 29, 2023
e74d7bb
Feat: vouchers 테이블에 타입 컬럼을 추가한다.
ZZAMBAs Oct 30, 2023
b959918
Feat: DB로 Voucher를 관리하는 Repository를 추가한다.
ZZAMBAs Oct 30, 2023
957dc40
Refactor: 구성 파일을 수정한다.
ZZAMBAs Oct 30, 2023
facf373
Test: DB 관리 VoucherRepository 테스트를 작성한다.
ZZAMBAs Oct 30, 2023
e2f9d15
Feat: 바우처 지갑 콘솔 입력을 받는 WalletConsole을 추가하고 최초 콘솔 입출력 클래스를 MainConsole…
ZZAMBAs Oct 30, 2023
a059942
Feat: 바우처 지갑 컨트롤러를 추가한다.
ZZAMBAs Oct 30, 2023
abc4063
Refactor: 필요없는 메서드를 삭제한다.
ZZAMBAs Oct 30, 2023
326419f
Feat: String을 UUID로 변경하는 공통 메서드를 추가한다.
ZZAMBAs Oct 30, 2023
c9caf0d
Refactor: Id 입력을 받으면 UUID로 반환하도록 한다.
ZZAMBAs Oct 30, 2023
e34bf01
Refactor: 직관적인 메서드 명으로 변경한다.
ZZAMBAs Oct 30, 2023
350a181
Feat: 지갑 테이블 wallet 생성 SQL문을 작성한다.
ZZAMBAs Oct 30, 2023
5b98ac4
Refactor: Colection 출력을 공통 콘솔 부분으로 분리한다.
ZZAMBAs Oct 30, 2023
f773ecf
Feat: 바우처 지갑 콘솔과 서비스 부분을 완성한다.
ZZAMBAs Oct 30, 2023
aa4e08f
Feat: 데이터베이스 예외 처리를 잡도록 한다.
ZZAMBAs Oct 30, 2023
7a81749
Feat: DataAccessException 발생 시, 로그에 스택 트레이스를 남기도록 한다.
ZZAMBAs Oct 30, 2023
96d6121
Refactor: 이미 존재하는 메서드를 이용한다.
ZZAMBAs Oct 30, 2023
3b1136b
Feat: DB에서 관리하는 바우처 지갑 Repository를 추가한다.
ZZAMBAs Oct 30, 2023
193f73c
Fix: 부트 설정을 변경한다.
ZZAMBAs Oct 30, 2023
ad0baa3
Refactor: 직관적인 이름으로 변경한다.
ZZAMBAs Oct 30, 2023
97b54cf
Refactor: deleteById가 void 반환값을 가지게 하고 save 메서드 명을 직관적으로 바꾼다.
ZZAMBAs Oct 31, 2023
f5fda67
Refactor: 하나의 Console, 하나의 Controller로 통합한다.
ZZAMBAs Oct 31, 2023
eb7da2e
Feat: Voucher를 새로 정의한다.
ZZAMBAs Oct 31, 2023
4b64bf1
Refactor: 정의된 Voucher에 따라 기존 코드를 VoucherPolicy에서 Voucher로 처리하게 한다.
ZZAMBAs Nov 1, 2023
3bb2f99
Feat: Policy에 따라 생성자 조건을 추가하고 VoucherPolicy의 getter를 생성한다.
ZZAMBAs Nov 1, 2023
c6e8871
Refactor: import 문을 최적화한다.
ZZAMBAs Nov 1, 2023
0ddbbfb
Refactor: 클래스명을 직관적으로 수정한다.
ZZAMBAs Nov 1, 2023
80b422a
Chore: DataSource 빈을 생성하지 못하는 문제를 해결하기 위해 테스트용 DB와 연결하도록 한다.
ZZAMBAs Nov 1, 2023
716ee19
Feat: Customer에 대한 create, findAll을 콘솔 기능에 추가한다.
ZZAMBAs Nov 1, 2023
26019b0
Test: CustomerService의 테스트 코드를 작성한다.
ZZAMBAs Nov 1, 2023
96392b0
Feat: findById 기능을 추가한다.
ZZAMBAs Nov 2, 2023
f3e265c
Refactor: 네이밍을 적절히 수정한다.
ZZAMBAs Nov 2, 2023
3b423d7
Test: 바우처 지갑의 역할을 하는 Customer, Voucher 관리 클래스 테스트를 추가한다.
ZZAMBAs Nov 2, 2023
23ed012
Rename: Console 부분 패키지를 따로 뺀다.
ZZAMBAs Nov 2, 2023
4fb8b65
Chore: 웹 설정과 thymeleaf 의존성을 추가한다.
ZZAMBAs Nov 3, 2023
a1e2f1f
Refactor: MVC에 맞게 기존 콘솔 컨트롤러 명을 변경하고 특정 profile에서만 실행하도록 한다.
ZZAMBAs Nov 3, 2023
5182451
Fix: 생성자에서 생성일, 마지막 로그인 일시를 바꿔 작성한 것을 수정한다.
ZZAMBAs Nov 4, 2023
280b867
Feat: 홈 화면을 구성하고 홈 화면 컨트롤러를 생성한다.
ZZAMBAs Nov 4, 2023
6ff54fc
Feat: upsert를 insert와 update로 분리한다.
ZZAMBAs Nov 4, 2023
bbdfce1
Fix: 블랙 여부가 업데이트되지 않던 문제를 수정한다.
ZZAMBAs Nov 4, 2023
0062633
Refactor: header를 따로 둔다.
ZZAMBAs Nov 4, 2023
dd57cc1
Feat: 고객 요청 처리를 위한 DTO를 따로 생성한다.
ZZAMBAs Nov 4, 2023
f88b6ff
Feat: 고객 상세 페이지를 생성하고 업데이트도 가능하도록 설계한다.
ZZAMBAs Nov 4, 2023
f72960f
Feat: deleteById를 추가한다.
ZZAMBAs Nov 4, 2023
4b3c469
Feat: 고객 생성 페이지를 추가한다.
ZZAMBAs Nov 4, 2023
816153e
Fix: delete 시, 리다이렉트가 안되던 문제를 수정한다.
ZZAMBAs Nov 4, 2023
d018c03
Feat: policy 이름으로 VoucherType을 찾는 메서드를 추가한다.
ZZAMBAs Nov 5, 2023
afba9ec
Feat: VoucherService에 CRUD를 보충하여 추가하고 upsert를 insert와 update로 분리한다.
ZZAMBAs Nov 5, 2023
8e4d74e
Feat: Voucher 요청 DTO와 Voucher 생성 페이지를 추가한다.
ZZAMBAs Nov 5, 2023
8bd979a
Feat: Voucher 컨트롤러를 생성한다.
ZZAMBAs Nov 5, 2023
1a2ecbc
Feat: Voucher에 생성 날짜를 추가한다.
ZZAMBAs Nov 5, 2023
39dfd6e
Feat: Voucher 수정, 삭제 페이지를 추가한다.
ZZAMBAs Nov 5, 2023
1cd104c
Feat: XML 메시지 컨버터 추가를 위한 설정을 한다.
ZZAMBAs Nov 5, 2023
d148399
Feat: 고객 필터링, 삭제, 생성 REST API를 추가한다.
ZZAMBAs Nov 5, 2023
66b32bd
Feat: 정보가 없으면 정보가 없음을 페이지에 표시한다.
ZZAMBAs Nov 5, 2023
2067ce9
Feat: 고객 ID로 정보를 조회하는 API를 추가한다.
ZZAMBAs Nov 5, 2023
cb2fec1
Feat: 응답용 DTO를 생성한다.
ZZAMBAs Nov 5, 2023
7454971
Feat: Voucher를 VoucherResponseDto로 변환해주는 메서드를 생성한다.
ZZAMBAs Nov 5, 2023
56b7190
Feat: Voucher 관련 REST API를 추가한다.
ZZAMBAs Nov 5, 2023
28f12d4
Test: Voucher REST API 테스트를 생성한다.
ZZAMBAs Nov 6, 2023
4c252ee
Chore: 피드백을 기록한다.
ZZAMBAs Nov 14, 2023
7a75263
Fix: created_at 컬럼 값을 삽입하는 로직을 추가한다.
ZZAMBAs Nov 16, 2023
9a85088
Refactor: dto 패키지를 생성하고 엔티티에서 dto로 바꾸는 로직을 dto에 추가한다.
ZZAMBAs Nov 16, 2023
4ebb682
Rename: 컨트롤러-뷰 사이 DTO를 둠에 따라 패키지를 이동한다.
ZZAMBAs Nov 17, 2023
9809ec3
Feat: Service-Controller 사이 반환을 DTO로 주고받도록 한다.
ZZAMBAs Nov 17, 2023
ca4626d
Fix: GET 메서드 명세에 따라 쿼리 파라미터 형식으로 수정한다.
ZZAMBAs Nov 17, 2023
affa6bc
Test: DisplayName으로 테스트를 상세히 기록하고 단위 테스트로 변경한다.
ZZAMBAs Nov 18, 2023
5111edc
Refactor: MVC 패턴에 맞는 의존관계를 생각해 Model 쪽으로 DTO 패키지를 분리한다.
ZZAMBAs Nov 18, 2023
3b6cbef
Chore: 테스트 코드에도 Lombok을 적용하도록 설정을 추가한다.
ZZAMBAs Nov 19, 2023
7364456
Refactor: VoucherService에서 insert, update에 대해 따로 DTO를 생성하고 적용한다.
ZZAMBAs Nov 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@ repositories {

dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework:spring-oxm:6.0.13'
implementation 'com.thoughtworks.xstream:xstream:1.4.20'
runtimeOnly 'com.mysql:mysql-connector-j'
testCompileOnly 'org.projectlombok:lombok'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

Expand Down
13 changes: 10 additions & 3 deletions src/main/java/org/prgms/springbootbasic/BasicApplication.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
package org.prgms.springbootbasic;

import org.prgms.springbootbasic.controller.MainController;
import org.prgms.springbootbasic.controller.ConsoleController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.Arrays;

@SpringBootApplication
public class BasicApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(BasicApplication.class, args);
var mainController = applicationContext.getBean(MainController.class);
String[] activeProfiles = applicationContext.getEnvironment().getActiveProfiles();

if (Arrays.stream(activeProfiles)
.anyMatch(profile -> profile.equals("dev") || profile.equals("local") || profile.equals("test"))) { // 리스트로
var mainController = applicationContext.getBean(ConsoleController.class);

mainController.run();
mainController.run();
}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.prgms.springbootbasic.common;

import java.time.LocalDateTime;

public class CommonConstant {
public static final String CSV_PATTERN = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)";
public static final int INPUT_FIXED_AMOUNT_VOUCHER = 1;
public static final int INPUT_PERCENT_DISCOUNT_VOUCHER = 2;
public static final LocalDateTime MIN_LOCAL_DATE_TIME = LocalDateTime.of(1000, 1, 1, 1, 1, 1);
public static final LocalDateTime MAX_LOCAL_DATE_TIME = LocalDateTime.of(2060, 1, 1, 1, 1, 1);
}
59 changes: 0 additions & 59 deletions src/main/java/org/prgms/springbootbasic/common/Console.java

This file was deleted.

13 changes: 13 additions & 0 deletions src/main/java/org/prgms/springbootbasic/common/UtilMethod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.prgms.springbootbasic.common;

import java.nio.ByteBuffer;
import java.util.UUID;

public class UtilMethod {
public static UUID bytesToUUID(byte[] bytes) {
ByteBuffer wrappedByte = ByteBuffer.wrap(bytes);

return new UUID(wrappedByte.getLong(), wrappedByte.getLong());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

import java.io.*;
Expand All @@ -11,6 +12,7 @@
import java.util.function.Function;

@Component
@Profile("test")
public class CsvFileTemplate {
private static final Logger log = LoggerFactory.getLogger(CsvFileTemplate.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import static org.prgms.springbootbasic.common.CommonConstant.CSV_PATTERN;

@Component
@Profile({"dev", "prod"})
@Profile({"test"})
@Slf4j
public class CustomerCsvFileManager {
private static final String BLACK_PATH = "./src/main/resources/customer_blacklist.csv";
Expand All @@ -31,10 +31,10 @@ public CustomerCsvFileManager(CsvFileTemplate csvFileTemplate) {


public List<Customer> readBlack(){
return csvFileTemplate.read(BLACK_PATH, this::lineToBlack);
return csvFileTemplate.read(BLACK_PATH, this::convertToBlack);
}

private Customer lineToBlack(String line){
private Customer convertToBlack(String line){
log.debug("line = {}", line);

List<String> csvFields =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import lombok.extern.slf4j.Slf4j;
import org.prgms.springbootbasic.domain.VoucherType;
import org.prgms.springbootbasic.domain.voucher.Voucher;
import org.prgms.springbootbasic.domain.voucher.VoucherPolicy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

Expand All @@ -14,62 +16,62 @@

@Component
@Slf4j
@Profile({"dev", "prod"})
public class VoucherCsvFileManager { // CsvFileManager 하나로 합쳐서. domain은 최대한 순수하게 유지. 외부 의존성이 들어간다? 이게 도메인에 들어가면 변경이 취약. -> 분리
private static final String FILE_PATH = "./src/main/resources/voucher.csv";
@Profile({"test"})
public class VoucherCsvFileManager {
@Value("${basic.file.path}")
private String FILE_PATH;
private static final String CSV_FIRST_LINE = "UUID,Type,DiscountValue";
private static final int UUID_IDX = 0;
private static final int TYPE_IDX = 1;
private static final int DISCOUNT_VALUE_IDX = 2;
private static final int DISCOUNT_DEGREE_IDX = 2;

private final CsvFileTemplate csvFileTemplate;

public VoucherCsvFileManager(CsvFileTemplate csvFileTemplate) {
this.csvFileTemplate = csvFileTemplate;
}

public List<VoucherPolicy> read(){
return csvFileTemplate.read(FILE_PATH, this::lineToVoucher);
public List<Voucher> read(){
return csvFileTemplate.read(FILE_PATH, this::convertToVoucher);
}

public void write(List<VoucherPolicy> voucherPolicies){
csvFileTemplate.write(FILE_PATH, voucherPolicies, this::voucherToString, CSV_FIRST_LINE);
public void write(List<Voucher> voucherPolicies){
csvFileTemplate.write(FILE_PATH, voucherPolicies, this::convertToString, CSV_FIRST_LINE);
}

private VoucherPolicy lineToVoucher(String line){
private Voucher convertToVoucher(String line){
log.debug("line = {}", line);

List<String> splitLine = Arrays.stream(line.split(CSV_PATTERN))
.map(s -> s.replaceAll("\"", ""))
.toList();
VoucherType[] voucherTypes = VoucherType.values();

for (VoucherType type : voucherTypes) {
String voucherType = type.getDisplayName();
String curStringType = splitLine.get(TYPE_IDX);
VoucherType thisVoucherType =
Arrays.stream(voucherTypes)
.filter(type -> type.getDisplayName().equals(splitLine.get(TYPE_IDX)))
.findAny()
.orElseThrow(() -> {
log.error("Invalid voucher type.");
return new IllegalArgumentException("Invalid voucher type");
});

if (curStringType.equals(voucherType)) {
log.info("This voucher type is {}", voucherType);
VoucherPolicy voucherPolicy = thisVoucherType.create();
UUID voucherId = UUID.fromString(splitLine.get(UUID_IDX));
long discountDegree = Long.parseLong(splitLine.get(DISCOUNT_DEGREE_IDX));

return type.create(
UUID.fromString(splitLine.get(UUID_IDX)),
Long.parseLong(splitLine.get(DISCOUNT_VALUE_IDX))
);
}
}

log.error("Invalid voucher type.");
throw new IllegalArgumentException("Invalid voucher type.");
return new Voucher(voucherId, discountDegree, voucherPolicy);
}

private String voucherToString(VoucherPolicy voucherPolicy){
private String convertToString(Voucher voucher){ // 외부에 도메인을 맞추면 안됨. -> DB 의존적 클래스랑 실제 내부 도메인 분리.
// 이거를 위해서 VoucherPolicy가 getter를 들고있는게 말이 안됨. 얘를 도메인에 맞춰야지 얘때문에 도메인이 망가지면 안된다.
StringBuilder sb = new StringBuilder();

sb.append(voucherPolicy.getVoucherId());
sb.append(voucher.getVoucherId());
sb.append(",");
sb.append(voucherPolicy.getClass().getSimpleName());
sb.append(voucher.getVoucherPolicy().getClass().getSimpleName());
sb.append(",");
sb.append(voucherPolicy.getDiscountAmount());
sb.append(voucher.getDiscountDegree());
sb.append(System.lineSeparator());

return sb.toString();
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/org/prgms/springbootbasic/config/MvcConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.prgms.springbootbasic.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
import org.springframework.oxm.xstream.XStreamMarshaller;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/v1/**")
.allowedOrigins("*");
}

@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
MarshallingHttpMessageConverter messageConverter = new MarshallingHttpMessageConverter();
XStreamMarshaller marshaller = new XStreamMarshaller();
messageConverter.setMarshaller(marshaller);
messageConverter.setUnmarshaller(marshaller);

converters.add(messageConverter);
}
}
Loading