2018년 10월 9일 화요일

JDBC , DBCP, JNDI (수정필요)

JDBC(Java Database Connectivity)
: 데이터베이스에 접근하여 SQL문을 실행하기 위한 자바 라이브러리

>>  자바프로그래밍의 일반적인 데이터 엑세스 제공 
>> 데이터베이스 풀 방식을 사용하지 않고 DB에서 정보를 가져올 때마다 매번 디비 연결을 열고 닫음
>> 효율이 떨어짐 
>> 그렇기 때문에 보통 pool 방식을 사용함. (ex DBCP)

==========================================================

DBCP(Database Connection Pool) 
: 데이터베이스와 연결된 커넥션을 미리 만들어서 저장해두고 있다가 필요할 때 저장된 공간(Pool)에서 가져다 쓰고 반환하는 기법

>> DB커넥션을 어플리케이션 소스 내에서 제어하면서 DB 풀을 가짐
>> 사용자가 요청할 경우 드라이버를 로드하고, 커넥션 객체를 생성해 연결하고 종료하는 비효율적인 작업을 하지 않아도 됨
>> 데이터베이스의 부하를 줄이고 자원을 효율적으로 관리

==========================================================

JNDI(Java Naming and Directory Interface)
: 디렉터리 서비스에서 제공하는 데이터 및 객체를 발견하고 참고하기 위한 자바API
(외부에 있는 객체를 가져오기 위한 기술)

>> DB커넥션을 WAS단(외부)에서 제어하면서 서버에서 하나의 커넥션 풀을 가짐
>> DBCP처럼 어플리케이션 소스단에 설정하느 방식이 아닌 WAS단에 데이터베이스 커넥션 객체를 미리 네이밍함
>> 소스단에 정보를 설정해놓으면 소스 개발자 외에는 정보를 찾기가 힘들다. 하지만 JNDI를 사용하면  WAS단에 저장하기 때문에 파악하기 쉬움..????
>> 서버단에서 어플리케이션 컨테이너는 하나이더라도 내부 어플리케이션 소스는 홈페이지 하나 이상이 될 수있는데(디렉토리 서비스, 서브도메인을 사용하여 서비스하는 경우) 이 경우, DBCP를 사용하면 각 어플리케이션마다 DB Pool이 각자 생성되어 풀이 많아져 효율이 떨어질 수 있음. 
JNDI는 WAS단에서 DB Pool를 하나로 관리하기 때문에 효율이 좋아진다고 함..
(WAS에 스태틱 객체를 생성 후에 쉽게 가져다 쓸 수 있기 때문??)


참고

http://eongeuni.tistory.com/43
http://all-record.tistory.com/104

todo

http://nastyle.tistory.com/15
https://d2.naver.com/helloworld/5102792

2018년 10월 2일 화요일

자바 로그(log) 남기기 - log4j, log4j2, logback, slf4j (간단한 logback 실습)

로그란? (log)

애플리케이션의 상태를 관찰할 수 있도록 애플리케이션이 제공하는 정보 

log4j, logback, log4j2  셋 다 java 로깅 유틸리티이다.

스프링프레임워크에서는  예전에는 commons.logging을 기본으로 사용하였지만, 지금은 slf4j, log4j 를 기본으로 사용?
시간 순서로 보면 Log4j -> Logback -> Log4j2 인듯?
----------------------------------------------------------------------------------------------

Log4j ? (log for java) 

Apache에서 만든 오픈소스 라이브러리로 프로그램을 작성하는 도중에 로그를 남기기 위해 사용되는 자바 기반 로깅 유틸리티

- 구조
Logger - 로깅이 일어나는 부분을 그룹화해, 필요한 그룹의 로그만을 출력하거나, 카테고리에 우선순위를 부여함으로써, 여러가지 출력 방법을 지원함. 실제 로그 긴으을 수행하는 역할을 담당.

Appender - 로그의 출력 위치를 지정. 콘솔, 파일, outputstream, java.io.Writer, Email(STMP), Network 등이 있음.
 - ConsoleAppender : 콘솔에 로그 메세지를 출력한다.
 - FileAppender: 파일에 로그메시지리를 출력한다.
 - RollingFileAppender: 로그의 크기가 지정한 용량 이상이 되면 다른 이름의 파일을 출력한다.
 - DailyRollingFileAppender: 하루를 단위로 로그 메세지를 파일에 출력한다.
 - SMTPAppender: 로그 메세지를 이메일로 보낸다.
 - NTEventLogAppender: 윈도우의 이벤트 로그 시스템에 기록한다.

