-
Notifications
You must be signed in to change notification settings - Fork 24
[박진솔] sprint7 #213
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
base: 박진솔
Are you sure you want to change the base?
The head ref may contain hidden characters: "\uBC15\uC9C4\uC194-sprint2"
[박진솔] sprint7 #213
Conversation
@Target({ElementType.METHOD}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Documented | ||
public @interface Logging { | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LoggingAspect에서 사용하려고 하신듯 합니다. 다만 pointcut을 정하기 위해서 별도 애노테이션을 만들지 않아도 가능합니다. 클래스명이 Service나 Controller로 끝나는 모든 메소드에 대해 aop를 설정해서 쓰는 것도 가능해요~!
/* API 구현 절차 | ||
* 1. 엔드포인트(End-point) | ||
* - 엔드포인트는 URL과 HTTP 메서드로 구성됨. | ||
* - 엔드포인트는 다른 API와 겹치지 않는(중복되지 않는) 유일한 값으로 정의할 것. | ||
* 2. 요청(Request) | ||
* - 요청으로부터 어떤 값을 받아야 하는지 정의. | ||
* - 각 값을 HTTP 요청의 header, body 등 어느 부분에서 어떻게 받을지 정의. | ||
* 3. 응답(Response) - 뷰 기반이 아닌 데이터 기반(객체 반환) 응답으로 작성. | ||
* - 응답 상태 코드 정의 | ||
* - 응답 데이터 정의 | ||
* - (옵션) 응답 헤더 정의 | ||
* */ | ||
|
||
/* 반환값에 따라 사용되는 메서드 | ||
* 1. 논리 뷰 - ViewResolver, View | ||
* 2. Java 객체 - HttpResponse ..... | ||
* */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
주석을 달게 된다면 javadoc 포맷에 맞춰서 적용해서 문서로 보여질 수 있게 시도해보시면 좋을 것 같습니다~!
Javadoc 적용 방법 정리
Javadoc은 Java 소스 코드에 포함된 주석을 기반으로 HTML 형식의 API 문서를 자동으로 생성하는 도구입니다. 아래는 Javadoc을 작성하고 생성하는 방법을 단계별로 정리한 내용입니다.
1. Javadoc 주석 작성
Javadoc 주석은 클래스, 메서드, 필드 선언 바로 위에 작성하며 /**
로 시작합니다. 주요 태그는 다음과 같습니다:
- 클래스 주석: 클래스의 역할과 용도를 설명합니다.
- 메서드 주석: 메서드의 동작, 매개변수, 반환값 등을 설명합니다.
@param
: 메서드 매개변수를 설명.@return
: 반환값을 설명.@throws
또는@exception
: 발생할 수 있는 예외를 설명.
- 필드 주석: 필드의 역할을 설명.
예시:
/**
* 계산기 클래스입니다.
* 기본적인 사칙연산 기능을 제공합니다.
*/
public class Calculator {
/**
* 두 숫자를 더합니다.
*
* @param a 첫 번째 숫자
* @param b 두 번째 숫자
* @return 두 숫자의 합
*/
public int add(int a, int b) {
return a + b;
}
}
2. Javadoc 생성
Javadoc 문서를 생성하려면 JDK에 포함된 javadoc
도구를 사용하거나 IDE를 통해 생성할 수 있습니다.
(1) 명령줄에서 생성
- 터미널에서 프로젝트 디렉토리로 이동합니다.
- 다음 명령어를 실행하여 HTML 문서를 생성합니다:
javadoc -d docs -encoding UTF-8 -charset UTF-8 -sourcepath src -subpackages com.example
-d docs
: 문서를 저장할 디렉터리 지정.-encoding UTF-8
: 소스 파일 인코딩 설정.-sourcepath
: 소스 코드 경로 지정.-subpackages
: 하위 패키지 포함.
(2) IntelliJ IDEA에서 생성
- 메뉴에서 Tools > Generate JavaDoc 선택.
- Javadoc 설정 창에서 다음 항목을 지정:
- Scope: 문서를 생성할 파일/디렉터리 범위 선택 (예: 전체 프로젝트).
- Output Directory: 생성된 문서를 저장할 폴더 지정.
- Visibility Level: 공개 수준 선택 (Public, Protected 등).
- 한글 깨짐 방지를 위해 추가 명령어 입력:
-encoding UTF-8 -charset UTF-8 -docencoding UTF-8
- Generate 버튼 클릭 후 문서 생성.
3. Javadoc 활용
- IDE에서 Javadoc 보기:
- IntelliJ: 코드 위에 커서를 올려놓고
Ctrl+Q
를 눌러 빠른 문서 확인. - NetBeans/Eclipse: 클래스나 메서드를 우클릭하고 "Show Javadoc" 선택.
- IntelliJ: 코드 위에 커서를 올려놓고
- 브라우저에서 HTML 문서 열기:
- 생성된 디렉터리 내
index.html
파일을 열어 API 문서 확인.
- 생성된 디렉터리 내
4. 추가 팁
- 패키지 주석 작성: 패키지에 대한 설명은
package-info.java
파일에 작성합니다./** * 이 패키지는 계산기 관련 클래스들을 포함합니다. */ package com.example.calculator;
- Lombok 사용 시 문제 해결: Lombok으로 생성된 메서드는 기본적으로 Javadoc에 포함되지 않습니다. 이를 해결하려면 Gradle의 delombok 태스크를 사용해야 합니다.
5. 결론
Javadoc은 코드의 가독성과 유지보수성을 높이는 중요한 도구입니다. 표준 태그와 올바른 형식을 사용해 주석을 작성하고, IDE 또는 명령줄 도구를 통해 쉽게 HTML 문서를 생성할 수 있습니다.
public DiscodeitException(ErrorCode errorCode, Map<String, Object> details) { | ||
this.timestamp = Instant.now(); | ||
this.errorCode = errorCode; | ||
this.details = details; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
details 객체를 그대로 할당하면 어떤 문제가 생길 수 있을까요?
문제점
1. 불변성(Immutable) 보장 실패
details
가 외부에서 전달된Map<String, Object>
타입 그대로 할당되고 있습니다.- 만약 외부에서 전달된
details
맵이 이후에 변경된다면,DiscodeitException
객체 내부의details
도 함께 변경됩니다. - 이는 예외 객체의 상태가 예기치 않게 변할 수 있음을 의미하며, 예외 객체는 생성 이후 상태가 변하지 않는 것이 바람직합니다.
2. 캡슐화 위반
- 외부에서 전달된 객체를 그대로 참조하므로, 예외 객체의 내부 상태가 외부에 노출됩니다.
개선 방법
1. 방어적 복사(Defensive Copy)
- 생성자에서 전달받은 맵을 새로운 맵으로 복사하여 할당하면, 외부 변경으로부터 내부 상태를 보호할 수 있습니다.
public DiscodeitException(ErrorCode errorCode, Map<String, Object> details) {
super(errorCode.getMessage());
this.errorCode = errorCode;
this.details = (details == null) ? null : new HashMap<>(details);
}
2. 불변 맵 사용
- Java 9 이상이라면
Map.copyOf()
를 사용할 수도 있습니다.
this.details = (details == null) ? null : Map.copyOf(details);
결론
- 예외 객체의 내부 상태가 외부에 의해 변경될 수 있으므로, 방어적 복사를 통해 불변성을 보장하는 것이 좋습니다.
- 특히 예외 객체는 로그나 디버깅 용도로 많이 사용되므로, 상태가 변하지 않도록 주의해야 합니다.
public ErrorResponse(DiscodeitException ex, int status) { | ||
this(Instant.now(), ex.getErrorCode().name(), ex.getMessage(), ex.getDetails(), | ||
ex.getClass().getSimpleName(), status); | ||
} | ||
|
||
public ErrorResponse(Exception ex, int status) { | ||
this(Instant.now(), ex.getClass().getSimpleName(), ex.getMessage(), new HashMap<>(), | ||
ex.getClass().getSimpleName(), status); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
생성자에 사용된 파라미터를 이용해서 ErrorResponse를 생성하는 정적 생성자를 만들어보면 어떨까요?
이펙티브 자바에서는 생성자 대신 정적 생성자(정적 팩터리 메서드, static factory method)를 사용하라고 권장합니다. 그 이유와 주요 장점은 다음과 같습니다.
정적 팩터리 메서드의 장점
-
의미 있는 이름을 가질 수 있다
- 생성자는 클래스 이름과 같아야 하지만, 정적 팩터리 메서드는 이름을 자유롭게 정할 수 있어, 반환 객체의 특성을 명확하게 드러낼 수 있습니다.
-
호출할 때마다 새로운 객체를 생성하지 않아도 된다
- 내부적으로 캐싱된 객체를 반환하거나, 기존 객체를 재사용할 수 있어 불필요한 객체 생성을 줄이고 성능을 높일 수 있습니다.
-
반환 타입의 하위 타입 객체를 반환할 수 있다
- 반환 타입이 인터페이스나 추상 클래스라면, 실제 구현체를 숨기고 유연하게 객체를 반환할 수 있습니다. 예를 들어, 컬렉션 팩터리 메서드는 내부적으로 비공개 클래스를 반환하기도 합니다.
-
입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다
- 입력 값이나 상황에 따라 최적화된 하위 타입 객체를 반환할 수 있습니다. 클라이언트는 반환 객체의 구체 타입을 몰라도 되므로, API를 유연하게 설계할 수 있습니다.
-
반환할 객체의 클래스를 나중에 추가할 수 있다
- 정적 팩터리 메서드 작성 시점에 반환할 객체의 클래스가 없어도 되고, 추후에 추가할 수 있어 확장성이 높습니다.
단점
-
상속이 어렵다
- public 또는 protected 생성자가 없으면 하위 클래스를 만들 수 없습니다.
-
API에서 찾기 어렵다
- 생성자와 달리, 정적 팩터리 메서드는 명명 규칙이 필요하며, 문서화와 네이밍이 중요합니다.
대표적인 네이밍 패턴
- of: 여러 매개변수로 객체 생성
- from: 하나의 값을 변환해 객체 생성
- valueOf: 변환 또는 캐싱된 객체 반환
- getInstance: 인스턴스 반환(기존 객체일 수도 있음)
- newInstance: 항상 새로운 인스턴스 반환
- with: 일부 속성만 변경한 새 객체 생성
정리하면, 정적 팩터리 메서드는 생성자보다 더 많은 유연성과 명확성을 제공하므로, 객체 생성이 필요한 경우 먼저 정적 팩터리 메서드 사용을 고려하는 것이 이펙티브 자바의 권장 사항입니다.
private HttpStatus determineHttpStatus(DiscodeitException e) { | ||
ErrorCode errorCode = e.getErrorCode(); | ||
return switch (errorCode) { | ||
case USER_NOT_FOUND, CHANNEL_NOT_FOUND, MESSAGE_NOT_FOUND, BINARY_CONTENT_NOT_FOUND, | ||
READ_STATUS_NOT_FOUND, USER_STATUS_NOT_FOUND -> HttpStatus.NOT_FOUND; | ||
case DUPLICATE_USER, DUPLICATE_READ_STATUS, DUPLICATE_USER_STATUS -> HttpStatus.CONFLICT; | ||
case USER_PASSWORD_NOT_MATCHED -> HttpStatus.UNAUTHORIZED; | ||
case PRIVATE_CHANNEL_UPDATE, INVALID_REQUEST, VALIDATION_ERROR -> HttpStatus.BAD_REQUEST; | ||
case INTERNAL_SERVER_ERROR -> HttpStatus.INTERNAL_SERVER_ERROR; | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ErrorCode의 필드로 HttpStatus를 갖게하면 이부분은 생략할 수 있지 않을까요?
// .map(binaryContentService::create) | ||
// .map(binaryContentMapper::toEntity) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사용하지 않는 코드는 주석 대신 과감하게 삭제해주세요~!
username: ${{DB_USERNAME}} | ||
password: ${{DB_PASSWORD}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
환경변수 참조는 중괄호가 한쌍만 들어가야합니다~!
예시: ${DB_USERNAME}
|
||
spring: | ||
datasource: | ||
url: jdbc:postgresql://localhost:5432/discodeit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
production phase에서는 DB url도 환경변수를 사용해서 노출이 안되게 하는 것이 안전합니다~!
|
||
# 애플리케이션 정보 (Actuator info 엔드포인트용) | ||
info: | ||
app: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
app: 부분은 삭제되어도 무방해보입니다.
show-details: always | ||
|
||
# 애플리케이션 정보 (Actuator info 엔드포인트용) | ||
info: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
info log를 actuator api(http://localhost:8081/actuator/info) 를 통해 조회해보면 빈 json이 나옵니다. 이를 해결하기 위해 아래와 같은 설정이 추가로 필요합니다.
management:
endpoint:
health:
show-details: never
info:
env:
enabled: false
기본 요구사항
프로파일 기반 설정 관리
로그 관리
예외 처리 고도화
j5vtp941a-image.png
a6f585icy-image.png
3gqeampkw-image.png
유효성 검사
Actuator
단위 테스트
슬라이스 테스트
통합 테스트
멘토님께