open과 fopen과 가장 큰 차이점은 무엇인가요?[리눅스에서]

skylandi의 이미지

open과 fopen과 가장 큰 차이점은 무엇인가요?

open은 이진 파일을 못 만들지 않나요?
제 생각입니다.

미리 감사... 즐거운 하루되시길
-------------------------------------------------------------
텍스트와 이진 파일을 구분하려면 어캐 하는지 아시는분 답변 부탁 드립니다.

dotri의 이미지

open() 함수와 fopen() 함수의 차이는 라이브러리에 있습니다.

open() 함수는 POSIX.1 규정에 준수하는 시스템 함수로, open() 함수는 커널수준에서 동작합니다.

fopen() 함수는 ANSI-C 규정에 준수하는 라이브러리 함수로, 컴파일러에 의해 표준 라이브러리를 사용하여 동작하므로 어플리케이션 수준에서 동작합니다.

다시 말해보면, fopen() 함수는 ANSI-C 규정에 따르는 그 어떤 컴파일러에서라도 사용할 수 있습니다만, open() 함수는 POSIX.1 규정에 따르는 운영체제에서만 사용할 수 있습니다. 따라서 이 둘은 기종간 이식성과 호환성에서 차이가 있습니다. fopen() 함수가 좀 더 호환성이 좋다고 봐야겠죠. POSIX.1 표준을 따르지 않는 운영체제는 많이 있습니다만 ANSI-C 표준을 따르지 않는 C 컴파일러는 없으니까요.

하지만 프로그램의 효율성에서 생각해보면 open() 함수가 fopen() 함수보다 빠르므로 더 유리하다 볼 수 있습니다.

그리고 이진 파일과 텍스트 파일이라는 것은 파일 자체의 속성이 아니라, 개발자가 프로그램을 만들때 그 프로그램에서 파일을 어떻게 다룰것인지에 의해 좌우됩니다. 운영체제나 파일시스템에서 이진 파일/텍스트 파일의 구분이라는것은 없고 프로그래머가 작성하는 프로그램 내에서 어떻게 다룰것인가로 구분하는 것으로 알 고 있습니다. 어디서는 버퍼링 여부에 따라 이진 파일과 텍스트 파일이 구분된다고도 하는것 같은데 그건 정확하게는 모르겠네요.

cdpark의 이미지

dotri wrote:
하지만 프로그램의 효율성에서 생각해보면 open() 함수가 fopen() 함수보다 빠르므로 더 유리하다 볼 수 있습니다.

이런 말은 함부로 할 수 없습니다. fopen()이 open()을 통해 구현되었다 하더라도 C library 함수가 system call보다 무조건 느리지 않습니다. read()가 fread()보다 느릴 수도 있습니다.

partout의 이미지

dotri wrote:
어디서는 버퍼링 여부에 따라 이진 파일과 텍스트 파일이 구분된다고도 하는것 같은데 그건 정확하게는 모르겠네요.

???... 버퍼링 여부에 따라 이진 파일과 텍스트 파일이 구분되는 것은 아닌 것 같네요. 유닉스에서 이진 파일과 텍스트 파일의 구분은 없는 걸로 알고 있습니다.

아마 표준 입출력 함수가 성능 향상을 위해 버퍼링을 한다는 것을 잘못 기억하고 계신 건 아닌지?

Quote:
The goal of the buffering provided by the standard I/O library is to use the minimum of read and write calls. Also, it tries to do its buffering automatically for each I/O stream, obviating the need for the application to worry about it.

위의 문장은 "Advanced Programming in the Unix Environment"란 책에서 발췌한 것입니다.
얼핏 생각하기에, 보통 유닉스 환경에서 fread나 fwrite 같은 표준 입출력 함수가 read, write 시스템콜을 사용하여 구현되었기 때문에 성능이 떨어질 거라고 생각할 수도 있지만...
표준 입출력 함수는 버퍼링의 개념을 도입해서 실제 입출력 횟수를 줄임으로써 성능을 높이고 있습니다. 위에 cdpark님이 말씀하신 것도 이런 맥락일 겁니다.

어찌나 졸린지..~~

antz의 이미지

표준입출력라이브러리를 사용해서 nonblocking I/O를 사용하려면 fopen에서는 어떻게 하나요? buffering을 해서 nonblocking을 사용할 필요가 없나요? 아님, 자체적으로 nonblocking으로 되있나요?

file = open("xx.txt", O_RDONLY|O_NONBLOCK)

fopen ???

mach의 이미지