Layout - 로그의 출력 포맷을 지정.
 - %d : 로그의 기록시간
 - %p : 로깅의 레벨
 - %F : 로깅이 발생한 프로그램의 파일명
 - %M : 로깅이 발생한 메소드의 이름
 - %I : 호출지의 정보
 - %L : 로깅이 발생한 호출지의 라인 수
 - %t : 로깅이 발생한 Thread 명
 - %c : 로깅이 발생한 카테고리
 - %C : 로깅이 발생한 클래스명
 - %m : 로그 메세지
 - %% : % 출력
 - %r : 시작 이후로부터 로깅이 발생한 시점까지의 시간

----------------------------------------------------------------------------------------------

Log4j2 ? 

이 후에 나온 버전으로 성능과 메시지 처리량 및 대기 시간이 향상되었다고 한다.
log4j 는 xml과 properties를 이용해서 설정하지만, log4j2 는 properties는 지원하지 않는다고함.

-특징
 - 자동적인 로깅 구성설정(?) 리로딩
 - 속성 서포트: Log4j2는 시스템의 속성을 불러오고
 - 자바8: 람다식에서 로그 메시지를 래핑하는 API 제공
 - Log4j2에는 쓰레기 값이 거의 없다.
 - LMAX Disruptor를 사용하는 비동기 logger

----------------------------------------------------------------------------------------------

logback ?

log4j 를 토대로 새롭게 만들어진 로깅 라이브러리로 스프링 부트의 기본 로그 객체.
ERROR < WARN < INFO < DEBUG < TRACE
스프링이나 일반적인 자바프로그램의 경우 resources 디렉토리 안에 logback.xml 참조
(logback.groovy -> logback-test.xml -> logback.xml 순서로 찾는다고함..)
스프링 부트는 logback-spring.xml 파일을 참조

-구조
Log4j와 유사한구조

Logger - 실제 로깅을 수행하는 구성요소로 Level 속성을 통해서 출력할 로그의 레벨을 조절할 수있음.

Appender - 로그 메시지가 출력될 대상을 결정하는 요소
 - ConsoleAppender : 콘솔에 로그를 찍는 방법
 - FileAppender : 파일이 로그를 찍는 방법
 - RollingFileAppender: 여러개의 파일을 순회하면서 로그를 찍는 방법
(상당히 다양하게 쓸 수있는 듯.....)
 - SMTPAppender : 로그를 메일에 찍어 보내는 방법
 - DBAppender:  데이터베이스에 로그를 찍는 방법
Socket, SSLSocket 등이 있음

패턴에 사용되는 요소
 - %Logger{length} : Logger name을 축약할 수 있음 {length}는 최대 자리 수
 - %thread : 현재 Thread 이름
 - %-5level : 로그 레벨, -5는 출력의 고정폭 값
 - %msg : 로그 메시지 ( =%message)
 - %n : new line
 - %highlight: 로그레벨에 따른 색을 줄 수 있는 듯 함

 - 나머지 log4j 와 비슷한 듯..


Encoder - Appender에 포함되어 사용자가 지정한 형식으로 표현 될 로그 메시지를 변환

*layout과 encoder의 차이점: 레이아웃은 들어오는 이벤트를 String으로 변환하고 에빈트가 기록될 때 제어할 수 없으며 이벤트를 일관처리로 집계한다. 반면에 encoder는 바이트를 소유하고 있는 appender가 관리하는 outputStream에 쓸 시간과 내용을 완전히 제어할 수 있음. 
FileAppender와 하위 클래스는 encoder를 필요로 하고 더 이상 layout은 사용하지 않는다.



-특징
1. log4j보다 약 10배 정도 빠름. 메모리 효율성 향상
2. 설정 파일을 변경하였을 경우, 서버 재기동 없이 변경 내용이 자동으로 갱신됨.
3. RollingFileAppender로 자동으로 오래된 로그를 지워줌.

