현실 세계의 자바
이론에서 실습으로 이동하려면 다음 사항을 알아야 합니다. 모범 사례 전문 프로젝트 구성: 로깅, 구성, 환경 관리.
무엇을 배울 것인가
- 전문적인 프로젝트 구조
- SLF4J 및 Logback을 사용한 로깅
- 아웃소싱 구성
- 환경 관리(개발, 테스트, 프로덕션)
프로젝트 구조
my-project/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/
│ │ │ ├── Application.java
│ │ │ ├── config/
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ ├── repository/
│ │ │ ├── model/
│ │ │ └── util/
│ │ └── resources/
│ │ ├── application.properties
│ │ ├── application-dev.properties
│ │ ├── application-prod.properties
│ │ └── logback.xml
│ └── test/
│ ├── java/
│ └── resources/
├── pom.xml (o build.gradle)
└── README.md
벌채 반출
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserService {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
public User findUser(Long id) {
logger.debug("Cercando utente con ID: {}", id);
try {
User user = repository.findById(id);
logger.info("Utente trovato: {}", user.getName());
return user;
} catch (UserNotFoundException e) {
logger.warn("Utente non trovato: {}", id);
throw e;
} catch (Exception e) {
logger.error("Errore durante ricerca utente", e);
throw new ServiceException("Errore interno", e);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
<logger name="com.example" level="DEBUG" />
</configuration>
구성
# Database
db.url=jdbc:postgresql://localhost:5432/mydb
db.username=user
db.password=password
db.pool.size=10
# API
api.timeout.ms=5000
api.retry.count=3
# Feature flags
feature.newUi.enabled=true
import java.io.*;
import java.util.Properties;
public class ConfigurationManager {
private static final Properties props = new Properties();
static {
String env = System.getProperty("app.env", "dev");
String filename = "application-" + env + ".properties";
try (InputStream is = ConfigurationManager.class
.getClassLoader().getResourceAsStream(filename)) {
if (is != null) {
props.load(is);
}
} catch (IOException e) {
throw new RuntimeException("Impossibile caricare configurazione", e);
}
}
public static String get(String key) {
return props.getProperty(key);
}
public static int getInt(String key, int defaultValue) {
String value = props.getProperty(key);
return value != null ? Integer.parseInt(value) : defaultValue;
}
public static boolean getBoolean(String key) {
return Boolean.parseBoolean(props.getProperty(key));
}
}
// Uso
String dbUrl = ConfigurationManager.get("db.url");
int timeout = ConfigurationManager.getInt("api.timeout.ms", 3000);
모범 사례
전문 프로젝트에 대한 규칙
- 코드와 별도의 구성: 속성 파일, 환경 변수
- 구조화된 방식으로 로그인: 적절한 수준, System.out 없음
- 건축 레이어 사용: 컨트롤러, 서비스, 저장소
- 자동화된 테스트: 단위, 통합, e2e
- 문서: README, 공개 API용 Javadoc
- 예외 관리: 중앙 집중식, 로깅 포함