버퍼링입니다.
블럭디바이스(디스크파일이 대표적이지요)의 경우, 모든 IO는 커널레벨에서는 버퍼캐시를 통하게 되어 있습니다.
이 버퍼캐시로 부터 응용프로그램으로 데이터가 IO될때 사용되는 것이 당연하게 시스템호출이지요(read(), write()등).
그런데, read(), write()등은 가끔씩 불편한 사람도 있습니다. 포맷팅 때문인데요. 이를테면 %s %d 등등 이러한 불편함은
라이브러리를 만들게 하고(당연히 사용자 영역에서 수행되는), 이 라이브러리
중에 하나가 fopen()등등시리즈 입니다.
* 메모리 관리를 라이브러리에게 맡기고 싶지 않은 사람은 read() write()를 선호하게 됩니다.
* fopen()으로 얻은 파일포인터에 setbuf()를 사용해서 버퍼를 0으로 만들면 버퍼링(라이브러리수준;유저영역)을 없애고
포맷팅은 편하게 할 수 있겠습니다.
* fileno() fcntl()을 사용해서 NON-BLocking등의 세부제어를 할 수 있습니다.
* 결론적으로, fopen()은 open()을 가지고 만든 라이브러리이기 때문에,
open()으로 열고 (????) 했던 것들을 할 수 있는 방법이 존재합니다.

** 저는 개인적으로 fopen()은 별로 선호하지 않습니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

antz의 이미지

제 프로그램에서 open, read와 fopen, fread를 비교해서 검색시간을 비교한 결과 open과 read를 쓴것이 조금 빨랐습니다. 참고하세요.

...
file = open(FilePath, O_RDONLY|O_BINARY|O_NONBLOCK);
...
lseek(file, pListTemp->nIndexPointer, SEEK_SET);
...
read(file, (void *)pData, sizeof(Data))
...

...
fp = fopen(FilePath, "rb")
fcntl(fileno(fp), F_SETFD, O_NONBLOCK);
...
fseek(fp, pListTemp->nIndexPointer, SEEK_SET);
...
fread((void *)pData, sizeof(Data), 1, fp)
...

다음은 제 프로그램의 테스트 결과로
초당 처리 개수를 나타냅니다.
숫자가 높을 수록 처리 개수가 많다고 보시면 됩니다.

Quote:

시도| fopen | open
1차 | 8.27 | 9.10
2차 | 8.13 | 8.93
3차 | 8.43 | 8.48
4차 | 8.75 | 7.63
5차 | 8.33 | 8.40
6차 | 7.87 | 8.38
Testors의 이미지

특성이 워낙 다르기에 한가지 테스트만으로 system-call 과 standard C library 중 무엇이 단적으로 낫다라고 할 수는 없습니다.
read 의 경우는 구현에 따라 system-call 이 빠를수도 있겠지만 버퍼링의 효과가 확연히 드러나는 write 쪽은 어떨까요?

아래는 1024 byte 씩 write 를 해서 100MB 를 채운 결과입니다.

testors.net:/home/testors> time ./a.out open
open()
0.055u 3.512s 0:05.97 59.6%     5+177k 11+806io 8pf+0w
testors.net:/home/testors> time ./a.out fopen
fopen()
0.213u 2.045s 0:03.41 65.9%     5+198k 11+806io 8pf+0w

버퍼링을 하는 standard C library 쪽이 75% 빠르게 나왔지요?
일반적인 사용에 있어서는 standard C library 쪽이 미약하나마 성능이 나을것입니다.

(사실 저는 성능문제 보다는 fprintf() 때문에 standard C library 를 쓰는 편입니다. :wink: )

덧. cdpark 님 키즈에서도 뵌것 같은데.. ^^

mach의 이미지

단일 프로세스가 아닌 다중 프로세스(process)환경이고, 이들 간에 동기화가
필요한 상황이라면 버퍼링은 치명적인 약점으로 될 수 있습니다.
2개의 프로세스 A, B가 각각 produce(), consume()를 담당하고 있다고 하면,
1. A는 특정 데이터를 생산하여 B에게 전달한다.
2. B는 A로 부터의 데이터를 읽어 처리한다.
이때, 프로그래머가 세심하게 주의하지 않으면, A에서 B로 데이터가 전달되는
과정에서 A의 라이브러리에게 넘기고, 마치 B로 넘어간것으로 인식하는 경우
프로그램에 다소 문제가 발생할 여지가 있습니다.

그냥 참고하세요.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

cdpark의 이미지