----------------------------------------------------------------------------------------------

SLF4J ? (Simple Logging Facade for Java)

SLF4J 는 자바 로깅 유틸리티의 추상체 역할을 함. 인터페이스와 비슷한 역할을 하며, 사용하던 로깅 유틸리티가 변경되더라도 java소스의 변경을 방지해줌.

개발자는 어떤 상황에든 대처하고 확장될 수 있는 느슨하고 유연한 코드를 만들어야 합니다. 따라서 하나의 라이브러리에 너무 종속적이 되버리는 코드는 가급적 작성하지 않는쪽이 좋습니다. 그렇기에 어떤 라이브러리를 쓰든 동일하게 동작하는 코드를 만들어야하고 그것이 slf4j를 써야하는 이유입니다.


만약 log4j 에서 logback  으로 변경할 때 log4j를 import 하던 파일들을
다 logback 으로 바꿔줘야함.

1
2
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggerFactory;
cs
소스들 마다 박혀있는 log4j를 바꿔줘야함...


하지만 slf4j를 쓴다면 사용하지 않는 dependency만 제거하면 됨.
1
2
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
cs


======================================================

간단 실습

pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
...
    <properties>
...
        <jcloverslf4j.version>1.7.6</jcloverslf4j.version>
        <logback.version>1.1.7</logback.version>
...
    </properties>
...
        <!-- Logback --> 
         <dependency>                                    
                  <groupId>org.slf4j</groupId>                
                  <artifactId>jcl-over-slf4j</artifactId>     
                  <version>${jcloverslf4j.version}</version>  
         </dependency>
         <dependency>
                  <groupId>ch.qos.logback</groupId>
                  <artifactId>logback-classic</artifactId>
                  <version>${logback.version}</version>
         </dependency>
...
cs


src/main/resources 
logback.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
    <!-- 로그파일 경로  -->
    <property name="LogFileDir" value="/logs/data.log" />
    <!-- CONSOLE appender -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern> %d{yyyy-MM-dd HH:mm:ss} [%-5p] [%F]%M\(%L\) : %m%n </pattern>
        </encoder>
    </appender>
    <!--  FILE appender -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LogFileDir}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LogFileDir}.%d{yyyy-MM-dd}</fileNamePattern>
            <maxHistory>30</maxHistory> <!-- 보관의 기간 -->
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5p] [%F]%M\(%L\) : %m%n</pattern>
        </encoder>
    </appender>
    <logger name="org.springframework" level="info"/>
    <logger name="org.hibernate" level="debug"/>
    <root level="debug">
        <appender-ref ref="CONSOLE"/> <!-- Console에 로그를 출력하고자 할 때 사용 -->
        <appender-ref ref="FILE"/> <!-- File로 로그를 남기고자 할 때 사용 -->
    </root>
</configuration>
cs

컨트롤러
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Controller
@RequestMapping("/")
public class HomeController {
...
    private static final Logger LOG = LoggerFactory.getLogger(HomeController.class);
...
    @RequestMapping("/")
    public ModelAndView Home(HttpSession session) throws Exception{
        LOG.debug("-------------------WebBoardList_Start--------------------");
  ...
LOG.debug("-------------------WebBoardList_End--------------------");
...
    }
cs


콘솔창



log파일
파일 내부



출처 및 참고 :






2018년 9월 9일 일요일

git 작성자 수정하기

rebase란?

공부가 필요해.....
http://mafams.tistory.com/66
https://backlog.com/git-tutorial/kr/stepup/stepup2_8.html
https://elegantcoder.com/git-merge-or-rebase/
http://cyberx.tistory.com/96




git에 자꾸 다른 이름으로 커밋이 되어 작성자를 바꾸려고 하는데

rebase를 통해 가능한 것같다.


git저장소에

git rebase -i -p   [커밋번호]

>[커밋번호] 이 후의 커밋들이 rebase의 대상이 된다.


vi창이 보이는데 a를 눌러 바꾸고싶은 커밋을 pick 을 edit으로 교체 후 esc  > :wq

나의 경우에는 작성자를 바꾸려고했으니
 git commit --amend --author="cotgyu <이메일 주소>"

를 입력하면  해당 커밋 내용 같은게 보인다.. :wq 로 나와서
 git rebase --continue
를 입력하면 다음 수정할 커밋이 나온다.

이 과정을 마지막 커밋까지 반복하면
Successfully rebased and updated ~~ 가 나온다.

이제 pull 후 push하면 수정한 것들이 새롭게 커밋된다..


(그냥 새로운 작성자의 같은 내용의 기록이 새롭게 커밋되는 형태로 되었다.... 기존의 기록을 수정은 안되는건가.. 좀 더 공부할 것)

참조

2018년 8월 19일 일요일

Eclipse cannot open git-upload-pack 오류: 인증·인증서·프록시 확인

cannot open git-upload-pack만으로 원인을 단정할 수 없습니다. Eclipse의 Error Log에서 함께 나온 메시지를 확인한 뒤 저장소 주소, 인증, 인증서, 프록시 순서로 범위를 좁혀 보세요.

2026년 10월 16일 수정: 이 글의 예전 내용은 http.sslVerify=false 설정만 안내했습니다. 인증서 검증을 끄는 방법을 일반 해결책으로 제시한 부분을 바로잡았습니다.

1. 상세 오류부터 확인하기

Eclipse의 Error Log 보기에서 실패한 시각의 예외와 하위 원인을 확인합니다. 사용 중인 Eclipse·EGit·Java 버전, HTTPS인지 SSH인지도 함께 기록하세요. 오류 로그를 공유할 때 토큰·비밀번호·내부 주소는 가립니다.

  • 401 또는 인증 실패: 계정과 인증 수단을 확인합니다.
  • 403 또는 저장소 접근 거부: 계정의 접근 권한과 조직 정책을 확인합니다.
  • 404 또는 저장소를 찾을 수 없음: 복제 URL과 접근 권한을 함께 확인합니다. 비공개 저장소는 권한 문제도 의심해야 합니다.
  • 인증서·PKIX 관련 메시지: 서버 인증서와 Eclipse가 사용하는 Java 환경의 신뢰 설정을 확인합니다.
  • 타임아웃·호스트 조회 실패: 네트워크와 프록시 설정을 확인합니다.

이 목록은 진단 순서이며 각 메시지의 원인이 하나로 정해진다는 뜻은 아닙니다.

2. URL과 인증 확인하기

저장소 서비스에서 복제 URL을 다시 확인합니다. GitHub HTTPS 인증에서 토큰을 요구하는 경우 일반 계정 비밀번호 대신 적절한 권한의 토큰을 사용합니다. 토큰을 URL에 직접 넣지 말고 인증 입력란이나 지원되는 자격 증명 저장소를 사용하세요.

명령줄 Git이 설치되어 있다면 같은 저장소 폴더에서 아래 읽기 전용 조회로 비교할 수 있습니다. 출력에는 사설 저장소 주소가 포함될 수 있습니다.

git remote -v
git ls-remote origin

명령줄에서는 성공하고 Eclipse에서 실패해도 서버가 완전히 정상이라고 단정할 수는 없습니다. 두 도구가 사용하는 인증 저장소·프록시·인증서 환경을 비교하는 단서로 사용하세요.

3. 인증서 검증을 끄기보다 신뢰 경로 확인하기

Git의 http.sslVerify는 HTTPS 인증서 검증 여부이며 기본값은 true입니다. 인증서 오류라면 서버의 만료·호스트 이름·체인 설정을 확인하고, 사내 인증서를 사용하는 환경에서는 관리자가 제공한 신뢰 설정을 따르세요. EGit의 HTTP 구현과 Java 실행 환경도 확인 대상입니다.

이전 글을 따라 검증을 껐다면 해당 설정의 위치와 적용 범위를 확인해 해제한 설정을 되돌리세요. 인증 문제가 해결되는지 확인하지 않고 전역 설정을 반복 변경하지 마세요.

4. 프록시와 재확인

회사 네트워크에서만 실패한다면 Eclipse의 Preferences → General → Network Connections를 확인합니다. EGit은 HTTP 연결 구현에 따라 프록시 동작이 다를 수 있습니다. 설정을 하나씩 바꾸며 동일한 조회로 결과를 비교하세요.

이 글은 공식 문서에 근거한 진단 안내입니다. 특정 Eclipse 설치에서 같은 장애를 재현해 해결했다고 주장하는 글은 아닙니다.

공식 참고 문서

MySQL CSV 내보내기: INTO OUTFILE과 secure_file_priv 오류 확인

MySQL의 SELECT ... INTO OUTFILE은 DB 서버에 파일을 만듭니다. 내 PC의 다운로드 폴더로 받는 기능으로 생각하면 경로와 권한 문제를 혼동하기 쉽습니다. 먼저 서버의 출력 허용 경로를 확인하세요.

2018년 추천 알고리즘용 CSV 추출 경험을 남긴 글에 2026년 10월 16일 진단 절차를 보완했습니다. 아래 체크는 MySQL 8.4 공식 문서를 기준으로 정리했으며, 이번에 운영 DB에서 내보내기를 실행한 것은 아닙니다.

Error 1290이 나면 먼저 확인할 값

SELECT @@secure_file_priv;

출력 허용 디렉터리가 지정되어 있다면 그 안의 새 파일 경로를 사용해야 합니다. 또한 파일 출력에 필요한 권한, 서버 프로세스의 디렉터리 쓰기 권한, 같은 이름의 파일이 이미 있는지를 확인합니다. 원격 서버를 쓰고 있다면 경로도 원격 서버 기준입니다.

에러 메시지 전체를 확인하지 않고 설정 제한을 해제하거나 데이터베이스를 재시작하는 것부터 시도하지 마세요. 관리형 서비스 등 파일 출력이 허용되지 않는 환경이라면 사용 중인 클라이언트의 결과 내보내기 기능을 검토합니다.

CSV를 만든 뒤 확인할 항목