mach wrote:
단일 프로세스가 아닌 다중 프로세스(process)환경이고, 이들 간에 동기화가
필요한 상황이라면 버퍼링은 치명적인 약점으로 될 수 있습니다.
2개의 프로세스 A, B가 각각 produce(), consume()를 담당하고 있다고 하면,
1. A는 특정 데이터를 생산하여 B에게 전달한다.
2. B는 A로 부터의 데이터를 읽어 처리한다.
이때, 프로그래머가 세심하게 주의하지 않으면, A에서 B로 데이터가 전달되는
과정에서 A의 라이브러리에게 넘기고, 마치 B로 넘어간것으로 인식하는 경우
프로그램에 다소 문제가 발생할 여지가 있습니다.

그냥 참고하세요.

프로그래머의 잘못을 버퍼링의 잘못이라고 하지 마세요. :(

이 경우 당연히 버퍼를 비워줘야 하고, 가능하다면 handshaking까지 해야죠. 여러 TCP 프로토콜처럼요. 이런 식으로 가자면 OS에서 랜카드에게 자료를 넘겨줬다고 상대방에게 자료가 착하는 건 아니니깐요.

ssehoony의 이미지

윗 글중에 얼핏 질문이 있는 듯 해서 올립니다.

시스템이 따라서는 아스키를 바이너리와 다르게 처리하는 시스템이 있는 듯 합니다.
뭐 예상을 해본다면 아스키만 기록되는 파일은 불필요한 콘트롤 코드를 제거 하고 7비트 단위로 저장을 해서 저장공간 효율을 도모 할 수 있겠지요.
(실제 그렇다는게 아니고 예를 든다면 말이죠 ^^)
하지만 ANSI C 나 POSIX 호환 시스템은 실제 아무런 차이가 없는 듯 하네요.

다음은 MAN fopen 에 있는 문구중 일부 입니다.

Quote:

The mode string can also include the letter ``b'' either as a last
character or as a character between the characters in any of the two-
character strings described above. This is strictly for compatibility
with ANSI X3.159-1989 (``ANSI C'') and has no effect; the ``b'' is
ignored on all POSIX conforming systems, including Linux. (Other sys-
tems may treat text files and binary files differently, and adding the
``b'' may be a good idea if you do I/O to a binary file and expect that
your program may be ported to non-Unix environments.)
mach의 이미지

cdpark wrote:

프로그래머의 잘못을 버퍼링의 잘못이라고 하지 마세요. :(

이 경우 당연히 버퍼를 비워줘야 하고, 가능하다면 handshaking까지 해야죠. 여러 TCP 프로토콜처럼요. 이런 식으로 가자면 OS에서 랜카드에게 자료를 넘겨줬다고 상대방에게 자료가 착하는 건 아니니깐요.

예, 프로그래머의 잘못이지요. 버퍼링의 잘못이 아니고요.
즉, 동기화 필요시 항상 다음과 같은 형태의 코드가 필요할 수 있습니다.

...
fwrite(fd);
fflush(fd);
...

그러나, 이러한 코드 유형은 오류를 발생시키기가 쉽기 때문에 말씀드린것입니다.
동기화가 필요한데, fopen()시리즈를 썼고, 만일 fflush()를 게을리(?)한다면,
프로그램이 혼란스럽게 동작할 가능성이 아주 높습니다. 그렇다고, fflush()를
남발한다면 구지 이것(fopen 시리즈)을 사용할 필요가 없겠지요.

이러한 코드 스타일은, 어떤 때는 잘 돌고(?) 어떤 때는 안 도는(?) 프로그램을
생성할 가능성이 open()시리즈보다는 높으며, 디버깅에 어려움을 주기도
하는 경우가 많습니다.

저는 이러한 오류 가능성들에 주의하면서 코딩하기 보다는 아예 안쓰는게
어떤가? 하는 생각에서 기술했습니다.

다시 질문으로 돌아가서 기술하자면,
"open()을 사용하는것을 권장한다."
입니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

autofolder의 이미지

이미 오래된 주제인것 같습니다만, 제가 궁금한게 생겨서 질문을 추가해봅니다.

open과 fopen은 열 수 있는 파일 개수도 차이가 있다고 들었습니다.

확실한 답변을 해줄 수 있는 분 계신가요?

fdopen 에 대해서도 이야기 해주실수 있다면 감사하겠습니다.

왜사냐건 웃지요 ^^

ssehoony의 이미지

네 차이가 있는 듯 합니다.

제가 리눅스에서 작동하던 프로그램을 솔라리스로 포팅을 한적이 있는데, 리눅스에서 이상없이 작동하던 서버가 솔라리스에 문제가 발생했는데, 분석결과 솔라리스의 fopen 이 fd 를 255번까지만 열수 있었던게 문제가 됐습니다.

제 생각에서는 솔라리스에 구현된 fopen 은 255까지로 제한이 있던것 같습니다.
그래서 fopen 부분을 모두 open 으로 변경해서 해결을 했습니다.
하지만 리눅스의 fopen 은 이런 제한이 없는 것 같습니다.
테스트 해본건 아니지만 로그를 기록하기 위해 fopen 을 사용하는데 수백~수천명이 접속(tcp 소켓 fd가 수천까지 증가)해도 fopen 으로 리눅스에서는 잘 기록했으니깐요.

제 생각에 ansi c 에서는 fopen 의 fd 에 MAX 값에 대한 정확한 제한사항이 기술되어 있지 않은 것이 아닌가 조심스러 짐작해 봅니다.

그리고 fopen 과 open의 사용중 어떤걸 선호하냐는 글이 중간에 있는 듯 해서 제 의견을 말씀드리자면, 위의 경우 처럼 다른 이기종으로 포팅하는 경우가 있으므로 가급적 표준을 사용하는 것을 선호합니다.

mach의 이미지

* 파일시스템의 블럭사이즈에 대한 고려
오래된 얘기지만, 1024바이트라기 보다는 4096이 대세이옵니다.책(Bach의 Design of the Unix operating system)에서 보면 과거(한 20년전?)에 파일시스템 만들때, 블럭사이즈(한 페이지라고 봐도 될듯)에 대해 연구를 했는데, 4096바이트가 가장 좋은 성능을 보여서, 한 페이지를 4킬로로 만들게 되었습니다. 현재 대부분의 유닉스클론이 이 사이즈를 기본으로 하고 있는것으로 알고 있습니다.
따라서, open()과 fopen()을 테스트한다면, 블록사이즈를 1024로 한정짓지말고, 가변으로 1k, 2k, 3k, 4k, 8k등으로 테스트해봐야 할것입니다.
아마도 4k근처에서 open이 더 빠르지 않을까요?

* open() vs. fopen()으로 성능테스트시 혹시라도 fopen()이 성능이 나았다면?
- 왜? open은 시스템호출이므로, 불릴때마다, 커널과 유저모드의 컨텍스트 스위칭이 일어나게됩니다. 이로 인한 오버헤드(컨텍스트 스위칭)로 인한 성능 저하가 예측됩니다. 반면 fopen()은 입/출력시 특정 사이즈에 대해 버퍼링을 수행하므로, 그 특정사이즈보다 작은 양을 입출력하는 경우에 시스템호출 회수를 줄일 수 있으므로, 컨텍스트 스위치 회수에 사용되는 오버헤드 시간보다는 빠를 수 있습니다.
- 만일 그 특정사이즈를 안다면?
open()에서 한번 출력하는 양을 그 특정사이즈로 맞추고 출력하는 프로그램과, fopen()을 이용한 프로그램을 비교하면, 당연히 open으로 작성한 프로그램이 버퍼의 자료구조핸들링을 위한 fopen에 비해 빠르게 나올것입니다.
- 버퍼링을 해야겠다면?
버퍼링 정도야 만들어서 하면 되지 않을 까요?

** 하여간 open()을 애용합시다. ...... 아니면 말고......

--------------
* 열수 있는 파일 수?
- 대충 짐작해보면, fopen()은 사용자모드에서 버퍼링을 수행하기 위한 알고리즘 및 자료구조가(메모리) 사용될 것입니다. 실제 시스템(커널)에게 열어달라고 요청한 파일은 1개일테고요. 메모리만 많다면야, 그 열 수 있는 파일개수는 동등하겠지만, fopen()을 사용할 시 다소 불리할 것으로 예측됩니다.
--------------

* 여담으로, 저는 개인적으로, programming language vs. operating system을 구지 따진다면, 후자를 좋아합니다요. 이보다는 programming language가 과거 operating system이 제공했던 feature를 앗아가는게 불만이었나 봅니다. 그래서인지 오래전에는 자바가 처음 나왔을때,,,,자바를 별로 좋아하지는 않았습니다. 웬지, 뭔가를 뺏기는 느낌이 들었다고나 할까요? 게다가 nio가 나오기 전이라, 서버작성시 scalability를 중요시 하던 내게는 별로였고...... 지금은 많이 좋아졌지만 말입니다. 하여간,.... 그래도 돈주면 자바로 코딩했었고, 할겁니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

cinsk의 이미지

open(2)과 fopen(3)의 성능을 비교/테스트하는 것은 무의미합니다. 추구하는 방향이 다르기 때문입니다.

잠시 POSIX니, single unix spec이니, ISO C니 이런 것을 뒤로 하고.. 8)

먼저 open(2)은 대부분의 unix system에서 system call로 되어 있습니다. 즉 커널에게 요청하는 서비스이며, 따라서 상당히 저수준 함수입니다. 대개 (device driver 수준의 cache를 무시한다면) 버퍼링을 하지 않고 바로, 그 내용을 읽어서 사용자에게 돌려줍니다.

대부분 f*() 관련 함수는 C 언어 표준에서 제공하는 것으로, *nix에서는 open(2), read(2), write(2) 등을 써서 구현되어 있습니다. 그리고 이 f*()는 특별히 설정하지 않는한, 버퍼링을 수행합니다.

따라서 read(1)로 한 글자씩 여러번 읽어 오는 것보다 fgetc(3)로 한글자씩 여러번 읽어 오는 것이 효과적이라는 것을 추측할 수 있습니다. (내부적으로 f*() 함수들을 버퍼링된 데이터를 사용하기 때문에, fgetc(3)를 부른다고 해서, 실제 디스크 access가 무조건 일어나는 것이 아닙니다.)

대부분 f*() 함수들이 open(2)/read(2)/write(2)/close(2) 등을 써서 구현되어 있기 때문에, 단지 하나의 함수 콜로써만 두 function set을 비교한다면, 당연 후자가 빠를 수밖에 없습니다. 하지만 전자는 좀 더 추상적/복잡한 연산을 제공하기 때문에 전자가 더 적합할 수 있습니다.

fopen()으로 동시에 접근할 수 있는 파일의 갯수가 open(2)으로 접근할 수 있는 파일 갯수와 차이가 난다면, 이는 C library의 implementation에 따라 달린 문제입니다. 이 것을 가지고 fopen(3)이 open(2)보다 좋지 않다고 할 근거는 못됩니다. (참고로 ISO C 표준에서 fopen(3)으로 동시에 열 수 있는 최소 파일 갯수는 FOPEN_MAX 매크로에서 제공합니다. 또한 한 프로세스가 열 수 있는 최대 파일 갯수는 sysconf(3) 함수를 써서, OPEN_MAX 매크로 이용해서 알 수 있습니다.)

f*() 관련 함수에서 버퍼링을 제어하기 위해서 setbuf(3), setvbuf(3)를 쓸 수 있습니다. 이 함수들을 써서 버퍼링을 아예 하지 않을 수도 있습니다. 따라서 출력에 민감한 stream일 경우, (stderr처럼) 아예 버퍼링을 끌 수 있습니다.

참고로 성능을 극대화하기 위해서, 직접 open(2)/read(2) 등을 써서 연산을 수행할 때는 읽고 쓰는 단위를 파일 시스템의 블럭 단위로 하는 것이 좋습니다.
이 블럭 단위는, 해당 파일에 stat(2) 함수를 불러서 st_blksize 멤버를 통해서 알 수 있습니다. (st_blksize는 현재 Single Unix Spec에 포함되어 있음)

경험상, 여러분이 직접 cp(1)나 cat(1)과 같은 시스템 명령을 만든다거나, IO에 민감한 데이터베이스 시스템을 만든다거나 하는 경우가 아니면 f*() 계열의 표준 C 라이브러리를 이용하는 것이, 개발 효율상이나 빠르기 면에서 좋습니다.

참고로 시스템이 제공하는 여러 제한 사항이나 한계에 관심이 있으시면, sysconf(3)와 pathconf(3), setrlimit(2), getrlimit(2)에 대해서 잘 알아두시면 좋습니다. 여기를 꼭 읽어 보세요.

wputer의 이미지

저 사진때문에 기억하는데
저분글은 다 개념글 ^_^

mach의 이미지

cinsk wrote:

...

좋은 글입니다.
이 쓰레드에서 가장 적절하고 좋은 답변으로 보입니다.

한표~

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

Necromancer의 이미지

리눅스에서 fopen()을 제공하는건 glibc입니다.

아 참 그리고 glibc에서 제공하는 함수 중 커널에서 시스템콜로 구현되어
있지 않은 것들도 몇가지 있습니다.
(주로 domain name resolving과 관련된 함수들이죠.
getbyhostname() 등등. 어차피 커널 필요 없으니)

---

저도 open() 애용합니다.
파일을 한꺼번에 읽어버리고 쓰도록 만들기 때문에.

Written By the Black Knight of Destruction

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.