  • 문자 인코딩: 기존 예제의 EUC-KR은 당시 소비 프로그램에 맞춘 선택입니다. 새 내보내기는 받는 프로그램과 문자셋을 합의하세요.
  • 구분자·따옴표·이스케이프: 쉼표가 있는 데이터가 한 필드로 읽히는지 작은 샘플로 확인합니다. MySQL의 백슬래시 이스케이프 설정과 Python CSV 기본 설정을 무조건 같은 형식으로 취급하지 마세요.
  • 열 이름과 순서: 헤더 포함 여부와 열 순서를 받는 쪽과 맞춥니다. 안정된 교환 형식이 필요하다면 SELECT * 대신 열 목록을 명시하는 편이 검토하기 쉽습니다.
  • 기존 파일: OUTFILE은 기존 파일을 덮어쓰지 않습니다. 원본을 지우기보다 작업별 새 파일명을 사용하고 결과를 검증합니다.

공식 근거: MySQL 8.4 SELECT ... INTO.

당시 작업 기록

아래는 2018년 환경의 기록입니다. 경로·문자셋·서버 재시작 절차를 그대로 적용하지 말고 위의 확인 순서를 먼저 따르세요.

2018년 원문 펼치기머하웃의 간단한 아이템 기반 추천알고리즘을 적용해보는 과정에서,
알고리즘이 .csv 파일을 읽어 특정 개수의 아이템을 추천해주는 방식이었기 때문에, DB의 테이블을 .csv 파일로 뽑아내는 작업이 필요하였다. 


여기를 참고하여 데이터를 뽑았는데, 나는 첫번째 SQL을 사용하였다.

1
2
3
4
5
6
SELECT * FROM recommend_coursedata
INTO OUTFILE 'C:/MySqlOutputData/test.csv'
CHARACTER SET euckr
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
ESCAPED BY '\\'
LINES TERMINATED BY '\n';
cs
이를 실행하면 
Error Code: 1290. The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

에러가 발생하는데, 파일이 생성되는 경로와 mysql서버의 secure-file-priv 경로와 달라서 발생하는 에러 같다. 

INTO OUTFILE 의 경로는 
mysql 서버의 secure_file_priv 에 명시에되어있다. 


여기서 나오는 데이터를 기준으로 추천을 해주기 때문에 관리자 계정이 버튼으로 추천 데이터를 업데이트해주자는 생각으로 진행하였다. 그렇기 때문에 버튼을 누를 때 마다 
저 경로의 파일을 지우고, 새로 파일을 생성하는 방식으로 진행하려고 하였다. 

하지만, 경로가 ProgramData 속에 있기 때문에 수정/삭제에 대해 관리자 권한이 필요하였고, 경로를 바꾸기로 하였다. 

나의 경우에는 
my.ini 
secure-file-priv 의 경로를 직접 바꾼 후 mysql을 재시작하여 진행하였다. 


2018년 8월 12일 일요일

EJB / bean

엔터프라이즈 자바빈즈

위키백과, 우리 모두의 백과사전.
둘러보기로 가기검색하러 가기
엔터프라이즈 자바빈즈(Enterprise JavaBeans; EJB)는 기업환경의 시스템을 구현하기 위한 서버측 컴포넌트 모델이다. 즉, EJB는 애플리케이션의 업무 로직을 가지고 있는 서버 애플리케이션이다. EJB 사양은 Java EE의 자바 API 중 하나로, 주로 웹 시스템에서 JSP는 화면 로직을 처리하고, EJB는 업무 로직을 처리하는 역할을 한다.

EJB의 종류[편집]

EJB에는 다음 3가지 종류가 있다.
  • 세션 빈 (Session Bean) : DB 연동이 필요 없음
  • 엔티티 빈 (Entity Bean)
    • 데이터베이스의 데이터를 관리하는 객체
    • Insert(삽입), Update(수정), Delete(삭제), Select(조회)
    • DB 관련 쿼리는 자동으로 만들어지고 개발자는 고급 업무 처리에 집중할 수 있음
    • DB가 수정되면 코드 수정 없이 다시 배포(설정 문서 만들어서 복사)
  • 메시지 구동 빈 (Message-driven Bean) : JMS로 빈을 날려줌


EJB 배경, 설명(블로그 참조) 

http://pokey.tistory.com/7
>>>
EJB는 대규모 분산 객체 시스템을 구축하기 위한 기술 또는 자바로 서버 측 비즈니스 로직을 작성하기 위한 Enterprise 환경에서의 자바 표준이라고 보시면 됩니다. 흔히 프리젠테이션 로직이라고 하는 것이 화면에 보여지게 되는 정보의 타입, 포맷을 자동으로 처리하는 반면 비즈니스 로직은 급여계산 한다든지 하는 보이지 않는 어떤 처리를 하는 겁니다. 만약 EJB를 사용하기 위해 웹로직 서버를 이용한다고 하면 프로그램 개발자는 웹로직 서버의 컨테이너를 이용하여 작업을 하게 되는데 이는 트랜잭션의 지원, 보안, 동시 접근 처리 등 비즈니스 로직을 처리하는데 있어 필요한 모든 것을 제공 한다고 보면 됩니다.

참고
http://i-bada.blogspot.com/2014/09/enterprise-javabeanejb.html



********************************

빈(bean)

빈: 자바로 작성되어진 컴포넌트들로 JSP페이지에서 디자인부분과 로직부분을 분리시키고, 재사용성을 높여 효율성을 높여줌.

-규격
- 클래스는 패키지화 하여야 한다.
- 멤버변수는 프로퍼티(Property)라 칭한다.
- 클래스는 필요에 따라 직렬화가 가능하다.
- 프로퍼티의 접근자는 private이다.
- 프로퍼티마다 getter/setter 가 존재해야 하며, 그 이름은 각각 get/set으로 시작해야 한다.
- 위의 프로퍼티 getter/setter 메서드의 접근자는 public이어야 한다.
- 외부에서 프로퍼티에 접근은 메서드를 통해서 접근한다.
- 프로퍼티는 반드시 읽기/쓰기가 가능해야 하지만, 읽기 전용인 경우 getter만 정의할 수 있다.
- getter의 경우 파라미터가 존재하지 않아야 하고, setter의 경우 한 개 이상의 파라미터가 존재한다.
- 프로퍼티의 형이 boolean일 경우 get 메서드 대신 is메서드를 사용해도 된다.

참고




2018년 7월 29일 일요일

공통코드란? 코드 테이블 설계와 SQL 조회 예제

공통코드는 여러 화면과 테이블에서 사용하는 분류값을 코드와 표시 이름으로 나누어 관리하는 방법입니다. 예를 들어 게시판에는 B01을 저장하고, 화면에는 ‘일반게시판’을 표시합니다. 이 글에서는 게시판 종류와 회원 역할을 구분하는 작은 코드 테이블을 직접 만들어 봅니다.

2018년의 학습 메모를 2026년 10월 16일에 예제 중심으로 보완했습니다. 아래 구조는 설계 예시이며 모든 시스템에 적용해야 하는 표준은 아닙니다.

코드와 이름을 왜 나눌까?

게시글마다 ‘일반게시판’이라는 이름을 저장하면 명칭을 변경할 때 여러 데이터를 수정해야 할 수 있습니다. 코드와 이름을 분리하면 게시글의 분류값을 유지하면서 표시 이름을 관리할 수 있습니다. 다만 과거 화면의 명칭까지 보존해야 하는 서비스라면 별도의 이력 설계가 필요합니다.

그룹도 구분합니다. BOARD_TYPE은 게시판 종류, USER_ROLE은 회원 역할입니다. 코드만으로 찾지 않고 그룹과 코드를 함께 사용하면 서로 다른 분류의 값이 섞이는 실수를 줄일 수 있습니다.

테이블을 만들고 게시판 종류 조회하기

아래 예제는 빈 테스트 데이터베이스에서 실행하세요. Python의 SQLite 메모리 데이터베이스에서 생성·조회 및 중복 키 거부를 확인했습니다. MySQL·Oracle 실서버에서 실행한 결과는 아닙니다.

CREATE TABLE common_code (
    code_group VARCHAR(30) NOT NULL,
    code VARCHAR(20) NOT NULL,
    code_name VARCHAR(100) NOT NULL,
    sort_order INTEGER NOT NULL,
    active CHAR(1) NOT NULL,
    PRIMARY KEY (code_group, code)
);
INSERT INTO common_code VALUES
('BOARD_TYPE', 'B01', '일반게시판', 1, 'Y'),
('BOARD_TYPE', 'B02', '질문게시판', 2, 'Y'),
('BOARD_TYPE', 'B03', '사진게시판', 3, 'Y'),
('USER_ROLE', 'U01', '일반회원', 1, 'Y'),
('USER_ROLE', 'U09', '관리자', 2, 'Y');
SELECT code, code_name
FROM common_code
WHERE code_group = 'BOARD_TYPE' AND active = 'Y'
ORDER BY sort_order, code;

조회 결과:

B01 | 일반게시판
B02 | 질문게시판
B03 | 사진게시판

복합 기본 키는 같은 그룹 안의 코드 중복을 막습니다. sort_order는 화면 정렬 순서, active는 신규 선택 가능 여부를 표현하는 예시입니다. 이 테이블을 만든 것만으로 다른 업무 테이블의 코드값까지 검증되지는 않습니다. 참조 관계와 그룹 제약을 별도로 설계해야 합니다.

운영 전에 정할 네 가지 규칙

  1. 의미가 바뀌면 코드를 재사용하지 않기. 기존 데이터의 해석이 달라지지 않도록 새 코드를 검토합니다.
  2. 사용 중인 코드는 삭제보다 비활성화 검토. 신규 입력에서 숨겨도 과거 데이터의 이름은 조회할 수 있어야 합니다.
  3. 수정 권한과 변경 기록 정하기. 누가 이름·순서·활성 상태를 바꿨는지 추적합니다.
  4. 캐시 갱신 시점 정하기. 관리 화면에서 고친 이름이 서비스에 언제 반영될지 명확히 합니다.

회원 역할 코드를 저장하는 것과 접근 권한을 검사하는 것은 별개입니다. 클라이언트가 보낸 U09 값을 믿고 관리자 권한을 부여하면 안 됩니다.

공통코드 테이블과 enum 중 무엇을 쓸까?

배포 없이 운영자가 표시 이름이나 선택 항목을 관리해야 한다면 코드 테이블을 고려할 수 있습니다. 값이 프로그램의 분기와 강하게 연결되고 코드 변경과 함께 검토되어야 한다면 enum이 더 단순할 수 있습니다. 모든 상태값을 한 테이블에 몰아넣기보다 변경 주체와 참조 규칙을 먼저 정하는 편이 좋습니다.